]> Git Repo - linux.git/blobdiff - net/xfrm/xfrm_interface.c
xfrm interface: fix packet tx through bpf_redirect()
[linux.git] / net / xfrm / xfrm_interface.c
index 7ac1542feaf835af0f166788bef8931d3edd53bb..00393179f18521646c8377c29b21af156f4dd8e4 100644 (file)
@@ -268,9 +268,6 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
        int err = -1;
        int mtu;
 
-       if (!dst)
-               goto tx_err_link_failure;
-
        dst_hold(dst);
        dst = xfrm_lookup_with_ifid(xi->net, dst, fl, NULL, 0, xi->p.if_id);
        if (IS_ERR(dst)) {
@@ -343,6 +340,7 @@ static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct xfrm_if *xi = netdev_priv(dev);
        struct net_device_stats *stats = &xi->dev->stats;
+       struct dst_entry *dst = skb_dst(skb);
        struct flowi fl;
        int ret;
 
@@ -352,10 +350,33 @@ static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev)
        case htons(ETH_P_IPV6):
                xfrm_decode_session(skb, &fl, AF_INET6);
                memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
+               if (!dst) {
+                       fl.u.ip6.flowi6_oif = dev->ifindex;
+                       fl.u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC;
+                       dst = ip6_route_output(dev_net(dev), NULL, &fl.u.ip6);
+                       if (dst->error) {
+                               dst_release(dst);
+                               stats->tx_carrier_errors++;
+                               goto tx_err;
+                       }
+                       skb_dst_set(skb, dst);
+               }
                break;
        case htons(ETH_P_IP):
                xfrm_decode_session(skb, &fl, AF_INET);
                memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
+               if (!dst) {
+                       struct rtable *rt;
+
+                       fl.u.ip4.flowi4_oif = dev->ifindex;
+                       fl.u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC;
+                       rt = __ip_route_output_key(dev_net(dev), &fl.u.ip4);
+                       if (IS_ERR(rt)) {
+                               stats->tx_carrier_errors++;
+                               goto tx_err;
+                       }
+                       skb_dst_set(skb, &rt->dst);
+               }
                break;
        default:
                goto tx_err;
@@ -563,12 +584,9 @@ static void xfrmi_dev_setup(struct net_device *dev)
 {
        dev->netdev_ops         = &xfrmi_netdev_ops;
        dev->type               = ARPHRD_NONE;
-       dev->hard_header_len    = ETH_HLEN;
-       dev->min_header_len     = ETH_HLEN;
        dev->mtu                = ETH_DATA_LEN;
        dev->min_mtu            = ETH_MIN_MTU;
-       dev->max_mtu            = ETH_DATA_LEN;
-       dev->addr_len           = ETH_ALEN;
+       dev->max_mtu            = IP_MAX_MTU;
        dev->flags              = IFF_NOARP;
        dev->needs_free_netdev  = true;
        dev->priv_destructor    = xfrmi_dev_free;
This page took 0.031425 seconds and 4 git commands to generate.