lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Tue, 16 Sep 2008 18:08:05 +0300 From: Rémi Denis-Courmont <remi.denis-courmont@...ia.com> To: netdev@...r.kernel.org Subject: [PATCH 05/14] Phonet: network device and address handling This provides support for adding Phonet addresses to and removing Phonet addresses from network devices. Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@...ia.com> --- include/net/phonet/pn_dev.h | 63 ++++++++++++ net/phonet/Makefile | 1 + net/phonet/af_phonet.c | 12 ++ net/phonet/pn_dev.c | 233 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 309 insertions(+), 0 deletions(-) create mode 100644 include/net/phonet/pn_dev.h create mode 100644 net/phonet/pn_dev.c diff --git a/include/net/phonet/pn_dev.h b/include/net/phonet/pn_dev.h new file mode 100644 index 0000000..c53d364 --- /dev/null +++ b/include/net/phonet/pn_dev.h @@ -0,0 +1,63 @@ +/* + * File: pn_dev.h + * + * Phonet network device + * + * Copyright (C) 2008 Nokia Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef PN_DEV_H +#define PN_DEV_H + +struct phonet_device_list { + struct list_head list; + spinlock_t lock; +}; + +extern struct phonet_device_list pndevs; + +struct phonet_device { + struct list_head list; + struct net_device *netdev; + struct list_head own; +}; + +struct phonet_address { + struct list_head list; + struct phonet_device *pnd; + uint8_t addr; + unsigned char prefix; +}; + +int phonet_device_init(void); +void phonet_device_exit(void); +struct phonet_device *phonet_device_alloc(struct net_device *dev); +struct phonet_device *__phonet_get_by_index(unsigned ifindex); +void phonet_device_free(struct phonet_device *pnd); + +struct phonet_address *phonet_address_alloc(void); +void phonet_address_add(struct list_head *list, struct phonet_address *pna); +void phonet_address_free(struct phonet_address *pna); +struct phonet_address *phonet_addr2addr(uint8_t addr, int mode); +struct phonet_address *phonet_dev2addr(struct phonet_device *pnd, uint8_t addr, + int mode); + +#define PN_FIND_EXACT (1 << 0) + +#define MKMASK(a) ((1 << (a)) - 1) + +#endif diff --git a/net/phonet/Makefile b/net/phonet/Makefile index 5dbff68..980a386 100644 --- a/net/phonet/Makefile +++ b/net/phonet/Makefile @@ -1,4 +1,5 @@ obj-$(CONFIG_PHONET) += phonet.o phonet-objs := \ + pn_dev.o \ af_phonet.o diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c index ed66a81..744b47f 100644 --- a/net/phonet/af_phonet.c +++ b/net/phonet/af_phonet.c @@ -31,6 +31,7 @@ #include <linux/if_phonet.h> #include <linux/phonet.h> #include <net/phonet/phonet.h> +#include <net/phonet/pn_dev.h> static struct net_proto_family phonet_proto_family; static struct phonet_protocol *phonet_proto_get(int protocol); @@ -202,14 +203,25 @@ static int __init phonet_init(void) return err; } + err = phonet_device_init(); + if (err) { + printk(KERN_ALERT "phonet devices initialization failed\n"); + goto unregister; + } + dev_add_pack(&phonet_packet_type); return 0; + +unregister: + sock_unregister(AF_PHONET); + return err; } static void __exit phonet_exit(void) { sock_unregister(AF_PHONET); dev_remove_pack(&phonet_packet_type); + phonet_device_exit(); } module_init(phonet_init); diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c new file mode 100644 index 0000000..cae37a6 --- /dev/null +++ b/net/phonet/pn_dev.c @@ -0,0 +1,233 @@ +/* + * File: pn_dev.c + * + * Phonet network device + * + * Copyright (C) 2008 Nokia Corporation. + * + * Contact: Remi Denis-Courmont <remi.denis-courmont@...ia.com> + * Original author: Sakari Ailus <sakari.ailus@...ia.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include <linux/kernel.h> +#include <linux/net.h> +#include <linux/netdevice.h> +#include <linux/phonet.h> +#include <net/sock.h> +#include <net/phonet/pn_dev.h> + +static int phonet_device_notify(struct notifier_block *self, unsigned long what, + void *dev); + +/* when accessing, remember to lock with spin_lock(&pndevs.lock); */ +struct phonet_device_list pndevs; + +static struct notifier_block phonet_device_notifier = { + .notifier_call = &phonet_device_notify, + .priority = 0, +}; + +/* initialise Phonet device list */ +int phonet_device_init(void) +{ + INIT_LIST_HEAD(&pndevs.list); + spin_lock_init(&pndevs.lock); + register_netdevice_notifier(&phonet_device_notifier); + + return 0; +} + +void phonet_device_exit(void) +{ + struct list_head *ptr; + + rtnl_unregister_all(PF_PHONET); + rtnl_lock(); + spin_lock_bh(&pndevs.lock); + + for (ptr = pndevs.list.next; ptr != &pndevs.list; + ptr = pndevs.list.next) { + struct phonet_device *pnd = list_entry(ptr, + struct phonet_device, list); + phonet_device_free(pnd); + } + + spin_unlock_bh(&pndevs.lock); + rtnl_unlock(); + unregister_netdevice_notifier(&phonet_device_notifier); +} + +struct phonet_address *phonet_address_alloc(void) +{ + struct phonet_address *pna; + + pna = kmalloc(sizeof(struct phonet_address), GFP_KERNEL); + + if (pna == NULL) + return NULL; + + INIT_LIST_HEAD(&pna->list); + + return pna; +} + +/* add Phonet address to list */ +void phonet_address_add(struct list_head *list, struct phonet_address *pna) +{ + list_add(&pna->list, list); +} + +/* remove Phonet address from list and free it */ +void phonet_address_free(struct phonet_address *pna) +{ + list_del(&pna->list); + kfree(pna); +} + +/* Allocate new Phonet device. */ +struct phonet_device *phonet_device_alloc(struct net_device *dev) +{ + struct phonet_device *pnd; + + pnd = kmalloc(sizeof(struct phonet_device), GFP_ATOMIC); + + if (pnd == NULL) + return NULL; + + INIT_LIST_HEAD(&pnd->own); + pnd->netdev = dev; + list_add(&pnd->list, &pndevs.list); + return pnd; +} + +struct phonet_device *__phonet_get_by_index(unsigned ifindex) +{ + struct list_head *p; + + list_for_each(p, &pndevs.list) { + struct phonet_device *pnd; + + pnd = list_entry(p, struct phonet_device, list); + BUG_ON(!pnd->netdev); + + if (pnd->netdev->ifindex == ifindex) + return pnd; + } + return NULL; +} + +void phonet_device_free(struct phonet_device *pnd) +{ + struct list_head *ptr; + + /* remove device from list */ + list_del(&pnd->list); + + for (ptr = pnd->own.next; ptr != &pnd->own; ptr = pnd->own.next) { + struct phonet_address *pna = + list_entry(ptr, struct phonet_address, list); + phonet_address_free(pna); + } + + kfree(pnd); +} + +/* + * Find the address from the device's address list having the given address + */ +struct phonet_address *phonet_dev2addr(struct phonet_device *pnd, + uint8_t addr, int mode) +{ + struct list_head *list = &pnd->own, *ptr; + struct phonet_address *best = NULL; + + for (ptr = list->next; ptr != list; ptr = ptr->next) { + struct phonet_address *pna = + list_entry(ptr, struct phonet_address, list); + + if (mode & PN_FIND_EXACT) { + /* try to find exact address */ + if (pna->addr == addr) { + best = pna; + break; + } + } else if (best == NULL || + best->prefix < pna->prefix) { + if ((pna->addr & MKMASK(pna->prefix)) == + (addr & MKMASK(pna->prefix))) { + best = pna; + } + } + } + + return best; +} + +/* + * Find the device having a given address (remember locking!!) + */ +struct phonet_address *phonet_addr2addr(uint8_t addr, int mode) +{ + struct list_head *ptr; + struct phonet_address *best = NULL; + + for (ptr = pndevs.list.next; ptr != &pndevs.list; ptr = ptr->next) { + struct phonet_address *pna = NULL; + struct phonet_device *pnd = + list_entry(ptr, struct phonet_device, list); + + /* Don't allow unregistering devices! */ + if ((pnd->netdev->reg_state != NETREG_REGISTERED) || + ((pnd->netdev->flags & IFF_UP)) != IFF_UP) + continue; + + pna = phonet_dev2addr(pnd, addr, mode); + + if (pna != NULL) { + if (best == NULL || best->prefix < pna->prefix) + best = pna; + } + } + + return best; +} + +/* notify Phonet of device events */ +static int phonet_device_notify(struct notifier_block *self, unsigned long what, + void *_dev) +{ + struct net_device *dev = _dev; + struct phonet_device *pnd; + + spin_lock_bh(&pndevs.lock); + pnd = __phonet_get_by_index(dev->ifindex); + + switch (what) { + case NETDEV_UNREGISTER: + if (pnd == NULL) + break; + phonet_device_free(pnd); + break; + default: + break; + } + + spin_unlock_bh(&pndevs.lock); + + return 0; + +} -- 1.5.4.3 -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@...r.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists