Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* Copyright (c) 2014 Mahesh Bandewar <maheshb@google.com>
0003  */
0004 
0005 #include "ipvlan.h"
0006 
0007 static unsigned int ipvlan_netid __read_mostly;
0008 
0009 struct ipvlan_netns {
0010     unsigned int ipvl_nf_hook_refcnt;
0011 };
0012 
0013 static struct ipvl_addr *ipvlan_skb_to_addr(struct sk_buff *skb,
0014                         struct net_device *dev)
0015 {
0016     struct ipvl_addr *addr = NULL;
0017     struct ipvl_port *port;
0018     int addr_type;
0019     void *lyr3h;
0020 
0021     if (!dev || !netif_is_ipvlan_port(dev))
0022         goto out;
0023 
0024     port = ipvlan_port_get_rcu(dev);
0025     if (!port || port->mode != IPVLAN_MODE_L3S)
0026         goto out;
0027 
0028     lyr3h = ipvlan_get_L3_hdr(port, skb, &addr_type);
0029     if (!lyr3h)
0030         goto out;
0031 
0032     addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true);
0033 out:
0034     return addr;
0035 }
0036 
0037 static struct sk_buff *ipvlan_l3_rcv(struct net_device *dev,
0038                      struct sk_buff *skb, u16 proto)
0039 {
0040     struct ipvl_addr *addr;
0041     struct net_device *sdev;
0042 
0043     addr = ipvlan_skb_to_addr(skb, dev);
0044     if (!addr)
0045         goto out;
0046 
0047     sdev = addr->master->dev;
0048     switch (proto) {
0049     case AF_INET:
0050     {
0051         struct iphdr *ip4h = ip_hdr(skb);
0052         int err;
0053 
0054         err = ip_route_input_noref(skb, ip4h->daddr, ip4h->saddr,
0055                        ip4h->tos, sdev);
0056         if (unlikely(err))
0057             goto out;
0058         break;
0059     }
0060 #if IS_ENABLED(CONFIG_IPV6)
0061     case AF_INET6:
0062     {
0063         struct dst_entry *dst;
0064         struct ipv6hdr *ip6h = ipv6_hdr(skb);
0065         int flags = RT6_LOOKUP_F_HAS_SADDR;
0066         struct flowi6 fl6 = {
0067             .flowi6_iif   = sdev->ifindex,
0068             .daddr        = ip6h->daddr,
0069             .saddr        = ip6h->saddr,
0070             .flowlabel    = ip6_flowinfo(ip6h),
0071             .flowi6_mark  = skb->mark,
0072             .flowi6_proto = ip6h->nexthdr,
0073         };
0074 
0075         skb_dst_drop(skb);
0076         dst = ip6_route_input_lookup(dev_net(sdev), sdev, &fl6,
0077                          skb, flags);
0078         skb_dst_set(skb, dst);
0079         break;
0080     }
0081 #endif
0082     default:
0083         break;
0084     }
0085 out:
0086     return skb;
0087 }
0088 
0089 static const struct l3mdev_ops ipvl_l3mdev_ops = {
0090     .l3mdev_l3_rcv = ipvlan_l3_rcv,
0091 };
0092 
0093 static unsigned int ipvlan_nf_input(void *priv, struct sk_buff *skb,
0094                     const struct nf_hook_state *state)
0095 {
0096     struct ipvl_addr *addr;
0097     unsigned int len;
0098 
0099     addr = ipvlan_skb_to_addr(skb, skb->dev);
0100     if (!addr)
0101         goto out;
0102 
0103     skb->dev = addr->master->dev;
0104     len = skb->len + ETH_HLEN;
0105     ipvlan_count_rx(addr->master, len, true, false);
0106 out:
0107     return NF_ACCEPT;
0108 }
0109 
0110 static const struct nf_hook_ops ipvl_nfops[] = {
0111     {
0112         .hook     = ipvlan_nf_input,
0113         .pf       = NFPROTO_IPV4,
0114         .hooknum  = NF_INET_LOCAL_IN,
0115         .priority = INT_MAX,
0116     },
0117 #if IS_ENABLED(CONFIG_IPV6)
0118     {
0119         .hook     = ipvlan_nf_input,
0120         .pf       = NFPROTO_IPV6,
0121         .hooknum  = NF_INET_LOCAL_IN,
0122         .priority = INT_MAX,
0123     },
0124 #endif
0125 };
0126 
0127 static int ipvlan_register_nf_hook(struct net *net)
0128 {
0129     struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
0130     int err = 0;
0131 
0132     if (!vnet->ipvl_nf_hook_refcnt) {
0133         err = nf_register_net_hooks(net, ipvl_nfops,
0134                         ARRAY_SIZE(ipvl_nfops));
0135         if (!err)
0136             vnet->ipvl_nf_hook_refcnt = 1;
0137     } else {
0138         vnet->ipvl_nf_hook_refcnt++;
0139     }
0140 
0141     return err;
0142 }
0143 
0144 static void ipvlan_unregister_nf_hook(struct net *net)
0145 {
0146     struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
0147 
0148     if (WARN_ON(!vnet->ipvl_nf_hook_refcnt))
0149         return;
0150 
0151     vnet->ipvl_nf_hook_refcnt--;
0152     if (!vnet->ipvl_nf_hook_refcnt)
0153         nf_unregister_net_hooks(net, ipvl_nfops,
0154                     ARRAY_SIZE(ipvl_nfops));
0155 }
0156 
0157 void ipvlan_migrate_l3s_hook(struct net *oldnet, struct net *newnet)
0158 {
0159     struct ipvlan_netns *old_vnet;
0160 
0161     ASSERT_RTNL();
0162 
0163     old_vnet = net_generic(oldnet, ipvlan_netid);
0164     if (!old_vnet->ipvl_nf_hook_refcnt)
0165         return;
0166 
0167     ipvlan_register_nf_hook(newnet);
0168     ipvlan_unregister_nf_hook(oldnet);
0169 }
0170 
0171 static void ipvlan_ns_exit(struct net *net)
0172 {
0173     struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
0174 
0175     if (WARN_ON_ONCE(vnet->ipvl_nf_hook_refcnt)) {
0176         vnet->ipvl_nf_hook_refcnt = 0;
0177         nf_unregister_net_hooks(net, ipvl_nfops,
0178                     ARRAY_SIZE(ipvl_nfops));
0179     }
0180 }
0181 
0182 static struct pernet_operations ipvlan_net_ops = {
0183     .id   = &ipvlan_netid,
0184     .size = sizeof(struct ipvlan_netns),
0185     .exit = ipvlan_ns_exit,
0186 };
0187 
0188 int ipvlan_l3s_init(void)
0189 {
0190     return register_pernet_subsys(&ipvlan_net_ops);
0191 }
0192 
0193 void ipvlan_l3s_cleanup(void)
0194 {
0195     unregister_pernet_subsys(&ipvlan_net_ops);
0196 }
0197 
0198 int ipvlan_l3s_register(struct ipvl_port *port)
0199 {
0200     struct net_device *dev = port->dev;
0201     int ret;
0202 
0203     ASSERT_RTNL();
0204 
0205     ret = ipvlan_register_nf_hook(read_pnet(&port->pnet));
0206     if (!ret) {
0207         dev->l3mdev_ops = &ipvl_l3mdev_ops;
0208         dev->priv_flags |= IFF_L3MDEV_RX_HANDLER;
0209     }
0210 
0211     return ret;
0212 }
0213 
0214 void ipvlan_l3s_unregister(struct ipvl_port *port)
0215 {
0216     struct net_device *dev = port->dev;
0217 
0218     ASSERT_RTNL();
0219 
0220     dev->priv_flags &= ~IFF_L3MDEV_RX_HANDLER;
0221     ipvlan_unregister_nf_hook(read_pnet(&port->pnet));
0222     dev->l3mdev_ops = NULL;
0223 }