/*
* dvb_net.c
*
* Copyright (C) 2001 Convergence integrated media GmbH
* Ralph Metzler <ralph@convergence.de>
* Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
*
* ULE Decapsulation code:
* Copyright (C) 2003, 2004 gcs - Global Communication & Services GmbH.
* and Department of Scientific Computing
* Paris Lodron University of Salzburg.
* Hilmar Linder <hlinder@cosy.sbg.ac.at>
* and Wolfram Stering <wstering@cosy.sbg.ac.at>
*
* ULE Decaps according to RFC 4326.
*
* 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
*/
/*
* ULE ChangeLog:
* Feb 2004: hl/ws v1: Implementing draft-fair-ipdvb-ule-01.txt
*
* Dec 2004: hl/ws v2: Implementing draft-ietf-ipdvb-ule-03.txt:
* ULE Extension header handling.
* Bugreports by Moritz Vieth and Hanno Tersteegen,
* Fraunhofer Institute for Open Communication Systems
* Competence Center for Advanced Satellite Communications.
* Bugfixes and robustness improvements.
* Filtering on dest MAC addresses, if present (D-Bit = 0)
* ULE_DEBUG compile-time option.
* Apr 2006: cp v3: Bugfixes and compliency with RFC 4326 (ULE) by
* Christian Praehauser <cpraehaus@cosy.sbg.ac.at>,
* Paris Lodron University of Salzburg.
*/
/*
* FIXME / TODO (dvb_net.c):
*
* Unloading does not work for 2.6.9 kernels: a refcount doesn't go to zero.
*
*/
#define pr_fmt(fmt) "dvb_net: " fmt
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/dvb/net.h>
#include <linux/uio.h>
#include <asm/uaccess.h>
#include <linux/crc32.h>
#include <linux/mutex.h>
#include <linux/sched.h>
#include "dvb_demux.h"
#include "dvb_net.h"
static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt )
{
unsigned int j;
for (j = 0; j < cnt; j++)
c = crc32_be( c, iov[j].iov_base, iov[j].iov_len );
return c;
}
#define DVB_NET_MULTICAST_MAX 10
#undef ULE_DEBUG
#ifdef ULE_DEBUG
static void hexdump(const unsigned char *buf, unsigned short len)
{
print_hex_dump_debug("", DUMP_PREFIX_OFFSET, 16, 1, buf, len, true);
}
#endif
struct dvb_net_priv {
int in_use;
u16 pid;
struct net_device *net;
struct dvb_net *host;
struct dmx_demux *demux;
struct dmx_section_feed *secfeed;
struct dmx_section_filter *secfilter;
struct dmx_ts_feed *tsfeed;
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;
unsigned char feedtype; /* Either FEED_TYPE_ or FEED_TYPE_ULE */
int need_pusi; /* Set to 1, if synchronization on PUSI required. */
unsigned char tscc; /* TS continuity counter after sync on PUSI. */
struct sk_buff *ule_skb; /* ULE SNDU decodes into this buffer. */
unsigned char *ule_next_hdr; /* Pointer into skb to next ULE extension header. */
unsigned short ule_sndu_len; /* ULE SNDU length in bytes, w/o D-Bit. */
unsigned short ule_sndu_type; /* ULE SNDU type field, complete. */
unsigned char ule_sndu_type_1; /* ULE SNDU type field, if split across 2 TS cells. */
unsigned char ule_dbit; /* Whether the DestMAC address present
* or not (bit is set). */
unsigned char ule_bridged; /* Whether the ULE_BRIDGED extension header was found. */
int ule_sndu_remain; /* Nr. of bytes still required for current ULE SNDU. */
unsigned long ts_count; /* Current ts cell counter. */
struct mutex mutex;
};
/**
* 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 __be16 dvb_net_eth_type_trans(struct sk_buff *skb,
struct net_device *dev)
{
struct ethhdr *eth;
unsigned char *rawp;
skb_reset_mac_header(skb);
skb_pull(skb,dev->hard_header_len);
eth = eth_hdr(skb);
if (*eth->h_dest & 1) {
if(ether_addr_equal(eth->h_dest,dev->broadcast))
skb->pkt_type=PACKET_BROADCAST;
else
skb->pkt_type=PACKET_MULTICAST;
}
if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN)
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);
}
#define TS_SZ 188
#define TS_SYNC 0x47
#define TS_TEI 0x80
#define TS_SC 0xC0
#define TS_PUSI 0x40
#define TS_AF_A 0x20
#define TS_AF_D 0x10
/* ULE Extension Header handlers. */
#define ULE_TEST 0
#define ULE_BRIDGED 1
#define ULE_OPTEXTHDR_PADDING 0
static int ule_test_sndu( struct dvb_net_priv *p )
{
return -1;
}
static int ule_bridged_sndu( struct dvb_net_priv *p )
{
struct ethhdr *hdr = (struct ethhdr*) p->ule_next_hdr;
if(ntohs(hdr->h_proto) < ETH_P_802_3_MIN) {
int framelen = p->ule_sndu_len - ((p->ule_next_hdr+sizeof(struct ethhdr)) - p->ule_skb->data);
/* A frame Type < ETH_P_802_3_MIN for a bridged frame, introduces a LLC Length field. */
if(framelen != ntohs(hdr->h_proto)) {
return -1;
}
}
/* Note:
* From RFC4326:
* "A bridged SNDU is a Mandatory Extension Header of Type 1.
* It must be the final (or only) extension header specified in the header chain of a SNDU."
* The 'ule_bridged' flag will cause the extension header processing loop to terminate.
*/
p->ule_bridged = 1;
return 0;
}
static int ule_exthdr_padding(struct dvb_net_priv *p)
{
return 0;
}
/** Handle ULE extension headers.
* Function is called after a successful CRC32 verification of an ULE SNDU to complete its decoding.
* Returns: >= 0: nr. of bytes consumed by next extension header
* -1: Mandatory extension header that is not recognized or TEST SNDU; discard.
*/
static int handle_one_ule_extension( struct dvb_net_priv *p )
{
/* Table of mandatory extension header handlers. The header type is the index. */
static int (*ule_mandatory_ext_handlers[255])( struct dvb_net_priv *p ) =
{ [0] = ule_test_sndu, [1] = ule_bridged_sndu, [2] = NULL, };
/* Table of optional extension header handlers. The header type is the index. */
static int (*ule_optional_ext_handlers[255])( struct dvb_net_priv *p ) =
{ [0] = ule_exthdr_padding, [1] = NULL, };
int ext_len = 0;
unsigned char hlen = (p->ule_sndu_type & 0x
|