^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * File: pn_dev.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Phonet network device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2008 Nokia Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Authors: Sakari Ailus <sakari.ailus@nokia.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Rémi Denis-Courmont
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/net.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/phonet.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/if_arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <net/netns/generic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <net/phonet/pn_dev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct phonet_routes {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct net_device __rcu *table[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct phonet_net {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct phonet_device_list pndevs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct phonet_routes routes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static unsigned int phonet_net_id __read_mostly;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static struct phonet_net *phonet_pernet(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) return net_generic(net, phonet_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct phonet_device_list *phonet_device_list(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct phonet_net *pnn = phonet_pernet(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return &pnn->pndevs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* Allocate new Phonet device. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static struct phonet_device *__phonet_device_alloc(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct phonet_device *pnd = kmalloc(sizeof(*pnd), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (pnd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) pnd->netdev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) bitmap_zero(pnd->addrs, 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) BUG_ON(!mutex_is_locked(&pndevs->lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) list_add_rcu(&pnd->list, &pndevs->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return pnd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static struct phonet_device *__phonet_get(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct phonet_device *pnd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) BUG_ON(!mutex_is_locked(&pndevs->lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) list_for_each_entry(pnd, &pndevs->list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (pnd->netdev == dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return pnd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static struct phonet_device *__phonet_get_rcu(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct phonet_device *pnd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) list_for_each_entry_rcu(pnd, &pndevs->list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (pnd->netdev == dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return pnd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static void phonet_device_destroy(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct phonet_device *pnd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) mutex_lock(&pndevs->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) pnd = __phonet_get(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (pnd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) list_del_rcu(&pnd->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) mutex_unlock(&pndevs->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (pnd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) u8 addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) for_each_set_bit(addr, pnd->addrs, 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) phonet_address_notify(RTM_DELADDR, dev, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) kfree(pnd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct net_device *phonet_device_get(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct phonet_device_list *pndevs = phonet_device_list(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) struct phonet_device *pnd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct net_device *dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) list_for_each_entry_rcu(pnd, &pndevs->list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) dev = pnd->netdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) BUG_ON(!dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if ((dev->reg_state == NETREG_REGISTERED) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) ((pnd->netdev->flags & IFF_UP)) == IFF_UP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) dev_hold(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) int phonet_address_add(struct net_device *dev, u8 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct phonet_device *pnd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) mutex_lock(&pndevs->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /* Find or create Phonet-specific device data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) pnd = __phonet_get(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (pnd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) pnd = __phonet_device_alloc(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (unlikely(pnd == NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) else if (test_and_set_bit(addr >> 2, pnd->addrs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) err = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) mutex_unlock(&pndevs->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) int phonet_address_del(struct net_device *dev, u8 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct phonet_device *pnd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) mutex_lock(&pndevs->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) pnd = __phonet_get(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (!pnd || !test_and_clear_bit(addr >> 2, pnd->addrs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) err = -EADDRNOTAVAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) pnd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) } else if (bitmap_empty(pnd->addrs, 64))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) list_del_rcu(&pnd->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) pnd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) mutex_unlock(&pndevs->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (pnd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) kfree_rcu(pnd, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /* Gets a source address toward a destination, through a interface. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) u8 phonet_address_get(struct net_device *dev, u8 daddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct phonet_device *pnd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) u8 saddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) pnd = __phonet_get_rcu(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (pnd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) BUG_ON(bitmap_empty(pnd->addrs, 64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) /* Use same source address as destination, if possible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (test_bit(daddr >> 2, pnd->addrs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) saddr = daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) saddr = find_first_bit(pnd->addrs, 64) << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) saddr = PN_NO_ADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (saddr == PN_NO_ADDR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /* Fallback to another device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) struct net_device *def_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) def_dev = phonet_device_get(dev_net(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (def_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (def_dev != dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) saddr = phonet_address_get(def_dev, daddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) dev_put(def_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return saddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) int phonet_address_lookup(struct net *net, u8 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) struct phonet_device_list *pndevs = phonet_device_list(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) struct phonet_device *pnd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) int err = -EADDRNOTAVAIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) list_for_each_entry_rcu(pnd, &pndevs->list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /* Don't allow unregistering devices! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if ((pnd->netdev->reg_state != NETREG_REGISTERED) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) ((pnd->netdev->flags & IFF_UP)) != IFF_UP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (test_bit(addr >> 2, pnd->addrs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) /* automatically configure a Phonet device, if supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) static int phonet_device_autoconf(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) struct if_phonet_req req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (!dev->netdev_ops->ndo_do_ioctl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) ret = dev->netdev_ops->ndo_do_ioctl(dev, (struct ifreq *)&req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) SIOCPNGAUTOCONF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) ASSERT_RTNL();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) ret = phonet_address_add(dev, req.ifr_phonet_autoconf.device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) phonet_address_notify(RTM_NEWADDR, dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) req.ifr_phonet_autoconf.device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) static void phonet_route_autodel(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) struct phonet_net *pnn = phonet_pernet(dev_net(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) DECLARE_BITMAP(deleted, 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) /* Remove left-over Phonet routes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) bitmap_zero(deleted, 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) mutex_lock(&pnn->routes.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) for (i = 0; i < 64; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (rcu_access_pointer(pnn->routes.table[i]) == dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) RCU_INIT_POINTER(pnn->routes.table[i], NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) set_bit(i, deleted);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) mutex_unlock(&pnn->routes.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (bitmap_empty(deleted, 64))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return; /* short-circuit RCU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) synchronize_rcu();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) for_each_set_bit(i, deleted, 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) rtm_phonet_notify(RTM_DELROUTE, dev, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) /* notify Phonet of device events */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) static int phonet_device_notify(struct notifier_block *me, unsigned long what,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) void *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) struct net_device *dev = netdev_notifier_info_to_dev(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) switch (what) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) case NETDEV_REGISTER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (dev->type == ARPHRD_PHONET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) phonet_device_autoconf(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) case NETDEV_UNREGISTER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) phonet_device_destroy(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) phonet_route_autodel(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) static struct notifier_block phonet_device_notifier = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) .notifier_call = phonet_device_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) .priority = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) /* Per-namespace Phonet devices handling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static int __net_init phonet_init_net(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) struct phonet_net *pnn = phonet_pernet(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (!proc_create_net("phonet", 0, net->proc_net, &pn_sock_seq_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) sizeof(struct seq_net_private)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) INIT_LIST_HEAD(&pnn->pndevs.list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) mutex_init(&pnn->pndevs.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) mutex_init(&pnn->routes.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) static void __net_exit phonet_exit_net(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) struct phonet_net *pnn = phonet_pernet(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) remove_proc_entry("phonet", net->proc_net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) WARN_ON_ONCE(!list_empty(&pnn->pndevs.list));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) static struct pernet_operations phonet_net_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) .init = phonet_init_net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) .exit = phonet_exit_net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) .id = &phonet_net_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) .size = sizeof(struct phonet_net),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) /* Initialize Phonet devices list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) int __init phonet_device_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) int err = register_pernet_subsys(&phonet_net_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) proc_create_net("pnresource", 0, init_net.proc_net, &pn_res_seq_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) sizeof(struct seq_net_private));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) register_netdevice_notifier(&phonet_device_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) err = phonet_netlink_register();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) phonet_device_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) void phonet_device_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) rtnl_unregister_all(PF_PHONET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) unregister_netdevice_notifier(&phonet_device_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) unregister_pernet_subsys(&phonet_net_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) remove_proc_entry("pnresource", init_net.proc_net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) int phonet_route_add(struct net_device *dev, u8 daddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) struct phonet_net *pnn = phonet_pernet(dev_net(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) struct phonet_routes *routes = &pnn->routes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) int err = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) daddr = daddr >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) mutex_lock(&routes->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (routes->table[daddr] == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) rcu_assign_pointer(routes->table[daddr], dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) dev_hold(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) mutex_unlock(&routes->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) int phonet_route_del(struct net_device *dev, u8 daddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) struct phonet_net *pnn = phonet_pernet(dev_net(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) struct phonet_routes *routes = &pnn->routes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) daddr = daddr >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) mutex_lock(&routes->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (rcu_access_pointer(routes->table[daddr]) == dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) RCU_INIT_POINTER(routes->table[daddr], NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) mutex_unlock(&routes->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) synchronize_rcu();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) struct net_device *phonet_route_get_rcu(struct net *net, u8 daddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) struct phonet_net *pnn = phonet_pernet(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) struct phonet_routes *routes = &pnn->routes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) daddr >>= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) dev = rcu_dereference(routes->table[daddr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) struct net_device *phonet_route_output(struct net *net, u8 daddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) struct phonet_net *pnn = phonet_pernet(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) struct phonet_routes *routes = &pnn->routes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) daddr >>= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) dev = rcu_dereference(routes->table[daddr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) dev_hold(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) dev = phonet_device_get(net); /* Default route */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }