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 + -
显示快捷键?