[PATCH] 2.6.11.7 X.25 : x25tap

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Adds an x25tap module, like ethertap for X.25.

This allows X.25 to be done in userspace, and in particular 
X.25 over TCP (XOT RFC1613) when used with a userspace 
XOT daemon.

Signed-off-by: Andrew Hendry <[email protected]>

diff -uprN -X dontdiff linux-2.6.11.7-vanilla/drivers/net/Kconfig linux-2.6.11.7/drivers/net/Kconfig
--- linux-2.6.11.7-vanilla/drivers/net/Kconfig	2005-04-08 04:58:17.000000000 +1000
+++ linux-2.6.11.7/drivers/net/Kconfig	2005-04-15 12:32:42.000000000 +1000
@@ -128,6 +128,24 @@ config ETHERTAP
 
 	  If you don't know what to use this for, you don't need it.
 
+config X25TAP
+	tristate "X.25 network tap"
+	depends on NETDEVICES && EXPERIMENTAL && NETLINK_DEV && X25
+	---help---
+	  This is a very simple X.25 driver. It bounces X.25 level2 frames
+	  to user space and expects X.25 frames to be written back to it.
+
+	  Connection state handling is left to the user pluged into the tap
+	  as explained in Documentation/networking/x25-iface.txt
+
+	  As this is an X.25 level 2 device you can use it for user level
+	  drivers and for building bridging tunnels (XOT).
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called x25tap.
+
+	  If your using xotd or similar program say N.
+
 config NET_SB1000
 	tristate "General Instruments Surfboard 1000"
 	depends on NETDEVICES && PNP
diff -uprN -X dontdiff linux-2.6.11.7-vanilla/drivers/net/Makefile linux-2.6.11.7/drivers/net/Makefile
--- linux-2.6.11.7-vanilla/drivers/net/Makefile	2005-04-08 04:57:27.000000000 +1000
+++ linux-2.6.11.7/drivers/net/Makefile	2005-04-15 12:33:04.000000000 +1000
@@ -69,6 +69,7 @@ obj-$(CONFIG_HAMACHI) += hamachi.o
 obj-$(CONFIG_NET) += Space.o loopback.o
 obj-$(CONFIG_SEEQ8005) += seeq8005.o
 obj-$(CONFIG_ETHERTAP) += ethertap.o
+obj-$(CONFIG_X25TAP) += x25tap.o
 obj-$(CONFIG_NET_SB1000) += sb1000.o
 obj-$(CONFIG_MAC8390) += mac8390.o 8390.o
 obj-$(CONFIG_APNE) += apne.o 8390.o
