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 #if IS_ENABLED(CONFIG_IPV6) 106 if (addr->atype == IPVL_IPV6) 107 IP6CB(skb)->iif = skb->dev->ifindex; 108 #endif 109 len = skb->len + ETH_HLEN; 110 ipvlan_count_rx(addr->master, len, true, false); 111 out: 112 return NF_ACCEPT; 113 } 114 115 static const struct nf_hook_ops ipvl_nfops[] = { 116 { 117 .hook = ipvlan_nf_input, 118 .pf = NFPROTO_IPV4, 119 .hooknum = NF_INET_LOCAL_IN, 120 .priority = INT_MAX, 121 }, 122 #if IS_ENABLED(CONFIG_IPV6) 123 { 124 .hook = ipvlan_nf_input, 125 .pf = NFPROTO_IPV6, 126 .hooknum = NF_INET_LOCAL_IN, 127 .priority = INT_MAX, 128 }, 129 #endif 130 }; 131 132 static int ipvlan_register_nf_hook(struct net *net) 133 { 134 struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid); 135 int err = 0; 136 137 if (!vnet->ipvl_nf_hook_refcnt) { 138 err = nf_register_net_hooks(net, ipvl_nfops, 139 ARRAY_SIZE(ipvl_nfops)); 140 if (!err) 141 vnet->ipvl_nf_hook_refcnt = 1; 142 } else { 143 vnet->ipvl_nf_hook_refcnt++; 144 } 145 146 return err; 147 } 148 149 static void ipvlan_unregister_nf_hook(struct net *net) 150 { 151 struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid); 152 153 if (WARN_ON(!vnet->ipvl_nf_hook_refcnt)) 154 return; 155 156 vnet->ipvl_nf_hook_refcnt--; 157 if (!vnet->ipvl_nf_hook_refcnt) 158 nf_unregister_net_hooks(net, ipvl_nfops, 159 ARRAY_SIZE(ipvl_nfops)); 160 } 161 162 void ipvlan_migrate_l3s_hook(struct net *oldnet, struct net *newnet) 163 { 164 struct ipvlan_netns *old_vnet; 165 166 ASSERT_RTNL(); 167 168 old_vnet = net_generic(oldnet, ipvlan_netid); 169 if (!old_vnet->ipvl_nf_hook_refcnt) 170 return; 171 172 ipvlan_register_nf_hook(newnet); 173 ipvlan_unregister_nf_hook(oldnet); 174 } 175 176 static void ipvlan_ns_exit(struct net *net) 177 { 178 struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid); 179 180 if (WARN_ON_ONCE(vnet->ipvl_nf_hook_refcnt)) { 181 vnet->ipvl_nf_hook_refcnt = 0; 182 nf_unregister_net_hooks(net, ipvl_nfops, 183 ARRAY_SIZE(ipvl_nfops)); 184 } 185 } 186 187 static struct pernet_operations ipvlan_net_ops = { 188 .id = &ipvlan_netid, 189 .size = sizeof(struct ipvlan_netns), 190 .exit = ipvlan_ns_exit, 191 }; 192 193 int ipvlan_l3s_init(void) 194 { 195 return register_pernet_subsys(&ipvlan_net_ops); 196 } 197 198 void ipvlan_l3s_cleanup(void) 199 { 200 unregister_pernet_subsys(&ipvlan_net_ops); 201 } 202 203 int ipvlan_l3s_register(struct ipvl_port *port) 204 { 205 struct net_device *dev = port->dev; 206 int ret; 207 208 ASSERT_RTNL(); 209 210 ret = ipvlan_register_nf_hook(read_pnet(&port->pnet)); 211 if (!ret) { 212 dev->l3mdev_ops = &ipvl_l3mdev_ops; 213 dev->priv_flags |= IFF_L3MDEV_RX_HANDLER; 214 } 215 216 return ret; 217 } 218 219 void ipvlan_l3s_unregister(struct ipvl_port *port) 220 { 221 struct net_device *dev = port->dev; 222 223 ASSERT_RTNL(); 224 225 dev->priv_flags &= ~IFF_L3MDEV_RX_HANDLER; 226 ipvlan_unregister_nf_hook(read_pnet(&port->pnet)); 227 dev->l3mdev_ops = NULL; 228 } 229