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

📄 ip_to_dlpi.c

📁 7号信令功能代码,为开源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
int ip2xinetursrv(queue_t *q){    mblk_t *mp;    while ((mp = getq(q)))    {	putnext(q, mp);    }    return (0);}/************************************************************************ * * Function Name: ip2xinetlwsrv * Title: IP2XINET Lower Write Service routine * * Description: *      Send all of the messages on this queue down to the next driver. *      If we discover that we can't do a put, then stop the Linux *      devices from sending us stuff. * ************************************************************************/int ip2xinetlwsrv(queue_t *q){    mblk_t *mp;    int allsent = 1;    int i;    struct net_device *dev = ip2xinet_devs;    struct ip2xinet_priv *privp;     lis_flags_t oldpl;    while ((mp = getq(q)))    {	/* M_PROTO's should be last on the list.  If it is something	* else, then it should be ahead, and we can just go ahead and	* put it down.	*/	if (mp->b_datap->db_type == M_PROTO)	{	    if (canputnext(q))	    {		putnext(q, mp);	    }	    else	    {		noenable(q);		putbq(q, mp);		enableok(q);		allsent = 0;		break;	    }	}	else	{	    putnext(q, mp);	}    }    /* Handle the flow control.  If we were able to send everything     * then it is ok for the kernel to send us more stuff.  Otherwise     * it is not ok.  Go through all of the devices and set the appropriate     * state.     */    lis_spin_lock_irqsave(ip2xinet_lock, &oldpl);    for (i = 0; i<NUMIP2XINET; i++, dev++)    {        privp = (struct ip2xinet_priv *)dev->priv;	if (privp->state == 1 && ip2xinet_status.ip2x_dlstate == DL_IDLE)	{	    if (allsent)	    {	        netif_start_queue(dev);  /* kernel can transmit */	    }            else	    {	        netif_stop_queue(dev);  /* We are flow controlled. */	    }	}    }    lis_spin_unlock_irqrestore(ip2xinet_lock, &oldpl);    return (0);}/************************************************************************ * *  Function Name: ip2xinetlrput *  Title: IP2XINET Lower Read Put Routine * *  Description: *	Handle messages coming upstream. Valid messages will have *	a DLPI header associated with them.  *      Since we can't be flow controlled by Linux TCP/IP, don't need lrsrv * *  Arguments: *	q	- upper read queue  *	mp	- pointer to an message block * *  Return Value: *	none * ************************************************************************/int ip2xinetlrput(queue_t *q, mblk_t *mp){    struct iocblk *iocp;    union DL_primitives *dp;    struct ip2xinet_priv *privptr;    struct net_device *dev;    int i;    lis_flags_t oldpl;    lis_spin_lock_irqsave(ip2xinet_lock, &oldpl);    /* use the first open ip device */    for (i = 0; i<NUMIP2XINET; i++)    {    	privptr = &ip2xinet_private[i];	if (privptr->state == 1)	    break;    }    if (i == NUMIP2XINET)	i = 0;   /* All devices closed, pick the 1st one */    /* send data up to ip through the 1st open device */    dev = &ip2xinet_devs[i];    switch (mp->b_datap->db_type)    {    case M_CTL:	    freemsg(mp);	    break;    case M_DATA:	    /* NOTE:  We don't expect any M_DATA messages from xinet */	    freemsg(mp);	    break;	           case M_PROTO:    case M_PCPROTO:	dp = (union DL_primitives *) mp->b_rptr;#ifdef DEBUG	printk("ip2xinetlrput: %s size=%d\n",		x25dbdlpmsg(dp->dl_primitive),		x25dbmsgsize(mp));#endif	switch (dp->dl_primitive)	{	case DL_BIND_ACK:	    /*             * if we're in in BNDPND and receive a BIND_ACK we go to IDLE	     *             */	    ip2xinet_status.ip2x_dlstate = DL_IDLE;	    /* If we're DL_IDLE, then dev is open 	     * and the kernel can transmit 	     */	    for (i = 0; i<NUMIP2XINET; i++)	    {    		privptr = &ip2xinet_private[i];		if (privptr->state == 1)		    netif_start_queue(&(ip2xinet_devs[i]));	    }	    freemsg(mp);	/* Frees bind_ack no longer needed */	    break;	case DL_INFO_ACK:	    /* NOTE: currently we don't send info_req to xinet */	    freemsg(mp);	    break;	case DL_ERROR_ACK:	    switch (ip2xinet_status.ip2x_dlstate)	    {	    case DL_ATTACH_PENDING:		/*                 * if we receive ERROR_ACK and we're in ATTACH_PEND                 * go into UNATTACHED		*                 */		ip2xinet_status.ip2x_dlstate = DL_UNATTACHED;		freemsg(mp);		break;	    case DL_BIND_PENDING:		/*	         * if we're in BNDPND and receive an ERR ack we go to UNBND,		*		*/		ip2xinet_status.ip2x_dlstate = DL_UNBOUND;		freemsg(mp);		break;	    case DL_UNBIND_PENDING:		/*	         * If we're in UNBIND_PEND and we receive ERROR_ACK 		* we go into IDLE		*		*/		ip2xinet_status.ip2x_dlstate = DL_IDLE;		freemsg(mp);		break;	    case DL_DETACH_PENDING:		/*		* If we're in DETACH_PEND and receive and ERROR_ACK		* we go into UNBND		* 		*/		ip2xinet_status.ip2x_dlstate = DL_UNBOUND;		freemsg(mp);		break;	    default:		freemsg(mp);		break;	    }	    break;	case DL_UNITDATA_IND:	/*	* if we're in IDLE we can get DL_UNITDATA_IND with data	* and call the guy who would normally receive data from interrupt	* handler.	*	*/	/* Check state: can't transmit if dev is closed :-) 	*	* Note: we have to check both the dlpi state and dev->start	*       because during a close the DLPI state could remain	*       DL_IDLE if we couldn't allocate mblk for UNBIND_REQ.	*       There are many ways in which the dev->start could	*       be 1 but dlpi state - not DL_IDLE.	*/	if (ip2xinet_status.ip2x_dlstate == DL_IDLE && privptr->state == 1);	{	     mblk_t * newmp;	     char * buf;	     int len, tmplen;	     struct ethhdr *eth;	     struct sk_buff *skb;	     newmp = unlinkb(mp);	     freemsg(mp);	     mp = newmp;	     /* 1st pass through.  figure out the len */	     for (len=sizeof(struct ethhdr); newmp != NULL; newmp = newmp->b_cont)		len+=(newmp->b_wptr - newmp->b_rptr);	     /* ALLOCATE skb of length len+2, COPY from mp chain to skb */	     skb = dev_alloc_skb(len+2);	     if (!skb) 	     {		printk("ip2xinet rx: failed to allocate an skb\n");		freemsg(mp);		break;	     }	     skb_reserve(skb, 2); /* align IP on 16B boundary */  	    /*	     * The packet has been retrieved from the transmission	     * medium. Build an skb around it, so upper layers can handle it	     */	     buf = skb_put(skb, len);	     for (newmp=mp, tmplen=sizeof(struct ethhdr); newmp != NULL;							  newmp = newmp->b_cont)	     {		bcopy(newmp->b_rptr, buf+tmplen, newmp->b_wptr - newmp->b_rptr);		tmplen+=(newmp->b_wptr - newmp->b_rptr);	     }	     eth = (struct ethhdr *)buf;	     /* I am not sure it's necessary, but just in case... */	     memcpy(eth->h_source, dev->dev_addr, dev->addr_len);	     memcpy(eth->h_dest, dev->dev_addr, dev->addr_len);	     eth->h_proto = 0x8;   /* ETH_P_IP in network order */	     eth->h_source[ETH_ALEN-1]   ^= 0x01;   /* say src is us xor 1 */	    /* send it to ip2xinet_rx for handling */	    ip2xinet_rx(dev, skb);	}	freemsg(mp);	break;	case DL_UDERROR_IND:	    freemsg(mp);	    break;	case DL_OK_ACK:	    switch (dp->ok_ack.dl_correct_primitive)	    {	    case DL_ATTACH_REQ:		/*	         * if we're in ATTACH_PEND and we received OK_ACK1	         * change state to UNBND 		*		*/		ip2xinet_status.ip2x_dlstate = DL_UNBOUND;		freemsg(mp);		/*		* We just completed building up the X.25 stack below us.		* If IP is already above us, we need to send down the bind		* that we would normally do when IP opens us.  This allows		* us to restart the X.25 stack without restarting TCP/IP.		*/		if (ip2xinet_num_ip_opened != 0)		    ip2xinet_send_down_bind(WR(q));		break;	    case DL_UNBIND_REQ:	        /*		* If we're in UNBIND_PEND and receive OK_ACK1 we go to UNBND.		*/		ip2xinet_status.ip2x_dlstate = DL_UNBOUND;		freemsg(mp);		break;	    case DL_DETACH_REQ:	        /*		* If we're in DETACH_PEND and receive OK_ACK1 we go to UNATT		*		*/		ip2xinet_status.ip2x_dlstate = DL_UNATTACHED;		freemsg(mp);		break;	    default:		freemsg(mp);		break;	    }	    break;	default:	    printk("ip2xinetlrput: bad prim=0x%x", dp->dl_primitive);	    freemsg(mp);	    break;	}	break;    case M_FLUSH:	if (*mp->b_rptr & FLUSHR)	{	    flushq(q, FLUSHALL);	    qenable(q);	}	if (*mp->b_rptr & FLUSHW)	{	    *mp->b_rptr &= ~FLUSHR;	    flushq(WR(q), FLUSHALL);	    qenable(WR(q));	    putq(WR(q), mp);	}	else	    freemsg(mp);	break;    case M_HANGUP:	/* send it to the guy that linked us up, what he does is his problem. */	putq(ip2xinet_status.readq, mp);	break;    case M_IOCACK:	    iocp = (struct iocblk *) mp->b_rptr;	    if (iocp->ioc_cmd == SIOCSIFMTU)	    {	        /* The set MTU ioctl was a success	         * Rejoice :-)		*/		freemsg(mp);	    }	    else		putq(ip2xinet_status.readq, mp);	    break;    case M_IOCNAK:	    iocp = (struct iocblk *) mp->b_rptr;	    if (iocp->ioc_cmd == SIOCSIFMTU)	    {	        /* The set MTU ioctl was a failure		* From looking at xinet code this is		* impossible, so ignore it		*/		freemsg(mp);	    }	    else		putq(ip2xinet_status.readq, mp);	    break;    default:	printk("ip2xinetlrput: bad type=%d", mp->b_datap->db_type);	freemsg(mp);	break;    }    lis_spin_unlock_irqrestore(ip2xinet_lock, &oldpl);    return (0);}/************************************************************************ * *  Function Name: init_module  *  Title: Registering driver as a Streams kernel loadable module * *  Return Value: *      StrReg - major number registered or error number * ************************************************************************/int init_module(void){    int ip2_m_number, clonemajor;    ip2xinet_lock = lis_alloc_kernel(sizeof(lis_spin_lock_t));    if (!ip2xinet_lock)    {	return -ENOMEM;    }    lis_spin_lock_init(ip2xinet_lock, "IP2X Lock");    if( !(ip2_m_number = ip2xinetinit()) )    { 	ip2xinet_lock = lis_free_mem((void *)ip2xinet_lock);        return ip2_m_number;    }    if (( ip2_m_number = lis_register_strdev(0, &ip2xinetinfo, 		    NUMIP2XINET, ip2xinetminfo.mi_idname)) < 0 )    {	printk("ip2xinet.init_module: Unable to register driver.\n");	ip2xinet_lock = lis_free_mem((void *)ip2xinet_lock);	return ip2_m_number;    }    clonemajor = lis_clone_major();    /* Remove the old /dev/ip2xinet node.  We are about to create a new     * one, and that call may fail if the old one is still there.     * We don't actually care if the unlink call fails, just as long     * as the node isn't there.     */    lis_unlink("/dev/ip2xinet");    if ((ip2_m_number = lis_mknod("/dev/ip2xinet",		0666 | S_IFCHR,		MKDEV(clonemajor, ip2_m_number))) < 0)    {	ip2xinet_lock = lis_free_mem((void *)ip2xinet_lock);	return ip2_m_number;    }    return 0;}/************************************************************************ * *  Function Name: cleanup_module  *  Title: Unregistering driver as a Streams kernel loadable module * *  Return Value: *      none * ************************************************************************/void cleanup_module(void){    /* Before you unload this module, unregister all of the network     * devices.     */    if (lis_unregister_strdev(ip2_m_number) < 0 )    {        printk("ip2xinet: Unable to unregister driver.\n");    }    else    {	cleanup_linuxip();	lis_unlink("/dev/ip2xinet");        ip2xinet_lock = lis_free_mem((void *)ip2xinet_lock);        printk("ip2xinet: Unregistered, ready to be unloaded.\n");    }    return;}/* * The first part of the driver was all streams. * The second half is what talks to Linux. * They used to be in separate files, but for easier compilation in * the streams directory, I have joined them. */#define IP_SAP          0x800   /* SAP for IP protocol - currently enet type */#define ARP_SAP         0x806   /* SAP for ARP *//* This is a load-time options */static int eth = 0; /* Call yourself "ethX". Default is "ip2x0"/"ip2x1" */int ip2xinet_eth;int ip2xinet_num_ip_opened = 0; void ip2xinet_rx(struct net_device *dev, struct sk_buff *skb);void do_BUG(const char *file, int line){    return;}int ip2xinet_send_down_bind(queue_t *q){    mblk_t *mp;    dl_bind_req_t *bindmp;    if ((mp = allocb(sizeof(union DL_primitives), BPRI_LO)) == NULL)

⌨️ 快捷键说明

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