* [PATCH] CDP handler for linux
@ 2001-08-14 18:47 Chris Crowther
2001-08-14 19:30 ` Christoph Hellwig
` (2 more replies)
0 siblings, 3 replies; 17+ messages in thread
From: Chris Crowther @ 2001-08-14 18:47 UTC (permalink / raw)
To: linux-kernel
'lo all,
Hmm, why am I scared about this? Oh well, here goes.
I've been working on an addition to the kernel over the past
couple of days that enables the kernel to interpret CDP (Cisco Discovery
Protocol) packets which can be transmited by various pieces of Cisco kit.
I've got it to the stage where it will read neighbors packets and
display them via a /proc/net entry, but I've only really tested it with
the router I have access to here, so I was wondering:
1) am I nuts
2) is anyone else interested in this
3) can anyone tell me if it reads packets from other pieces of kit
OK? :)
The code is stable enough that the kernel does panic and my
workstation hasn't exploded yet, but there's still some gaps in the
recieve code, and it doesn't delete neighors whose TTL's have expired yet
(I'm about to start do that).
The plan is eventualy to make the addition transmit CDP packets as
well.
Please don't chargrill me :) Patch follows, option is flagged as
Experimental in the Config file and it's under Network Options, comments
and suggestions are very welcome (as long as they're nice and/or
contsructive).
diff -urN -X dontdiff linux-2.4/Documentation/Configure.help linux-2.4.7-cdp/Documentation/Configure.help
--- linux-2.4/Documentation/Configure.help Mon Jul 30 10:52:41 2001
+++ linux-2.4.7-cdp/Documentation/Configure.help Tue Aug 14 14:37:35 2001
@@ -4226,6 +4226,31 @@
The kHTTPd is experimental. Be careful when using it on a production
machine. Also note that kHTTPd doesn't support virtual servers yet.
+CDP Reporting (EXPERIMENTAL)
+CONFIG_CDP
+ This is support for reporting the Cisco CDP packets which can be
+ broadcast by various Cisco kit. Information is written to proc file
+ system.
+
+ This protocol support is also available as a module ( = code which
+ can be inserted in and removed from the running kernel whenever you
+ want). The module will be called cdp.o. If you want to compile it
+ as a module, say M here and read Documentation/modules.txt.
+
+ Be sure to say Y to "/proc file system support" otherwise you won't
+ see anything.
+
+CDP Debuging
+CONFIG_CDP_DEBUG
+ Enable debuging information in the CDP code - this generate a lot of
+ information at KERN_DEBUG level - it should only be used for
+ troubleshooting - you *really* do *not* want to use it on a production
+ system, your log files will be full of data. Every incoming packet
+ generates over 20 lines of debuging information.
+
+ You probably want to say N here - only enable if you know you really
+ want it.
+
IPX networking
CONFIG_IPX
This is support for the Novell networking protocol, IPX, commonly
diff -urN -X dontdiff linux-2.4/include/net/cdp.h linux-2.4.7-cdp/include/net/cdp.h
--- linux-2.4/include/net/cdp.h Thu Jan 1 01:00:00 1970
+++ linux-2.4.7-cdp/include/net/cdp.h Tue Aug 14 19:16:35 2001
@@ -0,0 +1,79 @@
+/*
+ *
+ * Bassed on documentation from Cisco, detailing the CDP packet format,
+ * which is available from:
+ * http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm#xtocid842812
+ *
+ * Portions Copyright (c) 2001 Chris Crowther
+ * Chris Crowther admits no liability nor provides warranty for any
+ * of this software. This material is provided "AS-IS" and at no charge.
+ *
+ * This software is released under the the GNU Public Licence (GPL).
+*/
+
+/* values for our cdp packets */
+#define CDP_VERSION 0x1
+#define CDP_TTL 180 /* send our packets with a TTL of 180 seconds */
+
+/* timer values */
+#define CDP_POLL HZ*5 /* poll the neighbor list every 5 seconds for expired
+ entires */
+#define CDP_TXTIME HZ*60 /* send out packets every 60 seconds */
+
+
+/* the packet types */
+#define CDP_TYPE_DEVICEID 0x0001
+#define CDP_TYPE_ADDRESS 0x0002
+#define CDP_TYPE_PORTID 0x0003
+#define CDP_TYPE_CAPABILITIES 0x0004
+#define CDP_TYPE_VERSION 0x0005
+#define CDP_TYPE_PLATFORM 0x0006
+#define CDP_TYPE_IPPREFIX 0x0007
+
+/* the capability masks */
+#define CDP_CAPABILITY_L3R 0x01 /* a layer 3 router */
+#define CDP_CAPABILITY_L2TB 0x02 /* a layer 2 transparent bridge */
+#define CDP_CAPABILITY_L2SRB 0x04 /* a layer 2 source-root bridge */
+#define CDP_CAPABILITY_L2SW 0x08 /* a layer 2 switch (non-spanning tree) */
+#define CDP_CAPABILITY_L3TXRX 0x10 /* a layer 3 (non routing) host */
+#define CDP_CAPABILITY_IGRPFW 0x20 /* does not forward IGMP Packets to non-routers */
+#define CDP_CAPABILITY_L1 0x40 /* a layer 1 repeater */
+
+/* the actual neighbor entry */
+struct s_cdp_neighbor {
+
+ unsigned char *remote_ethernet; /* Remote MAC */
+ char *local_iface; /* Device we saw the packet on*/
+ struct timeval timestamp; /* Time packet arrived */
+ unsigned char cdp_version; /* Version of CDP - always 1 afaik*/
+ unsigned char cdp_ttl; /* Holdtime */
+ unsigned short cdp_checksum; /* Standard IP packet checksum */
+ char *cdp_neighbor_sw_ver; /* Software version on neighbor */
+ char *cdp_neighbor_id; /* FQDN of remote device */
+ struct in_addr cdp_addresss; /* FIXME This should really be a linked list of
+ addresses, since routers can have more than one.
+ Is it possible to have IPX or AppleNet addresses
+ here also? */
+ char *cdp_capabitlities; /* String of capability codes */
+ int cdp_capab_mask; /* Mask of capabilities */
+ char *cdp_platform; /* Model name */
+ char *cdp_portID; /* Remote port origin */
+
+ struct s_cdp_neighbor *next;
+ struct s_cdp_neighbor *prev;
+};
+
+/* linked list of addresses */
+struct cdp_neighbor_addresses {
+ struct in_addr cdp_addresss;
+
+ struct cdp_neighbor_addresses *next;
+ struct cdp_neighbor_addresses *prev;
+};
+
+/* head struct */
+struct s_cdp_neighbors {
+ struct s_cdp_neighbor *head;
+ struct s_cdp_neighbor *foot;
+};
+
diff -urN -X dontdiff linux-2.4/net/802/Makefile linux-2.4.7-cdp/net/802/Makefile
--- linux-2.4/net/802/Makefile Fri Dec 29 22:07:24 2000
+++ linux-2.4.7-cdp/net/802/Makefile Thu Aug 9 12:17:09 2001
@@ -50,6 +50,10 @@
SNAP=y
endif
+ifdef CONFIG_CDP
+ SNAP=y
+endif
+
ifeq ($(SNAP),y)
obj-y += p8022.o psnap.o
endif
diff -urN -X dontdiff linux-2.4/net/Config.in linux-2.4.7-cdp/net/Config.in
--- linux-2.4/net/Config.in Wed Mar 7 06:44:15 2001
+++ linux-2.4.7-cdp/net/Config.in Tue Aug 14 14:48:59 2001
@@ -49,6 +49,14 @@
fi
comment ' '
+
+dep_tristate 'The Cisco Discovery Protocol (EXPERIMENTAL)' CONFIG_CDP $CONFIG_EXPERIMENTAL
+if [ "$CONFIG_CDP" != "n" ]; then
+ source net/cdp/Config.in
+fi
+
+comment ' '
+
tristate 'The IPX protocol' CONFIG_IPX
if [ "$CONFIG_IPX" != "n" ]; then
source net/ipx/Config.in
diff -urN -X dontdiff linux-2.4/net/Makefile linux-2.4.7-cdp/net/Makefile
--- linux-2.4/net/Makefile Tue Jun 12 03:15:27 2001
+++ linux-2.4.7-cdp/net/Makefile Thu Aug 9 12:13:33 2001
@@ -32,6 +32,7 @@
subdir-$(CONFIG_NET_SCHED) += sched
subdir-$(CONFIG_BRIDGE) += bridge
subdir-$(CONFIG_IPX) += ipx
+subdir-$(CONFIG_CDP) += cdp
subdir-$(CONFIG_ATALK) += appletalk
subdir-$(CONFIG_WAN_ROUTER) += wanrouter
subdir-$(CONFIG_X25) += x25
diff -urN -X dontdiff linux-2.4/net/cdp/Config.in linux-2.4.7-cdp/net/cdp/Config.in
--- linux-2.4/net/cdp/Config.in Thu Jan 1 01:00:00 1970
+++ linux-2.4.7-cdp/net/cdp/Config.in Tue Aug 14 14:48:00 2001
@@ -0,0 +1,5 @@
+#
+# CDP anscialry options
+#
+
+bool ' Enable Debug code' CONFIG_CDP_DEBUG $CONFIG_CDP
diff -urN -X dontdiff linux-2.4/net/cdp/Makefile linux-2.4.7-cdp/net/cdp/Makefile
--- linux-2.4/net/cdp/Makefile Thu Jan 1 01:00:00 1970
+++ linux-2.4.7-cdp/net/cdp/Makefile Thu Aug 9 12:11:44 2001
@@ -0,0 +1,25 @@
+#
+# Makefile for the Linux CDP layer.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+# We only get in/to here if CONFIG_CDP = 'y' or 'm'
+
+O_TARGET := cdp.o
+
+export-objs = af_cdp.o
+
+obj-y := af_cdp.o
+
+ifeq ($(CONFIG_CDP),m)
+ obj-m += $(O_TARGET)
+endif
+
+include $(TOPDIR)/Rules.make
+
+tar:
+ tar -cvf /dev/f1 .
diff -urN -X dontdiff linux-2.4/net/cdp/af_cdp.c linux-2.4.7-cdp/net/cdp/af_cdp.c
--- linux-2.4/net/cdp/af_cdp.c Thu Jan 1 01:00:00 1970
+++ linux-2.4.7-cdp/net/cdp/af_cdp.c Tue Aug 14 19:14:11 2001
@@ -0,0 +1,509 @@
+/*
+ * Implements a CDP handler.
+ *
+ * This code is derived from protocol specifications by Cisco Systems
+ * and various code culled from the Kernel source tree, mostly the IPX
+ * code.
+ *
+ * Unless otherwise commented, all revisions by Chris Crowther.
+ *
+ * Revision 0.1.0: Initial coding.
+ * Revision 0.1.1: Incoming CDP packet handling working, prefix's and addresses
+ * need handling still.
+ *
+ * Portions Copyright (c) 2001 Chris Crowther.
+ * Chris Crowther admits no liability nor provides warranty for any
+ * of this software. This material is provided "AS-IS" and at no charge.
+ *
+ * This software is released under the the GNU Public Licence (GPL).
+ *
+*/
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/if.h>
+#include <linux/if_ether.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/sockios.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/time.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+
+#include <asm/byteorder.h>
+#include <asm/system.h>
+
+#include <net/psnap.h>
+#include <net/cdp.h>
+
+/* module info */
+MODULE_AUTHOR("Chris Crowther <chrisc@shad0w.org.uk>");
+MODULE_DESCRIPTION("Linux Cisco Discovery Protocol");
+
+/* globals */
+static struct s_cdp_neighbors cdp_neighbors;
+static struct timer_list cdp_poll_neighbors_timer;
+static struct timer_list cdp_tx_data_timer;
+
+/* linked list functions */
+struct s_cdp_neighbor *cdp_find_neighbor(unsigned char *remote_ethernet)
+{
+
+ struct s_cdp_neighbor *p = cdp_neighbors.head;
+
+ while(p != NULL)
+ {
+ #ifdef CONFIG_CDP_DEBUG
+ printk(KERN_DEBUG "CDP: Comparing neighbor with %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n",
+ p->remote_ethernet[0],
+ p->remote_ethernet[1],
+ p->remote_ethernet[2],
+ p->remote_ethernet[3],
+ p->remote_ethernet[4],
+ p->remote_ethernet[5]);
+ #endif
+ if (!memcmp(remote_ethernet, p->remote_ethernet, ETH_ALEN))
+ {
+ #ifdef CONFIG_CDP_DEBUG
+ printk(KERN_DEBUG "CDP: Matches existing entry\n");
+ #endif
+ return p;
+ } else {
+ #ifdef CONFIG_CDP_DEBUG
+ printk(KERN_DEBUG "CDP: Doesn't match, trying next entry (if any)\n");
+ #endif
+ p = p->next;
+ }
+ }
+
+ /* fallthrough */
+ return NULL;
+}
+
+/* removes a neighbor element from the list, then free's it */
+void cdp_delete_neighbor(struct s_cdp_neighbor *p)
+{
+ if(p->prev)
+ p->prev->next = p->next;
+
+ if(p->next)
+ p->next->prev = p->prev;
+
+ if (cdp_neighbors.head == p)
+ cdp_neighbors.head = p->next;
+
+ if (cdp_neighbors.foot == p)
+ cdp_neighbors.foot = p->prev;
+
+ #ifdef CONFIG_CDP_DEBUG
+ printk(KERN_DEBUG "CDP: Freeing neighbor entry at memory ref: 0x%X\n",p);
+ #endif
+ kfree(p);
+}
+
+/* update a neighbor entry with newer values */
+int cdp_update_neighbor(struct sk_buff *skb, struct s_cdp_neighbor *p)
+{
+
+ /* We store all data localy in host byte order, which means we need to run ntoh[l/s] over
+ all the numeric values (except single bytes of course). It's safe to always run
+ this since it has no effect on the data if the host byte order is the same network
+ byte order (as is the case with Big Endian systmes). */
+
+ /* temporary holders for packet data */
+ unsigned short type = 0, length = 0, len = 0;
+ unsigned char *data = "";
+ char *buf = "";
+
+ /* If we have less than 4 bytes of data, we don't have a valid CDP packet, return
+ NULL so we know to toast the record */
+ if(skb->len < 4)
+ return NULL;
+
+ /* copy the timestamp from the skb to the neighbor so we know
+ when it arrived, and therefore know when to expire it */
+ memcpy(&(p->timestamp),&(skb->stamp),sizeof(struct timeval));
+ memcpy(&(p->cdp_version),(skb->data)++,1);
+ memcpy(&(p->cdp_ttl),(skb->data)++,1);
+ memcpy(&(p->cdp_checksum),(skb->data)++,2); (skb->data)++;
+
+ /* FIXME i haven't got round to actually checking this yet - we should really do it now */
+ p->cdp_checksum = ntohs(p->cdp_checksum);
+
+ /* FIXME compare the checksum here as a kludge to see if there's any change in data */
+
+ if ((p->remote_ethernet = (unsigned char *)kmalloc(sizeof(unsigned char)*ETH_ALEN,GFP_ATOMIC)) == NULL)
+ {
+ printk(KERN_CRIT "CDP: Could not allocate memory for neighbor key member.\n");
+ return NULL;
+ } else {
+ memcpy(p->remote_ethernet, (char *)(skb->mac.ethernet->h_source), ETH_ALEN);
+ }
+
+ if ((p->local_iface = (char *)kmalloc(sizeof(unsigned char)*strlen(skb->dev->name),GFP_ATOMIC)) == NULL)
+ {
+ printk(KERN_CRIT "CDP: Could not allocate memory for neighbor member.\n");
+ kfree(p->remote_ethernet);
+ return NULL;
+ } else {
+ strncpy(p->local_iface,(char *)(skb->dev->name),IFNAMSIZ);
+ }
+
+ /* only go while we're at less than the tail value - we can't actually go equal
+ to it, since we must have at least 4 bytes left for our type and length fields */
+
+ while(skb->data < skb->tail)
+ {
+ type = 0;
+ length = 0;
+
+ memcpy(&type, (skb->data)++, 2); (skb->data)++;
+ memcpy(&length, (skb->data)++, 2); (skb->data)++;
+ /* make sure the byte order is right */
+ type = ntohs(type);
+ length = (ntohs(length)-4); /* length includes the type field and length field
+ for some reason */
+
+ data = (unsigned char *)kmalloc(sizeof(unsigned char)*length,GFP_ATOMIC);
+ memcpy(data, (skb->data), length);
+
+ /* jump to the end of this piece of data */
+ skb->data += length;
+
+ #ifdef CONFIG_CDP_DEBUG
+ printk(KERN_DEBUG "CDP: Data Type = %.4X\n",type);
+ printk(KERN_DEBUG "CDP: Data Length = %d bytes\n",length);
+ #endif
+
+ /* process the data */
+ switch (type)
+ {
+ case CDP_TYPE_IPPREFIX:
+ /* FIXME Need to work out how the prefix is stored */
+
+ break;
+
+ case CDP_TYPE_PLATFORM:
+ p->cdp_platform = (char *)kmalloc(sizeof(char)*length+1,GFP_ATOMIC);
+ memcpy(p->cdp_platform, data, length);
+ *(p->cdp_platform+length) = '\000';
+ break;
+
+ case CDP_TYPE_VERSION:
+ p->cdp_neighbor_sw_ver = (char *)kmalloc(sizeof(char)*length+1,GFP_ATOMIC);
+ memcpy(p->cdp_neighbor_sw_ver, data, length);
+ *(p->cdp_neighbor_sw_ver+length) = '\000';
+ break;
+
+ case CDP_TYPE_CAPABILITIES:
+
+ memcpy(&(p->cdp_capab_mask), data, length);
+ p->cdp_capab_mask = ntohl(p->cdp_capab_mask);
+
+ #ifdef CONFIG_CDP_DEBUG
+ printk(KERN_DEBUG "CDP: Capab Mask = %.8X\n",p->cdp_capab_mask);
+ #endif
+
+ if ((p->cdp_capab_mask & CDP_CAPABILITY_L3R) == CDP_CAPABILITY_L3R)
+ len += sprintf(buf+len, "R");
+ if ((p->cdp_capab_mask & CDP_CAPABILITY_L2TB) == CDP_CAPABILITY_L2TB)
+ len += sprintf(buf+len, "T");
+ if ((p->cdp_capab_mask & CDP_CAPABILITY_L2SRB) == CDP_CAPABILITY_L2SRB)
+ len += sprintf(buf+len, "B");
+ if ((p->cdp_capab_mask & CDP_CAPABILITY_L2SW) == CDP_CAPABILITY_L2SW)
+ len += sprintf(buf+len, "S");
+ if ((p->cdp_capab_mask & CDP_CAPABILITY_L3TXRX) == CDP_CAPABILITY_L3TXRX)
+ len += sprintf(buf+len, "r");
+ if ((p->cdp_capab_mask & CDP_CAPABILITY_IGRPFW) == CDP_CAPABILITY_IGRPFW)
+ len += sprintf(buf+len, "I");
+ if ((p->cdp_capab_mask & CDP_CAPABILITY_L1) == CDP_CAPABILITY_L1)
+ len += sprintf(buf+len, "H");
+
+ memcpy(p->cdp_capabitlities, buf, len);
+ *(p->cdp_capabitlities+len) = '\000';
+ break;
+
+ case CDP_TYPE_PORTID:
+ p->cdp_portID = (char *)kmalloc(sizeof(char)*length+1,GFP_ATOMIC);
+ memcpy(p->cdp_portID, data, length);
+ *(p->cdp_portID+length) = '\000';
+ break;
+
+ case CDP_TYPE_ADDRESS:
+ /* FIXME Need to check which byteorder the address is in */
+ break;
+
+ case CDP_TYPE_DEVICEID:
+ p->cdp_neighbor_id = (char *)kmalloc(sizeof(char)*length+1,GFP_ATOMIC);
+ memcpy(p->cdp_neighbor_id, data, length);
+ *(p->cdp_neighbor_id+length) = '\000';
+ break;
+
+ default:
+ /* do nothing if we don't know what type it is */
+ #ifdef CONFIG_CDP_DEBUG
+ printk(KERN_DEBUG "CDP: Unknown type 0x%.4X\n",type);
+ #endif
+ break;
+ }
+
+ /* blast it */
+ kfree(data);
+
+ /* we must have at least 4 bytes left, if we don't, just skip out */
+ if ((skb->tail - skb->data) < 4)
+ break;
+ }
+
+ #ifdef CONFIG_CDP_DEBUG
+ printk(KERN_DEBUG "CDP: Version = %i\n",p->cdp_version);
+ printk(KERN_DEBUG "CDP: TTL = %i\n",p->cdp_ttl);
+ printk(KERN_DEBUG "CDP: Checksum = 0x%.4X\n",p->cdp_checksum);
+ #endif
+
+return 1;
+}
+
+void cdp_init_neighbor(struct s_cdp_neighbor *p)
+{
+ /* itialise all the memebers, in case no value is assigned */
+ p->remote_ethernet = "";
+ p->local_iface = "";
+ p->cdp_version = 1; /* the CDP definition says version is always 1 */
+ p->cdp_ttl = 128; /* a default TTL so it will timeout */
+ p->cdp_addresss.s_addr = 0;
+ p->cdp_neighbor_sw_ver = "";
+ p->cdp_neighbor_id = "";
+ p->cdp_capabitlities = "";
+ p->cdp_capab_mask = 0;
+ p->cdp_platform = "";
+ p->cdp_portID = "";
+ p->next = p->prev = NULL;
+}
+
+struct s_cdp_neighbor *cdp_add_neighbor(struct sk_buff *skb)
+{
+
+ struct s_cdp_neighbor *p;
+
+ if ((p = (struct s_cdp_neighbor *)kmalloc(sizeof(struct s_cdp_neighbor),GFP_ATOMIC)) == NULL)
+ {
+ printk(KERN_CRIT "CDP: Can not allocate memory for new neighbor.\n");
+ return NULL;
+ } else {
+ #ifdef CONFIG_CDP_DEBUG
+ printk(KERN_DEBUG "CDP: Allocated new neighbor at memory ref: 0x%X\n",p);
+ #endif
+
+ /* init all the fields so they have some data */
+ cdp_init_neighbor(p);
+
+ /* Try and assign values, if we can't blow the struct away */
+ if (!cdp_update_neighbor(skb,p))
+ {
+ kfree(p);
+ return NULL;
+ }
+
+ if (cdp_neighbors.head == NULL)
+ {
+ cdp_neighbors.foot = cdp_neighbors.head = p;
+ } else {
+ p->prev = cdp_neighbors.foot;
+ cdp_neighbors.foot->next = p;
+ cdp_neighbors.foot = p;
+ }
+ }
+
+ return p;
+}
+
+/* proc fs functions */
+int cdp_get_neighbor_info(char *buffer, char **start, off_t offset, int length)
+{
+ struct s_cdp_neighbor *p = cdp_neighbors.head;
+ int len=0;
+ off_t pos=0;
+ off_t begin=0;
+
+ len += sprintf(buffer,"Device ID\t\tLocal Intrfce\tHoldtme\tCapability\tPlatform\tPort ID\n");
+
+ cli();
+
+ while (p != NULL)
+ {
+ len += sprintf(buffer+len, "%s\t%s\t%d\t%s\t%s\t%s\n",p->cdp_neighbor_id,p->local_iface,p->cdp_ttl,p->cdp_capabitlities,p->cdp_platform,p->cdp_portID);
+
+ p = p->next;
+
+ pos=begin+len;
+ if(pos<offset)
+ {
+ len=0;
+ begin=pos;
+ }
+ if(pos>offset+length)
+ break;
+ }
+
+ sti();
+
+ *start=buffer+(offset-begin);
+ len-=(offset-begin);
+ if(len>length)
+ len=length;
+
+ return len;
+}
+
+/* network functions */
+
+/* deletes timed out neighbor entries (ie TTL expired) */
+static void SMP_TIMER_NAME(cdp_check_expire)(unsigned long unused)
+{
+ unsigned long now = jiffies;
+
+ mod_timer(&cdp_poll_neighbors_timer, now + CDP_POLL);
+}
+SMP_TIMER_DEFINE(cdp_check_expire, cdp_expire_task);
+
+/* announce to anyone who is listening (ie, Cisco kit) what we are */
+static void SMP_TIMER_NAME(cdp_send_update)(unsigned long unused)
+{
+ unsigned long now = jiffies;
+ unsigned int len = 0;
+ char *buf = "";
+
+ /*
+ * XXX How do we check for capabilities?
+ *
+ * L2 Switching: CONFIG_DGRS
+ * L2 SRB: CONFIG_NET_FASTROUTE
+ * L3 Routing: CONFIG_WAN_ROUTER, CONFIG_IP_ADVANCED_ROUTER, CONFIG_IP_MROUTE
+ * L3 RX/TX: !CONFIG_IP_ADVANCED_ROUTER & CONFIG_INET, CONFIG_IPX, CONFIG_SPX
+ *
+ * As far as I know, Linux doesn't do any of the other capabilities.
+ *
+ * I'm assuming that unless Advanced Router is enabled, we're not routing TCP/IP,
+ * this isn't technicaly true, but it's good enough - people using a linux box as
+ * a router are probably going to have it enabled.
+ *
+ * Can the kernel route IPX packets?
+ */
+
+ mod_timer(&cdp_tx_data_timer, now + CDP_TXTIME);
+}
+SMP_TIMER_DEFINE(cdp_send_update, cdp_update_task);
+
+/* function triggered by arriving CDP packets, as determined by the SNAP ID */
+int cdp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
+{
+
+ struct s_cdp_neighbor *p = NULL;
+
+ #ifdef CONFIG_CDP_DEBUG
+ printk(KERN_DEBUG "CDP: Packet from %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n",
+ skb->mac.ethernet->h_source[0],
+ skb->mac.ethernet->h_source[1],
+ skb->mac.ethernet->h_source[2],
+ skb->mac.ethernet->h_source[3],
+ skb->mac.ethernet->h_source[4],
+ skb->mac.ethernet->h_source[5]
+ );
+ #endif
+
+ p = cdp_find_neighbor(skb->mac.ethernet->h_source);
+
+ if ( p == NULL)
+ {
+ #ifdef CONFIG_CDP_DEBUG
+ printk(KERN_DEBUG "CDP: Creating new neighbor.\n");
+ #endif
+ cdp_add_neighbor(skb);
+ }
+ else
+ {
+ #ifdef CONFIG_CDP_DEBUG
+ printk(KERN_DEBUG "CDP: Updating existing neighbor at memory ref: 0x%X\n",p);
+ #endif
+ cdp_update_neighbor(skb,p);
+ }
+
+ /* we're done with the packet now */
+// kfree_skb(skb);
+
+return 0;
+}
+
+/* init/exit/module functions/globals */
+
+static struct datalink_proto *pSNAP_datalink;
+static unsigned char cdp_snap_id[5] = { 0x0, 0x0, 0x0c, 0x20, 0x00 };
+static const char banner[] __initdata =
+ KERN_INFO "CDP: Linux Cisco Discovery Protocol 0.0.1\n"
+ KERN_INFO "CDP: Portions Copyright (c) 2001 Chris Crowther\n";
+
+static int __init cdp_init(void)
+{
+ pSNAP_datalink = register_snap_client(cdp_snap_id, cdp_rcv);
+ if (!pSNAP_datalink)
+ {
+ printk(KERN_CRIT "CDP: Unable to register with SNAP\n");
+ return 0;
+ }
+ /* initialise the neighbors linked list */
+ cdp_neighbors.head = cdp_neighbors.foot = NULL;
+
+ /* initialise + register timers */
+ cdp_poll_neighbors_timer.function = cdp_check_expire;
+ cdp_tx_data_timer.function = cdp_send_update;
+
+ cdp_poll_neighbors_timer.expires = jiffies + CDP_POLL;
+ cdp_tx_data_timer.expires = jiffies + CDP_POLL;
+
+ add_timer(&cdp_poll_neighbors_timer);
+ add_timer(&cdp_tx_data_timer);
+
+ /* create /proc/net entry, if proc fs is enabled */
+#ifdef CONFIG_PROC_FS
+ proc_net_create("cdp_neighbors", 0, cdp_get_neighbor_info);
+#endif
+ printk(banner);
+ return 0;
+}
+
+module_init(cdp_init);
+
+static void __exit cdp_bibi(void)
+{
+
+ struct s_cdp_neighbor *p = cdp_neighbors.head;
+
+ proc_net_remove("cdp_neighbors");
+
+ unregister_snap_client(cdp_snap_id);
+ pSNAP_datalink = NULL;
+
+ /* remove timers */
+ del_timer(&cdp_poll_neighbors_timer);
+ del_timer(&cdp_tx_data_timer);
+
+ /* Unallocate all the neighbor entries */
+ while(p!=NULL)
+ {
+ cdp_delete_neighbor(p);
+ p = cdp_neighbors.head;
+ }
+
+ cdp_neighbors.foot = cdp_neighbors.head = NULL;
+
+ printk(KERN_INFO "CDP: Exiting\n");
+}
+
+module_exit(cdp_bibi);
+
--
Chris "_Shad0w_" Crowther
shad0w@shad0w.org.uk
http://www.shad0w.org.uk/
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: [PATCH] CDP handler for linux
2001-08-14 18:47 [PATCH] CDP handler for linux Chris Crowther
@ 2001-08-14 19:30 ` Christoph Hellwig
2001-08-14 19:56 ` Chris Crowther
2001-08-14 20:17 ` Alan Cox
2001-08-14 20:19 ` Dan Hollis
2 siblings, 1 reply; 17+ messages in thread
From: Christoph Hellwig @ 2001-08-14 19:30 UTC (permalink / raw)
To: Chris Crowther; +Cc: linux-kernel
Hi Chis,
In article <Pine.LNX.4.33.0108141934130.3283-100000@monolith.shad0w.org.uk> you wrote:
> I've been working on an addition to the kernel over the past
> couple of days that enables the kernel to interpret CDP (Cisco Discovery
> Protocol) packets which can be transmited by various pieces of Cisco kit.
>
> I've got it to the stage where it will read neighbors packets and
> display them via a /proc/net entry, but I've only really tested it with
> the router I have access to here, so I was wondering:
> --- linux-2.4/net/cdp/Makefile Thu Jan 1 01:00:00 1970
> +++ linux-2.4.7-cdp/net/cdp/Makefile Thu Aug 9 12:11:44 2001
> @@ -0,0 +1,25 @@
> +#
> +# Makefile for the Linux CDP layer.
> +#
> +# Note! Dependencies are done automagically by 'make dep', which also
> +# removes any old dependencies. DON'T put your own dependencies here
> +# unless it's something special (ie not a .c file).
> +#
> +# Note 2! The CFLAGS definition is now in the main makefile...
> +
> +# We only get in/to here if CONFIG_CDP = 'y' or 'm'
> +
> +O_TARGET := cdp.o
> +
> +export-objs = af_cdp.o
You don't export symbols, so you don't need to add your object to export-objs.
> +
> +obj-y := af_cdp.o
> +
> +ifeq ($(CONFIG_CDP),m)
> + obj-m += $(O_TARGET)
> +endif
> +
> +include $(TOPDIR)/Rules.make
> +
> +tar:
> + tar -cvf /dev/f1 .
Kill this tar rule, please :)
> diff -urN -X dontdiff linux-2.4/net/cdp/af_cdp.c linux-2.4.7-cdp/net/cdp/af_cdp.c
> --- linux-2.4/net/cdp/af_cdp.c Thu Jan 1 01:00:00 1970
> +++ linux-2.4.7-cdp/net/cdp/af_cdp.c Tue Aug 14 19:14:11 2001
> @@ -0,0 +1,509 @@
> +/*
> + * Implements a CDP handler.
> + *
> + * This code is derived from protocol specifications by Cisco Systems
> + * and various code culled from the Kernel source tree, mostly the IPX
> + * code.
> + *
> + * Unless otherwise commented, all revisions by Chris Crowther.
> + *
> + * Revision 0.1.0: Initial coding.
> + * Revision 0.1.1: Incoming CDP packet handling working, prefix's and addresses
> + * need handling still.
> + *
> + * Portions Copyright (c) 2001 Chris Crowther.
I think it's all yours, isn't it?
Besides this little nitpicks I'd like to give you the advise to send this
to linuxnetdev, too.
Christoph
--
Whip me. Beat me. Make me maintain AIX.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] CDP handler for linux
2001-08-14 19:30 ` Christoph Hellwig
@ 2001-08-14 19:56 ` Chris Crowther
2001-08-14 20:59 ` Bjoern A. Zeeb
0 siblings, 1 reply; 17+ messages in thread
From: Chris Crowther @ 2001-08-14 19:56 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: linux-kernel
On Tue, 14 Aug 2001, Christoph Hellwig wrote:
> > +export-objs = af_cdp.o
>
> You don't export symbols, so you don't need to add your object to export-objs.
Now removed :)
> > + tar -cvf /dev/f1 .
>
> Kill this tar rule, please :)
Ditto.
> > + * Portions Copyright (c) 2001 Chris Crowther.
>
> I think it's all yours, isn't it?
I was playing safe as usual - I'm not entirely sure on the
copyright of the CDP definition - it's created by Cisco so it's their
property - but there's a published break down of how it's built so I'm not
sure how things work re: implementing it on other systems.
> Besides this little nitpicks I'd like to give you the advise to send this
> to linuxnetdev, too.
ok, will do - just as soon as I find the addy :)
--
Chris "_Shad0w_" Crowther
shad0w@shad0w.org.uk
http://www.shad0w.org.uk/
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] CDP handler for linux
2001-08-14 19:56 ` Chris Crowther
@ 2001-08-14 20:59 ` Bjoern A. Zeeb
0 siblings, 0 replies; 17+ messages in thread
From: Bjoern A. Zeeb @ 2001-08-14 20:59 UTC (permalink / raw)
To: Chris Crowther; +Cc: linux-kernel, linux-net
On Tue, 14 Aug 2001, Chris Crowther wrote:
[snipped out everything]
Hi,
just give give my three cents to this:
- should soemthing like this really go into kernel ?
(as others mentioned too)
- there are major gaps in there that should be filled first
CDP Version 2 is also available but not (yet) well documented
enum {
CDP_DEVICE_ID = 0x0001,
CDP_ADDRESS, /* '0002 */
#define CDP_ADDR_PROTO_TYPE_NLPID 1
#define CDP_ADDR_PROTO_ISOCLNS 0x81
#define CDP_ADDR_PROTO_IP 0xcc
#define CDP_ADDR_PROTO_TYPE_8022 2
/* .. [snip] .. */
CDP_PORT_ID, /* '0003 */
CDP_CAPABILITIES, /* '0004 */
CDP_VERSION, /* '0005 */
CDP_PLATFORM, /* '0006 */
CDP_IP_PREFIX, /* '0007 */
CDP_PROTOCOL_HELLO, /* '0008 */
CDP_VTP_MGMT_DOM, /* '0009 */
CDP_NATIVE_VLAN_ID, /* '000a */
CDP_DUPLEX_MODE /* '000b */
} cdp_data_type_e;
is all that I ever found out about this.
see also tcpdump or ethereal for userspace decoders to fill some gaps
(decoding...)
- code looks fine but after skimming over I think it's exploitable to
malformed cdp packets easily generated with a short proggi (already
exists)
The idea there is giving p.ex. a longer length for some type than
whole packets is actually long. This will lead to accessing (and
later printing if we were still alive without an oops) illegal
memory addresses in cdp_update_neighbor()
--
Bjoern A. Zeeb bzeeb at Zabbadoz dot NeT
56 69 73 69 74 http://www.zabbadoz.net/
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] CDP handler for linux
2001-08-14 18:47 [PATCH] CDP handler for linux Chris Crowther
2001-08-14 19:30 ` Christoph Hellwig
@ 2001-08-14 20:17 ` Alan Cox
2001-08-14 20:54 ` Chris Crowther
2001-08-14 20:19 ` Dan Hollis
2 siblings, 1 reply; 17+ messages in thread
From: Alan Cox @ 2001-08-14 20:17 UTC (permalink / raw)
To: Chris Crowther; +Cc: linux-kernel
> I've been working on an addition to the kernel over the past
> couple of days that enables the kernel to interpret CDP (Cisco Discovery
> Protocol) packets which can be transmited by various pieces of Cisco kit.
It looks well written. I do have only one question, other than "because
I wanted to learn how to do it this way", is there a reason for putting
this into kernel space not a daemon ?
Alan
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] CDP handler for linux
2001-08-14 20:17 ` Alan Cox
@ 2001-08-14 20:54 ` Chris Crowther
2001-08-14 20:59 ` Alan Cox
` (2 more replies)
0 siblings, 3 replies; 17+ messages in thread
From: Chris Crowther @ 2001-08-14 20:54 UTC (permalink / raw)
To: Alan Cox; +Cc: linux-kernel
On Tue, 14 Aug 2001, Alan Cox wrote:
> It looks well written. I do have only one question, other than "because
> I wanted to learn how to do it this way", is there a reason for putting
> this into kernel space not a daemon ?
Hmm, looking at CDP there isn't really any reason to put it in
userspace either, it doesn't need to be configured, it doesn't pass
anything the way of the user, except by way of the output of (currently)
/proc/net/cdp_neighbors, and it doesn't need the user to interact with it
either - it just sits there, collecting and sending information. The only
thing you would really need in userspace, would be tools to read
information from the cdp handler if you wanted to do more than just look
at the neighbor summary. I can't see any real advantages of running it as
a daemon as opposed to a kernel component.
This said, if the consesus is that it belongs in userspace, I
shall set about porting the code over to a dameon and possibly maintaing
the kernel patch as a secondary "hobby project".
--
Chris "_Shad0w_" Crowther
chrisc@shad0w.org.uk
http://www.shad0w.org.uk/
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: [PATCH] CDP handler for linux
2001-08-14 20:54 ` Chris Crowther
@ 2001-08-14 20:59 ` Alan Cox
2001-08-15 5:48 ` David Luyer
2001-08-14 21:07 ` Bjoern A. Zeeb
2001-08-14 21:32 ` Dan Hollis
2 siblings, 1 reply; 17+ messages in thread
From: Alan Cox @ 2001-08-14 20:59 UTC (permalink / raw)
To: Chris Crowther; +Cc: Alan Cox, linux-kernel
> This said, if the consesus is that it belongs in userspace, I
> shall set about porting the code over to a dameon and possibly maintaing
> the kernel patch as a secondary "hobby project".
I really think user space is the right place for it. That keeps it in
pageable memory and likely to dump a core not an entire box on errors.
The hobby one is a nice little example of how to do the kernel net bits tho
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] CDP handler for linux
2001-08-14 20:59 ` Alan Cox
@ 2001-08-15 5:48 ` David Luyer
0 siblings, 0 replies; 17+ messages in thread
From: David Luyer @ 2001-08-15 5:48 UTC (permalink / raw)
To: Alan Cox; +Cc: Chris Crowther, linux-kernel
On 14 Aug 2001 21:59:02 +0100, Alan Cox wrote:
> > This said, if the consesus is that it belongs in userspace, I
> > shall set about porting the code over to a dameon and possibly maintaing
> > the kernel patch as a secondary "hobby project".
>
> I really think user space is the right place for it. That keeps it in
> pageable memory and likely to dump a core not an entire box on errors.
You're right (of course), but to a small extent it may depend how
critical CDP is to your routing. Both CDP and HSRP are things which
can be used by Ciscos to choose backup paths, but neither protocol is
really "urgent, real-time priority required" in the timing so that's
really the main reason to stay out of the kernel.
If you're using "set ip next-hop verify-availability" in a Cisco router
then you don't want CDP to fail unless the machine is unavailable to
route. But then I guess we don't have OSPF or BGP in the kernel, so CDP
doesn't belong there either.
One thing which would be nice though from a performance perspective is
a kernel NetFlow collector. I'm currently using a netflow collecter
which uses <asm/unistd.h> and doesn't link against libc or crt0.o,
accumulates all it's write()s as 128k chunks, etc, and that's damn fast,
but the kernel should be able to be even faster (avoid all those
context switches on each packet received).
--
David Luyer Phone: +61 3 9674 7525
Engineering Projects Manager P A C I F I C Fax: +61 3 9699 8693
Pacific Internet (Australia) I N T E R N E T Mobile: +61 4 1111 2983
http://www.pacific.net.au/ NASDAQ: PCNTF
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] CDP handler for linux
2001-08-14 20:54 ` Chris Crowther
2001-08-14 20:59 ` Alan Cox
@ 2001-08-14 21:07 ` Bjoern A. Zeeb
2001-08-14 21:32 ` Dan Hollis
2 siblings, 0 replies; 17+ messages in thread
From: Bjoern A. Zeeb @ 2001-08-14 21:07 UTC (permalink / raw)
To: Chris Crowther; +Cc: Alan Cox, linux-kernel
On Tue, 14 Aug 2001, Chris Crowther wrote:
> Hmm, looking at CDP there isn't really any reason to put it in
> userspace either, it doesn't need to be configured, it doesn't pass
That's wrong:
cisco-switch(config)#cdp ?
advertise-v2 CDP sends version-2 advertisements
holdtime Specify the holdtime (in sec) to be sent in packets
timer Specify the rate at which CDP packets are sent (in sec)
run
it can be enabled/disables on a per interface base.
There are also some different output possibilitites on cisco:
sh cdp
and:
sh cdp run
sh cdp timer
sh cdp traffic
and (no the interesting parts within here):
sh cdp neigh <detail>
sh cdp entry <*> <WORD>
sh cdp interface ..
> at the neighbor summary. I can't see any real advantages of running it as
> a daemon as opposed to a kernel component.
portability ? linux is not the only OS in world. Think about running
on *BSD, Solaris, AIX, HPUX, ...
--
Bjoern A. Zeeb bzeeb at Zabbadoz dot NeT
56 69 73 69 74 http://www.zabbadoz.net/
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] CDP handler for linux
2001-08-14 20:54 ` Chris Crowther
2001-08-14 20:59 ` Alan Cox
2001-08-14 21:07 ` Bjoern A. Zeeb
@ 2001-08-14 21:32 ` Dan Hollis
2001-08-14 22:46 ` David S. Miller
2 siblings, 1 reply; 17+ messages in thread
From: Dan Hollis @ 2001-08-14 21:32 UTC (permalink / raw)
To: Chris Crowther; +Cc: Alan Cox, linux-kernel
On Tue, 14 Aug 2001, Chris Crowther wrote:
> either - it just sits there, collecting and sending information. The only
> thing you would really need in userspace, would be tools to read
> information from the cdp handler if you wanted to do more than just look
> at the neighbor summary. I can't see any real advantages of running it as
> a daemon as opposed to a kernel component.
Except that as userspace daemon if cdpd goes splat the kernel generally
doesnt go splat either.
-Dan
--
[-] Omae no subete no kichi wa ore no mono da. [-]
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] CDP handler for linux
2001-08-14 21:32 ` Dan Hollis
@ 2001-08-14 22:46 ` David S. Miller
2001-08-15 9:13 ` Chris Crowther
0 siblings, 1 reply; 17+ messages in thread
From: David S. Miller @ 2001-08-14 22:46 UTC (permalink / raw)
To: goemon; +Cc: chrisc, alan, linux-kernel
From: Dan Hollis <goemon@anime.net>
Date: Tue, 14 Aug 2001 14:32:40 -0700 (PDT)
On Tue, 14 Aug 2001, Chris Crowther wrote:
> either - it just sits there, collecting and sending information. The only
> thing you would really need in userspace, would be tools to read
> information from the cdp handler if you wanted to do more than just look
> at the neighbor summary. I can't see any real advantages of running it as
> a daemon as opposed to a kernel component.
Except that as userspace daemon if cdpd goes splat the kernel generally
doesnt go splat either.
I really think this should be in userspace too.
Later,
David S. Miller
davem@redhat.com
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] CDP handler for linux
2001-08-14 18:47 [PATCH] CDP handler for linux Chris Crowther
2001-08-14 19:30 ` Christoph Hellwig
2001-08-14 20:17 ` Alan Cox
@ 2001-08-14 20:19 ` Dan Hollis
2 siblings, 0 replies; 17+ messages in thread
From: Dan Hollis @ 2001-08-14 20:19 UTC (permalink / raw)
To: Chris Crowther; +Cc: linux-kernel
On Tue, 14 Aug 2001, Chris Crowther wrote:
> 1) am I nuts
> 2) is anyone else interested in this
I cant see real justification to put cdp handler in kernelspace.
IMHO this belongs in userspace eg cdpd
-Dan
--
[-] Omae no subete no kichi wa ore no mono da. [-]
^ permalink raw reply [flat|nested] 17+ messages in thread
[parent not found: <Pine.LNX.4.33.0108141934130.3283-100000@monolith.shad0w.or g.uk>]
* Re: [PATCH] CDP handler for linux
[not found] <Pine.LNX.4.33.0108141934130.3283-100000@monolith.shad0w.or g.uk>
@ 2001-08-14 23:01 ` Lincoln Dale
2001-08-15 16:14 ` Chris Crowther
0 siblings, 1 reply; 17+ messages in thread
From: Lincoln Dale @ 2001-08-14 23:01 UTC (permalink / raw)
To: Chris Crowther; +Cc: linux-kernel
g'day,
At 07:47 PM 14/08/2001 +0100, Chris Crowther wrote:
> I've been working on an addition to the kernel over the past
>couple of days that enables the kernel to interpret CDP (Cisco Discovery
>Protocol) packets which can be transmited by various pieces of Cisco kit.
..
for various devices/developments inside Cisco, we've implemented CDP in
user-space.
basically all that is required to do that is to hook into the 802.2/SNAP
stuff that is already in the kernel (net/802) - in my case, i just used
netlink so as to allow user-space to receive the whole packet and avoid any
processing in the kernel.
you may want to consider the same. at least for cisco products, there are
LOTS of permutations of enabling/disabling CDP on a per-interface-basis and
what-ip-addresses-to-advertise-in-CDP and
what-functionality-to-advertise-in-CDP.
most of those kinds of policies are probably outside the scope of what
logic you would expect in the kernel.
my $0.02 worth,
cheers,
lincoln.
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: [PATCH] CDP handler for linux
2001-08-14 23:01 ` Lincoln Dale
@ 2001-08-15 16:14 ` Chris Crowther
0 siblings, 0 replies; 17+ messages in thread
From: Chris Crowther @ 2001-08-15 16:14 UTC (permalink / raw)
To: Lincoln Dale; +Cc: linux-kernel
On Tue, 14 Aug 2001, Lincoln Dale wrote:
> netlink so as to allow user-space to receive the whole packet and avoid any
> processing in the kernel.
Hmm, there's an idea.
> you may want to consider the same. at least for cisco products, there are
[...]
> most of those kinds of policies are probably outside the scope of what
> logic you would expect in the kernel.
I'm looking at doing something like you're doing, just need to
figure out which netlink family to use - ethertap seems overkill, is
adding a new family for CDP even more overkill?
> my $0.02 worth,
Oooh, £0.20 at least :)
> cheers,
Thanks for the ideas. Don't 'spose you know anything about CDP v2
that someone mentioned? :)
--
Chris "_Shad0w_" Crowther
chrisc@shad0w.org.uk
http://www.shad0w.org.uk/
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2001-08-15 16:12 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-08-14 18:47 [PATCH] CDP handler for linux Chris Crowther
2001-08-14 19:30 ` Christoph Hellwig
2001-08-14 19:56 ` Chris Crowther
2001-08-14 20:59 ` Bjoern A. Zeeb
2001-08-14 20:17 ` Alan Cox
2001-08-14 20:54 ` Chris Crowther
2001-08-14 20:59 ` Alan Cox
2001-08-15 5:48 ` David Luyer
2001-08-14 21:07 ` Bjoern A. Zeeb
2001-08-14 21:32 ` Dan Hollis
2001-08-14 22:46 ` David S. Miller
2001-08-15 9:13 ` Chris Crowther
2001-08-15 9:23 ` David S. Miller
2001-08-15 9:32 ` Chris Crowther
2001-08-14 20:19 ` Dan Hollis
[not found] <Pine.LNX.4.33.0108141934130.3283-100000@monolith.shad0w.or g.uk>
2001-08-14 23:01 ` Lincoln Dale
2001-08-15 16:14 ` Chris Crowther
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox