diff options
-rw-r--r-- | drivers/media/dvb/dvb-core/dvb_net.c | 35 |
1 files changed, 26 insertions, 9 deletions
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c index 997199cc5801..6a968c346a36 100644 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ b/drivers/media/dvb/dvb-core/dvb_net.c | |||
@@ -727,6 +727,7 @@ static void dvb_net_sec(struct net_device *dev, u8 *pkt, int pkt_len) | |||
727 | u8 *eth; | 727 | u8 *eth; |
728 | struct sk_buff *skb; | 728 | struct sk_buff *skb; |
729 | struct net_device_stats *stats = &(((struct dvb_net_priv *) dev->priv)->stats); | 729 | struct net_device_stats *stats = &(((struct dvb_net_priv *) dev->priv)->stats); |
730 | int snap = 0; | ||
730 | 731 | ||
731 | /* note: pkt_len includes a 32bit checksum */ | 732 | /* note: pkt_len includes a 32bit checksum */ |
732 | if (pkt_len < 16) { | 733 | if (pkt_len < 16) { |
@@ -750,9 +751,12 @@ static void dvb_net_sec(struct net_device *dev, u8 *pkt, int pkt_len) | |||
750 | return; | 751 | return; |
751 | } | 752 | } |
752 | if (pkt[5] & 0x02) { | 753 | if (pkt[5] & 0x02) { |
753 | //FIXME: handle LLC/SNAP | 754 | /* handle LLC/SNAP, see rfc-1042 */ |
754 | stats->rx_dropped++; | 755 | if (pkt_len < 24 || memcmp(&pkt[12], "\xaa\xaa\x03\0\0\0", 6)) { |
755 | return; | 756 | stats->rx_dropped++; |
757 | return; | ||
758 | } | ||
759 | snap = 8; | ||
756 | } | 760 | } |
757 | if (pkt[7]) { | 761 | if (pkt[7]) { |
758 | /* FIXME: assemble datagram from multiple sections */ | 762 | /* FIXME: assemble datagram from multiple sections */ |
@@ -762,9 +766,9 @@ static void dvb_net_sec(struct net_device *dev, u8 *pkt, int pkt_len) | |||
762 | } | 766 | } |
763 | 767 | ||
764 | /* we have 14 byte ethernet header (ip header follows); | 768 | /* we have 14 byte ethernet header (ip header follows); |
765 | * 12 byte MPE header; 4 byte checksum; + 2 byte alignment | 769 | * 12 byte MPE header; 4 byte checksum; + 2 byte alignment, 8 byte LLC/SNAP |
766 | */ | 770 | */ |
767 | if (!(skb = dev_alloc_skb(pkt_len - 4 - 12 + 14 + 2))) { | 771 | if (!(skb = dev_alloc_skb(pkt_len - 4 - 12 + 14 + 2 - snap))) { |
768 | //printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); | 772 | //printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); |
769 | stats->rx_dropped++; | 773 | stats->rx_dropped++; |
770 | return; | 774 | return; |
@@ -773,8 +777,8 @@ static void dvb_net_sec(struct net_device *dev, u8 *pkt, int pkt_len) | |||
773 | skb->dev = dev; | 777 | skb->dev = dev; |
774 | 778 | ||
775 | /* copy L3 payload */ | 779 | /* copy L3 payload */ |
776 | eth = (u8 *) skb_put(skb, pkt_len - 12 - 4 + 14); | 780 | eth = (u8 *) skb_put(skb, pkt_len - 12 - 4 + 14 - snap); |
777 | memcpy(eth + 14, pkt + 12, pkt_len - 12 - 4); | 781 | memcpy(eth + 14, pkt + 12 + snap, pkt_len - 12 - 4 - snap); |
778 | 782 | ||
779 | /* create ethernet header: */ | 783 | /* create ethernet header: */ |
780 | eth[0]=pkt[0x0b]; | 784 | eth[0]=pkt[0x0b]; |
@@ -786,8 +790,21 @@ static void dvb_net_sec(struct net_device *dev, u8 *pkt, int pkt_len) | |||
786 | 790 | ||
787 | eth[6]=eth[7]=eth[8]=eth[9]=eth[10]=eth[11]=0; | 791 | eth[6]=eth[7]=eth[8]=eth[9]=eth[10]=eth[11]=0; |
788 | 792 | ||
789 | eth[12] = 0x08; /* ETH_P_IP */ | 793 | if (snap) { |
790 | eth[13] = 0x00; | 794 | eth[12] = pkt[18]; |
795 | eth[13] = pkt[19]; | ||
796 | } else { | ||
797 | /* protocol numbers are from rfc-1700 or | ||
798 | * http://www.iana.org/assignments/ethernet-numbers | ||
799 | */ | ||
800 | if (pkt[12] >> 4 == 6) { /* version field from IP header */ | ||
801 | eth[12] = 0x86; /* IPv6 */ | ||
802 | eth[13] = 0xdd; | ||
803 | } else { | ||
804 | eth[12] = 0x08; /* IPv4 */ | ||
805 | eth[13] = 0x00; | ||
806 | } | ||
807 | } | ||
791 | 808 | ||
792 | skb->protocol = dvb_net_eth_type_trans(skb, dev); | 809 | skb->protocol = dvb_net_eth_type_trans(skb, dev); |
793 | 810 | ||