diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/Config.in | 7 | ||||
-rw-r--r-- | drivers/net/Makefile | 8 | ||||
-rw-r--r-- | drivers/net/Space.c | 11 | ||||
-rw-r--r-- | drivers/net/ipddp.c | 309 | ||||
-rw-r--r-- | drivers/net/ipddp.h | 27 | ||||
-rw-r--r-- | drivers/net/x25_asy.c | 5 |
6 files changed, 364 insertions, 3 deletions
diff --git a/drivers/net/Config.in b/drivers/net/Config.in index 2e721ba8d..b90affadc 100644 --- a/drivers/net/Config.in +++ b/drivers/net/Config.in @@ -126,7 +126,7 @@ if [ "$CONFIG_DLCI" = "y" -o "$CONFIG_DLCI" = "m" ]; then fi # -# LocalTalk +# AppleTalk # if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then if [ "$CONFIG_ATALK" != "n" ]; then @@ -136,6 +136,7 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then bool 'Dayna firmware support' CONFIG_COPS_DAYNA bool 'Tangent firmware support' CONFIG_COPS_TANGENT fi + dep_tristate 'IP-over-DDP driver support' CONFIG_IPDDP $CONFIG_ATALK fi fi @@ -202,10 +203,10 @@ fi # # WAN drivers support # -if [ "$CONFIG_WAN_ROUTER" = "y" ]; then +if [ "$CONFIG_WAN_ROUTER" != "n" ]; then bool 'WAN drivers' CONFIG_WAN_DRIVERS if [ "$CONFIG_WAN_DRIVERS" = "y" ]; then - bool 'Sangoma WANPIPE(tm) multiprotocol cards' CONFIG_VENDOR_SANGOMA + dep_tristate 'Sangoma WANPIPE(tm) multiprotocol cards' CONFIG_VENDOR_SANGOMA $CONFIG_WAN_DRIVERS if [ "$CONFIG_VENDOR_SANGOMA" = "y" ]; then int ' Maximum number of cards' CONFIG_WANPIPE_CARDS 1 bool ' WANPIPE X.25 support' CONFIG_WANPIPE_X25 diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 920c17dc2..a79d7b4ea 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -727,6 +727,14 @@ else endif endif +ifeq ($(CONFIG_IPDDP),y) +L_OBJS += ipddp.o +else + ifeq ($(CONFIG_IPDDP),m) + M_OBJS += ipddp.o + endif +endif + ifeq ($(CONFIG_BAYCOM),y) L_OBJS += baycom.o CONFIG_HDLCDRV_BUILTIN = y diff --git a/drivers/net/Space.c b/drivers/net/Space.c index 4fdfbb6b1..b568c12bf 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -326,6 +326,17 @@ static struct device atp_dev = { # define NEXT_DEV (&dev_cops) #endif /* COPS */ +#if defined(CONFIG_IPDDP) + extern int ipddp_init(struct device *dev); + static struct device dev_ipddp = { + "ipddp0\0 ", + 0, 0, 0, 0, + 0x0, 0, + 0, 0, 0, NEXT_DEV, ipddp_init }; +# undef NEXT_DEV +# define NEXT_DEV (&dev_ipddp) +#endif /* CONFIG_IPDDP */ + /* The first device defaults to I/O base '0', which means autoprobe. */ #ifndef ETH0_ADDR # define ETH0_ADDR 0 diff --git a/drivers/net/ipddp.c b/drivers/net/ipddp.c new file mode 100644 index 000000000..8106ffc2d --- /dev/null +++ b/drivers/net/ipddp.c @@ -0,0 +1,309 @@ +/* + * ipddp.c: IP-over-DDP driver for Linux + * + * Authors: + * - Original code by: Bradford W. Johnson <johns393@maroon.tc.umn.edu> + * - Moved to driver by: Jay Schulist <Jay.Schulist@spacs.k12.wi.us> + * + * Derived from: + * - Almost all code already existed in net/appletalk/ddp.c I just + * moved/reorginized it into a driver file. Original IP-over-DDP code + * was done by Bradford W. Johnson <johns393@maroon.tc.umn.edu> + * - skeleton.c: A network driver outline for linux. + * Written 1993-94 by Donald Becker. + * - dummy.c: A dummy net driver. By Nick Holloway. + * + * Copyright 1993 United States Government as represented by the + * Director, National Security Agency. + * + * This software may be used and distributed according to the terms + * of the GNU Public License, incorporated herein by reference. + */ + +static const char *version = +"ipddp.c:v0.01 8/28/97 Bradford W. Johnson <johns393@maroon.tc.umn.edu>\n"; + +#include <linux/config.h> +#ifdef MODULE +#include <linux/module.h> +#include <linux/version.h> +#endif + +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/fcntl.h> +#include <linux/interrupt.h> +#include <linux/ptrace.h> +#include <linux/ioport.h> +#include <linux/in.h> +#include <linux/malloc.h> +#include <linux/string.h> +#include <asm/uaccess.h> +#include <asm/system.h> +#include <asm/bitops.h> +#include <asm/io.h> +#include <asm/dma.h> +#include <linux/errno.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/skbuff.h> +#include <linux/if_arp.h> +#include <linux/atalk.h> +#include <linux/ip.h> +#include <net/route.h> + +#include "ipddp.h" /* Our stuff */ + +/* + * The name of the card. Is used for messages and in the requests for + * io regions, irqs and dma channels + */ + +static const char *cardname = "ipddp"; + +/* Use 0 for production, 1 for verification, 2 for debug, 3 for verbose debug */ +#ifndef IPDDP_DEBUG +#define IPDDP_DEBUG 1 +#endif +static unsigned int ipddp_debug = IPDDP_DEBUG; + +/* Index to functions, as function prototypes. */ +static int ipddp_xmit(struct sk_buff *skb, struct device *dev); +static struct net_device_stats *ipddp_get_stats(struct device *dev); +static int ipddp_rebuild_header(struct sk_buff *skb); +static int ipddp_header(struct sk_buff *skb, struct device *dev, + unsigned short type, void *daddr, void *saddr, unsigned len); +static int ipddp_ioctl(struct device *dev, struct ifreq *ifr, int cmd); + + +static int ipddp_open(struct device *dev) +{ +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif + + return 0; +} + +static int ipddp_close(struct device *dev) +{ +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif + + return 0; +} + +int ipddp_init(struct device *dev) +{ + static unsigned version_printed = 0; + + if (ipddp_debug && version_printed++ == 0) + printk("%s", version); + + /* Initalize the device structure. */ + dev->hard_start_xmit = ipddp_xmit; + + dev->priv = kmalloc(sizeof(struct enet_statistics), GFP_KERNEL); + if(!dev->priv) + return -ENOMEM; + memset(dev->priv,0,sizeof(struct enet_statistics)); + + dev->open = ipddp_open; + dev->stop = ipddp_close; + dev->get_stats = ipddp_get_stats; + dev->do_ioctl = ipddp_ioctl; + dev->hard_header = ipddp_header; /* see ip_output.c */ + dev->rebuild_header = ipddp_rebuild_header; + + dev->type = ARPHRD_IPDDP; /* IP over DDP tunnel */ + dev->family = AF_INET; + dev->mtu = 585; + dev->flags |= IFF_NOARP; + + /* + * The worst case header we will need is currently a + * ethernet header (14 bytes) and a ddp header (sizeof ddpehdr+1) + * We send over SNAP so that takes another 8 bytes. + */ + dev->hard_header_len = 14+8+sizeof(struct ddpehdr)+1; + + /* Fill in the device structure with ethernet-generic values. */ + ether_setup(dev); + + return 0; +} + +/* + * Transmit LLAP/ELAP frame using aarp_send_ddp. + */ +static int ipddp_xmit(struct sk_buff *skb, struct device *dev) +{ + /* Retrieve the saved address hint */ + struct at_addr *a=(struct at_addr *)skb->data; + skb_pull(skb,4); + + ((struct net_device_stats *) dev->priv)->tx_packets++; + ((struct net_device_stats *) dev->priv)->tx_bytes+=skb->len; + + if(ipddp_debug>1) + printk("ipddp_xmit: Headroom %d\n",skb_headroom(skb)); + + if(aarp_send_ddp(skb->dev,skb,a,NULL) < 0) + dev_kfree_skb(skb,FREE_WRITE); + + return 0; +} + +/* + * Get the current statistics. This may be called with the card open or closed. + */ +static struct net_device_stats *ipddp_get_stats(struct device *dev) +{ + return (struct net_device_stats *)dev->priv; +} + +/* + * Now the packet really wants to go out. + */ +static int ipddp_rebuild_header(struct sk_buff *skb) +{ + u32 paddr = ((struct rtable*)skb->dst)->rt_gateway; + struct ddpehdr *ddp; + struct at_addr at; + struct ipddp_route *rt; + struct at_addr *our_addr; + + /* + * On entry skb->data points to the ddpehdr we reserved earlier. + * skb->h.raw will be the higher level header. + */ + + /* + * We created this earlier. + */ + + ddp = (struct ddpehdr *) (skb->data+4); + + /* find appropriate route */ + + for(rt=ipddp_route_head;rt;rt=rt->next) + { + if(rt->ip == paddr) + break; + } + + if(!rt) { + printk("ipddp unreachable dst %08lx\n",ntohl(paddr)); + return -ENETUNREACH; + } + + our_addr = atalk_find_dev_addr(rt->dev); + + /* fill in ddpehdr */ + ddp->deh_len = skb->len; + ddp->deh_hops = 1; + ddp->deh_pad = 0; + ddp->deh_sum = 0; + ddp->deh_dnet = rt->at.s_net; /* FIXME more hops?? */ + ddp->deh_snet = our_addr->s_net; + ddp->deh_dnode = rt->at.s_node; + ddp->deh_snode = our_addr->s_node; + ddp->deh_dport = 72; + ddp->deh_sport = 72; + + *((__u8 *)(ddp+1)) = 22; /* ddp type = IP */ + + /* fix up length field */ + *((__u16 *)ddp)=ntohs(*((__u16 *)ddp)); + + /* set skb->dev to appropriate device */ + skb->dev = rt->dev; + + /* skb->raddr = (unsigned long) at */ + at = rt->at; + /* Hide it at the start of the buffer */ + memcpy(skb->data,(void *)&at,sizeof(at)); + skb->arp = 1; /* so the actual device doesn't try to arp it... */ + skb->protocol = htons(ETH_P_ATALK); /* Protocol has changed */ + + return 0; +} + +static int ipddp_header(struct sk_buff *skb, struct device *dev, + unsigned short type, void *daddr, void *saddr, unsigned len) +{ + if(ipddp_debug>=2) + printk("%s: ipddp_header\n", cardname); + + /* Push down the header space and the type byte */ + skb_push(skb, sizeof(struct ddpehdr)+1+4); + + return 0; +} + +static int ipddp_ioctl(struct device *dev, struct ifreq *ifr, int cmd) +{ + struct ipddp_route *urt = (struct ipddp_route *)ifr->ifr_data; + + if(!suser()) + return -EPERM; + + /* for now we only have one route at a time */ + + switch(cmd) + { + case SIOCADDIPDDPRT: + if(copy_from_user(&ipddp_route_test,urt,sizeof(struct ipddp_route))) + return -EFAULT; + ipddp_route_test.dev = atrtr_get_dev(&ipddp_route_test.at); + if (dev==NULL) + return -ENETUNREACH; + ipddp_route_test.next = NULL; + printk("%s: Added route through %s\n", + ipddp_route_test.dev->name, cardname); + ipddp_route_head = &ipddp_route_test; + return 0; + + case SIOCFINDIPDDPRT: + if(copy_to_user(urt,&ipddp_route_test,sizeof(struct ipddp_route))) + return -EFAULT; + return 0; + + case SIOCDELIPDDPRT: + ipddp_route_test.dev = NULL; + ipddp_route_head = NULL; + return 0; + + default: + return -EINVAL; + } +} + +#ifdef MODULE /* Module specific functions for ipddp.c */ + +static struct device dev_ipddp= +{ + "ipddp0\0 ", + 0, 0, 0, 0, + 0x0, 0, + 0, 0, 0, NULL, ipddp_init +}; + +int init_module(void) +{ + if (register_netdev(&dev_ipddp) != 0) + return -EIO; + + return 0; +} + +void cleanup_module(void) +{ + unregister_netdev(&dev_ipddp); + kfree(dev_ipddp.priv); + dev_ipddp.priv = NULL; +} + +#endif /* MODULE */ diff --git a/drivers/net/ipddp.h b/drivers/net/ipddp.h new file mode 100644 index 000000000..6093adfec --- /dev/null +++ b/drivers/net/ipddp.h @@ -0,0 +1,27 @@ +/* + * ipddp.h: Header for IP-over-DDP driver for Linux. + */ + +#ifndef __LINUX_IPDDP_H +#define __LINUX_IPDDP_H + +#ifdef __KERNEL__ + +#define SIOCADDIPDDPRT SIOCDEVPRIVATE +#define SIOCDELIPDDPRT SIOCDEVPRIVATE+1 +#define SIOCFINDIPDDPRT SIOCDEVPRIVATE+2 + +struct ipddp_route +{ + struct device *dev; /* Carrier device */ + __u32 ip; /* IP address */ + struct at_addr at; /* Gateway appletalk address */ + int flags; + struct ipddp_route *next; +}; + +static struct ipddp_route *ipddp_route_head; +static struct ipddp_route ipddp_route_test; + +#endif /* __KERNEL__ */ +#endif /* __LINUX_IPDDP_H */ diff --git a/drivers/net/x25_asy.c b/drivers/net/x25_asy.c index f6f953201..ce4aeb609 100644 --- a/drivers/net/x25_asy.c +++ b/drivers/net/x25_asy.c @@ -4,6 +4,11 @@ * o tbusy handling * o allow users to set the parameters * o sync/async switching ? + * + * Note: This does _not_ implement CCITT X.25 asynchronous framing + * recommendations. Its primarily for testing purposes. If you wanted + * to do CCITT then in theory all you need is to nick the HDLC async + * checksum routines from ppp.c */ #include <linux/config.h> |