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

📄 dvb_net.c

📁 linux_dvb的驱动程序:linuxtv-dvb-1.1.1.rar
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  * dvb_net.c * * Copyright (C) 2001 Convergence integrated media GmbH *                    Ralph Metzler <ralph@convergence.de> * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de> * * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Or, point your browser to http://www.gnu.org/copyleft/gpl.html *  */#include <linux/dvb/net.h>#include <asm/uaccess.h>#include "dvb_demux.h"#include "dvb_net.h"#include "dvb_functions.h"#if 1#define dprintk(x...) printk(x)#else#define dprintk(x...)#endif#define DVB_NET_MULTICAST_MAX 10struct dvb_net_priv {	int in_use;        struct net_device_stats stats;        char name[6];	u16 pid;        struct dmx_demux *demux;	struct dmx_section_feed *secfeed;	struct dmx_section_filter *secfilter;	int multi_num;	struct dmx_section_filter *multi_secfilter[DVB_NET_MULTICAST_MAX];	unsigned char multi_macs[DVB_NET_MULTICAST_MAX][6];	int rx_mode;#define RX_MODE_UNI 0#define RX_MODE_MULTI 1#define RX_MODE_ALL_MULTI 2#define RX_MODE_PROMISC 3	struct work_struct set_multicast_list_wq;	struct work_struct restart_net_feed_wq;};/** *	Determine the packet's protocol ID. The rule here is that we  *	assume 802.3 if the type field is short enough to be a length. *	This is normal practice and works for any 'now in use' protocol. * *  stolen from eth.c out of the linux kernel, hacked for dvb-device *  by Michael Holzt <kju@debian.org> */static unsigned short dvb_net_eth_type_trans(struct sk_buff *skb,				      struct net_device *dev){	struct ethhdr *eth;	unsigned char *rawp;		skb->mac.raw=skb->data;	skb_pull(skb,dev->hard_header_len);	eth= skb->mac.ethernet;		if (*eth->h_dest & 1) {		if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)			skb->pkt_type=PACKET_BROADCAST;		else			skb->pkt_type=PACKET_MULTICAST;	}		if (ntohs(eth->h_proto) >= 1536)		return eth->h_proto;			rawp = skb->data;		/**	 *	This is a magic hack to spot IPX packets. Older Novell breaks	 *	the protocol design and runs IPX over 802.3 without an 802.2 LLC	 *	layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This	 *	won't work for fault tolerant netware but does for the rest.	 */	if (*(unsigned short *)rawp == 0xFFFF)		return htons(ETH_P_802_3);			/**	 *	Real 802.2 LLC	 */	return htons(ETH_P_802_2);}static void dvb_net_sec(struct net_device *dev, u8 *pkt, int pkt_len){        u8 *eth;        struct sk_buff *skb;	struct net_device_stats *stats = &(((struct dvb_net_priv *) dev->priv)->stats);	/* note: pkt_len includes a 32bit checksum */	if (pkt_len < 16) {		printk("%s: IP/MPE packet length = %d too small.\n",			dev->name, pkt_len);		stats->rx_errors++;		stats->rx_length_errors++;		return;	}/* it seems some ISPs manage to screw up here, so we have to * relax the error checks... */#if 0	if ((pkt[5] & 0xfd) != 0xc1) {		/* drop scrambled or broken packets */#else	if ((pkt[5] & 0x3c) != 0x00) {		/* drop scrambled */#endif		stats->rx_errors++;		stats->rx_crc_errors++;		return;	}	if (pkt[5] & 0x02) {		//FIXME: handle LLC/SNAP                stats->rx_dropped++;                return;        }	if (pkt[7]) {		/* FIXME: assemble datagram from multiple sections */		stats->rx_errors++;		stats->rx_frame_errors++;		return;	}	/* we have 14 byte ethernet header (ip header follows);	 * 12 byte MPE header; 4 byte checksum; + 2 byte alignment	 */	if (!(skb = dev_alloc_skb(pkt_len - 4 - 12 + 14 + 2))) {		//printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);		stats->rx_dropped++;		return;	}	skb_reserve(skb, 2);    /* longword align L3 header */	skb->dev = dev;	/* copy L3 payload */	eth = (u8 *) skb_put(skb, pkt_len - 12 - 4 + 14);	memcpy(eth + 14, pkt + 12, pkt_len - 12 - 4);	/* create ethernet header: */        eth[0]=pkt[0x0b];        eth[1]=pkt[0x0a];        eth[2]=pkt[0x09];        eth[3]=pkt[0x08];        eth[4]=pkt[0x04];        eth[5]=pkt[0x03];        eth[6]=eth[7]=eth[8]=eth[9]=eth[10]=eth[11]=0;	eth[12] = 0x08;	/* ETH_P_IP */	eth[13] = 0x00;	skb->protocol = dvb_net_eth_type_trans(skb, dev);	stats->rx_packets++;	stats->rx_bytes+=skb->len;        netif_rx(skb);}static int dvb_net_callback(const u8 *buffer1, size_t buffer1_len,		 const u8 *buffer2, size_t buffer2_len,		 struct dmx_section_filter *filter,		 enum dmx_success success){        struct net_device *dev=(struct net_device *) filter->priv;	/**	 * we rely on the DVB API definition where exactly one complete	 * section is delivered in buffer1	 */	dvb_net_sec (dev, (u8*) buffer1, buffer1_len);	return 0;}static int dvb_net_tx(struct sk_buff *skb, struct net_device *dev){	return 0;}static u8 mask_normal[6]={0xff, 0xff, 0xff, 0xff, 0xff, 0xff};static u8 mask_allmulti[6]={0xff, 0xff, 0xff, 0x00, 0x00, 0x00};static u8 mac_allmulti[6]={0x01, 0x00, 0x5e, 0x00, 0x00, 0x00};static u8 mask_promisc[6]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00};static int dvb_net_filter_set(struct net_device *dev, 		   struct dmx_section_filter **secfilter,		   u8 *mac, u8 *mac_mask){	struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;	int ret;	*secfilter=0;	ret = priv->secfeed->allocate_filter(priv->secfeed, secfilter);	if (ret<0) {		printk("%s: could not get filter\n", dev->name);		return ret;	}	(*secfilter)->priv=(void *) dev;	memset((*secfilter)->filter_value, 0x00, DMX_MAX_FILTER_SIZE);	memset((*secfilter)->filter_mask,  0x00, DMX_MAX_FILTER_SIZE);	memset((*secfilter)->filter_mode,  0xff, DMX_MAX_FILTER_SIZE);	(*secfilter)->filter_value[0]=0x3e;	(*secfilter)->filter_value[3]=mac[5];	(*secfilter)->filter_value[4]=mac[4];	(*secfilter)->filter_value[8]=mac[3];	(*secfilter)->filter_value[9]=mac[2];	(*secfilter)->filter_value[10]=mac[1];	(*secfilter)->filter_value[11]=mac[0];	(*secfilter)->filter_mask[0] = 0xff;	(*secfilter)->filter_mask[3] = mac_mask[5];	(*secfilter)->filter_mask[4] = mac_mask[4];	(*secfilter)->filter_mask[8] = mac_mask[3];	(*secfilter)->filter_mask[9] = mac_mask[2];	(*secfilter)->filter_mask[10] = mac_mask[1];	(*secfilter)->filter_mask[11]=mac_mask[0];	dprintk("%s: filter mac=%02x %02x %02x %02x %02x %02x\n",	       dev->name, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);	dprintk("%s: filter mask=%02x %02x %02x %02x %02x %02x\n",	       dev->name, mac_mask[0], mac_mask[1], mac_mask[2],	       mac_mask[3], mac_mask[4], mac_mask[5]);	return 0;}static int dvb_net_feed_start(struct net_device *dev){	int ret, i;	struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;        struct dmx_demux *demux = priv->demux;        unsigned char *mac = (unsigned char *) dev->dev_addr;			dprintk("%s: rx_mode %i\n", __FUNCTION__, priv->rx_mode);	if (priv->secfeed || priv->secfilter || priv->multi_secfilter[0])		printk("%s: BUG %d\n", __FUNCTION__, __LINE__);	priv->secfeed=0;	priv->secfilter=0;	dprintk("%s: alloc secfeed\n", __FUNCTION__);	ret=demux->allocate_section_feed(demux, &priv->secfeed, 					 dvb_net_callback);	if (ret<0) {		printk("%s: could not allocate section feed\n", dev->name);		return ret;	}	ret = priv->secfeed->set(priv->secfeed, priv->pid, 32768, 0, 1);	if (ret<0) {		printk("%s: could not set section feed\n", dev->name);		priv->demux->release_section_feed(priv->demux, priv->secfeed);		priv->secfeed=0;		return ret;	}	if (priv->rx_mode != RX_MODE_PROMISC) {		dprintk("%s: set secfilter\n", __FUNCTION__);		dvb_net_filter_set(dev, &priv->secfilter, mac, mask_normal);	}	switch (priv->rx_mode) {	case RX_MODE_MULTI:		for (i = 0; i < priv->multi_num; i++) {			dprintk("%s: set multi_secfilter[%d]\n", __FUNCTION__, i);			dvb_net_filter_set(dev, &priv->multi_secfilter[i],					   priv->multi_macs[i], mask_normal);		}		break;	case RX_MODE_ALL_MULTI:		priv->multi_num=1;		dprintk("%s: set multi_secfilter[0]\n", __FUNCTION__);		dvb_net_filter_set(dev, &priv->multi_secfilter[0],				   mac_allmulti, mask_allmulti);		break;	case RX_MODE_PROMISC:		priv->multi_num=0;		dprintk("%s: set secfilter\n", __FUNCTION__);		dvb_net_filter_set(dev, &priv->secfilter, mac, mask_promisc);		break;	}		dprintk("%s: start filtering\n", __FUNCTION__);	priv->secfeed->start_filtering(priv->secfeed);	return 0;}static void dvb_net_feed_stop(struct net_device *dev){	struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;	int i;	dprintk("%s\n", __FUNCTION__);        if (priv->secfeed) {		if (priv->secfeed->is_filtering) {			dprintk("%s: stop secfeed\n", __FUNCTION__);		        priv->secfeed->stop_filtering(priv->secfeed);		}		if (priv->secfilter) {			dprintk("%s: release secfilter\n", __FUNCTION__);			priv->secfeed->release_filter(priv->secfeed,					       priv->secfilter);		priv->secfilter=0;		}		for (i=0; i<priv->multi_num; i++) {			if (priv->multi_secfilter[i]) {				dprintk("%s: release multi_filter[%d]\n", __FUNCTION__, i);				priv->secfeed->release_filter(priv->secfeed,						       priv->multi_secfilter[i]);			priv->multi_secfilter[i]=0;		}		}		priv->demux->release_section_feed(priv->demux, priv->secfeed);		priv->secfeed=0;	} else		printk("%s: no feed to stop\n", dev->name);}static int dvb_set_mc_filter (struct net_device *dev, struct dev_mc_list *mc){	struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;	if (priv->multi_num == DVB_NET_MULTICAST_MAX)		return -ENOMEM;	memcpy(priv->multi_macs[priv->multi_num], mc->dmi_addr, 6);	priv->multi_num++;	return 0;}static void wq_set_multicast_list (void *data){	struct net_device *dev = data;	struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;

⌨️ 快捷键说明

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