⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mkiss.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *	MKISS Driver * *	This module: *		This module is free software; you can redistribute it and/or *		modify it under the terms of the GNU General Public License *		as published by the Free Software Foundation; either version *		2 of the License, or (at your option) any later version. * * 		This module implements the AX.25 protocol for kernel-based *		devices like TTYs. It interfaces between a raw TTY, and the *		kernel's AX.25 protocol layers, just like slip.c. *		AX.25 needs to be separated from slip.c while slip.c is no *		longer a static kernel device since it is a module. *		This method clears the way to implement other kiss protocols *		like mkiss smack g8bpq ..... so far only mkiss is implemented. * * Hans Alblas <hans@esrac.ele.tue.nl> * *	History *	Jonathan (G4KLX)	Fixed to match Linux networking changes - 2.1.15. *	Matthias (DG2FEF)       Added support for FlexNet CRC (on special request) *                              Fixed bug in ax25_close(): dev_lock_wait() was *                              called twice, causing a deadlock. */#include <linux/config.h>#include <linux/module.h>#include <asm/system.h>#include <asm/segment.h>#include <asm/bitops.h>#include <asm/uaccess.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/interrupt.h>#include <linux/in.h>#include <linux/inet.h>#include <linux/tty.h>#include <linux/errno.h>#include <linux/netdevice.h>#include <linux/major.h>#include <linux/init.h>#include <linux/rtnetlink.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <linux/if_arp.h>#include <net/ax25.h>#include "mkiss.h"#ifdef CONFIG_INET#include <linux/ip.h>#include <linux/tcp.h>#endifstatic char banner[] __initdata = KERN_INFO "mkiss: AX.25 Multikiss, Hans Albas PE1AYX\n";#define NR_MKISS 4#define MKISS_SERIAL_TYPE_NORMAL 1struct mkiss_channel {	int magic;		/* magic word */	int init;		/* channel exists? */	struct tty_struct *tty; /* link to tty control structure */};typedef struct ax25_ctrl {	struct ax_disp ctrl;	/* 				*/	struct net_device  dev;	/* the device			*/} ax25_ctrl_t;static ax25_ctrl_t **ax25_ctrls;int ax25_maxdev = AX25_MAXDEV;		/* Can be overridden with insmod! */static struct tty_ldisc	ax_ldisc;static int ax25_init(struct net_device *);static int kiss_esc(unsigned char *, unsigned char *, int);static int kiss_esc_crc(unsigned char *, unsigned char *, unsigned short, int);static void kiss_unesc(struct ax_disp *, unsigned char);/*---------------------------------------------------------------------------*/static const unsigned short Crc_flex_table[] = {  0x0f87, 0x1e0e, 0x2c95, 0x3d1c, 0x49a3, 0x582a, 0x6ab1, 0x7b38,  0x83cf, 0x9246, 0xa0dd, 0xb154, 0xc5eb, 0xd462, 0xe6f9, 0xf770,  0x1f06, 0x0e8f, 0x3c14, 0x2d9d, 0x5922, 0x48ab, 0x7a30, 0x6bb9,  0x934e, 0x82c7, 0xb05c, 0xa1d5, 0xd56a, 0xc4e3, 0xf678, 0xe7f1,  0x2e85, 0x3f0c, 0x0d97, 0x1c1e, 0x68a1, 0x7928, 0x4bb3, 0x5a3a,  0xa2cd, 0xb344, 0x81df, 0x9056, 0xe4e9, 0xf560, 0xc7fb, 0xd672,  0x3e04, 0x2f8d, 0x1d16, 0x0c9f, 0x7820, 0x69a9, 0x5b32, 0x4abb,  0xb24c, 0xa3c5, 0x915e, 0x80d7, 0xf468, 0xe5e1, 0xd77a, 0xc6f3,  0x4d83, 0x5c0a, 0x6e91, 0x7f18, 0x0ba7, 0x1a2e, 0x28b5, 0x393c,  0xc1cb, 0xd042, 0xe2d9, 0xf350, 0x87ef, 0x9666, 0xa4fd, 0xb574,  0x5d02, 0x4c8b, 0x7e10, 0x6f99, 0x1b26, 0x0aaf, 0x3834, 0x29bd,  0xd14a, 0xc0c3, 0xf258, 0xe3d1, 0x976e, 0x86e7, 0xb47c, 0xa5f5,  0x6c81, 0x7d08, 0x4f93, 0x5e1a, 0x2aa5, 0x3b2c, 0x09b7, 0x183e,  0xe0c9, 0xf140, 0xc3db, 0xd252, 0xa6ed, 0xb764, 0x85ff, 0x9476,  0x7c00, 0x6d89, 0x5f12, 0x4e9b, 0x3a24, 0x2bad, 0x1936, 0x08bf,  0xf048, 0xe1c1, 0xd35a, 0xc2d3, 0xb66c, 0xa7e5, 0x957e, 0x84f7,  0x8b8f, 0x9a06, 0xa89d, 0xb914, 0xcdab, 0xdc22, 0xeeb9, 0xff30,  0x07c7, 0x164e, 0x24d5, 0x355c, 0x41e3, 0x506a, 0x62f1, 0x7378,  0x9b0e, 0x8a87, 0xb81c, 0xa995, 0xdd2a, 0xcca3, 0xfe38, 0xefb1,  0x1746, 0x06cf, 0x3454, 0x25dd, 0x5162, 0x40eb, 0x7270, 0x63f9,  0xaa8d, 0xbb04, 0x899f, 0x9816, 0xeca9, 0xfd20, 0xcfbb, 0xde32,  0x26c5, 0x374c, 0x05d7, 0x145e, 0x60e1, 0x7168, 0x43f3, 0x527a,  0xba0c, 0xab85, 0x991e, 0x8897, 0xfc28, 0xeda1, 0xdf3a, 0xceb3,  0x3644, 0x27cd, 0x1556, 0x04df, 0x7060, 0x61e9, 0x5372, 0x42fb,  0xc98b, 0xd802, 0xea99, 0xfb10, 0x8faf, 0x9e26, 0xacbd, 0xbd34,  0x45c3, 0x544a, 0x66d1, 0x7758, 0x03e7, 0x126e, 0x20f5, 0x317c,  0xd90a, 0xc883, 0xfa18, 0xeb91, 0x9f2e, 0x8ea7, 0xbc3c, 0xadb5,  0x5542, 0x44cb, 0x7650, 0x67d9, 0x1366, 0x02ef, 0x3074, 0x21fd,  0xe889, 0xf900, 0xcb9b, 0xda12, 0xaead, 0xbf24, 0x8dbf, 0x9c36,  0x64c1, 0x7548, 0x47d3, 0x565a, 0x22e5, 0x336c, 0x01f7, 0x107e,  0xf808, 0xe981, 0xdb1a, 0xca93, 0xbe2c, 0xafa5, 0x9d3e, 0x8cb7,  0x7440, 0x65c9, 0x5752, 0x46db, 0x3264, 0x23ed, 0x1176, 0x00ff};/*---------------------------------------------------------------------------*/static unsigned short calc_crc_flex(unsigned char *cp, int size){    unsigned short crc = 0xffff;        while (size--)	crc = (crc << 8) ^ Crc_flex_table[((crc >> 8) ^ *cp++) & 0xff];    return crc;}/*---------------------------------------------------------------------------*/static int check_crc_flex(unsigned char *cp, int size){  unsigned short crc = 0xffff;  if (size < 3)      return -1;  while (size--)      crc = (crc << 8) ^ Crc_flex_table[((crc >> 8) ^ *cp++) & 0xff];  if ((crc & 0xffff) != 0x7070)       return -1;  return 0;}/*---------------------------------------------------------------------------*//* Find a free channel, and link in this `tty' line. */static inline struct ax_disp *ax_alloc(void){	ax25_ctrl_t *axp=NULL;	int i;	for (i = 0; i < ax25_maxdev; i++) {		axp = ax25_ctrls[i];		/* Not allocated ? */		if (axp == NULL)			break;		/* Not in use ? */		if (!test_and_set_bit(AXF_INUSE, &axp->ctrl.flags))			break;	}	/* Sorry, too many, all slots in use */	if (i >= ax25_maxdev)		return NULL;	/* If no channels are available, allocate one */	if (axp == NULL && (ax25_ctrls[i] = kmalloc(sizeof(ax25_ctrl_t), GFP_KERNEL)) != NULL) {		axp = ax25_ctrls[i];		memset(axp, 0, sizeof(ax25_ctrl_t));		/* Initialize channel control data */		set_bit(AXF_INUSE, &axp->ctrl.flags);		sprintf(axp->dev.name, "ax%d", i++);		axp->ctrl.tty      = NULL;		axp->dev.base_addr = i;		axp->dev.priv      = (void *)&axp->ctrl;		axp->dev.next      = NULL;		axp->dev.init      = ax25_init;	}	if (axp != NULL) {		/*		 * register device so that it can be ifconfig'ed		 * ax25_init() will be called as a side-effect		 * SIDE-EFFECT WARNING: ax25_init() CLEARS axp->ctrl !		 */		if (register_netdev(&axp->dev) == 0) {			/* (Re-)Set the INUSE bit.   Very Important! */			set_bit(AXF_INUSE, &axp->ctrl.flags);			axp->ctrl.dev = &axp->dev;			axp->dev.priv = (void *) &axp->ctrl;			return &axp->ctrl;		} else {			clear_bit(AXF_INUSE,&axp->ctrl.flags);			printk(KERN_ERR "mkiss: ax_alloc() - register_netdev() failure.\n");		}	}	return NULL;}/* Free an AX25 channel. */static inline void ax_free(struct ax_disp *ax){	/* Free all AX25 frame buffers. */	if (ax->rbuff)		kfree(ax->rbuff);	ax->rbuff = NULL;	if (ax->xbuff)		kfree(ax->xbuff);	ax->xbuff = NULL;	if (!test_and_clear_bit(AXF_INUSE, &ax->flags))		printk(KERN_ERR "mkiss: %s: ax_free for already free unit.\n", ax->dev->name);}static void ax_changedmtu(struct ax_disp *ax){	struct net_device *dev = ax->dev;	unsigned char *xbuff, *rbuff, *oxbuff, *orbuff;	int len;	unsigned long flags;	len = dev->mtu * 2;	/*	 * allow for arrival of larger UDP packets, even if we say not to	 * also fixes a bug in which SunOS sends 512-byte packets even with	 * an MSS of 128	 */	if (len < 576 * 2)		len = 576 * 2;	xbuff = kmalloc(len + 4, GFP_ATOMIC);	rbuff = kmalloc(len + 4, GFP_ATOMIC);	if (xbuff == NULL || rbuff == NULL)  {		printk(KERN_ERR "mkiss: %s: unable to grow ax25 buffers, MTU change cancelled.\n",		       ax->dev->name);		dev->mtu = ax->mtu;		if (xbuff != NULL)			kfree(xbuff);		if (rbuff != NULL)			kfree(rbuff);		return;	}	save_flags(flags);	cli();	oxbuff    = ax->xbuff;	ax->xbuff = xbuff;	orbuff    = ax->rbuff;	ax->rbuff = rbuff;	if (ax->xleft) {		if (ax->xleft <= len) {			memcpy(ax->xbuff, ax->xhead, ax->xleft);		} else  {			ax->xleft = 0;			ax->tx_dropped++;		}	}	ax->xhead = ax->xbuff;	if (ax->rcount) {		if (ax->rcount <= len) {			memcpy(ax->rbuff, orbuff, ax->rcount);		} else  {			ax->rcount = 0;			ax->rx_over_errors++;			set_bit(AXF_ERROR, &ax->flags);		}	}	ax->mtu      = dev->mtu + 73;	ax->buffsize = len;	restore_flags(flags);	if (oxbuff != NULL)		kfree(oxbuff);	if (orbuff != NULL)		kfree(orbuff);}/* Set the "sending" flag.  This must be atomic. */static inline void ax_lock(struct ax_disp *ax){	netif_stop_queue(ax->dev);}/* Clear the "sending" flag.  This must be atomic. */static inline void ax_unlock(struct ax_disp *ax){	netif_start_queue(ax->dev);}/* Send one completely decapsulated AX.25 packet to the AX.25 layer. */static void ax_bump(struct ax_disp *ax){	struct ax_disp *tmp_ax;	struct sk_buff *skb;	struct mkiss_channel *mkiss;	int count;        tmp_ax = ax;	if (ax->rbuff[0] > 0x0f) {		if (ax->mkiss != NULL) {			mkiss= ax->mkiss->tty->driver_data;			if (mkiss->magic == MKISS_DRIVER_MAGIC)				tmp_ax = ax->mkiss;		} else if (ax->rbuff[0] & 0x20) {		        ax->crcmode = CRC_MODE_FLEX;			if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {			        ax->rx_errors++;				return;			}			ax->rcount -= 2;                        /* dl9sau bugfix: the trailling two bytes flexnet crc                         * will not be passed to the kernel. thus we have                         * to correct the kissparm signature, because it                         * indicates a crc but there's none			 */                        *ax->rbuff &= ~0x20;		} 	}	count = ax->rcount;	if ((skb = dev_alloc_skb(count)) == NULL) {		printk(KERN_ERR "mkiss: %s: memory squeeze, dropping packet.\n", ax->dev->name);		ax->rx_dropped++;		return;	}	skb->dev      = tmp_ax->dev;	memcpy(skb_put(skb,count), ax->rbuff, count);	skb->mac.raw  = skb->data;	skb->protocol = htons(ETH_P_AX25);	netif_rx(skb);	tmp_ax->rx_packets++;	tmp_ax->rx_bytes+=count;}/* Encapsulate one AX.25 packet and stuff into a TTY queue. */static void ax_encaps(struct ax_disp *ax, unsigned char *icp, int len){	unsigned char *p;	int actual, count;	struct mkiss_channel *mkiss = ax->tty->driver_data;	if (ax->mtu != ax->dev->mtu + 73)	/* Someone has been ifconfigging */		ax_changedmtu(ax);	if (len > ax->mtu) {		/* Sigh, shouldn't occur BUT ... */		len = ax->mtu;		printk(KERN_ERR "mkiss: %s: truncating oversized transmit packet!\n", ax->dev->name);		ax->tx_dropped++;		ax_unlock(ax);		return;	}	p = icp;	if (mkiss->magic  != MKISS_DRIVER_MAGIC) {	        switch (ax->crcmode) {		         unsigned short crc;		case CRC_MODE_FLEX:		         *p |= 0x20;		         crc = calc_crc_flex(p, len);			 count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);			 break;		default:		         count = kiss_esc(p, (unsigned char *)ax->xbuff, len);			 break;		}		ax->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);		actual = ax->tty->driver.write(ax->tty, 0, ax->xbuff, count);		ax->tx_packets++;		ax->tx_bytes+=actual;		ax->dev->trans_start = jiffies;		ax->xleft = count - actual;		ax->xhead = ax->xbuff + actual;	} else {		count = kiss_esc(p, (unsigned char *) ax->mkiss->xbuff, len);		ax->mkiss->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);		actual = ax->mkiss->tty->driver.write(ax->mkiss->tty, 0, ax->mkiss->xbuff, count);		ax->tx_packets++;		ax->tx_bytes+=actual;		ax->mkiss->dev->trans_start = jiffies;		ax->mkiss->xleft = count - actual;		ax->mkiss->xhead = ax->mkiss->xbuff + actual;	}}/* * Called by the driver when there's room for more data.  If we have * more packets to send, we send them here. */static void ax25_write_wakeup(struct tty_struct *tty){	int actual;	struct ax_disp *ax = (struct ax_disp *) tty->disc_data;	struct mkiss_channel *mkiss;	/* First make sure we're connected. */	if (ax == NULL || ax->magic != AX25_MAGIC || !netif_running(ax->dev))		return;	if (ax->xleft <= 0)  {		/* Now serial buffer is almost free & we can start		 * transmission of another packet		 */		tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);		if (ax->mkiss != NULL) {			mkiss= ax->mkiss->tty->driver_data;			if (mkiss->magic  == MKISS_DRIVER_MAGIC)				ax_unlock(ax->mkiss);	        }		netif_wake_queue(ax->dev);		return;	}	actual = tty->driver.write(tty, 0, ax->xhead, ax->xleft);	ax->xleft -= actual;	ax->xhead += actual;}/* Encapsulate an AX.25 packet and kick it into a TTY queue. */static int ax_xmit(struct sk_buff *skb, struct net_device *dev){	struct ax_disp *ax = (struct ax_disp *) dev->priv;	struct mkiss_channel *mkiss = ax->tty->driver_data;	struct ax_disp *tmp_ax;	tmp_ax = NULL;	if (mkiss->magic  == MKISS_DRIVER_MAGIC) {		if (skb->data[0] < 0x10)			skb->data[0] = skb->data[0] + 0x10;		tmp_ax = ax->mkiss;	}	if (!netif_running(dev))  {		printk(KERN_ERR "mkiss: %s: xmit call when iface is down\n", dev->name);		return 1;	}	if (tmp_ax != NULL)		if (netif_queue_stopped(tmp_ax->dev))			return 1;	if (tmp_ax != NULL)		if (netif_queue_stopped(dev)) {			printk(KERN_ERR "mkiss: dev busy while serial dev is free\n");			ax_unlock(ax);	        }	if (netif_queue_stopped(dev)) {		/*		 * May be we must check transmitter timeout here ?		 *      14 Oct 1994 Dmitry Gorodchanin.		 */		if (jiffies - dev->trans_start  < 20 * HZ) {			/* 20 sec timeout not reached */			return 1;		}		printk(KERN_ERR "mkiss: %s: transmit timed out, %s?\n", dev->name,		       (ax->tty->driver.chars_in_buffer(ax->tty) || ax->xleft) ?		       "bad line quality" : "driver error");		ax->xleft = 0;		ax->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);		ax_unlock(ax);	}	/* We were not busy, so we are now... :-) */	if (skb != NULL) {		ax_lock(ax);		if (tmp_ax != NULL)			ax_lock(tmp_ax);		ax_encaps(ax, skb->data, skb->len);		kfree_skb(skb);	}	return 0;}#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)/* Return the frame type ID */static int ax_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,	  void *daddr, void *saddr, unsigned len){#ifdef CONFIG_INET

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -