Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) }