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

📄 ip_to_dlpi.c

📁 7号信令功能代码,为开源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/************************************************************************* * *  Copyright (C)  1998-2003 The Software Group Limited. * *  This library is free software; you can redistribute it and/or *  modify it under the terms of the GNU Library General Public *  License as published by the Free Software Foundation; either *  version 2 of the License, or (at your option) any later version. *  *  This library 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 *  Library General Public License for more details. *  *  You should have received a copy of the GNU Library General Public *  License along with this library; if not, write to the *  Free Software Foundation, Inc., 59 Temple Place - Suite 330, Cambridge, *  MA 02139, USA. *  *************************************************************************//* * This driver provides a mapping between Linux IP and an underlying * DLPI streams driver.  The DLPI messages are the same as what * IP on a System V system would expect. * * TSG uses this driver to allow it's IP/X.25 software to work on * Linux.  Since that driver is called xinet, you can probably guess * how the name "ip2xinet" came about. * * It creates a device "/dev/ip2xinet".  Open this device and link it * to the driver below. * * This driver supports up to 8 network devices: ip2x0-7. * They can be configured using the ifconfig program. *  * A few things are required in order to make this work: * 1)  You must create a static arp entry in the table indicating *     the remote machines that we are directly connected to.  If *     you look at ip2xinet_hw_tx, you will see how this address ends up *     being used. *     eg.  arp -s 10.1.1.2 0A:01:01:02:00:00 * * 2)  The driver underneath must have the routing information *     so that it can figure out how to send the IP datagram *     that it has received.  This step is specific to that driver. */#include <linux/version.h>#include <linux/config.h>#ifdef CONFIG_MODVERSIONS#include <linux/modversions.h>#endif#include <linux/module.h>#include <asm/param.h>#include <linux/sched.h> #include <linux/kernel.h> /* printk() */#include <linux/errno.h>  /* error codes */#include <linux/types.h>  /* size_t */#include <linux/interrupt.h> /* mark_bh */#include <linux/netdevice.h>   /* struct net_device, and other headers */#include <linux/etherdevice.h> /* eth_type_trans */#include <linux/ip.h>          /* struct iphdr */#include <linux/tcp.h>         /* struct tcphdr */#include <linux/skbuff.h>#include <linux/if_arp.h>#include <net/arp.h>#include <sys/stream.h>#include <sys/dlpi.h>#include <sys/lismem.h>#include <sys/lislocks.h>/*************************************************************************                         Module Information                            *************************************************************************//* * Note:  We are labeling the module license as "GPL and additional rights". * This is said to be equivalent to GPL for symbol exporting purposes and * is also supposed to span LGPL. */#if defined(MODULE_LICENSE)MODULE_LICENSE("GPL and additional rights");#endif#if defined(MODULE_AUTHOR)MODULE_AUTHOR("The Software Group Ltd.");#endif#if defined(MODULE_DESCRIPTION)MODULE_DESCRIPTION("Linux IP to Streams driver");#endif/* version dependencies have been confined to a separate file *//* * Macros to help debugging */#undef PDEBUG             /* undef it, just in case */#ifdef IP2XINET_DEBUG#  ifdef __KERNEL__     /* This one if debugging is on, and kernel space */#    define PDEBUG(fmt, args...) printk( KERN_DEBUG "ip2xinet: " fmt, ## args)#  else     /* This one for user space */#    define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)#  endif#else#  define PDEBUG(fmt, args...) /* not debugging: nothing */#endif#undef PDEBUGG#define PDEBUGG(fmt, args...) /* nothing: it's a placeholder *//* * This structure is private to each device. It is used to pass * packets in and out, so there is place for a packet */#define NUMIP2XINET 8struct ip2xinet_priv {    struct net_device_stats stats;    int state;    int packetlen;    u8 *packetdata;} ip2xinet_private[NUMIP2XINET];struct ip2xinet_state {    int ip2x_dlstate;  /* TSG: DLPI user state */    int myminor;       /* store getminor result */    queue_t *lowerq;   /* lower write queue corresponding 		        * to myminor 		        */    queue_t *readq;    /* upper read queue for my minor			* (just in case we care)			*/    int index;         /* Unique ID of lower stream */ } ip2xinet_status;extern struct net_device ip2xinet_devs[];/* These are the flags in the statusword */#define IP2XINETM_ID 568#define UNLINKED        0x20        /* our addition to DLPI states */int ip2xinetdevflag = 0;int ip2xinetopen(queue_t *, dev_t *, int, int, cred_t *);int ip2xinetclose(queue_t *, int, cred_t *);int ip2xinetuwput(queue_t* q, mblk_t* mp);int ip2xinetlrput(queue_t* q, mblk_t* mp);int ip2xinetursrv(queue_t *q);int ip2xinetlwsrv(queue_t *q);void ip2xinet_rx(struct net_device *dev, struct sk_buff *skb);int ip2xinet_send_down_bind(queue_t *q);int init_linuxip(void);void cleanup_linuxip(void);int ip2xinet_num_ip_opened;lis_spin_lock_t *ip2xinet_lock;int ip2_m_number;int ip2xinetinit(void);	  struct module_info ip2xinetminfo ={    IP2XINETM_ID, "ip2xinet", 0, 8192, 8192, 1024};struct qinit ip2xineturinit ={				/* upper read	*/    NULL, ip2xinetursrv, ip2xinetopen, ip2xinetclose, NULL, &ip2xinetminfo, NULL};struct qinit ip2xinetuwinit ={				/* upper write	*/    ip2xinetuwput, NULL, ip2xinetopen, ip2xinetclose, NULL, &ip2xinetminfo, NULL};struct qinit ip2xinetlrinit ={				/* lower read	*/    ip2xinetlrput, NULL, NULL, NULL, NULL, &ip2xinetminfo, NULL};struct qinit ip2xinetlwinit ={				/* lower write	*/    NULL, ip2xinetlwsrv, NULL, NULL, NULL, &ip2xinetminfo, NULL};struct streamtab ip2xinetinfo ={    &ip2xineturinit, &ip2xinetuwinit, &ip2xinetlrinit, &ip2xinetlwinit};static int ip2xinet_numopen = 0;  /* How many times ip2xinet was opened as			       * a STREAMS device			       */char kernel_version[] = UTS_RELEASE;int ip2xinetinit(void){    if (0 == init_linuxip())	return 1;    else	return 0;}/************************************************************************ * *  Function Name: ip2xinetopen *  Title: IP2XINET driver Open Routine * *  Description: *	Open a queue (device) * *  Arguments: *	q	- read queue pointer *	dev	- major/minor device number *	flag	- file open flags *	sflag	- STREAM open flags * *  Return Value: *	dev	- minor device * ************************************************************************/int ip2xinetopen(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp){    mblk_t *bp;    minor_t minor;    struct stroptions *sop;    lis_flags_t oldpl;    /*     * already open     */    if (sflag != CLONEOPEN)	return ENXIO;    lis_spin_lock_irqsave(ip2xinet_lock, &oldpl);    /* Can only open one time */    if (ip2xinet_numopen)    {	lis_spin_unlock_irqrestore(ip2xinet_lock, &oldpl);	return ENXIO;    }    else	ip2xinet_numopen = 1;    if (q->q_count != 0)	printk("ip2x level:q_count is %lu",q->q_count);    /*     * Set up the flow control parameters and send them up to the stream head.     */    minor = getminor(*devp);    if ((bp = allocb(sizeof(struct stroptions), BPRI_LO)) == NULL)    {	lis_spin_unlock_irqrestore(ip2xinet_lock, &oldpl);	printk("ip2xinetopen: allocb failed");	return ENOMEM;    }    ip2xinet_status.myminor = minor;    ip2xinet_status.ip2x_dlstate = DL_UNATTACHED;    /* These are dummy to keep track of the fact the device is open */    q->q_ptr = (char *) &ip2xinet_numopen;    WR(q)->q_ptr = (char *) &ip2xinet_numopen;    lis_spin_unlock_irqrestore(ip2xinet_lock, &oldpl);    bp->b_datap->db_type = M_SETOPTS;    bp->b_wptr += sizeof(struct stroptions);    sop = (struct stroptions *) bp->b_rptr;    sop->so_flags = SO_HIWAT | SO_LOWAT;    sop->so_hiwat = ip2xinetminfo.mi_hiwat;    sop->so_lowat = ip2xinetminfo.mi_lowat;    putnext(q, bp);    MOD_INC_USE_COUNT;    *devp = makedevice(getmajor(*devp), 0);    return 0;}/************************************************************************ * *  Function Name: ip2xinetclose *  Title: IP2XINET Driver Close Routine * *  Description: *	Close an ip2xinet queue (device) * *  Arguments: *	q	- read queue pointer * *  Return Value: *	none * ************************************************************************/int ip2xinetclose(queue_t *q, int flag, cred_t *credp){    lis_flags_t oldpl;    if (q->q_ptr == NULL)	return (0);    lis_spin_lock_irqsave(ip2xinet_lock, &oldpl);    ip2xinet_numopen = 0;    flushq(WR(q), FLUSHALL);    q->q_ptr = NULL;    WR(q)->q_ptr = NULL;     MOD_DEC_USE_COUNT;    lis_spin_unlock_irqrestore(ip2xinet_lock, &oldpl);    return (0);}/************************************************************************ * *  Function Name: ip2xinetuwput *  Title: IP2XINET Upper Write Put Routine * *  Description: *	Handle messages coming downstream. Should be no data in these *      just stupid stuff like flushq * *  Arguments: *	q	- upper write queue *	mp	- pointer to an message block * *  Return Value: *	none * ************************************************************************/int ip2xinetuwput(queue_t *q, mblk_t *mp){    int i;    lis_flags_t oldpl;    lis_spin_lock_irqsave(ip2xinet_lock, &oldpl);    switch (mp->b_datap->db_type)    {    case M_FLUSH:	if (*mp->b_rptr & FLUSHW)	{	    flushq(q, FLUSHALL);	    qenable(q);	    *mp->b_rptr &= ~FLUSHW;	}	if (*mp->b_rptr & FLUSHR)	{	    flushq(RD(q), FLUSHALL);	    putq(RD(q), mp);	}	else	    freemsg(mp);	break;    case M_IOCTL:	/* Process at least the I_LINK, I_UNLINK  */	/* THINKME:  Failure to correctly process I_LINK/I_UNLINK while	*           returning correctly a nack to stream head will	*           leave us in a possibly totally screwed up DLPI state	*           from which we have to somehow recover.  The possible	*           problematic states are DL_UNBOUND, any DL_PENDING states	*	*           Note: if we stay in UNATTACHED on I_LINK failure or in	*                 IDLE on I_UNLINK failure we're ok as long as the	*                 private data structure stuff is consistent with	*                 the state	*/	{	    struct iocblk *iocp;	    mblk_t *nmp;	    dl_attach_req_t *attach;	    struct linkblk *lp;	    iocp = (struct iocblk *) mp->b_rptr;	#ifdef DEBUG	    pkt_debug(X25DBIOCTL) KPRINTF("%s size %d\n",		x25dbiocmsg(iocp->ioc_cmd), x25dbmsgsize(mp));	#endif	    switch ((unsigned) iocp->ioc_cmd)	    {	    case I_LINK:		iocp->ioc_error = 0;		iocp->ioc_rval = 0;		iocp->ioc_count = 0;		lp = (struct linkblk *) mp->b_cont->b_rptr;		/* Use only one xinet queue for all devices */		ip2xinet_status.lowerq = lp->l_qbot;		ip2xinet_status.index = lp->l_index;		/* Only one read q to get data from xinet */		ip2xinet_status.readq = RD(q);		/* These are dummy ones to indicate the queues are being used */		ip2xinet_status.lowerq->q_ptr = (char *) &ip2xinet_numopen;		RD(ip2xinet_status.lowerq)->q_ptr = (char *) &ip2xinet_numopen;		if ((nmp = allocb(sizeof(union DL_primitives), BPRI_LO)) == NULL)		{		    iocp->ioc_error = ENOSR;		    mp->b_datap->db_type = M_IOCNAK;		    putq(RD(q), mp);		    lis_spin_unlock_irqrestore(ip2xinet_lock, &oldpl);		    printk("pktioctl: I_LINK failed: allocb failed");		    return (0);		}		/*		* Setup and send an ATTACH		*/		nmp->b_datap->db_type = M_PROTO;		nmp->b_wptr += DL_ATTACH_REQ_SIZE;		attach = (dl_attach_req_t *) nmp->b_rptr;		attach->dl_primitive = DL_ATTACH_REQ;		attach->dl_ppa = ip2xinet_status.myminor;		ip2xinet_status.ip2x_dlstate = DL_ATTACH_PENDING;		/* experience shows that an I_LINKed queue needs to 		* be enabled so that the service routine will be run.		*/		qenable(ip2xinet_status.lowerq);		putq(ip2xinet_status.lowerq, nmp);		/* all went well */		mp->b_datap->db_type = M_IOCACK;		putq(RD(q), mp);		break;	    case I_UNLINK:		{		    struct linkblk *lp;		    iocp->ioc_error = 0;		    iocp->ioc_rval = 0;		    iocp->ioc_count = 0;		    lp = (struct linkblk *) mp->b_cont->b_rptr;		    /* 		     * Ignore the DLPI state, the stack is being torn		     * down regardless.   		     */		    ip2xinet_status.ip2x_dlstate = UNLINKED;		    /* can't transmit any more */		    for (i = 0; i<NUMIP2XINET; i++)		    {    			struct ip2xinet_priv *privptr = &ip2xinet_private[i];			if (privptr->state == 1)			    netif_stop_queue(&(ip2xinet_devs[i]));		    }		    flushq(q, FLUSHALL);		    flushq(RD(lp->l_qbot), FLUSHALL);		    ip2xinet_status.readq = NULL;		    ip2xinet_status.lowerq = NULL;		    mp->b_datap->db_type = M_IOCACK;		    putq(RD(q), mp);		    break;		}	    default:		iocp->ioc_error = EINVAL;		mp->b_datap->db_type = M_IOCNAK;		putq(RD(q), mp);		break;	    }	}	break;    case M_DATA:    case M_PCPROTO:    case M_PROTO:    default:	printk("ip2xinetuwput: unexpected type=0x%x", mp->b_datap->db_type);	freemsg(mp);	break;    }    lis_spin_unlock_irqrestore(ip2xinet_lock, &oldpl);    return (0);}/************************************************************************ * * Function Name: ip2xinetursrv * Title: IP2XINET Upper Read Service routine * * Description: *      Send all of the messages on this queue up to the next driver. *      We don't worry about doing flow control.  This is used because in *      the places where we might want to call putnext, we call putq *      instead. * ************************************************************************/

⌨️ 快捷键说明

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