ip_strm_mod.c

来自「7号信令功能代码,为开源代码」· C语言 代码 · 共 1,537 行 · 第 1/3 页

C
1,537
字号
	    "\nip_to_streams_rput: q=%x mp=%x minor:0x%x, dev:0x%x\n",		 q, mp, minor_ptr, dev) ;    /* checking, checking, checking... */    if (   minor_ptr == (ip_to_streams_minor_t *) NULL )    {	if (ip_to_streams_debug_mask & DBG_SQUAWK)	    cmn_err(CE_NOTE, "ip_to_streams_rput: bad stream") ;	if (mp != (mblk_t *) NULL) freemsg(mp) ;	/* mark an error, so the world can see it */	minor_ptr->stats.rx_errors++;	return(0) ;    }    /*     * the way this is structured, you can convert the buffer to a linux skbuf     * and also send it upstairs to the process what has the stream open.     * Or you could pass this over to another 'device driver' that looks     * like a device that tcp_dump can look at.     * This way you could have a hook for tcp_dump into this area.     */    switch(mp->b_datap->db_type)    {	case M_DATA:	{	    if ( minor_ptr->contype == IP )	    {		/* if we are putting up to IP, convert to sk buff */		if ( convert_to_skbuf(minor_ptr, mp) != 0 )		{		    minor_ptr->stats.rx_errors++;		    break;		}		minor_ptr->stats.rx_packets++;	    }	    else	    {		/* It will go here if we are not putting to IP */		if ( canputnext(q) )		    putnext(q, mp);		else		    putq(q, mp);	    }	    break;	}	case M_PROTO:	case M_PCPROTO:	{	    int err;	    union DL_primitives *dlp;	    err = 0;	    dlp = (union DL_primitives *)mp->b_rptr;	    switch(dlp->dl_primitive)	    {	    case DL_BIND_ACK:		if ( ip_to_streams_debug_mask & DBG_WPUT)		    printk("ip_to_streams_rput: DL_BIND_ACK:\n");		minor_ptr->dlstate = DL_DATAXFER;		putnext(q, mp);		break;	    case DL_UNITDATA_IND:		/*		 * When we get the unitdata indication, we need to determine		 * where to put it.  If an ip stream is connected here, we need		 * to convert the msg buf to a linux sk buf and send it up		 * to IP.		 * 		 * If ip is not connected, then we just need to do a putnext.		 */		if ( minor_ptr->contype == IP )		{		    if (convert_to_skbuf(minor_ptr, mp) != 0 )		    {			minor_ptr->stats.rx_errors++;			break;		    }		    minor_ptr->stats.rx_packets++;		}		else		{		    if ( canputnext(q) )			putnext(q, mp);		    else			putq(q, mp);		}		break;	    default:		/* everything else just goes upstream */		if ( canputnext(q) )		    putnext(q, mp);		else		    putq(q, mp);		break;	    }	    break;	}	case M_FLUSH:	{	    if (*mp->b_rptr & FLUSHR)	    {		flushq(q, FLUSHDATA);	    }	    if (*mp->b_rptr & FLUSHW)	    {		flushq(WR(q), FLUSHDATA);		*mp->b_rptr &= ~FLUSHR;		qreply(q, mp);	    }	    else		freemsg(mp);	    break;	}	default:		/* send upstream */	{	    putnext(q, mp);	    break;	}    } /* switch */    return(0) ;} /* ip_to_streams_rput *//*************************************************************************                           convert_to_skbuf                          	***************************************************************************									** Convert from a streams msg buffer to a Linux skbuf			**									*************************************************************************/int convert_to_skbuf( ip_to_streams_minor_t *minor_ptr, mblk_t *mp){    struct sk_buff *skb;    int		    len;    mblk_t 	   *tmp = mp;    char	   *ctmp ;    if ( ( mp->b_datap->db_type == M_PROTO)        || ( mp->b_datap->db_type == M_PCPROTO)       )	tmp = mp->b_cont;    len = msgdsize(tmp);    if ( ip_to_streams_debug_mask & DBG_SQUAWK )	cmn_err(CE_CONT, "\nconvert_to_skbuf: minor_ptr 0x%x, mp 0x%x, len %d\n", minor_ptr, mp, len);    skb = dev_alloc_skb(len+4);    if ( skb == NULL )    {	if ( ip_to_streams_debug_mask & DBG_SQUAWK )	    cmn_err(CE_CONT, "\nconvert_to_skbuf: could not allocate %d bytes\n", len);       return(-1);    }    /* set up the skb data structure */    skb->dev = &minor_ptr->mydev;    skb_reserve(skb,2);    skb->protocol = htons(ETH_P_IP);    skb->pkt_type = PACKET_HOST;    skb->h.raw = skb->data ;    skb->mac.raw = skb->data ;#if defined(KERNEL_2_1)    skb->nh.raw = skb->data ;#endif    skb->ip_summed = CHECKSUM_NONE ;    ctmp = skb->data;    /*     * skip over proto stuff, and copy the data over.     */    while(tmp)    {	len = (tmp->b_wptr - tmp->b_rptr);	ctmp = skb_put(skb, len);        memcpy(ctmp, tmp->b_rptr, len);#ifdef GCOM	if ( ip_to_streams_debug_mask & DBG_SQUAWK )	    Rsys_hex_print("convert_to_skbuf:", ctmp, len);#endif        tmp = tmp->b_cont;    }    /* make sure we don't lose any buffers */    freemsg(mp);    /* inform system that an IP packet is ready to go */    netif_rx(skb);    return(0);}/* * The higher levels take care of making this non-reentrant (it's * called with bh's disabled). *//*************************************************************************                           ip_strm_xmit                          	***************************************************************************									** This routine will convert from the Linux native buffer types to 	** a streams msgblk and then send down the buffer.			**									** We are not returning erros, here for a reason.  This is the same as if** IP 'lost' data.  When the bind completes, or a call completes, we 	** will then send the data out.						**									*************************************************************************/#if defined(KERNEL_2_1)#define SKB_FREE(skb)    dev_kfree_skb(skb)#else#define SKB_FREE(skb)    dev_kfree_skb(skb, FREE_WRITE)#endifstatic int ip_strm_xmit(struct sk_buff *skb, struct ism_dev *dev){    ip_to_streams_minor_t  *ipptr    = (ip_to_streams_minor_t *)dev->priv ;    dl_unitdata_req_t	   *dl;    mblk_t *mp, *mpt;      if ( ip_to_streams_debug_mask & DBG_PUT )	cmn_err(CE_CONT, "\nip_strm_xmit: skb 0x%lx dev 0x%lx\n", skb, dev) ;    /* make sure everything is ok */    if (skb == NULL || dev == NULL)     {	if ( ip_to_streams_debug_mask & DBG_PUT )	    cmn_err(CE_CONT, "\nip_strm_xmit: skb NULL or dev NULL\n") ;	return(0);    }    /* is someone trying to confuse us? */    if ( ipptr == NULL )    {	if ( ip_to_streams_debug_mask & DBG_PUT )	    cmn_err(CE_CONT, "\nip_strm_xmit: ipptr NULL\n") ;	ipptr->stats.tx_errors++;	SKB_FREE(skb);				/* don't want a rexmit */	return(0);    }    if (ipptr->dl_magic != DL_MAGIC)		/* not already open */    {	if ( ip_to_streams_debug_mask & DBG_PUT )	    cmn_err(CE_CONT, "\nip_strm_xmit: ipptr->dl_magic\n") ;	ipptr->stats.tx_errors++;	SKB_FREE(skb);				/* don't want a rexmit */        return(0);    }    if ( ipptr->dlstate != DL_DATAXFER )	/* BIND not complete? */    {	if ( ip_to_streams_debug_mask & DBG_PUT )	    cmn_err(CE_CONT, "\nip_strm_xmit: state != DL_DATAXFER\n") ;	ipptr->stats.tx_errors++;	SKB_FREE(skb);				/* don't want a rexmit */        return(0);    }    /* convert to a streams message */    /* put a proto message in front of the data */    mpt = allocb(sizeof(dl_unitdata_req_t), BPRI_MED);    if ( mpt == NULL )    {	if ( ip_to_streams_debug_mask & DBG_PUT )	    cmn_err(CE_CONT, "\nip_strm_xmit: mpt NULL\n") ;	ipptr->stats.tx_errors++;	SKB_FREE(skb);				/* don't want a rexmit */	return(0);    }    mpt->b_datap->db_type = M_PROTO;    mp = allocb(skb->len, BPRI_MED);    if ( mp == NULL )    {	if ( ip_to_streams_debug_mask & DBG_PUT )	    cmn_err(CE_CONT, "\nip_strm_xmit: mp NULL\n") ;	ipptr->stats.tx_errors++;	SKB_FREE(skb);				/* don't want a rexmit */	freemsg(mpt);	return(0);    }    mpt->b_cont = mp;	/* hook the message off the proto */    mpt->b_wptr += sizeof(dl_unitdata_req_t);    dl = (dl_unitdata_req_t *)mpt->b_rptr;    dl->dl_primitive        = DL_UNITDATA_REQ;    dl->dl_dest_addr_length = 0;    dl->dl_dest_addr_offset = 0;    /* copy data over to the streams buffer */    memcpy(mp->b_rptr, skb->data, skb->len);#ifdef GCOM    if ( ip_to_streams_debug_mask & DBG_SQUAWK )	Rsys_hex_print("ip_strm_xmit:", mp->b_rptr, skb->len);#endif    /* set write pointer to correct place */    mp->b_wptr += skb->len;    /* free the skb buffer */    SKB_FREE(skb);    /* send it down to the streams modules */    if ( canputnext(ipptr->dl_wrq) )    {        putnext(ipptr->dl_wrq, mpt);        ipptr->stats.tx_packets++;    }    else    {	netif_stop_queue(dev) ;        putq(ipptr->dl_wrq, mpt);    }    if ( ip_to_streams_debug_mask & DBG_PUT )	cmn_err(CE_CONT, "\nip_strm_xmit: putnext complete\n") ;    return(0);}#undef SKB_FREE/*************************************************************************                           ip_strm_ioctl                               ***************************************************************************									**									*************************************************************************/int ip_strm_ioctl(struct ism_dev *dev, struct ifreq *ifr, int cmd){    return(-EINVAL) ;} /* ip_strm_ioctl *//*************************************************************************                           enet_statistics                          	***************************************************************************									** return a pointer to the stats area					**									*************************************************************************/static struct enet_statistics *get_stats(struct ism_dev *dev){    ip_to_streams_minor_t  *ipptr    = (ip_to_streams_minor_t *)dev->priv ;    if (ipptr == NULL)	return(NULL) ;    return (&ipptr->stats);}/*************************************************************************                           ip_strm_open                          	***************************************************************************									** This routine gets called when the ifconfig command is used to set up	** the IP address and device.						**									** We have to provide linkage between the streams and linux calls and	** data structure.  The streams side has already been done, now the linux** side has to finish up the job.					**									** The minor structure allocated by the streams open routine contains	** the dev structure used by ip.  The "priv" pointer in the dev struct	** points back to the minor structure.					**									*************************************************************************/int ip_strm_open(struct ism_dev *dev){    ip_to_streams_minor_t	*ipptr = (ip_to_streams_minor_t *) dev->priv;    if ( ip_to_streams_debug_mask & (DBG_OPEN) )	cmn_err(CE_CONT, "ip_strm_open: dev 0x%x\n", dev);    /* if the stream has not been opened, fail */    if (ipptr == NULL)	return(EIO);    if ( ip_to_streams_debug_mask & (DBG_OPEN) )	printk("ip_strm_open: %s: ipptr = 0x%px\n", ipptr->myname, ipptr);    dev->flags |= IFF_POINTOPOINT ;    if ( ip_to_streams_debug_mask & (DBG_OPEN) )    {	printk("ip_strm_open: ipptr: 0x%lx, dl_wrq: 0x%lx\n",			 (unsigned long)ipptr,			 (unsigned long)ipptr->dl_wrq);    }    if ( ipptr->dl_wrq == NULL)    {	if ( ip_to_streams_debug_mask & (DBG_OPEN) )	{	    printk("ip_strm_open: dl_wrq not setup correctly\n");	}	return(EIO);    }    /* this flag is used to control where we send the reads from the     * streams modules.  If it is IP, then we will convert to a LINUX     * sk_buf and send it up to ip, otherwise we send it to the process     * that has opened the stream.     */    ipptr->contype = IP;    ipptr->ip_open = 1 ;    return 0;}/*************************************************************************                          ip_strm_close                                ***************************************************************************									** Called when IP wants to close our device.				**									** The STREAMS side is still set up, so we just stop steering incoming	** packets to IP.							**									** Loadable modules treat this as the last thing before module unload.	**									** In our case the stream is still open and a new ifconfig can re-	** instate this IP interface.						**									*************************************************************************/int ip_strm_close(struct ism_dev *dev){    ip_to_streams_minor_t    *ipptr = (ip_to_streams_minor_t *) dev->priv ;    netif_stop_queue(dev) ;    ipptr->contype = 0 ;    ipptr->ip_open = 0 ;    return(0) ;} /* ip_strm_close *//*************************************************************************                           ip_strm_init                          	***************************************************************************									** Initialize the dlpi -> sk_buf device. 				**									*************************************************************************/int ip_strm_init(struct ism_dev *dev){#ifndef KERNEL_2_1    int i;#endif    dev->mtu		   = IP_STRM_MTU;    dev->hard_start_xmit   = ip_strm_xmit;    dev->do_ioctl	   = ip_strm_ioctl;    dev->hard_header	   = 0;    dev->hard_header_len   = 0;    dev->addr_len	   = 0;    dev->tx_queue_len	   = 100;    dev->type		   = ARPHRD_DLCI;	/* 0x0001		*/    dev->rebuild_header	   = 0;    dev->open		   = ip_strm_open;    dev->flags		  |= IFF_POINTOPOINT;#ifdef KERNEL_2_1    dev->addr_len	   = 4;#else    dev->family		   = AF_INET;    dev->pa_addr	   = 0;    dev->pa_brdaddr	   = 0;    dev->pa_mask	   = 0;    dev->pa_alen	   = 4;#endif    dev->irq		   = 0;    memset(dev->dev_addr, 0, MAX_ADDR_LEN);    dev->get_stats = get_stats;    netif_start_queue(dev) ;#if !defined(KERNEL_2_1)    for (i = 0; i < DEV_NUMBUFFS; i++)	    skb_queue_head_init(&dev->buffs[i]);#endif    return(0);}

⌨️ 快捷键说明

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