diff options
Diffstat (limited to 'net/atm/br2684.c')
-rw-r--r-- | net/atm/br2684.c | 78 |
1 files changed, 45 insertions, 33 deletions
diff --git a/net/atm/br2684.c b/net/atm/br2684.c index 9d52ebfc1962..05fafdc2eea3 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c | |||
@@ -188,10 +188,13 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev, | |||
188 | return 0; | 188 | return 0; |
189 | } | 189 | } |
190 | } | 190 | } |
191 | } else { | 191 | } else { /* e_vc */ |
192 | skb_push(skb, 2); | 192 | if (brdev->payload == p_bridged) { |
193 | if (brdev->payload == p_bridged) | 193 | skb_push(skb, 2); |
194 | memset(skb->data, 0, 2); | 194 | memset(skb->data, 0, 2); |
195 | } else { /* p_routed */ | ||
196 | skb_pull(skb, ETH_HLEN); | ||
197 | } | ||
195 | } | 198 | } |
196 | skb_debug(skb); | 199 | skb_debug(skb); |
197 | 200 | ||
@@ -377,11 +380,8 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb) | |||
377 | (skb->data + 6, ethertype_ipv4, | 380 | (skb->data + 6, ethertype_ipv4, |
378 | sizeof(ethertype_ipv4)) == 0) | 381 | sizeof(ethertype_ipv4)) == 0) |
379 | skb->protocol = __constant_htons(ETH_P_IP); | 382 | skb->protocol = __constant_htons(ETH_P_IP); |
380 | else { | 383 | else |
381 | brdev->stats.rx_errors++; | 384 | goto error; |
382 | dev_kfree_skb(skb); | ||
383 | return; | ||
384 | } | ||
385 | skb_pull(skb, sizeof(llc_oui_ipv4)); | 385 | skb_pull(skb, sizeof(llc_oui_ipv4)); |
386 | skb_reset_network_header(skb); | 386 | skb_reset_network_header(skb); |
387 | skb->pkt_type = PACKET_HOST; | 387 | skb->pkt_type = PACKET_HOST; |
@@ -394,44 +394,56 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb) | |||
394 | (memcmp(skb->data, llc_oui_pid_pad, 7) == 0)) { | 394 | (memcmp(skb->data, llc_oui_pid_pad, 7) == 0)) { |
395 | skb_pull(skb, sizeof(llc_oui_pid_pad)); | 395 | skb_pull(skb, sizeof(llc_oui_pid_pad)); |
396 | skb->protocol = eth_type_trans(skb, net_dev); | 396 | skb->protocol = eth_type_trans(skb, net_dev); |
397 | } else { | 397 | } else |
398 | brdev->stats.rx_errors++; | 398 | goto error; |
399 | dev_kfree_skb(skb); | ||
400 | return; | ||
401 | } | ||
402 | 399 | ||
403 | } else { | 400 | } else { /* e_vc */ |
404 | /* first 2 chars should be 0 */ | 401 | if (brdev->payload == p_routed) { |
405 | if (*((u16 *) (skb->data)) != 0) { | 402 | struct iphdr *iph; |
406 | brdev->stats.rx_errors++; | 403 | |
407 | dev_kfree_skb(skb); | 404 | skb_reset_network_header(skb); |
408 | return; | 405 | iph = ip_hdr(skb); |
406 | if (iph->version == 4) | ||
407 | skb->protocol = __constant_htons(ETH_P_IP); | ||
408 | else if (iph->version == 6) | ||
409 | skb->protocol = __constant_htons(ETH_P_IPV6); | ||
410 | else | ||
411 | goto error; | ||
412 | skb->pkt_type = PACKET_HOST; | ||
413 | } else { /* p_bridged */ | ||
414 | /* first 2 chars should be 0 */ | ||
415 | if (*((u16 *) (skb->data)) != 0) | ||
416 | goto error; | ||
417 | skb_pull(skb, BR2684_PAD_LEN); | ||
418 | skb->protocol = eth_type_trans(skb, net_dev); | ||
409 | } | 419 | } |
410 | skb_pull(skb, BR2684_PAD_LEN + ETH_HLEN); /* pad, dstmac, srcmac, ethtype */ | ||
411 | skb->protocol = eth_type_trans(skb, net_dev); | ||
412 | } | 420 | } |
413 | 421 | ||
414 | #ifdef CONFIG_ATM_BR2684_IPFILTER | 422 | #ifdef CONFIG_ATM_BR2684_IPFILTER |
415 | if (unlikely(packet_fails_filter(skb->protocol, brvcc, skb))) { | 423 | if (unlikely(packet_fails_filter(skb->protocol, brvcc, skb))) |
416 | brdev->stats.rx_dropped++; | 424 | goto dropped; |
417 | dev_kfree_skb(skb); | ||
418 | return; | ||
419 | } | ||
420 | #endif /* CONFIG_ATM_BR2684_IPFILTER */ | 425 | #endif /* CONFIG_ATM_BR2684_IPFILTER */ |
421 | skb->dev = net_dev; | 426 | skb->dev = net_dev; |
422 | ATM_SKB(skb)->vcc = atmvcc; /* needed ? */ | 427 | ATM_SKB(skb)->vcc = atmvcc; /* needed ? */ |
423 | pr_debug("received packet's protocol: %x\n", ntohs(skb->protocol)); | 428 | pr_debug("received packet's protocol: %x\n", ntohs(skb->protocol)); |
424 | skb_debug(skb); | 429 | skb_debug(skb); |
425 | if (unlikely(!(net_dev->flags & IFF_UP))) { | 430 | /* sigh, interface is down? */ |
426 | /* sigh, interface is down */ | 431 | if (unlikely(!(net_dev->flags & IFF_UP))) |
427 | brdev->stats.rx_dropped++; | 432 | goto dropped; |
428 | dev_kfree_skb(skb); | ||
429 | return; | ||
430 | } | ||
431 | brdev->stats.rx_packets++; | 433 | brdev->stats.rx_packets++; |
432 | brdev->stats.rx_bytes += skb->len; | 434 | brdev->stats.rx_bytes += skb->len; |
433 | memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data)); | 435 | memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data)); |
434 | netif_rx(skb); | 436 | netif_rx(skb); |
437 | return; | ||
438 | |||
439 | dropped: | ||
440 | brdev->stats.rx_dropped++; | ||
441 | goto free_skb; | ||
442 | error: | ||
443 | brdev->stats.rx_errors++; | ||
444 | free_skb: | ||
445 | dev_kfree_skb(skb); | ||
446 | return; | ||
435 | } | 447 | } |
436 | 448 | ||
437 | /* | 449 | /* |
@@ -518,9 +530,9 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg) | |||
518 | struct sk_buff *next = skb->next; | 530 | struct sk_buff *next = skb->next; |
519 | 531 | ||
520 | skb->next = skb->prev = NULL; | 532 | skb->next = skb->prev = NULL; |
533 | br2684_push(atmvcc, skb); | ||
521 | BRPRIV(skb->dev)->stats.rx_bytes -= skb->len; | 534 | BRPRIV(skb->dev)->stats.rx_bytes -= skb->len; |
522 | BRPRIV(skb->dev)->stats.rx_packets--; | 535 | BRPRIV(skb->dev)->stats.rx_packets--; |
523 | br2684_push(atmvcc, skb); | ||
524 | 536 | ||
525 | skb = next; | 537 | skb = next; |
526 | } | 538 | } |