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

📄 dvb_net.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
		}		/* Check if new payload needs to be started. */		if (priv->ule_skb == NULL) {			/* Start a new payload with skb.			 * Find ULE header.  It is only guaranteed that the			 * length field (2 bytes) is contained in the current			 * TS.			 * Check ts_remain has to be >= 2 here. */			if (ts_remain < 2) {				printk(KERN_WARNING "Invalid payload packing: only %d "				       "bytes left in TS.  Resyncing.\n", ts_remain);				priv->ule_sndu_len = 0;				priv->need_pusi = 1;				continue;			}			if (! priv->ule_sndu_len) {				/* Got at least two bytes, thus extrace the SNDU length. */				priv->ule_sndu_len = from_where[0] << 8 | from_where[1];				if (priv->ule_sndu_len & 0x8000) {					/* D-Bit is set: no dest mac present. */					priv->ule_sndu_len &= 0x7FFF;					priv->ule_dbit = 1;				} else					priv->ule_dbit = 0;				if (priv->ule_sndu_len > 32763) {					printk(KERN_WARNING "%lu: Invalid ULE SNDU length %u. "					       "Resyncing.\n", priv->ts_count, priv->ule_sndu_len);					priv->ule_sndu_len = 0;					priv->need_pusi = 1;					new_ts = 1;					ts += TS_SZ;					priv->ts_count++;					continue;				}				ts_remain -= 2;	/* consume the 2 bytes SNDU length. */				from_where += 2;			}			/*			 * State of current TS:			 *   ts_remain (remaining bytes in the current TS cell)			 *   0	ule_type is not available now, we need the next TS cell			 *   1	the first byte of the ule_type is present			 * >=2	full ULE header present, maybe some payload data as well.			 */			switch (ts_remain) {				case 1:					priv->ule_sndu_type = from_where[0] << 8;					priv->ule_sndu_type_1 = 1; /* first byte of ule_type is set. */					ts_remain -= 1; from_where += 1;					/* Continue w/ next TS. */				case 0:					new_ts = 1;					ts += TS_SZ;					priv->ts_count++;					continue;				default: /* complete ULE header is present in current TS. */					/* Extract ULE type field. */					if (priv->ule_sndu_type_1) {						priv->ule_sndu_type |= from_where[0];						from_where += 1; /* points to payload start. */						ts_remain -= 1;					} else {						/* Complete type is present in new TS. */						priv->ule_sndu_type = from_where[0] << 8 | from_where[1];						from_where += 2; /* points to payload start. */						ts_remain -= 2;					}					break;			}			/* Allocate the skb (decoder target buffer) with the correct size, as follows:			 * prepare for the largest case: bridged SNDU with MAC address (dbit = 0). */			priv->ule_skb = dev_alloc_skb( priv->ule_sndu_len + ETH_HLEN + ETH_ALEN );			if (priv->ule_skb == NULL) {				printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n",				       dev->name);				((struct dvb_net_priv *)dev->priv)->stats.rx_dropped++;				return;			}			/* This includes the CRC32 _and_ dest mac, if !dbit. */			priv->ule_sndu_remain = priv->ule_sndu_len;			priv->ule_skb->dev = dev;			/* Leave space for Ethernet or bridged SNDU header (eth hdr plus one MAC addr). */			skb_reserve( priv->ule_skb, ETH_HLEN + ETH_ALEN );		}		/* Copy data into our current skb. */		how_much = min(priv->ule_sndu_remain, (int)ts_remain);		memcpy(skb_put(priv->ule_skb, how_much), from_where, how_much);		priv->ule_sndu_remain -= how_much;		ts_remain -= how_much;		from_where += how_much;		/* Check for complete payload. */		if (priv->ule_sndu_remain <= 0) {			/* Check CRC32, we've got it in our skb already. */			unsigned short ulen = htons(priv->ule_sndu_len);			unsigned short utype = htons(priv->ule_sndu_type);			struct kvec iov[3] = {				{ &ulen, sizeof ulen },				{ &utype, sizeof utype },				{ priv->ule_skb->data, priv->ule_skb->len - 4 }			};			unsigned long ule_crc = ~0L, expected_crc;			if (priv->ule_dbit) {				/* Set D-bit for CRC32 verification,				 * if it was set originally. */				ulen |= 0x0080;			}			ule_crc = iov_crc32(ule_crc, iov, 3);			expected_crc = *((u8 *)priv->ule_skb->tail - 4) << 24 |				       *((u8 *)priv->ule_skb->tail - 3) << 16 |				       *((u8 *)priv->ule_skb->tail - 2) << 8 |				       *((u8 *)priv->ule_skb->tail - 1);			if (ule_crc != expected_crc) {				printk(KERN_WARNING "%lu: CRC32 check FAILED: %#lx / %#lx, SNDU len %d type %#x, ts_remain %d, next 2: %x.\n",				       priv->ts_count, ule_crc, expected_crc, priv->ule_sndu_len, priv->ule_sndu_type, ts_remain, ts_remain > 2 ? *(unsigned short *)from_where : 0);#ifdef ULE_DEBUG				hexdump( iov[0].iov_base, iov[0].iov_len );				hexdump( iov[1].iov_base, iov[1].iov_len );				hexdump( iov[2].iov_base, iov[2].iov_len );				if (ule_where == ule_hist) {					hexdump( &ule_hist[98*TS_SZ], TS_SZ );					hexdump( &ule_hist[99*TS_SZ], TS_SZ );				} else if (ule_where == &ule_hist[TS_SZ]) {					hexdump( &ule_hist[99*TS_SZ], TS_SZ );					hexdump( ule_hist, TS_SZ );				} else {					hexdump( ule_where - TS_SZ - TS_SZ, TS_SZ );					hexdump( ule_where - TS_SZ, TS_SZ );				}				ule_dump = 1;#endif				((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;				((struct dvb_net_priv *) dev->priv)->stats.rx_crc_errors++;				dev_kfree_skb(priv->ule_skb);			} else {				/* CRC32 verified OK. */				/* Handle ULE Extension Headers. */				if (priv->ule_sndu_type < 1536) {					/* There is an extension header.  Handle it accordingly. */					int l = handle_ule_extensions( priv );					if (l < 0) {						/* Mandatory extension header unknown or TEST SNDU.  Drop it. */						// printk( KERN_WARNING "Dropping SNDU, extension headers.\n" );						dev_kfree_skb( priv->ule_skb );						goto sndu_done;					}					skb_pull( priv->ule_skb, l );				}				/* CRC32 was OK. Remove it from skb. */				priv->ule_skb->tail -= 4;				priv->ule_skb->len -= 4;				/* Filter on receiver's destination MAC address, if present. */				if (!priv->ule_dbit) {					/* The destination MAC address is the next data in the skb. */					if (memcmp( priv->ule_skb->data, dev->dev_addr, ETH_ALEN )) {						/* MAC addresses don't match.  Drop SNDU. */						// printk( KERN_WARNING "Dropping SNDU, MAC address.\n" );						dev_kfree_skb( priv->ule_skb );						goto sndu_done;					}					if (! priv->ule_bridged) {						skb_push( priv->ule_skb, ETH_ALEN + 2 );						ethh = (struct ethhdr *)priv->ule_skb->data;						memcpy( ethh->h_dest, ethh->h_source, ETH_ALEN );						memset( ethh->h_source, 0, ETH_ALEN );						ethh->h_proto = htons( priv->ule_sndu_type );					} else {						/* Skip the Receiver destination MAC address. */						skb_pull( priv->ule_skb, ETH_ALEN );					}				} else {					if (! priv->ule_bridged) {						skb_push( priv->ule_skb, ETH_HLEN );						ethh = (struct ethhdr *)priv->ule_skb->data;						memcpy( ethh->h_dest, dev->dev_addr, ETH_ALEN );						memset( ethh->h_source, 0, ETH_ALEN );						ethh->h_proto = htons( priv->ule_sndu_type );					} else {						/* skb is in correct state; nothing to do. */					}				}				priv->ule_bridged = 0;				/* Stuff into kernel's protocol stack. */				priv->ule_skb->protocol = dvb_net_eth_type_trans(priv->ule_skb, dev);				/* If D-bit is set (i.e. destination MAC address not present),				 * receive the packet anyhow. */				/* if (priv->ule_dbit && skb->pkt_type == PACKET_OTHERHOST)					priv->ule_skb->pkt_type = PACKET_HOST; */				((struct dvb_net_priv *) dev->priv)->stats.rx_packets++;				((struct dvb_net_priv *) dev->priv)->stats.rx_bytes += priv->ule_skb->len;				netif_rx(priv->ule_skb);			}			sndu_done:			/* Prepare for next SNDU. */			reset_ule(priv);		}		/* More data in current TS (look at the bytes following the CRC32)? */		if (ts_remain >= 2 && *((unsigned short *)from_where) != 0xFFFF) {			/* Next ULE SNDU starts right there. */			new_ts = 0;			priv->ule_skb = NULL;			priv->ule_sndu_type_1 = 0;			priv->ule_sndu_len = 0;			// printk(KERN_WARNING "More data in current TS: [%#x %#x %#x %#x]\n",			//	*(from_where + 0), *(from_where + 1),			//	*(from_where + 2), *(from_where + 3));			// printk(KERN_WARNING "ts @ %p, stopped @ %p:\n", ts, from_where + 0);			// hexdump(ts, 188);		} else {			new_ts = 1;			ts += TS_SZ;			priv->ts_count++;			if (priv->ule_skb == NULL) {				priv->need_pusi = 1;				priv->ule_sndu_type_1 = 0;				priv->ule_sndu_len = 0;			}		}	}	/* for all available TS cells */}static int dvb_net_ts_callback(const u8 *buffer1, size_t buffer1_len,			       const u8 *buffer2, size_t buffer2_len,			       struct dmx_ts_feed *feed, enum dmx_success success){	struct net_device *dev = feed->priv;	if (buffer2 != 0)		printk(KERN_WARNING "buffer2 not 0: %p.\n", buffer2);	if (buffer1_len > 32768)		printk(KERN_WARNING "length > 32k: %zu.\n", buffer1_len);	/* printk("TS callback: %u bytes, %u TS cells @ %p.\n",		  buffer1_len, buffer1_len / TS_SZ, buffer1); */	dvb_net_ule(dev, buffer1, buffer1_len);	return 0;}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);	int snap = 0;	/* 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) {		/* handle LLC/SNAP, see rfc-1042 */		if (pkt_len < 24 || memcmp(&pkt[12], "\xaa\xaa\x03\0\0\0", 6)) {			stats->rx_dropped++;			return;		}		snap = 8;	}	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, 8 byte LLC/SNAP	 */	if (!(skb = dev_alloc_skb(pkt_len - 4 - 12 + 14 + 2 - snap))) {		//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 - snap);	memcpy(eth + 14, pkt + 12 + snap, pkt_len - 12 - 4 - snap);	/* 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;	if (snap) {		eth[12] = pkt[18];		eth[13] = pkt[19];	} else {		/* protocol numbers are from rfc-1700 or		 * http://www.iana.org/assignments/ethernet-numbers		 */		if (pkt[12] >> 4 == 6) { /* version field from IP header */			eth[12] = 0x86;	/* IPv6 */			eth[13] = 0xdd;		} else {			eth[12] = 0x08;	/* IPv4 */			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_sec_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 = 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){	dev_kfree_skb(skb);	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_sec_set(struct net_device *dev,		   struct dmx_section_filter **secfilter,		   u8 *mac, u8 *mac_mask){	struct dvb_net_priv *priv = dev->priv;	int ret;	*secfilter=NULL;	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 = 0, i;	struct dvb_net_priv *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);	down(&priv->mutex);	if (priv->tsfeed || priv->secfeed || priv->secfilter || priv->multi_secfilter[0])		printk("%s: BUG %d\n", __FUNCTION__, __LINE__);	priv->secfeed=NULL;	priv->secfilter=NULL;	priv->tsfeed = NULL;	if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {		dprintk("%s: alloc secfeed\n", __FUNCTION__);		ret=demux->allocate_section_feed(demux, &priv->secfeed,					 dvb_net_sec_callback);		if (ret<0) {			printk("%s: could not allocate section feed\n", dev->name);			goto error;		}		ret = priv->secfeed->set(priv->secfeed, priv->pid, 32768, 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=NULL;			goto error;		}		if (priv->rx_mode != RX_MODE_PROMISC) {			dprintk("%s: set secfilter\n", __FUNCTION__);			dvb_net_filter_sec_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_sec_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_sec_set(dev, &priv->multi_secfilter[0],

⌨️ 快捷键说明

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