1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* Copyright (c) 2014 Mahesh Bandewar <maheshb@google.com> 3 */ 4 5 #include "ipvlan.h" 6 7 static unsigned int ipvlan_netid __read_mostly; 8 9 struct ipvlan_netns { 10 unsigned int ipvl_nf_hook_refcnt; 11 }; 12 13 static struct ipvl_addr *ipvlan_skb_to_addr(struct sk_buff *skb, 14 struct net_device *dev) 15 { 16 struct ipvl_addr *addr = NULL; 17 struct ipvl_port *port; 18 int addr_type; 19 void *lyr3h; 20 21 if (!dev || !netif_is_ipvlan_port(dev)) 22 goto out; 23 24 port = ipvlan_port_get_rcu(dev); 25 if (!port || port->mode != IPVLAN_MODE_L3S) 26 goto out; 27 28 lyr3h = ipvlan_get_L3_hdr(port, skb, &addr_type); 29 if (!lyr3h) 30 goto out; 31 32 addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true); 33 out: 34 return addr; 35 } 36 37 static struct sk_buff *ipvlan_l3_rcv(struct net_device *dev, 38 struct sk_buff *skb, u16 proto) 39 { 40 struct ipvl_addr *addr; 41 struct net_device *sdev; 42 43 addr = ipvlan_skb_to_addr(skb, dev); 44 if (!addr) 45 goto out; 46 47 sdev = addr->master->dev; 48 switch (proto) { 49 case AF_INET: 50 { 51 struct iphdr *ip4h = ip_hdr(skb); 52 int err; 53 54 err = ip_route_input_noref(skb, ip4h->daddr, ip4h->saddr, 55 ip4h->tos, sdev); 56 if (unlikely(err)) 57 goto out; 58 break; 59 } 60 #if IS_ENABLED(CONFIG_IPV6) 61 case AF_INET6: 62 { 63 struct dst_entry *dst; 64 struct ipv6hdr *ip6h = ipv6_hdr(skb); 65 int flags = RT6_LOOKUP_F_HAS_SADDR; 66 struct flowi6 fl6 = { 67 .flowi6_iif = sdev->ifindex, 68 .daddr = ip6h->daddr, 69 .saddr = ip6h->saddr, 70 .flowlabel = ip6_flowinfo(ip6h), 71 .flowi6_mark = skb->mark, 72 .flowi6_proto = ip6h->nexthdr, 73 }; 74 75 skb_dst_drop(skb); 76 dst = ip6_route_input_lookup(dev_net(sdev), sdev, &fl6, 77 skb, flags); 78 skb_dst_set(skb, dst); 79 break; 80 } 81 #endif 82 default: 83 break; 84 } 85 out: 86 return skb; 87 } 88 89 static const struct l3mdev_ops ipvl_l3mdev_ops = { 90 .l3mdev_l3_rcv = ipvlan_l3_rcv, 91 }; 92 93 static unsigned int ipvlan_nf_input(void *priv, struct sk_buff *skb, 94 const struct nf_hook_state *state) 95 { 96 struct ipvl_addr *addr; 97 unsigned int len; 98 99 addr = ipvlan_skb_to_addr(skb, skb->dev); 100 if (!addr) 101 goto out; 102 103 skb->dev = addr->master->dev; 104 skb->skb_iif = skb->dev->ifindex; 105 len = skb->len + ETH_HLEN; 106 ipvlan_count_rx(addr->master, len, true, false); 107 out: 108 return NF_ACCEPT; 109 } 110 111 static const struct nf_hook_ops ipvl_nfops[] = { 112 { 113 .hook = ipvlan_nf_input, 114 .pf = NFPROTO_IPV4, 115 .hooknum = NF_INET_LOCAL_IN, 116 .priority = INT_MAX, 117 }, 118 #if IS_ENABLED(CONFIG_IPV6) 119 { 120 .hook = ipvlan_nf_input, 121 .pf = NFPROTO_IPV6, 122 .hooknum = NF_INET_LOCAL_IN, 123 .priority = INT_MAX, 124 }, 125 #endif 126 }; 127 128 static int ipvlan_register_nf_hook(struct net *net) 129 { 130 struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid); 131 int err = 0; 132 133 if (!vnet->ipvl_nf_hook_refcnt) { 134 err = nf_register_net_hooks(net, ipvl_nfops, 135 ARRAY_SIZE(ipvl_nfops)); 136 if (!err) 137 vnet->ipvl_nf_hook_refcnt = 1; 138 } else { 139 vnet->ipvl_nf_hook_refcnt++; 140 } 141 142 return err; 143 } 144 145 static void ipvlan_unregister_nf_hook(struct net *net) 146 { 147 struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid); 148 149 if (WARN_ON(!vnet->ipvl_nf_hook_refcnt)) 150 return; 151 152 vnet->ipvl_nf_hook_refcnt--; 153 if (!vnet->ipvl_nf_hook_refcnt) 154 nf_unregister_net_hooks(net, ipvl_nfops, 155 ARRAY_SIZE(ipvl_nfops)); 156 } 157 158 void ipvlan_migrate_l3s_hook(struct net *oldnet, struct net *newnet) 159 { 160 struct ipvlan_netns *old_vnet; 161 162 ASSERT_RTNL(); 163 164 old_vnet = net_generic(oldnet, ipvlan_netid); 165 if (!old_vnet->ipvl_nf_hook_refcnt) 166 return; 167 168 ipvlan_register_nf_hook(newnet); 169 ipvlan_unregister_nf_hook(oldnet); 170 } 171 172 static void ipvlan_ns_exit(struct net *net) 173 { 174 struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid); 175 176 if (WARN_ON_ONCE(vnet->ipvl_nf_hook_refcnt)) { 177 vnet->ipvl_nf_hook_refcnt = 0; 178 nf_unregister_net_hooks(net, ipvl_nfops, 179 ARRAY_SIZE(ipvl_nfops)); 180 } 181 } 182 183 static struct pernet_operations ipvlan_net_ops = { 184 .id = &ipvlan_netid, 185 .size = sizeof(struct ipvlan_netns), 186 .exit = ipvlan_ns_exit, 187 }; 188 189 int ipvlan_l3s_init(void) 190 { 191 return register_pernet_subsys(&ipvlan_net_ops); 192 } 193 194 void ipvlan_l3s_cleanup(void) 195 { 196 unregister_pernet_subsys(&ipvlan_net_ops); 197 } 198 199 int ipvlan_l3s_register(struct ipvl_port *port) 200 { 201 struct net_device *dev = port->dev; 202 int ret; 203 204 ASSERT_RTNL(); 205 206 ret = ipvlan_register_nf_hook(read_pnet(&port->pnet)); 207 if (!ret) { 208 dev->l3mdev_ops = &ipvl_l3mdev_ops; 209 dev->priv_flags |= IFF_L3MDEV_RX_HANDLER; 210 } 211 212 return ret; 213 } 214 215 void ipvlan_l3s_unregister(struct ipvl_port *port) 216 { 217 struct net_device *dev = port->dev; 218 219 ASSERT_RTNL(); 220 221 dev->priv_flags &= ~IFF_L3MDEV_RX_HANDLER; 222 ipvlan_unregister_nf_hook(read_pnet(&port->pnet)); 223 dev->l3mdev_ops = NULL; 224 } 225