]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/net/vrf.c
net: fddi: skfp: use %p format specifier for addresses rather than %x
[karo-tx-linux.git] / drivers / net / vrf.c
index 820de6a9ddde1dcfa8ee389bc20e56ae61afa1b9..7532646c3b7bedb89c2cbe95e84f09e32e0a8391 100644 (file)
@@ -272,11 +272,6 @@ static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb,
        if (IS_ERR(rt))
                goto err;
 
-       if (rt->rt_type != RTN_UNICAST && rt->rt_type != RTN_LOCAL) {
-               ip_rt_put(rt);
-               goto err;
-       }
-
        skb_dst_drop(skb);
 
        /* if dst.dev is loopback or the VRF device again this is locally
@@ -371,6 +366,8 @@ static int vrf_finish_output6(struct net *net, struct sock *sk,
        struct in6_addr *nexthop;
        int ret;
 
+       nf_reset(skb);
+
        skb->protocol = htons(ETH_P_IPV6);
        skb->dev = dev;
 
@@ -552,6 +549,8 @@ static int vrf_finish_output(struct net *net, struct sock *sk, struct sk_buff *s
        u32 nexthop;
        int ret = -EINVAL;
 
+       nf_reset(skb);
+
        /* Be paranoid, rather than too clever. */
        if (unlikely(skb_headroom(skb) < hh_len && dev->header_ops)) {
                struct sk_buff *skb2;
@@ -611,6 +610,10 @@ static struct sk_buff *vrf_ip_out(struct net_device *vrf_dev,
        struct dst_entry *dst = NULL;
        struct rtable *rth;
 
+       /* don't divert multicast */
+       if (ipv4_is_multicast(ip_hdr(skb)->daddr))
+               return skb;
+
        rcu_read_lock();
 
        rth = rcu_dereference(vrf->rth);
@@ -850,8 +853,6 @@ static struct sk_buff *vrf_rcv_nfhook(u8 pf, unsigned int hook,
 {
        struct net *net = dev_net(dev);
 
-       nf_reset(skb);
-
        if (NF_HOOK(pf, hook, net, NULL, skb, dev, NULL, vrf_rcv_finish) < 0)
                skb = NULL;    /* kfree_skb(skb) handled by nf code */
 
@@ -999,6 +1000,9 @@ static struct sk_buff *vrf_ip_rcv(struct net_device *vrf_dev,
        skb->skb_iif = vrf_dev->ifindex;
        IPCB(skb)->flags |= IPSKB_L3SLAVE;
 
+       if (ipv4_is_multicast(ip_hdr(skb)->daddr))
+               goto out;
+
        /* loopback traffic; do not push through packet taps again.
         * Reset pkt_type for upper layers to process skb
         */
@@ -1162,8 +1166,19 @@ static int vrf_add_fib_rules(const struct net_device *dev)
        if (err < 0)
                goto ipv6_err;
 
+#if IS_ENABLED(CONFIG_IP_MROUTE_MULTIPLE_TABLES)
+       err = vrf_fib_rule(dev, RTNL_FAMILY_IPMR, true);
+       if (err < 0)
+               goto ipmr_err;
+#endif
+
        return 0;
 
+#if IS_ENABLED(CONFIG_IP_MROUTE_MULTIPLE_TABLES)
+ipmr_err:
+       vrf_fib_rule(dev, AF_INET6,  false);
+#endif
+
 ipv6_err:
        vrf_fib_rule(dev, AF_INET,  false);