diff options
author | Christian Praehauser <cpraehaus@cosy.sbg.ac.at> | 2006-05-22 09:31:47 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-06-25 00:59:54 -0400 |
commit | 18232ca61b4c73b849850200a5e6ec40517f35ab (patch) | |
tree | db62beb024d77bac0bb4351a01535d71cb0bc227 /drivers/media | |
parent | adcb0fa2504aac35e0ed285147b11e75a6db34c7 (diff) |
V4L/DVB (3966): Core: ULE fixes and RFC4326 additions
Fix some problems regarding support for Unidirectional Lightweight
Encapsulation (ULE) in dvbnet.c.
The original ULE code was based on a draft. In the meantime, ULE has been
published in RFC 4326 (ftp://ftp.rfc-editor.org/in-notes/rfc4326.txt).
With these fixes, and some additions (which are included in the patch), the
decaps code should now be complient to RFC4326.
Signed-off-by: Christian Praehauser <cpraehaus@cosy.sbg.ac.at>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/dvb/dvb-core/dvb_net.c | 230 |
1 files changed, 154 insertions, 76 deletions
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c index 9fd87521a163..8859ab74f0fe 100644 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ b/drivers/media/dvb/dvb-core/dvb_net.c | |||
@@ -12,7 +12,7 @@ | |||
12 | * Hilmar Linder <hlinder@cosy.sbg.ac.at> | 12 | * Hilmar Linder <hlinder@cosy.sbg.ac.at> |
13 | * and Wolfram Stering <wstering@cosy.sbg.ac.at> | 13 | * and Wolfram Stering <wstering@cosy.sbg.ac.at> |
14 | * | 14 | * |
15 | * ULE Decaps according to draft-ietf-ipdvb-ule-03.txt. | 15 | * ULE Decaps according to RFC 4326. |
16 | * | 16 | * |
17 | * This program is free software; you can redistribute it and/or | 17 | * This program is free software; you can redistribute it and/or |
18 | * modify it under the terms of the GNU General Public License | 18 | * modify it under the terms of the GNU General Public License |
@@ -42,6 +42,9 @@ | |||
42 | * Bugfixes and robustness improvements. | 42 | * Bugfixes and robustness improvements. |
43 | * Filtering on dest MAC addresses, if present (D-Bit = 0) | 43 | * Filtering on dest MAC addresses, if present (D-Bit = 0) |
44 | * ULE_DEBUG compile-time option. | 44 | * ULE_DEBUG compile-time option. |
45 | * Apr 2006: cp v3: Bugfixes and compliency with RFC 4326 (ULE) by | ||
46 | * Christian Praehauser <cpraehaus@cosy.sbg.ac.at>, | ||
47 | * Paris Lodron University of Salzburg. | ||
45 | */ | 48 | */ |
46 | 49 | ||
47 | /* | 50 | /* |
@@ -49,9 +52,6 @@ | |||
49 | * | 52 | * |
50 | * Unloading does not work for 2.6.9 kernels: a refcount doesn't go to zero. | 53 | * Unloading does not work for 2.6.9 kernels: a refcount doesn't go to zero. |
51 | * | 54 | * |
52 | * TS_FEED callback is called once for every single TS cell although it is | ||
53 | * registered (in dvb_net_feed_start()) for 100 TS cells (used for dvb_net_ule()). | ||
54 | * | ||
55 | */ | 55 | */ |
56 | 56 | ||
57 | #include <linux/module.h> | 57 | #include <linux/module.h> |
@@ -89,6 +89,9 @@ static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt ) | |||
89 | 89 | ||
90 | #ifdef ULE_DEBUG | 90 | #ifdef ULE_DEBUG |
91 | 91 | ||
92 | #define MAC_ADDR_PRINTFMT "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" | ||
93 | #define MAX_ADDR_PRINTFMT_ARGS(macap) (macap)[0],(macap)[1],(macap)[2],(macap)[3],(macap)[4],(macap)[5] | ||
94 | |||
92 | #define isprint(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) | 95 | #define isprint(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) |
93 | 96 | ||
94 | static void hexdump( const unsigned char *buf, unsigned short len ) | 97 | static void hexdump( const unsigned char *buf, unsigned short len ) |
@@ -214,6 +217,8 @@ static unsigned short dvb_net_eth_type_trans(struct sk_buff *skb, | |||
214 | #define ULE_TEST 0 | 217 | #define ULE_TEST 0 |
215 | #define ULE_BRIDGED 1 | 218 | #define ULE_BRIDGED 1 |
216 | 219 | ||
220 | #define ULE_OPTEXTHDR_PADDING 0 | ||
221 | |||
217 | static int ule_test_sndu( struct dvb_net_priv *p ) | 222 | static int ule_test_sndu( struct dvb_net_priv *p ) |
218 | { | 223 | { |
219 | return -1; | 224 | return -1; |
@@ -221,14 +226,28 @@ static int ule_test_sndu( struct dvb_net_priv *p ) | |||
221 | 226 | ||
222 | static int ule_bridged_sndu( struct dvb_net_priv *p ) | 227 | static int ule_bridged_sndu( struct dvb_net_priv *p ) |
223 | { | 228 | { |
224 | /* BRIDGE SNDU handling sucks in draft-ietf-ipdvb-ule-03.txt. | 229 | struct ethhdr *hdr = (struct ethhdr*) p->ule_next_hdr; |
225 | * This has to be the last extension header, otherwise it won't work. | 230 | if(ntohs(hdr->h_proto) < 1536) { |
226 | * Blame the authors! | 231 | int framelen = p->ule_sndu_len - ((p->ule_next_hdr+sizeof(struct ethhdr)) - p->ule_skb->data); |
232 | /* A frame Type < 1536 for a bridged frame, introduces a LLC Length field. */ | ||
233 | if(framelen != ntohs(hdr->h_proto)) { | ||
234 | return -1; | ||
235 | } | ||
236 | } | ||
237 | /* Note: | ||
238 | * From RFC4326: | ||
239 | * "A bridged SNDU is a Mandatory Extension Header of Type 1. | ||
240 | * It must be the final (or only) extension header specified in the header chain of a SNDU." | ||
241 | * The 'ule_bridged' flag will cause the extension header processing loop to terminate. | ||
227 | */ | 242 | */ |
228 | p->ule_bridged = 1; | 243 | p->ule_bridged = 1; |
229 | return 0; | 244 | return 0; |
230 | } | 245 | } |
231 | 246 | ||
247 | static int ule_exthdr_padding(struct dvb_net_priv *p) | ||
248 | { | ||
249 | return 0; | ||
250 | } | ||
232 | 251 | ||
233 | /** Handle ULE extension headers. | 252 | /** Handle ULE extension headers. |
234 | * Function is called after a successful CRC32 verification of an ULE SNDU to complete its decoding. | 253 | * Function is called after a successful CRC32 verification of an ULE SNDU to complete its decoding. |
@@ -242,7 +261,8 @@ static int handle_one_ule_extension( struct dvb_net_priv *p ) | |||
242 | { [0] = ule_test_sndu, [1] = ule_bridged_sndu, [2] = NULL, }; | 261 | { [0] = ule_test_sndu, [1] = ule_bridged_sndu, [2] = NULL, }; |
243 | 262 | ||
244 | /* Table of optional extension header handlers. The header type is the index. */ | 263 | /* Table of optional extension header handlers. The header type is the index. */ |
245 | static int (*ule_optional_ext_handlers[255])( struct dvb_net_priv *p ) = { NULL, }; | 264 | static int (*ule_optional_ext_handlers[255])( struct dvb_net_priv *p ) = |
265 | { [0] = ule_exthdr_padding, [1] = NULL, }; | ||
246 | 266 | ||
247 | int ext_len = 0; | 267 | int ext_len = 0; |
248 | unsigned char hlen = (p->ule_sndu_type & 0x0700) >> 8; | 268 | unsigned char hlen = (p->ule_sndu_type & 0x0700) >> 8; |
@@ -253,25 +273,31 @@ static int handle_one_ule_extension( struct dvb_net_priv *p ) | |||
253 | /* Mandatory extension header */ | 273 | /* Mandatory extension header */ |
254 | if (ule_mandatory_ext_handlers[htype]) { | 274 | if (ule_mandatory_ext_handlers[htype]) { |
255 | ext_len = ule_mandatory_ext_handlers[htype]( p ); | 275 | ext_len = ule_mandatory_ext_handlers[htype]( p ); |
256 | p->ule_next_hdr += ext_len; | 276 | if(ext_len >= 0) { |
257 | if (! p->ule_bridged) { | 277 | p->ule_next_hdr += ext_len; |
258 | p->ule_sndu_type = ntohs( *(unsigned short *)p->ule_next_hdr ); | 278 | if (!p->ule_bridged) { |
259 | p->ule_next_hdr += 2; | 279 | p->ule_sndu_type = ntohs(*(unsigned short *)p->ule_next_hdr); |
260 | } else { | 280 | p->ule_next_hdr += 2; |
261 | p->ule_sndu_type = ntohs( *(unsigned short *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN)) ); | 281 | } else { |
262 | /* This assures the extension handling loop will terminate. */ | 282 | p->ule_sndu_type = ntohs(*(unsigned short *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN))); |
283 | /* This assures the extension handling loop will terminate. */ | ||
284 | } | ||
263 | } | 285 | } |
286 | // else: extension handler failed or SNDU should be discarded | ||
264 | } else | 287 | } else |
265 | ext_len = -1; /* SNDU has to be discarded. */ | 288 | ext_len = -1; /* SNDU has to be discarded. */ |
266 | } else { | 289 | } else { |
267 | /* Optional extension header. Calculate the length. */ | 290 | /* Optional extension header. Calculate the length. */ |
268 | ext_len = hlen << 2; | 291 | ext_len = hlen << 1; |
269 | /* Process the optional extension header according to its type. */ | 292 | /* Process the optional extension header according to its type. */ |
270 | if (ule_optional_ext_handlers[htype]) | 293 | if (ule_optional_ext_handlers[htype]) |
271 | (void)ule_optional_ext_handlers[htype]( p ); | 294 | (void)ule_optional_ext_handlers[htype]( p ); |
272 | p->ule_next_hdr += ext_len; | 295 | p->ule_next_hdr += ext_len; |
273 | p->ule_sndu_type = ntohs( *(unsigned short *)p->ule_next_hdr ); | 296 | p->ule_sndu_type = ntohs( *(unsigned short *)(p->ule_next_hdr-2) ); |
274 | p->ule_next_hdr += 2; | 297 | /* |
298 | * note: the length of the next header type is included in the | ||
299 | * length of THIS optional extension header | ||
300 | */ | ||
275 | } | 301 | } |
276 | 302 | ||
277 | return ext_len; | 303 | return ext_len; |
@@ -284,8 +310,14 @@ static int handle_ule_extensions( struct dvb_net_priv *p ) | |||
284 | p->ule_next_hdr = p->ule_skb->data; | 310 | p->ule_next_hdr = p->ule_skb->data; |
285 | do { | 311 | do { |
286 | l = handle_one_ule_extension( p ); | 312 | l = handle_one_ule_extension( p ); |
287 | if (l == -1) return -1; /* Stop extension header processing and discard SNDU. */ | 313 | if (l < 0) |
314 | return l; /* Stop extension header processing and discard SNDU. */ | ||
288 | total_ext_len += l; | 315 | total_ext_len += l; |
316 | #ifdef ULE_DEBUG | ||
317 | dprintk("handle_ule_extensions: ule_next_hdr=%p, ule_sndu_type=%i, " | ||
318 | "l=%i, total_ext_len=%i\n", p->ule_next_hdr, | ||
319 | (int) p->ule_sndu_type, l, total_ext_len); | ||
320 | #endif | ||
289 | 321 | ||
290 | } while (p->ule_sndu_type < 1536); | 322 | } while (p->ule_sndu_type < 1536); |
291 | 323 | ||
@@ -355,8 +387,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) | |||
355 | if (priv->ule_skb) { | 387 | if (priv->ule_skb) { |
356 | dev_kfree_skb( priv->ule_skb ); | 388 | dev_kfree_skb( priv->ule_skb ); |
357 | /* Prepare for next SNDU. */ | 389 | /* Prepare for next SNDU. */ |
358 | ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++; | 390 | priv->stats.rx_errors++; |
359 | ((struct dvb_net_priv *) dev->priv)->stats.rx_frame_errors++; | 391 | priv->stats.rx_frame_errors++; |
360 | } | 392 | } |
361 | reset_ule(priv); | 393 | reset_ule(priv); |
362 | priv->need_pusi = 1; | 394 | priv->need_pusi = 1; |
@@ -396,27 +428,25 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) | |||
396 | } | 428 | } |
397 | } | 429 | } |
398 | 430 | ||
399 | /* Check continuity counter. */ | ||
400 | if (new_ts) { | 431 | if (new_ts) { |
432 | /* Check continuity counter. */ | ||
401 | if ((ts[3] & 0x0F) == priv->tscc) | 433 | if ((ts[3] & 0x0F) == priv->tscc) |
402 | priv->tscc = (priv->tscc + 1) & 0x0F; | 434 | priv->tscc = (priv->tscc + 1) & 0x0F; |
403 | else { | 435 | else { |
404 | /* TS discontinuity handling: */ | 436 | /* TS discontinuity handling: */ |
405 | printk(KERN_WARNING "%lu: TS discontinuity: got %#x, " | 437 | printk(KERN_WARNING "%lu: TS discontinuity: got %#x, " |
406 | "exptected %#x.\n", priv->ts_count, ts[3] & 0x0F, priv->tscc); | 438 | "expected %#x.\n", priv->ts_count, ts[3] & 0x0F, priv->tscc); |
407 | /* Drop partly decoded SNDU, reset state, resync on PUSI. */ | 439 | /* Drop partly decoded SNDU, reset state, resync on PUSI. */ |
408 | if (priv->ule_skb) { | 440 | if (priv->ule_skb) { |
409 | dev_kfree_skb( priv->ule_skb ); | 441 | dev_kfree_skb( priv->ule_skb ); |
410 | /* Prepare for next SNDU. */ | 442 | /* Prepare for next SNDU. */ |
411 | // reset_ule(priv); moved to below. | 443 | // reset_ule(priv); moved to below. |
412 | ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++; | 444 | priv->stats.rx_errors++; |
413 | ((struct dvb_net_priv *) dev->priv)->stats.rx_frame_errors++; | 445 | priv->stats.rx_frame_errors++; |
414 | } | 446 | } |
415 | reset_ule(priv); | 447 | reset_ule(priv); |
416 | /* skip to next PUSI. */ | 448 | /* skip to next PUSI. */ |
417 | priv->need_pusi = 1; | 449 | priv->need_pusi = 1; |
418 | ts += TS_SZ; | ||
419 | priv->ts_count++; | ||
420 | continue; | 450 | continue; |
421 | } | 451 | } |
422 | /* If we still have an incomplete payload, but PUSI is | 452 | /* If we still have an incomplete payload, but PUSI is |
@@ -425,7 +455,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) | |||
425 | * cells (continuity counter wrap). */ | 455 | * cells (continuity counter wrap). */ |
426 | if (ts[1] & TS_PUSI) { | 456 | if (ts[1] & TS_PUSI) { |
427 | if (! priv->need_pusi) { | 457 | if (! priv->need_pusi) { |
428 | if (*from_where > 181) { | 458 | if (!(*from_where < (ts_remain-1)) || *from_where != priv->ule_sndu_remain) { |
429 | /* Pointer field is invalid. Drop this TS cell and any started ULE SNDU. */ | 459 | /* Pointer field is invalid. Drop this TS cell and any started ULE SNDU. */ |
430 | printk(KERN_WARNING "%lu: Invalid pointer " | 460 | printk(KERN_WARNING "%lu: Invalid pointer " |
431 | "field: %u.\n", priv->ts_count, *from_where); | 461 | "field: %u.\n", priv->ts_count, *from_where); |
@@ -438,8 +468,6 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) | |||
438 | } | 468 | } |
439 | reset_ule(priv); | 469 | reset_ule(priv); |
440 | priv->need_pusi = 1; | 470 | priv->need_pusi = 1; |
441 | ts += TS_SZ; | ||
442 | priv->ts_count++; | ||
443 | continue; | 471 | continue; |
444 | } | 472 | } |
445 | /* Skip pointer field (we're processing a | 473 | /* Skip pointer field (we're processing a |
@@ -452,8 +480,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) | |||
452 | if (priv->ule_sndu_remain > 183) { | 480 | if (priv->ule_sndu_remain > 183) { |
453 | /* Current SNDU lacks more data than there could be available in the | 481 | /* Current SNDU lacks more data than there could be available in the |
454 | * current TS cell. */ | 482 | * current TS cell. */ |
455 | ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++; | 483 | priv->stats.rx_errors++; |
456 | ((struct dvb_net_priv *) dev->priv)->stats.rx_length_errors++; | 484 | priv->stats.rx_length_errors++; |
457 | printk(KERN_WARNING "%lu: Expected %d more SNDU bytes, but " | 485 | printk(KERN_WARNING "%lu: Expected %d more SNDU bytes, but " |
458 | "got PUSI (pf %d, ts_remain %d). Flushing incomplete payload.\n", | 486 | "got PUSI (pf %d, ts_remain %d). Flushing incomplete payload.\n", |
459 | priv->ts_count, priv->ule_sndu_remain, ts[4], ts_remain); | 487 | priv->ts_count, priv->ule_sndu_remain, ts[4], ts_remain); |
@@ -492,9 +520,11 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) | |||
492 | } else | 520 | } else |
493 | priv->ule_dbit = 0; | 521 | priv->ule_dbit = 0; |
494 | 522 | ||
495 | if (priv->ule_sndu_len > 32763) { | 523 | if (priv->ule_sndu_len < 5) { |
496 | printk(KERN_WARNING "%lu: Invalid ULE SNDU length %u. " | 524 | printk(KERN_WARNING "%lu: Invalid ULE SNDU length %u. " |
497 | "Resyncing.\n", priv->ts_count, priv->ule_sndu_len); | 525 | "Resyncing.\n", priv->ts_count, priv->ule_sndu_len); |
526 | priv->stats.rx_errors++; | ||
527 | priv->stats.rx_length_errors++; | ||
498 | priv->ule_sndu_len = 0; | 528 | priv->ule_sndu_len = 0; |
499 | priv->need_pusi = 1; | 529 | priv->need_pusi = 1; |
500 | new_ts = 1; | 530 | new_ts = 1; |
@@ -608,58 +638,103 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) | |||
608 | ule_dump = 1; | 638 | ule_dump = 1; |
609 | #endif | 639 | #endif |
610 | 640 | ||
611 | ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++; | 641 | priv->stats.rx_errors++; |
612 | ((struct dvb_net_priv *) dev->priv)->stats.rx_crc_errors++; | 642 | priv->stats.rx_crc_errors++; |
613 | dev_kfree_skb(priv->ule_skb); | 643 | dev_kfree_skb(priv->ule_skb); |
614 | } else { | 644 | } else { |
615 | /* CRC32 verified OK. */ | 645 | /* CRC32 verified OK. */ |
646 | u8 dest_addr[ETH_ALEN]; | ||
647 | static const u8 bc_addr[ETH_ALEN] = | ||
648 | { [ 0 ... ETH_ALEN-1] = 0xff }; | ||
649 | |||
650 | /* CRC32 was OK. Remove it from skb. */ | ||
651 | priv->ule_skb->tail -= 4; | ||
652 | priv->ule_skb->len -= 4; | ||
653 | |||
654 | if (!priv->ule_dbit) { | ||
655 | /* | ||
656 | * The destination MAC address is the | ||
657 | * next data in the skb. It comes | ||
658 | * before any extension headers. | ||
659 | * | ||
660 | * Check if the payload of this SNDU | ||
661 | * should be passed up the stack. | ||
662 | */ | ||
663 | register int drop = 0; | ||
664 | if (priv->rx_mode != RX_MODE_PROMISC) { | ||
665 | if (priv->ule_skb->data[0] & 0x01) { | ||
666 | /* multicast or broadcast */ | ||
667 | if (memcmp(priv->ule_skb->data, bc_addr, ETH_ALEN)) { | ||
668 | /* multicast */ | ||
669 | if (priv->rx_mode == RX_MODE_MULTI) { | ||
670 | int i; | ||
671 | for(i = 0; i < priv->multi_num && memcmp(priv->ule_skb->data, priv->multi_macs[i], ETH_ALEN); i++) | ||
672 | ; | ||
673 | if (i == priv->multi_num) | ||
674 | drop = 1; | ||
675 | } else if (priv->rx_mode != RX_MODE_ALL_MULTI) | ||
676 | drop = 1; /* no broadcast; */ | ||
677 | /* else: all multicast mode: accept all multicast packets */ | ||
678 | } | ||
679 | /* else: broadcast */ | ||
680 | } | ||
681 | else if (memcmp(priv->ule_skb->data, dev->dev_addr, ETH_ALEN)) | ||
682 | drop = 1; | ||
683 | /* else: destination address matches the MAC address of our receiver device */ | ||
684 | } | ||
685 | /* else: promiscious mode; pass everything up the stack */ | ||
686 | |||
687 | if (drop) { | ||
688 | #ifdef ULE_DEBUG | ||
689 | dprintk("Dropping SNDU: MAC destination address does not match: dest addr: "MAC_ADDR_PRINTFMT", dev addr: "MAC_ADDR_PRINTFMT"\n", | ||
690 | MAX_ADDR_PRINTFMT_ARGS(priv->ule_skb->data), MAX_ADDR_PRINTFMT_ARGS(dev->dev_addr)); | ||
691 | #endif | ||
692 | dev_kfree_skb(priv->ule_skb); | ||
693 | goto sndu_done; | ||
694 | } | ||
695 | else | ||
696 | { | ||
697 | memcpy(dest_addr, priv->ule_skb->data, ETH_ALEN); | ||
698 | skb_pull(priv->ule_skb, ETH_ALEN); | ||
699 | } | ||
700 | } | ||
701 | |||
616 | /* Handle ULE Extension Headers. */ | 702 | /* Handle ULE Extension Headers. */ |
617 | if (priv->ule_sndu_type < 1536) { | 703 | if (priv->ule_sndu_type < 1536) { |
618 | /* There is an extension header. Handle it accordingly. */ | 704 | /* There is an extension header. Handle it accordingly. */ |
619 | int l = handle_ule_extensions( priv ); | 705 | int l = handle_ule_extensions(priv); |
620 | if (l < 0) { | 706 | if (l < 0) { |
621 | /* Mandatory extension header unknown or TEST SNDU. Drop it. */ | 707 | /* Mandatory extension header unknown or TEST SNDU. Drop it. */ |
622 | // printk( KERN_WARNING "Dropping SNDU, extension headers.\n" ); | 708 | // printk( KERN_WARNING "Dropping SNDU, extension headers.\n" ); |
623 | dev_kfree_skb( priv->ule_skb ); | 709 | dev_kfree_skb(priv->ule_skb); |
624 | goto sndu_done; | 710 | goto sndu_done; |
625 | } | 711 | } |
626 | skb_pull( priv->ule_skb, l ); | 712 | skb_pull(priv->ule_skb, l); |
627 | } | 713 | } |
628 | 714 | ||
629 | /* CRC32 was OK. Remove it from skb. */ | 715 | /* |
630 | priv->ule_skb->tail -= 4; | 716 | * Construct/assure correct ethernet header. |
631 | priv->ule_skb->len -= 4; | 717 | * Note: in bridged mode (priv->ule_bridged != |
632 | 718 | * 0) we already have the (original) ethernet | |
633 | /* Filter on receiver's destination MAC address, if present. */ | 719 | * header at the start of the payload (after |
634 | if (!priv->ule_dbit) { | 720 | * optional dest. address and any extension |
635 | /* The destination MAC address is the next data in the skb. */ | 721 | * headers). |
636 | if (memcmp( priv->ule_skb->data, dev->dev_addr, ETH_ALEN )) { | 722 | */ |
637 | /* MAC addresses don't match. Drop SNDU. */ | 723 | |
638 | // printk( KERN_WARNING "Dropping SNDU, MAC address.\n" ); | 724 | if (!priv->ule_bridged) { |
639 | dev_kfree_skb( priv->ule_skb ); | 725 | skb_push(priv->ule_skb, ETH_HLEN); |
640 | goto sndu_done; | 726 | ethh = (struct ethhdr *)priv->ule_skb->data; |
641 | } | 727 | if (!priv->ule_dbit) { |
642 | if (! priv->ule_bridged) { | 728 | /* dest_addr buffer is only valid if priv->ule_dbit == 0 */ |
643 | skb_push( priv->ule_skb, ETH_ALEN + 2 ); | 729 | memcpy(ethh->h_dest, dest_addr, ETH_ALEN); |
644 | ethh = (struct ethhdr *)priv->ule_skb->data; | 730 | memset(ethh->h_source, 0, ETH_ALEN); |
645 | memcpy( ethh->h_dest, ethh->h_source, ETH_ALEN ); | ||
646 | memset( ethh->h_source, 0, ETH_ALEN ); | ||
647 | ethh->h_proto = htons( priv->ule_sndu_type ); | ||
648 | } else { | ||
649 | /* Skip the Receiver destination MAC address. */ | ||
650 | skb_pull( priv->ule_skb, ETH_ALEN ); | ||
651 | } | ||
652 | } else { | ||
653 | if (! priv->ule_bridged) { | ||
654 | skb_push( priv->ule_skb, ETH_HLEN ); | ||
655 | ethh = (struct ethhdr *)priv->ule_skb->data; | ||
656 | memcpy( ethh->h_dest, dev->dev_addr, ETH_ALEN ); | ||
657 | memset( ethh->h_source, 0, ETH_ALEN ); | ||
658 | ethh->h_proto = htons( priv->ule_sndu_type ); | ||
659 | } else { | ||
660 | /* skb is in correct state; nothing to do. */ | ||
661 | } | 731 | } |
732 | else /* zeroize source and dest */ | ||
733 | memset( ethh, 0, ETH_ALEN*2 ); | ||
734 | |||
735 | ethh->h_proto = htons(priv->ule_sndu_type); | ||
662 | } | 736 | } |
737 | /* else: skb is in correct state; nothing to do. */ | ||
663 | priv->ule_bridged = 0; | 738 | priv->ule_bridged = 0; |
664 | 739 | ||
665 | /* Stuff into kernel's protocol stack. */ | 740 | /* Stuff into kernel's protocol stack. */ |
@@ -668,8 +743,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len ) | |||
668 | * receive the packet anyhow. */ | 743 | * receive the packet anyhow. */ |
669 | /* if (priv->ule_dbit && skb->pkt_type == PACKET_OTHERHOST) | 744 | /* if (priv->ule_dbit && skb->pkt_type == PACKET_OTHERHOST) |
670 | priv->ule_skb->pkt_type = PACKET_HOST; */ | 745 | priv->ule_skb->pkt_type = PACKET_HOST; */ |
671 | ((struct dvb_net_priv *) dev->priv)->stats.rx_packets++; | 746 | priv->stats.rx_packets++; |
672 | ((struct dvb_net_priv *) dev->priv)->stats.rx_bytes += priv->ule_skb->len; | 747 | priv->stats.rx_bytes += priv->ule_skb->len; |
673 | netif_rx(priv->ule_skb); | 748 | netif_rx(priv->ule_skb); |
674 | } | 749 | } |
675 | sndu_done: | 750 | sndu_done: |
@@ -944,7 +1019,7 @@ static int dvb_net_feed_start(struct net_device *dev) | |||
944 | dprintk("%s: start filtering\n", __FUNCTION__); | 1019 | dprintk("%s: start filtering\n", __FUNCTION__); |
945 | priv->secfeed->start_filtering(priv->secfeed); | 1020 | priv->secfeed->start_filtering(priv->secfeed); |
946 | } else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) { | 1021 | } else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) { |
947 | struct timespec timeout = { 0, 30000000 }; // 30 msec | 1022 | struct timespec timeout = { 0, 10000000 }; // 10 msec |
948 | 1023 | ||
949 | /* we have payloads encapsulated in TS */ | 1024 | /* we have payloads encapsulated in TS */ |
950 | dprintk("%s: alloc tsfeed\n", __FUNCTION__); | 1025 | dprintk("%s: alloc tsfeed\n", __FUNCTION__); |
@@ -956,10 +1031,13 @@ static int dvb_net_feed_start(struct net_device *dev) | |||
956 | 1031 | ||
957 | /* Set netdevice pointer for ts decaps callback. */ | 1032 | /* Set netdevice pointer for ts decaps callback. */ |
958 | priv->tsfeed->priv = (void *)dev; | 1033 | priv->tsfeed->priv = (void *)dev; |
959 | ret = priv->tsfeed->set(priv->tsfeed, priv->pid, | 1034 | ret = priv->tsfeed->set(priv->tsfeed, |
960 | TS_PACKET, DMX_TS_PES_OTHER, | 1035 | priv->pid, /* pid */ |
1036 | TS_PACKET, /* type */ | ||
1037 | DMX_TS_PES_OTHER, /* pes type */ | ||
961 | 32768, /* circular buffer size */ | 1038 | 32768, /* circular buffer size */ |
962 | timeout); | 1039 | timeout /* timeout */ |
1040 | ); | ||
963 | 1041 | ||
964 | if (ret < 0) { | 1042 | if (ret < 0) { |
965 | printk("%s: could not set ts feed\n", dev->name); | 1043 | printk("%s: could not set ts feed\n", dev->name); |