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

📄 ldl.c

📁 7号信令功能代码,为开源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *  ldl: Yet another unfinished DLPI driver * *  Version: 0.4.1 * *  Copyright (C) 1998, 1999 Ole Husgaard (sparre@login.dknet.dk) * *  Token ring support by Dave Grothe Copyright (C) 1999 * *  This program 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 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., 675 Mass Ave, Cambridge, MA 02139, USA. * *  *  * This driver does not attempt to do any hardware programming. Instead * this driver is an interface between the existing Linux network device * driver interface and the DLPI interface. *  * It will also work in cooperation with Linux protocol drivers. You can * BIND the IP protocol to a Linux netdevice that is also used by the * Linux IP socket interface: * Incoming packets are delivered to this DLPI driver *and* to the Linux * IP socket interface. But packets sent out by this DLPI driver are *not* * seen by the Linux IP socket interface, and packets send out by the Linux * IP socket interface are *not* seen by this driver. This means that the * Linux IP code will see a response to an IP protocol packet sent out from * this DLPI driver. * To avoid this sort of confusion, you should do one of: *   1) Use this driver for listening only. *   2) Use protocols *not* used by the Linux socket code. *   3) Tell Linux that the interface is down (does this work?) * * The PPA (device number) used for ATTACH is determined by looking at * the Linux netdevice list. The first netdevice has PPA 0. You can see * the device list in /proc/net/dev, or you can do a LDL_FINDPPA IOCTL if * you know the netdevice name. * You can OR the PPA with one of the LDL_FRAME_xxx constants defined in * ldl.h if you want to use other framing types that the default ethernet II. *  * Currently only ethernet devices and the loopback device are supported. *  *  * TODO: Sending IP packets from ldl to the native Linux IP layer across * the loopback interface no longer works. The native IP receive code now * checks a field skb->dst to see if the packet is bogus. This field is set * on receive from a network card, but due to some optimizations this is * set before transmit when using the loopback interface. The skb->dst field * should point to an entry in the ipv4 FIB, and I do not think that there is * any way to get at this without changing the native Linux ipv4 code. * And it looks like doing this would either slow down the native ipv4 code, * open up a security hole, or make the kernel significantly bigger. * Another option could be to change this driver to check for ipv4 on the * loopback interface. When this is detected, we could set skb->dst. *  */#ifdef DEBUG#undef DEBUG			/* unused symbol that causes a warning */#endif#include <linux/config.h>#include <linux/version.h>#ifdef CONFIG_MODVERSIONS#include <linux/modversions.h>#endif#include <linux/module.h>#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)#define	KERNEL_2_0#else#define	KERNEL_2_1# if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)# define KERNEL_2_3# endif#endif#include <linux/spinlock.h>#include <sys/stream.h>		/* stream.h comes first */#include <sys/stropts.h> /*  * irda uses queue_t which interferes with our use later  */#define queue_t	irda_queue_t#include <asm/byteorder.h>   /* ntohs() etc..			*/#include <linux/errno.h>#include <linux/string.h>    /* memcpy() and family		*/# ifdef RH_71_KLUDGE	     /* boogered up incls in 2.4.2 */#  undef CONFIG_HIGHMEM	     /* b_page has semi-circular reference */# endif#include <linux/netdevice.h> /* Linux netdevice header		*/#include <linux/if_arp.h>    /* Linux netdevice types		*/#include <linux/if_ether.h>  /* Linux ethernet defs		*/#include <linux/skbuff.h>    /* Linux socket buffer		*/#ifdef KERNEL_2_1 /*  * This file is not available if kernel source is not installed  */#if !defined(NOKSRC)#include <net/pkt_sched.h>   /* Linux queue disciplines		*/#elsevoid qdisc_reset(struct Qdisc *qdisc);#endif#endif#ifdef KERNEL_2_0#define atomic_read(int_ptr)	(*(int_ptr))#define	ARPHRD_HDLC		513		/* 2.1 compatibility */#endif#undef queue_t			/* allow visibility again */#include <sys/dlpi.h>#include <sys/dki.h>#include <sys/ddi.h>#include <sys/ldl.h>#include <sys/LiS/config.h>#include <sys/osif.h>#if defined(KERNEL_2_3)#define ldldev		net_device#define driver_started(dev)	 1#define	START_BH_ATOMIC(dev)	spin_lock_bh(&(dev)->queue_lock)#define	END_BH_ATOMIC(dev)	spin_unlock_bh(&(dev)->queue_lock)#else#define ldldev		device#define netif_queue_stopped(dev) ((dev)->tbusy)#define driver_started(dev)	 ((dev)->start)#define	START_BH_ATOMIC(dev)	start_bh_atomic()#define	END_BH_ATOMIC(dev)	end_bh_atomic()#endif#if defined(ARPHRD_IEEE802_TR)#define	IS_ARPHRD_IEEE802_TR(dev) (dev)->type == ARPHRD_IEEE802_TR#else#define	IS_ARPHRD_IEEE802_TR(dev) 0#endif#if defined(KERNEL_2_1) && defined(LISMODVERS)/*extern void qdisc_reset(struct Qdisc *qdisc);*/#endif/* *  Some configuration sanity checks */#ifndef LDL_#error Not configured#endif#if !defined(LDL__CMAJORS) || LDL__CMAJORS != 1#error There should be exactly one major number#endif#if !defined(LDL__CMAJOR_0)#error The major number should be defined#endif#define LDL_MAX_HDR_LEN	64#define MAXADDRLEN	8#define MAXSAPLEN	8#define MAXDLSAPLEN	(MAXSAPLEN + MAXADDRLEN)#define MINDATA		46#define MAXDATA		4096#define DONE		0#define RETRY		1typedef struct { unsigned char sap[MAXSAPLEN]; } sap_t;/* *  Private per stream flags */#define LDLFLAG_PROMISC_SAP     0x0400 /* Promiscous SAP mode		*/#define LDLFLAG_SET_ADDR	0x1000 /* Changing physical address	*/#define LDLFLAG_HANGUP		0x2000 /* Deferred M_HANGUP needed	*/#define LDLFLAG_HANGUP_DONE	0x4000 /* M_HANGUP completed		*/#define LDLFLAG_PRIVATE		0x7400 /* Private flag mask		*//* *  Transmission priorities */#if defined(TC_PRIO_BULK)#define LDLPRI_LO	TC_PRIO_BULK#define LDLPRI_MED	TC_PRIO_BESTEFFORT#define LDLPRI_HI	TC_PRIO_INTERACTIVE#elif defined(SOPRI_BACKGROUND)#define LDLPRI_LO	SOPRI_BACKGROUND#define LDLPRI_MED	SOPRI_NORMAL#define LDLPRI_HI	SOPRI_INTERACTIVE#else#define LDLPRI_LO       0#define LDLPRI_MED      0#define LDLPRI_HI       0#endif/* *  How long to backout in case of congestion */#define CONGESTION_BACKOFF_TICKS ((HZ/200 <= 1) ? 2 : (HZ/200))/* *  The following structures are a bit complicated, but they give efficient *  code in the receive data code path and fair behaviour in the transmit *  path when local transmit congestion is happening. * *  Data is received from a native Linux netdevice as follows: *  - First a struct packet_type that identifies the device and/or protocol *    must be registered with the Linux kernel using the dev_add_pack() *    function. *  - When a packet (with the right protocol) is received (on the right *    device) a callback function (a field of the struct packet_type) is *    called. Here the callback function is rcv_func(). The callback function *    takes three arguments: *	struct sk_buff *skb	Native Linux network data buffer *	struct device *dev	The native Linux device that data arrived on *	struct packet_type *pt	The packet type that matched protocol/device *    The callback is not called during the receive interrupt, but just after. *    The data is copied into a STREAMS data message. (We could use esballoc()) *  - When the receive function should stop, dev_remove_pack() must be called. * *  The following considerations are taken: *  - For every packet_type (but the first) listening on a Linux netdevice, *    a sk_buff structure is copied. The data is not copied, but the sk_buff *    is large (compared to mblk_t). This copy should be avoided by using *    only a single packet_type when several DLPI devices are bound to the *    same SAP on the same device. (Have a look at function net_bh() in *    file net/core/dev.c of the Linux kernel if you want to see what happens.) *  - When several DLPI devices are bound to the same SAP on the same device, *    only the message blocks (not the data blocks) should be copied. *    (Use dupmsg() instead of copymsg() whenever possible). *  - When several DLPI devices are bound to the same SAP on the same device, *    the DLPI devices that data must be delivered to should be trivially easy *    to find. *  - Subsequent (peer) bindings must be supported by the DLPI device. (This *    complicates things a bit.) *  - We want to limit the amount of data we have in the Linux netdevice *    transmit queue at any time to be fair to the native Linux networking *    code. * *  To facilitate this the following structures are used: *  struct ndev *    This is the internal representation of a native Linux netdevice. It has *    the following members: *	- A pointer to the native Linux netdevice. *	- The maximum byte count that is allowed to be on the transmission *        queue of this netdevice. *	- The current byte count that this driver currently has on the *	  transmission queue of this netdevice. *	- A timer handle for a timeout to restart after congestion has been *	  detected. *	- A list of the endpoints attached to this netdevice. *  struct pt *    This is the native Linux struct packet_type with some extra fields. The *    first member is a struct packet_type so we can use a simple typecast in *    the receive callback function. Apart from a magic number for debugging *    purposes, the only other member is a pointer to the first entry of a *    linked list of listeners for this packet_type. *  struct sap *    This represents a DLPI binding (and also a listener for a certain packet *    type). It has the following members: *	- A pointer to the DLPI stream that is bound (is listening). *	- A pointer to the struct pt that is used for receiving. *	- A pointer to the next entry on the linked list of listeners for this *	  packet type. *	- A pointer to the next entry on a linked list of subsequent (peer) *	  bindings on the same DLPI stream. *      - The SAP that is bound (length and type determined from dl->framing). *//* Netdevice structure */struct ndev{	dl_ulong magic;		/* Debugging paranoia (==0 iff free)	*/	struct ldldev *dev;	/* Linux netdevice			*/	struct dl *endpoints;	/* List of endpoints attached to this	*/	struct ndev *next;	/* List of all struct ndev		*/	atomic_t wr_cur;	/* Currently on write queue		*/	int wr_max;		/* Max. outstanding on write queue	*/	int wr_min;		/* Min. outstanding on write queue	*/	toid_t tx_congest_timer;/* Tx. congestion backoff restart timer	*/	int sleeping;		/* Tx. sleeping flag			*/};/* Packet type structure */struct pt{	struct packet_type pt;	/* Packet type filter			*/	dl_ulong magic;		/* Debugging paranoia (==0 iff free)	*/	lis_rw_lock_t lock;	/* listening SAP list synchronization	*/	struct sap *listen;	/* listening SAP list (==NULL iff free)	*/	struct pt *next;	/* List of all struct pt		*/};/* Binding structure */struct sap {	sap_t sap;		/* Bound SAP				*/	dl_ulong magic;		/* Debugging paranoia (==0 iff free)	*/	struct dl *dl;		/* DLPI minor pointer (==NULL iff free)	*/	struct pt *pt;		/* Packet type filter			*/	struct sap *next_listen;/* Listening sap list (same pkt. type)	*/	struct sap *next_sap;	/* Subsequent sap list (same dl)	*/};/* DLPI endpoint structure */struct dl{	dl_ulong magic;		/* Debugging paranoia (==0 iff free)	*/	queue_t	*rq;		/* Read queue				*/	ulong dlstate;		/* State				*/	dl_ulong flags;		/* Current flags			*/	dl_ulong lost_rcv, lost_send; /* Statistics			*/	dl_ulong priority;	/* Current priority			*/	struct dl *next_open;	/* List of open devices			*/	struct ndev *ndev;	/* Our netdevice, known after ATTACH	*/	struct dl *next_ndev;	/* List of endpoints on same netdevice	*/	int bufwait;		/* Flag: We are waiting for a buffer	*/	int addr_len;		/* Link physical address length		*/	int sap_len;		/* Link SAP length			*/	int machdr_len;		/* MAC header length			*/	int machdr_reserve;	/* MAC header alloc length		*/	int mtu;		/* DLSDU				*/	struct sap *sap;	/* Primary SAP				*/	struct sap *subs;	/* Subsequent (peer) SAPs		*/	dl_ulong framing;	/* Data link framing used		*/	unsigned char oui[3];	/* OUI for SNAP framing			*/	int (*wantsframe)(struct dl *dl, unsigned char *fr, int len);	mblk_t *(*rcvind)(struct dl *dl, mblk_t *dp);	int (*mkhdr)(struct dl *dl, unsigned char *dst,		     int datalen, struct sk_buff *skb);};/* Magic numbers */#define NDEV_MAGIC	0xA5B4C3D1#define PT_MAGIC	0xA5B4C3D2#define SAP_MAGIC	0xA5B4C3D3#define DL_MAGIC	0xA5B4C3D4/* Default netdevice write queue water marks */#define DEV_WR_MIN 0x08000 /* Low water:  32 Kb */#define DEV_WR_MAX 0x10000 /* High water: 64 Kb */ldl_gstats_ioctl_t	ldl_gstats ;#define	ginc(field)	lis_atomic_inc(&ldl_gstats.field)STATIC unsigned long	ldl_debug_mask ;STATIC struct pt *first_pt;STATIC lis_spin_lock_t first_pt_lock;STATIC struct ndev *first_ndev;STATIC struct dl dl_dl[LDL_N_MINOR];STATIC struct dl *first_open;STATIC lis_spin_lock_t first_open_lock;STATIC int initialized = 0;STATIC int n_hangup;STATIC int pt_n_alloc = 0;STATIC int sap_n_alloc = 0;STATIC int ndev_n_alloc = 0;STATIC char *ldl_pkt_type(unsigned saptype) ;STATIC int dl_open(queue_t *, dev_t *, int, int, cred_t *);STATIC int dl_close(queue_t *, int, cred_t *);STATIC int dl_rsrv(queue_t *);STATIC int dl_wput(queue_t *, mblk_t *);STATIC int dl_wsrv(queue_t *);STATIC int rcv_func(struct sk_buff *skb,		    struct ldldev *dev, struct packet_type *pt);STATIC INLINE int tx_func_raw(struct dl *dl, mblk_t *mp);STATIC struct module_info dl_minfo = {	0x7253,		/* Module ID number		*/	"ldl",		/* Module name: Linux DataLink	*/	4,		/* Min packet size accepted	*/	INFPSZ,		/* Max packet size accepted	*/	0x10000,	/* Hi water mark: 64 Kb		*/	0x04000		/* Low water mark: 16 Kb	*/};STATIC struct qinit dl_rinit = {	NULL,		/* No read put		*/	dl_rsrv,	/* Read service		*/	dl_open,	/* Each open		*/	dl_close,	/* Last close		*/	NULL,		/* Reserved		*/	&dl_minfo,	/* Information		*/	NULL		/* No statistics	*/};STATIC struct qinit dl_winit = {	dl_wput,	/* Write put		*/	dl_wsrv,	/* Write service	*/	NULL,		/* Ignored		*/	NULL,		/* Ignored		*/	NULL,		/* Reserved		*/	&dl_minfo,	/* Information		*/	NULL		/* No statistics	*/};#ifdef MODULESTATIC#endifstruct streamtab ldl_info = {	&dl_rinit,	/* Read queue		*/	&dl_winit,	/* Write queue		*/	NULL,		/* Unused		*/	NULL		/* Unused		*/};STATIC void ldl_bfr_dump(char *msg, void *ptr, int len, int alldata){    unsigned char	*p = ptr ;    int			 bytes = 0 ;    int			 trunc = 0 ;    int			 nl = 0 ;    printk("%s -- %d bytes\n", msg, len) ;    if (!alldata && len > 24)    {	len = 24 ;	trunc = 1 ;    }    for (; len > 0; len--, p++)    {	printk("%02x ", *p) ;	nl = 0 ;	if (!trunc && ++bytes == 16)	{	    printk("\n");	    nl = 1 ;	    bytes = 0 ;	}    }    if (!nl)	printk("\n") ;}STATIC void ldl_mp_dump(char *msg, mblk_t *mp, int alldata){    ldl_bfr_dump(msg, mp->b_rptr, mp->b_wptr - mp->b_rptr, alldata) ;}STATIC void ldl_mp_data_dump(char *msg, mblk_t *mp, int alldata){    for (; mp != NULL && mp->b_datap->db_type != M_DATA; mp = mp->b_cont) ;    if (mp == NULL)	return ;    ldl_mp_dump(msg, mp, alldata) ;}STATIC void ldl_skbuff_dump(char *msg, struct sk_buff *skb, int alldata){#define	L	unsigned long    int		cnt ;    if (msg != NULL)	printk("%s:\n", msg) ;    printk("head=%lx data=%lx tail=%lx end=%lx truesize=%d\n"           "h.raw=%lx nh.raw=%lx mac.raw=%lx type=%s len=%d\n",	   (L)skb->head, (L)skb->data, (L)skb->tail, (L)skb->end, skb->truesize,	   (L)skb->h.raw, (L)skb->nh.raw, (L)skb->mac.raw, 	   ldl_pkt_type(skb->pkt_type),

⌨️ 快捷键说明

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