diff -uprN -X dontdiff linux-2.6.11.7-vanilla/drivers/net/x25tap.c linux-2.6.11.7/drivers/net/x25tap.c
--- linux-2.6.11.7-vanilla/drivers/net/x25tap.c	1970-01-01 10:00:00.000000000 +1000
+++ linux-2.6.11.7/drivers/net/x25tap.c	2005-04-15 12:33:34.000000000 +1000
@@ -0,0 +1,331 @@
+/*
+ *	X.25: A network device for bouncing x.25 frames via user space
+ *
+ *	X.25tap is cloned from ethertap.
+ *
+ *	This is a very simple X.25 driver. It bounces X.25 frames
+ *	to user space on x25tapX and expects X.25 frames to be written
+ *	back to it.
+ *
+ *	As this is an X.25 level 2 device you can use it for user level drivers
+ *	even for building bridging tunnels (XOT).
+ *
+ *	Original version, August 1998 [email protected]
+ *	2.6 version, October 2004 [email protected]
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/jiffies.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+
+#include <net/sock.h>
+#include <linux/netlink.h>
+#include <linux/if_arp.h>
+
+/*
+ *	Index to functions.
+ */
+
+static int  x25tap_open(struct net_device *dev);
+static int  x25tap_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int  x25tap_close(struct net_device *dev);
+static struct net_device_stats *x25tap_get_stats(struct net_device *dev);
+static void x25tap_rx(struct sock *sk, int len);
+
+static int x25tap_debug = 0;
+
+static int max_taps = 1;
+module_param(max_taps, int, 0);
+MODULE_PARM_DESC(max_taps,"Max number of x25 tap devices");
+
+static struct net_device **tap_map;	/* Returns the tap device for a given netlink */
+
+/*
+ *	Board-specific info in dev->priv.
+ */
+
+struct net_local
+{
+	struct sock	*nl;
+	struct net_device_stats stats;
+};
+
+/*
+ *	To call this a probe is a bit misleading, however for real
+ *	hardware it would have to check what was present.
+ */
+static int  __init x25tap_probe(int unit)
+{
+	struct net_device *dev;
+	int err = -ENOMEM;
+
+	dev = alloc_etherdev(sizeof(struct net_local));
+
+	if (!dev)
+		goto out;
+
+	SET_MODULE_OWNER(dev);
+
+	sprintf(dev->name, "x25tap%d", unit);
+	dev->base_addr = unit + NETLINK_TAPBASE;
+
+	netdev_boot_setup_check(dev);
+
+	memcpy(dev->dev_addr, "\xFE\xFD\x00\x00\x00\x00", 6);
+	if (dev->mem_start & 0xf)
+		x25tap_debug = dev->mem_start & 0x7;
+
+	/*
+	 *	The tap specific entries in the device structure.
+	 */
+
+	dev->open = x25tap_open;
+	dev->hard_start_xmit = x25tap_start_xmit;
+	dev->stop = x25tap_close;
+	dev->get_stats = x25tap_get_stats;
+
+	dev->flags|=IFF_NOARP;
+	dev->mtu = 1024;
+	dev->hard_header_len = 1;
+	dev->addr_len = 0;
+	dev->type = ARPHRD_X25;
+	dev->tx_queue_len = 10;
+
+	err = register_netdev(dev);
+	if (err)
+		goto out_free;
+
+	tap_map[unit]=dev;
+	return 0;
+out_free:
+	free_netdev(dev);
+out:
+	return err;
+}
+
+/*
+ *	Open/initialize the board.
+ */
+
+static int x25tap_open(struct net_device *dev)
+{
+	struct net_local *lp = netdev_priv(dev);
+
+	if (x25tap_debug > 2)
+		printk(KERN_DEBUG "%s: Doing x25tap_open()...\n", dev->name);
+
+	lp->nl = netlink_kernel_create(dev->base_addr, x25tap_rx);
+	if (lp->nl == NULL)
+		return -ENOBUFS;
+
+	netif_start_queue(dev);
+	return 0;
+}
+
+/*
+ *	We transmit by throwing the packet at netlink. We have to clone
+ *	it for 2.0 so that we dev_kfree_skb() the locked original.
+ */
+
+static int x25tap_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct net_local *lp = netdev_priv(dev);
+
+	/* Make the same thing, which loopback does. */
+	if (skb_shared(skb)) {
+	  	struct sk_buff *skb2 = skb;
+	  	skb = skb_clone(skb, GFP_ATOMIC);	/* Clone the buffer */
+	  	if (skb==NULL) {
+			dev_kfree_skb(skb2);
+			lp->stats.tx_dropped++;
+			return 0;
+		}
+	  	dev_kfree_skb(skb2);
+	}
+	switch (skb->data[0])
+	{
+		case 0x00:	/* Data request */
+			lp->stats.tx_bytes+=skb->len -1;
+			lp->stats.tx_packets++;
+			break;
+		case 0x01:	/* Connection request, do nothing */
+			if (x25tap_debug > 1)
+				printk(KERN_DEBUG "x25tap_start_xmit: "
+					"Connection request\n");
+			break;
+		case 0x02:	/* Disconnect request */
+			if (x25tap_debug > 1)
+				printk(KERN_DEBUG "x25tap_start_xmit: "
+					"Disconnect request\n");
+			break;
+		case 0x03:	/* changing lapb parameters requested */
+			printk(KERN_DEBUG "x25tap_start_xmit: setting of "
+				"options not supported\n");
+			break;
+		default:
+			printk(KERN_DEBUG "x25tap_start_xmit: "
+				"unknown firstbyte\n");
+			lp->stats.tx_dropped++;
+			kfree_skb(skb);
+			return -1;
+			break;
+	}
+
+	netlink_broadcast(lp->nl, skb, 0, ~0, GFP_ATOMIC);
+
+	return 0;
+}
+
+static __inline__ int x25tap_rx_skb(struct sk_buff *skb, struct net_device *dev)
+{
+	struct net_local *lp = netdev_priv(dev);
+	int len = skb->len;
+
+
+	if (len < 1) {
+		printk(KERN_DEBUG "%s : rx len = %d\n", dev->name, len);
+		kfree_skb(skb);
+		lp->stats.rx_errors++;
+		return -EINVAL;
+	}
+	if (NETLINK_CREDS(skb)->uid) {
+		printk(KERN_INFO "%s : user %d\n", dev->name, NETLINK_CREDS(skb)->uid);
+		kfree_skb(skb);
+		return -EPERM;
+	}
+
+	if (skb_shared(skb)) {
+	  	struct sk_buff *skb2 = skb;
+	  	skb = skb_clone(skb, GFP_KERNEL);	/* Clone the buffer */
+	  	if (skb==NULL) {
+			kfree_skb(skb2);
+			lp->stats.rx_dropped++;
+			return -ENOBUFS;
+		}
+	  	kfree_skb(skb2);
+	} else
+		skb_orphan(skb);
+
+	skb->dev = dev;
+	skb->protocol=htons(ETH_P_X25);
+	skb->mac.raw = skb->data;
+	skb->pkt_type = PACKET_HOST;
+	memset(skb->cb, 0, sizeof(skb->cb));
+
+	if (skb->data[0] == 0) {
+		lp->stats.rx_packets++;
+		lp->stats.rx_bytes+=len;
+	}
+
+	netif_rx(skb);
+	dev->last_rx = jiffies;
+	return len;
+}
+
+/*
+ *	The typical workload of the driver:
+ *	Handle the ether interface interrupts.
+ *
+ *	(In this case handle the packets posted from user space..)
+ */
+
+static void x25tap_rx(struct sock *sk, int len)
+{
+	unsigned unit = sk->sk_protocol - NETLINK_TAPBASE;
+	struct net_device *dev;
+	struct sk_buff *skb;
+
+	if (unit >= max_taps || (dev = tap_map[unit]) == NULL) {
+		printk(KERN_CRIT "x25tap: bad unit %u!\n", unit);
+		skb_queue_purge(&sk->sk_receive_queue);
+		return;
+	}
+
+	if (x25tap_debug > 3)
+		printk(KERN_DEBUG "%s: x25tap_rx() %d\n", dev->name, len);
+
+	while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL)
+		x25tap_rx_skb(skb, dev);
+}
+
+static int x25tap_close(struct net_device *dev)
+{
+	struct net_local *lp = netdev_priv(dev);
+	struct sock *sk = lp->nl;
+
+	if (x25tap_debug > 2)
+		printk(KERN_DEBUG "%s: Shutting down.\n", dev->name);
+
+	netif_stop_queue(dev);
+
+	if (sk) {
+		lp->nl = NULL;
+		sock_release(sk->sk_socket);
+	}
+
+	return 0;
+}
+
+static struct net_device_stats *x25tap_get_stats(struct net_device *dev)
+{
+	struct net_local *lp = netdev_priv(dev);
+	return &lp->stats;
+}
+
+
+int __init x25tap_init(void)
+{
+	int i, err = 0;
+
+	/* netlink can only hande 16 entries unless modified */
+	if (max_taps > MAX_LINKS - NETLINK_TAPBASE)
+		return -E2BIG;
+
+	tap_map = kmalloc(sizeof(struct net_device *)*max_taps, GFP_KERNEL);
+	if (!tap_map)
+		return -ENOMEM;
+
+	for (i = 0; i < max_taps; i++) {
+		err = x25tap_probe(i);
+		if (err) {
+			while (--i > 0) {
+				unregister_netdev(tap_map[i]);
+				free_netdev(tap_map[i]);
+			}
+			break;
+		}
+	}
+	if (err)
+		kfree(tap_map);
+	return err;
+}
+module_init(x25tap_init);
+
+void __exit x25tap_cleanup(void)
+{
+	int i;
+
+	for (i = 0; i < max_taps; i++) {
+		struct net_device *dev = tap_map[i];
+		if (dev) {
+			tap_map[i] = NULL;
+			unregister_netdev(dev);
+			free_netdev(dev);
+		}
+	}
+	kfree(tap_map);
+}
+module_exit(x25tap_cleanup);
+
+MODULE_LICENSE("GPL");


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux