Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * File: pn_dev.c
0004  *
0005  * Phonet network device
0006  *
0007  * Copyright (C) 2008 Nokia Corporation.
0008  *
0009  * Authors: Sakari Ailus <sakari.ailus@nokia.com>
0010  *          Rémi Denis-Courmont
0011  */
0012 
0013 #include <linux/kernel.h>
0014 #include <linux/net.h>
0015 #include <linux/slab.h>
0016 #include <linux/netdevice.h>
0017 #include <linux/phonet.h>
0018 #include <linux/proc_fs.h>
0019 #include <linux/if_arp.h>
0020 #include <net/sock.h>
0021 #include <net/netns/generic.h>
0022 #include <net/phonet/pn_dev.h>
0023 
0024 struct phonet_routes {
0025     struct mutex        lock;
0026     struct net_device __rcu *table[64];
0027 };
0028 
0029 struct phonet_net {
0030     struct phonet_device_list pndevs;
0031     struct phonet_routes routes;
0032 };
0033 
0034 static unsigned int phonet_net_id __read_mostly;
0035 
0036 static struct phonet_net *phonet_pernet(struct net *net)
0037 {
0038     return net_generic(net, phonet_net_id);
0039 }
0040 
0041 struct phonet_device_list *phonet_device_list(struct net *net)
0042 {
0043     struct phonet_net *pnn = phonet_pernet(net);
0044     return &pnn->pndevs;
0045 }
0046 
0047 /* Allocate new Phonet device. */
0048 static struct phonet_device *__phonet_device_alloc(struct net_device *dev)
0049 {
0050     struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
0051     struct phonet_device *pnd = kmalloc(sizeof(*pnd), GFP_ATOMIC);
0052     if (pnd == NULL)
0053         return NULL;
0054     pnd->netdev = dev;
0055     bitmap_zero(pnd->addrs, 64);
0056 
0057     BUG_ON(!mutex_is_locked(&pndevs->lock));
0058     list_add_rcu(&pnd->list, &pndevs->list);
0059     return pnd;
0060 }
0061 
0062 static struct phonet_device *__phonet_get(struct net_device *dev)
0063 {
0064     struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
0065     struct phonet_device *pnd;
0066 
0067     BUG_ON(!mutex_is_locked(&pndevs->lock));
0068     list_for_each_entry(pnd, &pndevs->list, list) {
0069         if (pnd->netdev == dev)
0070             return pnd;
0071     }
0072     return NULL;
0073 }
0074 
0075 static struct phonet_device *__phonet_get_rcu(struct net_device *dev)
0076 {
0077     struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
0078     struct phonet_device *pnd;
0079 
0080     list_for_each_entry_rcu(pnd, &pndevs->list, list) {
0081         if (pnd->netdev == dev)
0082             return pnd;
0083     }
0084     return NULL;
0085 }
0086 
0087 static void phonet_device_destroy(struct net_device *dev)
0088 {
0089     struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
0090     struct phonet_device *pnd;
0091 
0092     ASSERT_RTNL();
0093 
0094     mutex_lock(&pndevs->lock);
0095     pnd = __phonet_get(dev);
0096     if (pnd)
0097         list_del_rcu(&pnd->list);
0098     mutex_unlock(&pndevs->lock);
0099 
0100     if (pnd) {
0101         u8 addr;
0102 
0103         for_each_set_bit(addr, pnd->addrs, 64)
0104             phonet_address_notify(RTM_DELADDR, dev, addr);
0105         kfree(pnd);
0106     }
0107 }
0108 
0109 struct net_device *phonet_device_get(struct net *net)
0110 {
0111     struct phonet_device_list *pndevs = phonet_device_list(net);
0112     struct phonet_device *pnd;
0113     struct net_device *dev = NULL;
0114 
0115     rcu_read_lock();
0116     list_for_each_entry_rcu(pnd, &pndevs->list, list) {
0117         dev = pnd->netdev;
0118         BUG_ON(!dev);
0119 
0120         if ((dev->reg_state == NETREG_REGISTERED) &&
0121             ((pnd->netdev->flags & IFF_UP)) == IFF_UP)
0122             break;
0123         dev = NULL;
0124     }
0125     dev_hold(dev);
0126     rcu_read_unlock();
0127     return dev;
0128 }
0129 
0130 int phonet_address_add(struct net_device *dev, u8 addr)
0131 {
0132     struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
0133     struct phonet_device *pnd;
0134     int err = 0;
0135 
0136     mutex_lock(&pndevs->lock);
0137     /* Find or create Phonet-specific device data */
0138     pnd = __phonet_get(dev);
0139     if (pnd == NULL)
0140         pnd = __phonet_device_alloc(dev);
0141     if (unlikely(pnd == NULL))
0142         err = -ENOMEM;
0143     else if (test_and_set_bit(addr >> 2, pnd->addrs))
0144         err = -EEXIST;
0145     mutex_unlock(&pndevs->lock);
0146     return err;
0147 }
0148 
0149 int phonet_address_del(struct net_device *dev, u8 addr)
0150 {
0151     struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
0152     struct phonet_device *pnd;
0153     int err = 0;
0154 
0155     mutex_lock(&pndevs->lock);
0156     pnd = __phonet_get(dev);
0157     if (!pnd || !test_and_clear_bit(addr >> 2, pnd->addrs)) {
0158         err = -EADDRNOTAVAIL;
0159         pnd = NULL;
0160     } else if (bitmap_empty(pnd->addrs, 64))
0161         list_del_rcu(&pnd->list);
0162     else
0163         pnd = NULL;
0164     mutex_unlock(&pndevs->lock);
0165 
0166     if (pnd)
0167         kfree_rcu(pnd, rcu);
0168 
0169     return err;
0170 }
0171 
0172 /* Gets a source address toward a destination, through a interface. */
0173 u8 phonet_address_get(struct net_device *dev, u8 daddr)
0174 {
0175     struct phonet_device *pnd;
0176     u8 saddr;
0177 
0178     rcu_read_lock();
0179     pnd = __phonet_get_rcu(dev);
0180     if (pnd) {
0181         BUG_ON(bitmap_empty(pnd->addrs, 64));
0182 
0183         /* Use same source address as destination, if possible */
0184         if (test_bit(daddr >> 2, pnd->addrs))
0185             saddr = daddr;
0186         else
0187             saddr = find_first_bit(pnd->addrs, 64) << 2;
0188     } else
0189         saddr = PN_NO_ADDR;
0190     rcu_read_unlock();
0191 
0192     if (saddr == PN_NO_ADDR) {
0193         /* Fallback to another device */
0194         struct net_device *def_dev;
0195 
0196         def_dev = phonet_device_get(dev_net(dev));
0197         if (def_dev) {
0198             if (def_dev != dev)
0199                 saddr = phonet_address_get(def_dev, daddr);
0200             dev_put(def_dev);
0201         }
0202     }
0203     return saddr;
0204 }
0205 
0206 int phonet_address_lookup(struct net *net, u8 addr)
0207 {
0208     struct phonet_device_list *pndevs = phonet_device_list(net);
0209     struct phonet_device *pnd;
0210     int err = -EADDRNOTAVAIL;
0211 
0212     rcu_read_lock();
0213     list_for_each_entry_rcu(pnd, &pndevs->list, list) {
0214         /* Don't allow unregistering devices! */
0215         if ((pnd->netdev->reg_state != NETREG_REGISTERED) ||
0216                 ((pnd->netdev->flags & IFF_UP)) != IFF_UP)
0217             continue;
0218 
0219         if (test_bit(addr >> 2, pnd->addrs)) {
0220             err = 0;
0221             goto found;
0222         }
0223     }
0224 found:
0225     rcu_read_unlock();
0226     return err;
0227 }
0228 
0229 /* automatically configure a Phonet device, if supported */
0230 static int phonet_device_autoconf(struct net_device *dev)
0231 {
0232     struct if_phonet_req req;
0233     int ret;
0234 
0235     if (!dev->netdev_ops->ndo_siocdevprivate)
0236         return -EOPNOTSUPP;
0237 
0238     ret = dev->netdev_ops->ndo_siocdevprivate(dev, (struct ifreq *)&req,
0239                           NULL, SIOCPNGAUTOCONF);
0240     if (ret < 0)
0241         return ret;
0242 
0243     ASSERT_RTNL();
0244     ret = phonet_address_add(dev, req.ifr_phonet_autoconf.device);
0245     if (ret)
0246         return ret;
0247     phonet_address_notify(RTM_NEWADDR, dev,
0248                 req.ifr_phonet_autoconf.device);
0249     return 0;
0250 }
0251 
0252 static void phonet_route_autodel(struct net_device *dev)
0253 {
0254     struct phonet_net *pnn = phonet_pernet(dev_net(dev));
0255     unsigned int i;
0256     DECLARE_BITMAP(deleted, 64);
0257 
0258     /* Remove left-over Phonet routes */
0259     bitmap_zero(deleted, 64);
0260     mutex_lock(&pnn->routes.lock);
0261     for (i = 0; i < 64; i++)
0262         if (rcu_access_pointer(pnn->routes.table[i]) == dev) {
0263             RCU_INIT_POINTER(pnn->routes.table[i], NULL);
0264             set_bit(i, deleted);
0265         }
0266     mutex_unlock(&pnn->routes.lock);
0267 
0268     if (bitmap_empty(deleted, 64))
0269         return; /* short-circuit RCU */
0270     synchronize_rcu();
0271     for_each_set_bit(i, deleted, 64) {
0272         rtm_phonet_notify(RTM_DELROUTE, dev, i);
0273         dev_put(dev);
0274     }
0275 }
0276 
0277 /* notify Phonet of device events */
0278 static int phonet_device_notify(struct notifier_block *me, unsigned long what,
0279                 void *ptr)
0280 {
0281     struct net_device *dev = netdev_notifier_info_to_dev(ptr);
0282 
0283     switch (what) {
0284     case NETDEV_REGISTER:
0285         if (dev->type == ARPHRD_PHONET)
0286             phonet_device_autoconf(dev);
0287         break;
0288     case NETDEV_UNREGISTER:
0289         phonet_device_destroy(dev);
0290         phonet_route_autodel(dev);
0291         break;
0292     }
0293     return 0;
0294 
0295 }
0296 
0297 static struct notifier_block phonet_device_notifier = {
0298     .notifier_call = phonet_device_notify,
0299     .priority = 0,
0300 };
0301 
0302 /* Per-namespace Phonet devices handling */
0303 static int __net_init phonet_init_net(struct net *net)
0304 {
0305     struct phonet_net *pnn = phonet_pernet(net);
0306 
0307     if (!proc_create_net("phonet", 0, net->proc_net, &pn_sock_seq_ops,
0308             sizeof(struct seq_net_private)))
0309         return -ENOMEM;
0310 
0311     INIT_LIST_HEAD(&pnn->pndevs.list);
0312     mutex_init(&pnn->pndevs.lock);
0313     mutex_init(&pnn->routes.lock);
0314     return 0;
0315 }
0316 
0317 static void __net_exit phonet_exit_net(struct net *net)
0318 {
0319     struct phonet_net *pnn = phonet_pernet(net);
0320 
0321     remove_proc_entry("phonet", net->proc_net);
0322     WARN_ON_ONCE(!list_empty(&pnn->pndevs.list));
0323 }
0324 
0325 static struct pernet_operations phonet_net_ops = {
0326     .init = phonet_init_net,
0327     .exit = phonet_exit_net,
0328     .id   = &phonet_net_id,
0329     .size = sizeof(struct phonet_net),
0330 };
0331 
0332 /* Initialize Phonet devices list */
0333 int __init phonet_device_init(void)
0334 {
0335     int err = register_pernet_subsys(&phonet_net_ops);
0336     if (err)
0337         return err;
0338 
0339     proc_create_net("pnresource", 0, init_net.proc_net, &pn_res_seq_ops,
0340             sizeof(struct seq_net_private));
0341     register_netdevice_notifier(&phonet_device_notifier);
0342     err = phonet_netlink_register();
0343     if (err)
0344         phonet_device_exit();
0345     return err;
0346 }
0347 
0348 void phonet_device_exit(void)
0349 {
0350     rtnl_unregister_all(PF_PHONET);
0351     unregister_netdevice_notifier(&phonet_device_notifier);
0352     unregister_pernet_subsys(&phonet_net_ops);
0353     remove_proc_entry("pnresource", init_net.proc_net);
0354 }
0355 
0356 int phonet_route_add(struct net_device *dev, u8 daddr)
0357 {
0358     struct phonet_net *pnn = phonet_pernet(dev_net(dev));
0359     struct phonet_routes *routes = &pnn->routes;
0360     int err = -EEXIST;
0361 
0362     daddr = daddr >> 2;
0363     mutex_lock(&routes->lock);
0364     if (routes->table[daddr] == NULL) {
0365         rcu_assign_pointer(routes->table[daddr], dev);
0366         dev_hold(dev);
0367         err = 0;
0368     }
0369     mutex_unlock(&routes->lock);
0370     return err;
0371 }
0372 
0373 int phonet_route_del(struct net_device *dev, u8 daddr)
0374 {
0375     struct phonet_net *pnn = phonet_pernet(dev_net(dev));
0376     struct phonet_routes *routes = &pnn->routes;
0377 
0378     daddr = daddr >> 2;
0379     mutex_lock(&routes->lock);
0380     if (rcu_access_pointer(routes->table[daddr]) == dev)
0381         RCU_INIT_POINTER(routes->table[daddr], NULL);
0382     else
0383         dev = NULL;
0384     mutex_unlock(&routes->lock);
0385 
0386     if (!dev)
0387         return -ENOENT;
0388     synchronize_rcu();
0389     dev_put(dev);
0390     return 0;
0391 }
0392 
0393 struct net_device *phonet_route_get_rcu(struct net *net, u8 daddr)
0394 {
0395     struct phonet_net *pnn = phonet_pernet(net);
0396     struct phonet_routes *routes = &pnn->routes;
0397     struct net_device *dev;
0398 
0399     daddr >>= 2;
0400     dev = rcu_dereference(routes->table[daddr]);
0401     return dev;
0402 }
0403 
0404 struct net_device *phonet_route_output(struct net *net, u8 daddr)
0405 {
0406     struct phonet_net *pnn = phonet_pernet(net);
0407     struct phonet_routes *routes = &pnn->routes;
0408     struct net_device *dev;
0409 
0410     daddr >>= 2;
0411     rcu_read_lock();
0412     dev = rcu_dereference(routes->table[daddr]);
0413     dev_hold(dev);
0414     rcu_read_unlock();
0415 
0416     if (!dev)
0417         dev = phonet_device_get(net); /* Default route */
0418     return dev;
0419 }