aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ipvlan
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ipvlan')
-rw-r--r--drivers/net/ipvlan/ipvlan_core.c72
-rw-r--r--drivers/net/ipvlan/ipvlan_main.c48
2 files changed, 85 insertions, 35 deletions
diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c
index c1f008fe4e1d..1b5dc200b573 100644
--- a/drivers/net/ipvlan/ipvlan_core.c
+++ b/drivers/net/ipvlan/ipvlan_core.c
@@ -35,6 +35,7 @@ void ipvlan_count_rx(const struct ipvl_dev *ipvlan,
35} 35}
36EXPORT_SYMBOL_GPL(ipvlan_count_rx); 36EXPORT_SYMBOL_GPL(ipvlan_count_rx);
37 37
38#if IS_ENABLED(CONFIG_IPV6)
38static u8 ipvlan_get_v6_hash(const void *iaddr) 39static u8 ipvlan_get_v6_hash(const void *iaddr)
39{ 40{
40 const struct in6_addr *ip6_addr = iaddr; 41 const struct in6_addr *ip6_addr = iaddr;
@@ -42,6 +43,12 @@ static u8 ipvlan_get_v6_hash(const void *iaddr)
42 return __ipv6_addr_jhash(ip6_addr, ipvlan_jhash_secret) & 43 return __ipv6_addr_jhash(ip6_addr, ipvlan_jhash_secret) &
43 IPVLAN_HASH_MASK; 44 IPVLAN_HASH_MASK;
44} 45}
46#else
47static u8 ipvlan_get_v6_hash(const void *iaddr)
48{
49 return 0;
50}
51#endif
45 52
46static u8 ipvlan_get_v4_hash(const void *iaddr) 53static u8 ipvlan_get_v4_hash(const void *iaddr)
47{ 54{
@@ -51,6 +58,23 @@ static u8 ipvlan_get_v4_hash(const void *iaddr)
51 IPVLAN_HASH_MASK; 58 IPVLAN_HASH_MASK;
52} 59}
53 60
61static bool addr_equal(bool is_v6, struct ipvl_addr *addr, const void *iaddr)
62{
63 if (!is_v6 && addr->atype == IPVL_IPV4) {
64 struct in_addr *i4addr = (struct in_addr *)iaddr;
65
66 return addr->ip4addr.s_addr == i4addr->s_addr;
67#if IS_ENABLED(CONFIG_IPV6)
68 } else if (is_v6 && addr->atype == IPVL_IPV6) {
69 struct in6_addr *i6addr = (struct in6_addr *)iaddr;
70
71 return ipv6_addr_equal(&addr->ip6addr, i6addr);
72#endif
73 }
74
75 return false;
76}
77
54static struct ipvl_addr *ipvlan_ht_addr_lookup(const struct ipvl_port *port, 78static struct ipvl_addr *ipvlan_ht_addr_lookup(const struct ipvl_port *port,
55 const void *iaddr, bool is_v6) 79 const void *iaddr, bool is_v6)
56{ 80{
@@ -59,15 +83,9 @@ static struct ipvl_addr *ipvlan_ht_addr_lookup(const struct ipvl_port *port,
59 83
60 hash = is_v6 ? ipvlan_get_v6_hash(iaddr) : 84 hash = is_v6 ? ipvlan_get_v6_hash(iaddr) :
61 ipvlan_get_v4_hash(iaddr); 85 ipvlan_get_v4_hash(iaddr);
62 hlist_for_each_entry_rcu(addr, &port->hlhead[hash], hlnode) { 86 hlist_for_each_entry_rcu(addr, &port->hlhead[hash], hlnode)
63 if (is_v6 && addr->atype == IPVL_IPV6 && 87 if (addr_equal(is_v6, addr, iaddr))
64 ipv6_addr_equal(&addr->ip6addr, iaddr))
65 return addr;
66 else if (!is_v6 && addr->atype == IPVL_IPV4 &&
67 addr->ip4addr.s_addr ==
68 ((struct in_addr *)iaddr)->s_addr)
69 return addr; 88 return addr;
70 }
71 return NULL; 89 return NULL;
72} 90}
73 91
@@ -93,13 +111,9 @@ struct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan,
93{ 111{
94 struct ipvl_addr *addr; 112 struct ipvl_addr *addr;
95 113
96 list_for_each_entry(addr, &ipvlan->addrs, anode) { 114 list_for_each_entry(addr, &ipvlan->addrs, anode)
97 if ((is_v6 && addr->atype == IPVL_IPV6 && 115 if (addr_equal(is_v6, addr, iaddr))
98 ipv6_addr_equal(&addr->ip6addr, iaddr)) ||
99 (!is_v6 && addr->atype == IPVL_IPV4 &&
100 addr->ip4addr.s_addr == ((struct in_addr *)iaddr)->s_addr))
101 return addr; 116 return addr;
102 }
103 return NULL; 117 return NULL;
104} 118}
105 119
@@ -150,6 +164,7 @@ static void *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int
150 lyr3h = ip4h; 164 lyr3h = ip4h;
151 break; 165 break;
152 } 166 }
167#if IS_ENABLED(CONFIG_IPV6)
153 case htons(ETH_P_IPV6): { 168 case htons(ETH_P_IPV6): {
154 struct ipv6hdr *ip6h; 169 struct ipv6hdr *ip6h;
155 170
@@ -188,6 +203,7 @@ static void *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int
188 } 203 }
189 break; 204 break;
190 } 205 }
206#endif
191 default: 207 default:
192 return NULL; 208 return NULL;
193 } 209 }
@@ -337,14 +353,18 @@ static struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port,
337{ 353{
338 struct ipvl_addr *addr = NULL; 354 struct ipvl_addr *addr = NULL;
339 355
340 if (addr_type == IPVL_IPV6) { 356 switch (addr_type) {
357#if IS_ENABLED(CONFIG_IPV6)
358 case IPVL_IPV6: {
341 struct ipv6hdr *ip6h; 359 struct ipv6hdr *ip6h;
342 struct in6_addr *i6addr; 360 struct in6_addr *i6addr;
343 361
344 ip6h = (struct ipv6hdr *)lyr3h; 362 ip6h = (struct ipv6hdr *)lyr3h;
345 i6addr = use_dest ? &ip6h->daddr : &ip6h->saddr; 363 i6addr = use_dest ? &ip6h->daddr : &ip6h->saddr;
346 addr = ipvlan_ht_addr_lookup(port, i6addr, true); 364 addr = ipvlan_ht_addr_lookup(port, i6addr, true);
347 } else if (addr_type == IPVL_ICMPV6) { 365 break;
366 }
367 case IPVL_ICMPV6: {
348 struct nd_msg *ndmh; 368 struct nd_msg *ndmh;
349 struct in6_addr *i6addr; 369 struct in6_addr *i6addr;
350 370
@@ -356,14 +376,19 @@ static struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port,
356 i6addr = &ndmh->target; 376 i6addr = &ndmh->target;
357 addr = ipvlan_ht_addr_lookup(port, i6addr, true); 377 addr = ipvlan_ht_addr_lookup(port, i6addr, true);
358 } 378 }
359 } else if (addr_type == IPVL_IPV4) { 379 break;
380 }
381#endif
382 case IPVL_IPV4: {
360 struct iphdr *ip4h; 383 struct iphdr *ip4h;
361 __be32 *i4addr; 384 __be32 *i4addr;
362 385
363 ip4h = (struct iphdr *)lyr3h; 386 ip4h = (struct iphdr *)lyr3h;
364 i4addr = use_dest ? &ip4h->daddr : &ip4h->saddr; 387 i4addr = use_dest ? &ip4h->daddr : &ip4h->saddr;
365 addr = ipvlan_ht_addr_lookup(port, i4addr, false); 388 addr = ipvlan_ht_addr_lookup(port, i4addr, false);
366 } else if (addr_type == IPVL_ARP) { 389 break;
390 }
391 case IPVL_ARP: {
367 struct arphdr *arph; 392 struct arphdr *arph;
368 unsigned char *arp_ptr; 393 unsigned char *arp_ptr;
369 __be32 dip; 394 __be32 dip;
@@ -377,6 +402,8 @@ static struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port,
377 402
378 memcpy(&dip, arp_ptr, 4); 403 memcpy(&dip, arp_ptr, 4);
379 addr = ipvlan_ht_addr_lookup(port, &dip, false); 404 addr = ipvlan_ht_addr_lookup(port, &dip, false);
405 break;
406 }
380 } 407 }
381 408
382 return addr; 409 return addr;
@@ -420,6 +447,7 @@ out:
420 return ret; 447 return ret;
421} 448}
422 449
450#if IS_ENABLED(CONFIG_IPV6)
423static int ipvlan_process_v6_outbound(struct sk_buff *skb) 451static int ipvlan_process_v6_outbound(struct sk_buff *skb)
424{ 452{
425 const struct ipv6hdr *ip6h = ipv6_hdr(skb); 453 const struct ipv6hdr *ip6h = ipv6_hdr(skb);
@@ -456,6 +484,12 @@ err:
456out: 484out:
457 return ret; 485 return ret;
458} 486}
487#else
488static int ipvlan_process_v6_outbound(struct sk_buff *skb)
489{
490 return NET_XMIT_DROP;
491}
492#endif
459 493
460static int ipvlan_process_outbound(struct sk_buff *skb) 494static int ipvlan_process_outbound(struct sk_buff *skb)
461{ 495{
@@ -759,6 +793,7 @@ struct sk_buff *ipvlan_l3_rcv(struct net_device *dev, struct sk_buff *skb,
759 goto out; 793 goto out;
760 break; 794 break;
761 } 795 }
796#if IS_ENABLED(CONFIG_IPV6)
762 case AF_INET6: 797 case AF_INET6:
763 { 798 {
764 struct dst_entry *dst; 799 struct dst_entry *dst;
@@ -778,6 +813,7 @@ struct sk_buff *ipvlan_l3_rcv(struct net_device *dev, struct sk_buff *skb,
778 skb_dst_set(skb, dst); 813 skb_dst_set(skb, dst);
779 break; 814 break;
780 } 815 }
816#endif
781 default: 817 default:
782 break; 818 break;
783 } 819 }
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index 2469df118fbf..67c91ceda979 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -22,12 +22,14 @@ static const struct nf_hook_ops ipvl_nfops[] = {
22 .hooknum = NF_INET_LOCAL_IN, 22 .hooknum = NF_INET_LOCAL_IN,
23 .priority = INT_MAX, 23 .priority = INT_MAX,
24 }, 24 },
25#if IS_ENABLED(CONFIG_IPV6)
25 { 26 {
26 .hook = ipvlan_nf_input, 27 .hook = ipvlan_nf_input,
27 .pf = NFPROTO_IPV6, 28 .pf = NFPROTO_IPV6,
28 .hooknum = NF_INET_LOCAL_IN, 29 .hooknum = NF_INET_LOCAL_IN,
29 .priority = INT_MAX, 30 .priority = INT_MAX,
30 }, 31 },
32#endif
31}; 33};
32 34
33static const struct l3mdev_ops ipvl_l3mdev_ops = { 35static const struct l3mdev_ops ipvl_l3mdev_ops = {
@@ -800,12 +802,14 @@ static int ipvlan_add_addr(struct ipvl_dev *ipvlan, void *iaddr, bool is_v6)
800 return -ENOMEM; 802 return -ENOMEM;
801 803
802 addr->master = ipvlan; 804 addr->master = ipvlan;
803 if (is_v6) { 805 if (!is_v6) {
804 memcpy(&addr->ip6addr, iaddr, sizeof(struct in6_addr));
805 addr->atype = IPVL_IPV6;
806 } else {
807 memcpy(&addr->ip4addr, iaddr, sizeof(struct in_addr)); 806 memcpy(&addr->ip4addr, iaddr, sizeof(struct in_addr));
808 addr->atype = IPVL_IPV4; 807 addr->atype = IPVL_IPV4;
808#if IS_ENABLED(CONFIG_IPV6)
809 } else {
810 memcpy(&addr->ip6addr, iaddr, sizeof(struct in6_addr));
811 addr->atype = IPVL_IPV6;
812#endif
809 } 813 }
810 list_add_tail(&addr->anode, &ipvlan->addrs); 814 list_add_tail(&addr->anode, &ipvlan->addrs);
811 815
@@ -833,6 +837,20 @@ static void ipvlan_del_addr(struct ipvl_dev *ipvlan, void *iaddr, bool is_v6)
833 return; 837 return;
834} 838}
835 839
840static bool ipvlan_is_valid_dev(const struct net_device *dev)
841{
842 struct ipvl_dev *ipvlan = netdev_priv(dev);
843
844 if (!netif_is_ipvlan(dev))
845 return false;
846
847 if (!ipvlan || !ipvlan->port)
848 return false;
849
850 return true;
851}
852
853#if IS_ENABLED(CONFIG_IPV6)
836static int ipvlan_add_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr) 854static int ipvlan_add_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr)
837{ 855{
838 if (ipvlan_addr_busy(ipvlan->port, ip6_addr, true)) { 856 if (ipvlan_addr_busy(ipvlan->port, ip6_addr, true)) {
@@ -850,19 +868,6 @@ static void ipvlan_del_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr)
850 return ipvlan_del_addr(ipvlan, ip6_addr, true); 868 return ipvlan_del_addr(ipvlan, ip6_addr, true);
851} 869}
852 870
853static bool ipvlan_is_valid_dev(const struct net_device *dev)
854{
855 struct ipvl_dev *ipvlan = netdev_priv(dev);
856
857 if (!netif_is_ipvlan(dev))
858 return false;
859
860 if (!ipvlan || !ipvlan->port)
861 return false;
862
863 return true;
864}
865
866static int ipvlan_addr6_event(struct notifier_block *unused, 871static int ipvlan_addr6_event(struct notifier_block *unused,
867 unsigned long event, void *ptr) 872 unsigned long event, void *ptr)
868{ 873{
@@ -913,6 +918,7 @@ static int ipvlan_addr6_validator_event(struct notifier_block *unused,
913 918
914 return NOTIFY_OK; 919 return NOTIFY_OK;
915} 920}
921#endif
916 922
917static int ipvlan_add_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr) 923static int ipvlan_add_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr)
918{ 924{
@@ -993,6 +999,7 @@ static struct notifier_block ipvlan_notifier_block __read_mostly = {
993 .notifier_call = ipvlan_device_event, 999 .notifier_call = ipvlan_device_event,
994}; 1000};
995 1001
1002#if IS_ENABLED(CONFIG_IPV6)
996static struct notifier_block ipvlan_addr6_notifier_block __read_mostly = { 1003static struct notifier_block ipvlan_addr6_notifier_block __read_mostly = {
997 .notifier_call = ipvlan_addr6_event, 1004 .notifier_call = ipvlan_addr6_event,
998}; 1005};
@@ -1000,6 +1007,7 @@ static struct notifier_block ipvlan_addr6_notifier_block __read_mostly = {
1000static struct notifier_block ipvlan_addr6_vtor_notifier_block __read_mostly = { 1007static struct notifier_block ipvlan_addr6_vtor_notifier_block __read_mostly = {
1001 .notifier_call = ipvlan_addr6_validator_event, 1008 .notifier_call = ipvlan_addr6_validator_event,
1002}; 1009};
1010#endif
1003 1011
1004static void ipvlan_ns_exit(struct net *net) 1012static void ipvlan_ns_exit(struct net *net)
1005{ 1013{
@@ -1024,9 +1032,11 @@ static int __init ipvlan_init_module(void)
1024 1032
1025 ipvlan_init_secret(); 1033 ipvlan_init_secret();
1026 register_netdevice_notifier(&ipvlan_notifier_block); 1034 register_netdevice_notifier(&ipvlan_notifier_block);
1035#if IS_ENABLED(CONFIG_IPV6)
1027 register_inet6addr_notifier(&ipvlan_addr6_notifier_block); 1036 register_inet6addr_notifier(&ipvlan_addr6_notifier_block);
1028 register_inet6addr_validator_notifier( 1037 register_inet6addr_validator_notifier(
1029 &ipvlan_addr6_vtor_notifier_block); 1038 &ipvlan_addr6_vtor_notifier_block);
1039#endif
1030 register_inetaddr_notifier(&ipvlan_addr4_notifier_block); 1040 register_inetaddr_notifier(&ipvlan_addr4_notifier_block);
1031 register_inetaddr_validator_notifier(&ipvlan_addr4_vtor_notifier_block); 1041 register_inetaddr_validator_notifier(&ipvlan_addr4_vtor_notifier_block);
1032 1042
@@ -1045,9 +1055,11 @@ error:
1045 unregister_inetaddr_notifier(&ipvlan_addr4_notifier_block); 1055 unregister_inetaddr_notifier(&ipvlan_addr4_notifier_block);
1046 unregister_inetaddr_validator_notifier( 1056 unregister_inetaddr_validator_notifier(
1047 &ipvlan_addr4_vtor_notifier_block); 1057 &ipvlan_addr4_vtor_notifier_block);
1058#if IS_ENABLED(CONFIG_IPV6)
1048 unregister_inet6addr_notifier(&ipvlan_addr6_notifier_block); 1059 unregister_inet6addr_notifier(&ipvlan_addr6_notifier_block);
1049 unregister_inet6addr_validator_notifier( 1060 unregister_inet6addr_validator_notifier(
1050 &ipvlan_addr6_vtor_notifier_block); 1061 &ipvlan_addr6_vtor_notifier_block);
1062#endif
1051 unregister_netdevice_notifier(&ipvlan_notifier_block); 1063 unregister_netdevice_notifier(&ipvlan_notifier_block);
1052 return err; 1064 return err;
1053} 1065}
@@ -1060,9 +1072,11 @@ static void __exit ipvlan_cleanup_module(void)
1060 unregister_inetaddr_notifier(&ipvlan_addr4_notifier_block); 1072 unregister_inetaddr_notifier(&ipvlan_addr4_notifier_block);
1061 unregister_inetaddr_validator_notifier( 1073 unregister_inetaddr_validator_notifier(
1062 &ipvlan_addr4_vtor_notifier_block); 1074 &ipvlan_addr4_vtor_notifier_block);
1075#if IS_ENABLED(CONFIG_IPV6)
1063 unregister_inet6addr_notifier(&ipvlan_addr6_notifier_block); 1076 unregister_inet6addr_notifier(&ipvlan_addr6_notifier_block);
1064 unregister_inet6addr_validator_notifier( 1077 unregister_inet6addr_validator_notifier(
1065 &ipvlan_addr6_vtor_notifier_block); 1078 &ipvlan_addr6_vtor_notifier_block);
1079#endif
1066} 1080}
1067 1081
1068module_init(ipvlan_init_module); 1082module_init(ipvlan_init_module);