.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* Copyright (c) 2014 Mahesh Bandewar <maheshb@google.com> |
---|
2 | | - * |
---|
3 | | - * This program is free software; you can redistribute it and/or |
---|
4 | | - * modify it under the terms of the GNU General Public License as |
---|
5 | | - * published by the Free Software Foundation; either version 2 of |
---|
6 | | - * the License, or (at your option) any later version. |
---|
7 | | - * |
---|
8 | 3 | */ |
---|
9 | 4 | |
---|
10 | 5 | #include "ipvlan.h" |
---|
.. | .. |
---|
138 | 133 | return ret; |
---|
139 | 134 | } |
---|
140 | 135 | |
---|
141 | | -static void *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int *type) |
---|
| 136 | +void *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int *type) |
---|
142 | 137 | { |
---|
143 | 138 | void *lyr3h = NULL; |
---|
144 | 139 | |
---|
.. | .. |
---|
356 | 351 | return ret; |
---|
357 | 352 | } |
---|
358 | 353 | |
---|
359 | | -static struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port, |
---|
360 | | - void *lyr3h, int addr_type, |
---|
361 | | - bool use_dest) |
---|
| 354 | +struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port, void *lyr3h, |
---|
| 355 | + int addr_type, bool use_dest) |
---|
362 | 356 | { |
---|
363 | 357 | struct ipvl_addr *addr = NULL; |
---|
364 | 358 | |
---|
.. | .. |
---|
443 | 437 | goto err; |
---|
444 | 438 | } |
---|
445 | 439 | skb_dst_set(skb, &rt->dst); |
---|
| 440 | + |
---|
| 441 | + memset(IPCB(skb), 0, sizeof(*IPCB(skb))); |
---|
| 442 | + |
---|
446 | 443 | err = ip_local_out(net, skb->sk, skb); |
---|
447 | 444 | if (unlikely(net_xmit_eval(err))) |
---|
448 | 445 | dev->stats.tx_errors++; |
---|
.. | .. |
---|
481 | 478 | goto err; |
---|
482 | 479 | } |
---|
483 | 480 | skb_dst_set(skb, dst); |
---|
| 481 | + |
---|
| 482 | + memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); |
---|
| 483 | + |
---|
484 | 484 | err = ip6_local_out(net, skb->sk, skb); |
---|
485 | 485 | if (unlikely(net_xmit_eval(err))) |
---|
486 | 486 | dev->stats.tx_errors++; |
---|
.. | .. |
---|
502 | 502 | |
---|
503 | 503 | static int ipvlan_process_outbound(struct sk_buff *skb) |
---|
504 | 504 | { |
---|
505 | | - struct ethhdr *ethh = eth_hdr(skb); |
---|
506 | 505 | int ret = NET_XMIT_DROP; |
---|
507 | 506 | |
---|
508 | 507 | /* The ipvlan is a pseudo-L2 device, so the packets that we receive |
---|
.. | .. |
---|
512 | 511 | if (skb_mac_header_was_set(skb)) { |
---|
513 | 512 | /* In this mode we dont care about |
---|
514 | 513 | * multicast and broadcast traffic */ |
---|
| 514 | + struct ethhdr *ethh = eth_hdr(skb); |
---|
| 515 | + |
---|
515 | 516 | if (is_multicast_ether_addr(ethh->h_dest)) { |
---|
516 | 517 | pr_debug_ratelimited( |
---|
517 | 518 | "Dropped {multi|broad}cast of type=[%x]\n", |
---|
.. | .. |
---|
585 | 586 | consume_skb(skb); |
---|
586 | 587 | return NET_XMIT_DROP; |
---|
587 | 588 | } |
---|
588 | | - return ipvlan_rcv_frame(addr, &skb, true); |
---|
| 589 | + ipvlan_rcv_frame(addr, &skb, true); |
---|
| 590 | + return NET_XMIT_SUCCESS; |
---|
589 | 591 | } |
---|
590 | 592 | } |
---|
591 | 593 | out: |
---|
.. | .. |
---|
596 | 598 | static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev) |
---|
597 | 599 | { |
---|
598 | 600 | const struct ipvl_dev *ipvlan = netdev_priv(dev); |
---|
599 | | - struct ethhdr *eth = eth_hdr(skb); |
---|
| 601 | + struct ethhdr *eth = skb_eth_hdr(skb); |
---|
600 | 602 | struct ipvl_addr *addr; |
---|
601 | 603 | void *lyr3h; |
---|
602 | 604 | int addr_type; |
---|
.. | .. |
---|
611 | 613 | consume_skb(skb); |
---|
612 | 614 | return NET_XMIT_DROP; |
---|
613 | 615 | } |
---|
614 | | - return ipvlan_rcv_frame(addr, &skb, true); |
---|
| 616 | + ipvlan_rcv_frame(addr, &skb, true); |
---|
| 617 | + return NET_XMIT_SUCCESS; |
---|
615 | 618 | } |
---|
616 | 619 | } |
---|
617 | 620 | skb = skb_share_check(skb, GFP_ATOMIC); |
---|
.. | .. |
---|
623 | 626 | * the skb for the main-dev. At the RX side we just return |
---|
624 | 627 | * RX_PASS for it to be processed further on the stack. |
---|
625 | 628 | */ |
---|
626 | | - return dev_forward_skb(ipvlan->phy_dev, skb); |
---|
| 629 | + dev_forward_skb(ipvlan->phy_dev, skb); |
---|
| 630 | + return NET_XMIT_SUCCESS; |
---|
627 | 631 | |
---|
628 | 632 | } else if (is_multicast_ether_addr(eth->h_dest)) { |
---|
| 633 | + skb_reset_mac_header(skb); |
---|
629 | 634 | ipvlan_skb_crossing_ns(skb, NULL); |
---|
630 | 635 | ipvlan_multicast_enqueue(ipvlan->port, skb, true); |
---|
631 | 636 | return NET_XMIT_SUCCESS; |
---|
.. | .. |
---|
650 | 655 | case IPVLAN_MODE_L2: |
---|
651 | 656 | return ipvlan_xmit_mode_l2(skb, dev); |
---|
652 | 657 | case IPVLAN_MODE_L3: |
---|
| 658 | +#ifdef CONFIG_IPVLAN_L3S |
---|
653 | 659 | case IPVLAN_MODE_L3S: |
---|
| 660 | +#endif |
---|
654 | 661 | return ipvlan_xmit_mode_l3(skb, dev); |
---|
655 | 662 | } |
---|
656 | 663 | |
---|
.. | .. |
---|
746 | 753 | return ipvlan_handle_mode_l2(pskb, port); |
---|
747 | 754 | case IPVLAN_MODE_L3: |
---|
748 | 755 | return ipvlan_handle_mode_l3(pskb, port); |
---|
| 756 | +#ifdef CONFIG_IPVLAN_L3S |
---|
749 | 757 | case IPVLAN_MODE_L3S: |
---|
750 | 758 | return RX_HANDLER_PASS; |
---|
| 759 | +#endif |
---|
751 | 760 | } |
---|
752 | 761 | |
---|
753 | 762 | /* Should not reach here */ |
---|
.. | .. |
---|
755 | 764 | port->mode); |
---|
756 | 765 | kfree_skb(skb); |
---|
757 | 766 | return RX_HANDLER_CONSUMED; |
---|
758 | | -} |
---|
759 | | - |
---|
760 | | -static struct ipvl_addr *ipvlan_skb_to_addr(struct sk_buff *skb, |
---|
761 | | - struct net_device *dev) |
---|
762 | | -{ |
---|
763 | | - struct ipvl_addr *addr = NULL; |
---|
764 | | - struct ipvl_port *port; |
---|
765 | | - void *lyr3h; |
---|
766 | | - int addr_type; |
---|
767 | | - |
---|
768 | | - if (!dev || !netif_is_ipvlan_port(dev)) |
---|
769 | | - goto out; |
---|
770 | | - |
---|
771 | | - port = ipvlan_port_get_rcu(dev); |
---|
772 | | - if (!port || port->mode != IPVLAN_MODE_L3S) |
---|
773 | | - goto out; |
---|
774 | | - |
---|
775 | | - lyr3h = ipvlan_get_L3_hdr(port, skb, &addr_type); |
---|
776 | | - if (!lyr3h) |
---|
777 | | - goto out; |
---|
778 | | - |
---|
779 | | - addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true); |
---|
780 | | -out: |
---|
781 | | - return addr; |
---|
782 | | -} |
---|
783 | | - |
---|
784 | | -struct sk_buff *ipvlan_l3_rcv(struct net_device *dev, struct sk_buff *skb, |
---|
785 | | - u16 proto) |
---|
786 | | -{ |
---|
787 | | - struct ipvl_addr *addr; |
---|
788 | | - struct net_device *sdev; |
---|
789 | | - |
---|
790 | | - addr = ipvlan_skb_to_addr(skb, dev); |
---|
791 | | - if (!addr) |
---|
792 | | - goto out; |
---|
793 | | - |
---|
794 | | - sdev = addr->master->dev; |
---|
795 | | - switch (proto) { |
---|
796 | | - case AF_INET: |
---|
797 | | - { |
---|
798 | | - int err; |
---|
799 | | - struct iphdr *ip4h = ip_hdr(skb); |
---|
800 | | - |
---|
801 | | - err = ip_route_input_noref(skb, ip4h->daddr, ip4h->saddr, |
---|
802 | | - ip4h->tos, sdev); |
---|
803 | | - if (unlikely(err)) |
---|
804 | | - goto out; |
---|
805 | | - break; |
---|
806 | | - } |
---|
807 | | -#if IS_ENABLED(CONFIG_IPV6) |
---|
808 | | - case AF_INET6: |
---|
809 | | - { |
---|
810 | | - struct dst_entry *dst; |
---|
811 | | - struct ipv6hdr *ip6h = ipv6_hdr(skb); |
---|
812 | | - int flags = RT6_LOOKUP_F_HAS_SADDR; |
---|
813 | | - struct flowi6 fl6 = { |
---|
814 | | - .flowi6_iif = sdev->ifindex, |
---|
815 | | - .daddr = ip6h->daddr, |
---|
816 | | - .saddr = ip6h->saddr, |
---|
817 | | - .flowlabel = ip6_flowinfo(ip6h), |
---|
818 | | - .flowi6_mark = skb->mark, |
---|
819 | | - .flowi6_proto = ip6h->nexthdr, |
---|
820 | | - }; |
---|
821 | | - |
---|
822 | | - skb_dst_drop(skb); |
---|
823 | | - dst = ip6_route_input_lookup(dev_net(sdev), sdev, &fl6, |
---|
824 | | - skb, flags); |
---|
825 | | - skb_dst_set(skb, dst); |
---|
826 | | - break; |
---|
827 | | - } |
---|
828 | | -#endif |
---|
829 | | - default: |
---|
830 | | - break; |
---|
831 | | - } |
---|
832 | | - |
---|
833 | | -out: |
---|
834 | | - return skb; |
---|
835 | | -} |
---|
836 | | - |
---|
837 | | -unsigned int ipvlan_nf_input(void *priv, struct sk_buff *skb, |
---|
838 | | - const struct nf_hook_state *state) |
---|
839 | | -{ |
---|
840 | | - struct ipvl_addr *addr; |
---|
841 | | - unsigned int len; |
---|
842 | | - |
---|
843 | | - addr = ipvlan_skb_to_addr(skb, skb->dev); |
---|
844 | | - if (!addr) |
---|
845 | | - goto out; |
---|
846 | | - |
---|
847 | | - skb->dev = addr->master->dev; |
---|
848 | | - len = skb->len + ETH_HLEN; |
---|
849 | | - ipvlan_count_rx(addr->master, len, true, false); |
---|
850 | | -out: |
---|
851 | | - return NF_ACCEPT; |
---|
852 | 767 | } |
---|