1 /* 2 * File: pn_dev.c 3 * 4 * Phonet network device 5 * 6 * Copyright (C) 2008 Nokia Corporation. 7 * 8 * Contact: Remi Denis-Courmont <remi.denis-courmont@nokia.com> 9 * Original author: Sakari Ailus <sakari.ailus@nokia.com> 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License 13 * version 2 as published by the Free Software Foundation. 14 * 15 * This program is distributed in the hope that it will be useful, but 16 * WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 23 * 02110-1301 USA 24 */ 25 26 #include <linux/kernel.h> 27 #include <linux/net.h> 28 #include <linux/netdevice.h> 29 #include <linux/phonet.h> 30 #include <linux/proc_fs.h> 31 #include <linux/if_arp.h> 32 #include <net/sock.h> 33 #include <net/netns/generic.h> 34 #include <net/phonet/pn_dev.h> 35 36 struct phonet_net { 37 struct phonet_device_list pndevs; 38 }; 39 40 int phonet_net_id; 41 42 struct phonet_device_list *phonet_device_list(struct net *net) 43 { 44 struct phonet_net *pnn = net_generic(net, phonet_net_id); 45 return &pnn->pndevs; 46 } 47 48 /* Allocate new Phonet device. */ 49 static struct phonet_device *__phonet_device_alloc(struct net_device *dev) 50 { 51 struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev)); 52 struct phonet_device *pnd = kmalloc(sizeof(*pnd), GFP_ATOMIC); 53 if (pnd == NULL) 54 return NULL; 55 pnd->netdev = dev; 56 bitmap_zero(pnd->addrs, 64); 57 58 list_add(&pnd->list, &pndevs->list); 59 return pnd; 60 } 61 62 static struct phonet_device *__phonet_get(struct net_device *dev) 63 { 64 struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev)); 65 struct phonet_device *pnd; 66 67 list_for_each_entry(pnd, &pndevs->list, list) { 68 if (pnd->netdev == dev) 69 return pnd; 70 } 71 return NULL; 72 } 73 74 static void phonet_device_destroy(struct net_device *dev) 75 { 76 struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev)); 77 struct phonet_device *pnd; 78 79 ASSERT_RTNL(); 80 81 spin_lock_bh(&pndevs->lock); 82 pnd = __phonet_get(dev); 83 if (pnd) 84 list_del(&pnd->list); 85 spin_unlock_bh(&pndevs->lock); 86 87 if (pnd) { 88 u8 addr; 89 90 for (addr = find_first_bit(pnd->addrs, 64); addr < 64; 91 addr = find_next_bit(pnd->addrs, 64, 1+addr)) 92 phonet_address_notify(RTM_DELADDR, dev, addr); 93 kfree(pnd); 94 } 95 } 96 97 struct net_device *phonet_device_get(struct net *net) 98 { 99 struct phonet_device_list *pndevs = phonet_device_list(net); 100 struct phonet_device *pnd; 101 struct net_device *dev = NULL; 102 103 spin_lock_bh(&pndevs->lock); 104 list_for_each_entry(pnd, &pndevs->list, list) { 105 dev = pnd->netdev; 106 BUG_ON(!dev); 107 108 if ((dev->reg_state == NETREG_REGISTERED) && 109 ((pnd->netdev->flags & IFF_UP)) == IFF_UP) 110 break; 111 dev = NULL; 112 } 113 if (dev) 114 dev_hold(dev); 115 spin_unlock_bh(&pndevs->lock); 116 return dev; 117 } 118 119 int phonet_address_add(struct net_device *dev, u8 addr) 120 { 121 struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev)); 122 struct phonet_device *pnd; 123 int err = 0; 124 125 spin_lock_bh(&pndevs->lock); 126 /* Find or create Phonet-specific device data */ 127 pnd = __phonet_get(dev); 128 if (pnd == NULL) 129 pnd = __phonet_device_alloc(dev); 130 if (unlikely(pnd == NULL)) 131 err = -ENOMEM; 132 else if (test_and_set_bit(addr >> 2, pnd->addrs)) 133 err = -EEXIST; 134 spin_unlock_bh(&pndevs->lock); 135 return err; 136 } 137 138 int phonet_address_del(struct net_device *dev, u8 addr) 139 { 140 struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev)); 141 struct phonet_device *pnd; 142 int err = 0; 143 144 spin_lock_bh(&pndevs->lock); 145 pnd = __phonet_get(dev); 146 if (!pnd || !test_and_clear_bit(addr >> 2, pnd->addrs)) 147 err = -EADDRNOTAVAIL; 148 else if (bitmap_empty(pnd->addrs, 64)) { 149 list_del(&pnd->list); 150 kfree(pnd); 151 } 152 spin_unlock_bh(&pndevs->lock); 153 return err; 154 } 155 156 /* Gets a source address toward a destination, through a interface. */ 157 u8 phonet_address_get(struct net_device *dev, u8 addr) 158 { 159 struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev)); 160 struct phonet_device *pnd; 161 162 spin_lock_bh(&pndevs->lock); 163 pnd = __phonet_get(dev); 164 if (pnd) { 165 BUG_ON(bitmap_empty(pnd->addrs, 64)); 166 167 /* Use same source address as destination, if possible */ 168 if (!test_bit(addr >> 2, pnd->addrs)) 169 addr = find_first_bit(pnd->addrs, 64) << 2; 170 } else 171 addr = PN_NO_ADDR; 172 spin_unlock_bh(&pndevs->lock); 173 return addr; 174 } 175 176 int phonet_address_lookup(struct net *net, u8 addr) 177 { 178 struct phonet_device_list *pndevs = phonet_device_list(net); 179 struct phonet_device *pnd; 180 int err = -EADDRNOTAVAIL; 181 182 spin_lock_bh(&pndevs->lock); 183 list_for_each_entry(pnd, &pndevs->list, list) { 184 /* Don't allow unregistering devices! */ 185 if ((pnd->netdev->reg_state != NETREG_REGISTERED) || 186 ((pnd->netdev->flags & IFF_UP)) != IFF_UP) 187 continue; 188 189 if (test_bit(addr >> 2, pnd->addrs)) { 190 err = 0; 191 goto found; 192 } 193 } 194 found: 195 spin_unlock_bh(&pndevs->lock); 196 return err; 197 } 198 199 /* automatically configure a Phonet device, if supported */ 200 static int phonet_device_autoconf(struct net_device *dev) 201 { 202 struct if_phonet_req req; 203 int ret; 204 205 if (!dev->netdev_ops->ndo_do_ioctl) 206 return -EOPNOTSUPP; 207 208 ret = dev->netdev_ops->ndo_do_ioctl(dev, (struct ifreq *)&req, 209 SIOCPNGAUTOCONF); 210 if (ret < 0) 211 return ret; 212 213 ASSERT_RTNL(); 214 ret = phonet_address_add(dev, req.ifr_phonet_autoconf.device); 215 if (ret) 216 return ret; 217 phonet_address_notify(RTM_NEWADDR, dev, 218 req.ifr_phonet_autoconf.device); 219 return 0; 220 } 221 222 /* notify Phonet of device events */ 223 static int phonet_device_notify(struct notifier_block *me, unsigned long what, 224 void *arg) 225 { 226 struct net_device *dev = arg; 227 228 switch (what) { 229 case NETDEV_REGISTER: 230 if (dev->type == ARPHRD_PHONET) 231 phonet_device_autoconf(dev); 232 break; 233 case NETDEV_UNREGISTER: 234 phonet_device_destroy(dev); 235 break; 236 } 237 return 0; 238 239 } 240 241 static struct notifier_block phonet_device_notifier = { 242 .notifier_call = phonet_device_notify, 243 .priority = 0, 244 }; 245 246 /* Per-namespace Phonet devices handling */ 247 static int phonet_init_net(struct net *net) 248 { 249 struct phonet_net *pnn = kmalloc(sizeof(*pnn), GFP_KERNEL); 250 if (!pnn) 251 return -ENOMEM; 252 253 if (!proc_net_fops_create(net, "phonet", 0, &pn_sock_seq_fops)) { 254 kfree(pnn); 255 return -ENOMEM; 256 } 257 258 INIT_LIST_HEAD(&pnn->pndevs.list); 259 spin_lock_init(&pnn->pndevs.lock); 260 net_assign_generic(net, phonet_net_id, pnn); 261 return 0; 262 } 263 264 static void phonet_exit_net(struct net *net) 265 { 266 struct phonet_net *pnn = net_generic(net, phonet_net_id); 267 struct net_device *dev; 268 269 rtnl_lock(); 270 for_each_netdev(net, dev) 271 phonet_device_destroy(dev); 272 rtnl_unlock(); 273 274 proc_net_remove(net, "phonet"); 275 kfree(pnn); 276 } 277 278 static struct pernet_operations phonet_net_ops = { 279 .init = phonet_init_net, 280 .exit = phonet_exit_net, 281 }; 282 283 /* Initialize Phonet devices list */ 284 int __init phonet_device_init(void) 285 { 286 int err = register_pernet_gen_device(&phonet_net_id, &phonet_net_ops); 287 if (err) 288 return err; 289 290 register_netdevice_notifier(&phonet_device_notifier); 291 err = phonet_netlink_register(); 292 if (err) 293 phonet_device_exit(); 294 return err; 295 } 296 297 void phonet_device_exit(void) 298 { 299 rtnl_unregister_all(PF_PHONET); 300 unregister_netdevice_notifier(&phonet_device_notifier); 301 unregister_pernet_gen_device(phonet_net_id, &phonet_net_ops); 302 } 303