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  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
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