diff options
Diffstat (limited to 'drivers/staging/batman-adv/routing.c')
-rw-r--r-- | drivers/staging/batman-adv/routing.c | 563 |
1 files changed, 244 insertions, 319 deletions
diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index f8464cad30b..e0d093f5d52 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c | |||
@@ -36,15 +36,16 @@ | |||
36 | 36 | ||
37 | DECLARE_WAIT_QUEUE_HEAD(thread_wait); | 37 | DECLARE_WAIT_QUEUE_HEAD(thread_wait); |
38 | 38 | ||
39 | static atomic_t data_ready_cond; | ||
40 | atomic_t exit_cond; | 39 | atomic_t exit_cond; |
40 | |||
41 | void slide_own_bcast_window(struct batman_if *batman_if) | 41 | void slide_own_bcast_window(struct batman_if *batman_if) |
42 | { | 42 | { |
43 | HASHIT(hashit); | 43 | HASHIT(hashit); |
44 | struct orig_node *orig_node; | 44 | struct orig_node *orig_node; |
45 | TYPE_OF_WORD *word; | 45 | TYPE_OF_WORD *word; |
46 | unsigned long flags; | ||
46 | 47 | ||
47 | spin_lock(&orig_hash_lock); | 48 | spin_lock_irqsave(&orig_hash_lock, flags); |
48 | 49 | ||
49 | while (hash_iterate(orig_hash, &hashit)) { | 50 | while (hash_iterate(orig_hash, &hashit)) { |
50 | orig_node = hashit.bucket->data; | 51 | orig_node = hashit.bucket->data; |
@@ -55,7 +56,7 @@ void slide_own_bcast_window(struct batman_if *batman_if) | |||
55 | bit_packet_count(word); | 56 | bit_packet_count(word); |
56 | } | 57 | } |
57 | 58 | ||
58 | spin_unlock(&orig_hash_lock); | 59 | spin_unlock_irqrestore(&orig_hash_lock, flags); |
59 | } | 60 | } |
60 | 61 | ||
61 | static void update_HNA(struct orig_node *orig_node, | 62 | static void update_HNA(struct orig_node *orig_node, |
@@ -365,10 +366,9 @@ static char count_real_packets(struct ethhdr *ethhdr, | |||
365 | } | 366 | } |
366 | 367 | ||
367 | void receive_bat_packet(struct ethhdr *ethhdr, | 368 | void receive_bat_packet(struct ethhdr *ethhdr, |
368 | struct batman_packet *batman_packet, | 369 | struct batman_packet *batman_packet, |
369 | unsigned char *hna_buff, | 370 | unsigned char *hna_buff, int hna_buff_len, |
370 | int hna_buff_len, | 371 | struct batman_if *if_incoming) |
371 | struct batman_if *if_incoming) | ||
372 | { | 372 | { |
373 | struct batman_if *batman_if; | 373 | struct batman_if *batman_if; |
374 | struct orig_node *orig_neigh_node, *orig_node; | 374 | struct orig_node *orig_neigh_node, *orig_node; |
@@ -566,95 +566,118 @@ void receive_bat_packet(struct ethhdr *ethhdr, | |||
566 | 0, hna_buff_len, if_incoming); | 566 | 0, hna_buff_len, if_incoming); |
567 | } | 567 | } |
568 | 568 | ||
569 | 569 | int recv_bat_packet(struct sk_buff *skb, | |
570 | static int receive_raw_packet(struct socket *raw_sock, | 570 | struct batman_if *batman_if) |
571 | unsigned char *packet_buff, int packet_buff_len) | ||
572 | { | 571 | { |
573 | struct kvec iov; | 572 | struct ethhdr *ethhdr; |
574 | struct msghdr msg; | 573 | unsigned long flags; |
575 | 574 | ||
576 | iov.iov_base = packet_buff; | 575 | /* drop packet if it has not necessary minimum size */ |
577 | iov.iov_len = packet_buff_len; | 576 | if (skb_headlen(skb) < sizeof(struct batman_packet)) |
577 | return NET_RX_DROP; | ||
578 | 578 | ||
579 | msg.msg_flags = MSG_DONTWAIT; /* non-blocking */ | 579 | ethhdr = (struct ethhdr *)skb_mac_header(skb); |
580 | msg.msg_name = NULL; | ||
581 | msg.msg_namelen = 0; | ||
582 | msg.msg_control = NULL; | ||
583 | 580 | ||
584 | return kernel_recvmsg(raw_sock, &msg, &iov, 1, packet_buff_len, | ||
585 | MSG_DONTWAIT); | ||
586 | } | ||
587 | |||
588 | static void recv_bat_packet(struct ethhdr *ethhdr, | ||
589 | unsigned char *packet_buff, | ||
590 | int result, | ||
591 | struct batman_if *batman_if) | ||
592 | { | ||
593 | /* packet with broadcast indication but unicast recipient */ | 581 | /* packet with broadcast indication but unicast recipient */ |
594 | if (!is_bcast(ethhdr->h_dest)) | 582 | if (!is_bcast(ethhdr->h_dest)) |
595 | return; | 583 | return NET_RX_DROP; |
596 | 584 | ||
597 | /* packet with broadcast sender address */ | 585 | /* packet with broadcast sender address */ |
598 | if (is_bcast(ethhdr->h_source)) | 586 | if (is_bcast(ethhdr->h_source)) |
599 | return; | 587 | return NET_RX_DROP; |
600 | 588 | ||
601 | /* drop packet if it has not at least one batman packet as payload */ | 589 | spin_lock_irqsave(&orig_hash_lock, flags); |
602 | if (result < sizeof(struct ethhdr) + sizeof(struct batman_packet)) | 590 | /* TODO: we use headlen instead of "length", because |
603 | return; | 591 | * only this data is paged in. */ |
604 | 592 | /* TODO: is another skb_copy needed here? there will be | |
605 | spin_lock(&orig_hash_lock); | 593 | * written on the data, but nobody (?) should further use |
594 | * this data */ | ||
606 | receive_aggr_bat_packet(ethhdr, | 595 | receive_aggr_bat_packet(ethhdr, |
607 | packet_buff + sizeof(struct ethhdr), | 596 | skb->data, |
608 | result - sizeof(struct ethhdr), | 597 | skb_headlen(skb), |
609 | batman_if); | 598 | batman_if); |
610 | spin_unlock(&orig_hash_lock); | 599 | spin_unlock_irqrestore(&orig_hash_lock, flags); |
600 | |||
601 | kfree_skb(skb); | ||
602 | return NET_RX_SUCCESS; | ||
611 | } | 603 | } |
612 | 604 | ||
613 | static void recv_my_icmp_packet(struct ethhdr *ethhdr, | 605 | static int recv_my_icmp_packet(struct sk_buff *skb) |
614 | struct icmp_packet *icmp_packet, | ||
615 | unsigned char *packet_buff, | ||
616 | int result) | ||
617 | { | 606 | { |
618 | struct orig_node *orig_node; | 607 | struct orig_node *orig_node; |
608 | struct icmp_packet *icmp_packet; | ||
609 | struct ethhdr *ethhdr; | ||
610 | struct sk_buff *skb_old; | ||
611 | struct batman_if *batman_if; | ||
612 | int ret; | ||
613 | unsigned long flags; | ||
614 | uint8_t dstaddr[ETH_ALEN]; | ||
615 | |||
616 | icmp_packet = (struct icmp_packet *) skb->data; | ||
617 | ethhdr = (struct ethhdr *) skb_mac_header(skb); | ||
619 | 618 | ||
620 | /* add data to device queue */ | 619 | /* add data to device queue */ |
621 | if (icmp_packet->msg_type != ECHO_REQUEST) { | 620 | if (icmp_packet->msg_type != ECHO_REQUEST) { |
622 | bat_device_receive_packet(icmp_packet); | 621 | bat_device_receive_packet(icmp_packet); |
623 | return; | 622 | return NET_RX_DROP; |
624 | } | 623 | } |
625 | 624 | ||
626 | /* answer echo request (ping) */ | 625 | /* answer echo request (ping) */ |
627 | /* get routing information */ | 626 | /* get routing information */ |
628 | spin_lock(&orig_hash_lock); | 627 | spin_lock_irqsave(&orig_hash_lock, flags); |
629 | orig_node = ((struct orig_node *)hash_find(orig_hash, | 628 | orig_node = ((struct orig_node *)hash_find(orig_hash, |
630 | icmp_packet->orig)); | 629 | icmp_packet->orig)); |
630 | ret = NET_RX_DROP; | ||
631 | 631 | ||
632 | if ((orig_node != NULL) && | 632 | if ((orig_node != NULL) && |
633 | (orig_node->batman_if != NULL) && | 633 | (orig_node->batman_if != NULL) && |
634 | (orig_node->router != NULL)) { | 634 | (orig_node->router != NULL)) { |
635 | |||
636 | /* don't lock while sending the packets ... we therefore | ||
637 | * copy the required data before sending */ | ||
638 | batman_if = orig_node->batman_if; | ||
639 | memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); | ||
640 | spin_unlock_irqrestore(&orig_hash_lock, flags); | ||
641 | |||
642 | /* create a copy of the skb, if needed, to modify it. */ | ||
643 | skb_old = NULL; | ||
644 | if (!skb_clone_writable(skb, sizeof(struct icmp_packet))) { | ||
645 | skb_old = skb; | ||
646 | skb = skb_copy(skb, GFP_ATOMIC); | ||
647 | if (!skb) | ||
648 | return NET_RX_DROP; | ||
649 | icmp_packet = (struct icmp_packet *) skb->data; | ||
650 | kfree_skb(skb_old); | ||
651 | } | ||
652 | |||
635 | memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); | 653 | memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); |
636 | memcpy(icmp_packet->orig, ethhdr->h_dest, ETH_ALEN); | 654 | memcpy(icmp_packet->orig, ethhdr->h_dest, ETH_ALEN); |
637 | icmp_packet->msg_type = ECHO_REPLY; | 655 | icmp_packet->msg_type = ECHO_REPLY; |
638 | icmp_packet->ttl = TTL; | 656 | icmp_packet->ttl = TTL; |
639 | 657 | ||
640 | send_raw_packet(packet_buff + sizeof(struct ethhdr), | 658 | send_skb_packet(skb, batman_if, dstaddr); |
641 | result - sizeof(struct ethhdr), | 659 | ret = NET_RX_SUCCESS; |
642 | orig_node->batman_if, | ||
643 | orig_node->router->addr); | ||
644 | } | ||
645 | 660 | ||
646 | spin_unlock(&orig_hash_lock); | 661 | } else |
647 | return; | 662 | spin_unlock_irqrestore(&orig_hash_lock, flags); |
663 | |||
664 | return ret; | ||
648 | } | 665 | } |
649 | 666 | ||
650 | static void recv_icmp_ttl_exceeded(struct icmp_packet *icmp_packet, | 667 | static int recv_icmp_ttl_exceeded(struct sk_buff *skb) |
651 | struct ethhdr *ethhdr, | ||
652 | unsigned char *packet_buff, | ||
653 | int result, | ||
654 | struct batman_if *batman_if) | ||
655 | { | 668 | { |
656 | unsigned char src_str[ETH_STR_LEN], dst_str[ETH_STR_LEN]; | 669 | unsigned char src_str[ETH_STR_LEN], dst_str[ETH_STR_LEN]; |
657 | struct orig_node *orig_node; | 670 | struct orig_node *orig_node; |
671 | struct icmp_packet *icmp_packet; | ||
672 | struct ethhdr *ethhdr; | ||
673 | struct sk_buff *skb_old; | ||
674 | struct batman_if *batman_if; | ||
675 | int ret; | ||
676 | unsigned long flags; | ||
677 | uint8_t dstaddr[ETH_ALEN]; | ||
678 | |||
679 | icmp_packet = (struct icmp_packet *) skb->data; | ||
680 | ethhdr = (struct ethhdr *) skb_mac_header(skb); | ||
658 | 681 | ||
659 | addr_to_string(src_str, icmp_packet->orig); | 682 | addr_to_string(src_str, icmp_packet->orig); |
660 | addr_to_string(dst_str, icmp_packet->dst); | 683 | addr_to_string(dst_str, icmp_packet->dst); |
@@ -663,74 +686,93 @@ static void recv_icmp_ttl_exceeded(struct icmp_packet *icmp_packet, | |||
663 | 686 | ||
664 | /* send TTL exceeded if packet is an echo request (traceroute) */ | 687 | /* send TTL exceeded if packet is an echo request (traceroute) */ |
665 | if (icmp_packet->msg_type != ECHO_REQUEST) | 688 | if (icmp_packet->msg_type != ECHO_REQUEST) |
666 | return; | 689 | return NET_RX_DROP; |
667 | 690 | ||
668 | /* get routing information */ | 691 | /* get routing information */ |
669 | spin_lock(&orig_hash_lock); | 692 | spin_lock_irqsave(&orig_hash_lock, flags); |
670 | orig_node = ((struct orig_node *) | 693 | orig_node = ((struct orig_node *) |
671 | hash_find(orig_hash, icmp_packet->orig)); | 694 | hash_find(orig_hash, icmp_packet->orig)); |
695 | ret = NET_RX_DROP; | ||
672 | 696 | ||
673 | if ((orig_node != NULL) && | 697 | if ((orig_node != NULL) && |
674 | (orig_node->batman_if != NULL) && | 698 | (orig_node->batman_if != NULL) && |
675 | (orig_node->router != NULL)) { | 699 | (orig_node->router != NULL)) { |
700 | |||
701 | /* don't lock while sending the packets ... we therefore | ||
702 | * copy the required data before sending */ | ||
703 | batman_if = orig_node->batman_if; | ||
704 | memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); | ||
705 | spin_unlock_irqrestore(&orig_hash_lock, flags); | ||
706 | |||
707 | /* create a copy of the skb, if needed, to modify it. */ | ||
708 | if (!skb_clone_writable(skb, sizeof(struct icmp_packet))) { | ||
709 | skb_old = skb; | ||
710 | skb = skb_copy(skb, GFP_ATOMIC); | ||
711 | if (!skb) | ||
712 | return NET_RX_DROP; | ||
713 | icmp_packet = (struct icmp_packet *) skb->data; | ||
714 | kfree_skb(skb_old); | ||
715 | } | ||
716 | |||
676 | memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); | 717 | memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); |
677 | memcpy(icmp_packet->orig, ethhdr->h_dest, ETH_ALEN); | 718 | memcpy(icmp_packet->orig, ethhdr->h_dest, ETH_ALEN); |
678 | icmp_packet->msg_type = TTL_EXCEEDED; | 719 | icmp_packet->msg_type = TTL_EXCEEDED; |
679 | icmp_packet->ttl = TTL; | 720 | icmp_packet->ttl = TTL; |
680 | 721 | ||
681 | send_raw_packet(packet_buff + sizeof(struct ethhdr), | 722 | send_skb_packet(skb, batman_if, dstaddr); |
682 | result - sizeof(struct ethhdr), | 723 | ret = NET_RX_SUCCESS; |
683 | orig_node->batman_if, | ||
684 | orig_node->router->addr); | ||
685 | 724 | ||
686 | } | 725 | } else |
726 | spin_unlock_irqrestore(&orig_hash_lock, flags); | ||
687 | 727 | ||
688 | spin_unlock(&orig_hash_lock); | 728 | return ret; |
689 | } | 729 | } |
690 | 730 | ||
691 | 731 | ||
692 | 732 | int recv_icmp_packet(struct sk_buff *skb) | |
693 | static void recv_icmp_packet(struct ethhdr *ethhdr, | ||
694 | unsigned char *packet_buff, | ||
695 | int result, | ||
696 | struct batman_if *batman_if) | ||
697 | { | 733 | { |
698 | struct icmp_packet *icmp_packet; | 734 | struct icmp_packet *icmp_packet; |
735 | struct ethhdr *ethhdr; | ||
699 | struct orig_node *orig_node; | 736 | struct orig_node *orig_node; |
737 | struct sk_buff *skb_old; | ||
738 | struct batman_if *batman_if; | ||
739 | int hdr_size = sizeof(struct icmp_packet); | ||
740 | int ret; | ||
741 | unsigned long flags; | ||
742 | uint8_t dstaddr[ETH_ALEN]; | ||
743 | |||
744 | /* drop packet if it has not necessary minimum size */ | ||
745 | if (skb_headlen(skb) < hdr_size) | ||
746 | return NET_RX_DROP; | ||
747 | |||
748 | ethhdr = (struct ethhdr *)skb_mac_header(skb); | ||
700 | 749 | ||
701 | /* packet with unicast indication but broadcast recipient */ | 750 | /* packet with unicast indication but broadcast recipient */ |
702 | if (is_bcast(ethhdr->h_dest)) | 751 | if (is_bcast(ethhdr->h_dest)) |
703 | return; | 752 | return NET_RX_DROP; |
704 | 753 | ||
705 | /* packet with broadcast sender address */ | 754 | /* packet with broadcast sender address */ |
706 | if (is_bcast(ethhdr->h_source)) | 755 | if (is_bcast(ethhdr->h_source)) |
707 | return; | 756 | return NET_RX_DROP; |
708 | 757 | ||
709 | /* not for me */ | 758 | /* not for me */ |
710 | if (!is_my_mac(ethhdr->h_dest)) | 759 | if (!is_my_mac(ethhdr->h_dest)) |
711 | return; | 760 | return NET_RX_DROP; |
712 | 761 | ||
713 | /* drop packet if it has not necessary minimum size */ | 762 | icmp_packet = (struct icmp_packet *) skb->data; |
714 | if (result < sizeof(struct ethhdr) + sizeof(struct icmp_packet)) | ||
715 | return; | ||
716 | |||
717 | icmp_packet = (struct icmp_packet *) | ||
718 | (packet_buff + sizeof(struct ethhdr)); | ||
719 | 763 | ||
720 | /* packet for me */ | 764 | /* packet for me */ |
721 | if (is_my_mac(icmp_packet->dst)) | 765 | if (is_my_mac(icmp_packet->dst)) |
722 | recv_my_icmp_packet(ethhdr, icmp_packet, packet_buff, result); | 766 | return recv_my_icmp_packet(skb); |
723 | 767 | ||
724 | /* TTL exceeded */ | 768 | /* TTL exceeded */ |
725 | if (icmp_packet->ttl < 2) { | 769 | if (icmp_packet->ttl < 2) |
726 | recv_icmp_ttl_exceeded(icmp_packet, ethhdr, packet_buff, result, | 770 | return recv_icmp_ttl_exceeded(skb); |
727 | batman_if); | ||
728 | return; | ||
729 | 771 | ||
730 | } | 772 | ret = NET_RX_DROP; |
731 | 773 | ||
732 | /* get routing information */ | 774 | /* get routing information */ |
733 | spin_lock(&orig_hash_lock); | 775 | spin_lock_irqsave(&orig_hash_lock, flags); |
734 | orig_node = ((struct orig_node *) | 776 | orig_node = ((struct orig_node *) |
735 | hash_find(orig_hash, icmp_packet->dst)); | 777 | hash_find(orig_hash, icmp_packet->dst)); |
736 | 778 | ||
@@ -738,133 +780,169 @@ static void recv_icmp_packet(struct ethhdr *ethhdr, | |||
738 | (orig_node->batman_if != NULL) && | 780 | (orig_node->batman_if != NULL) && |
739 | (orig_node->router != NULL)) { | 781 | (orig_node->router != NULL)) { |
740 | 782 | ||
783 | /* don't lock while sending the packets ... we therefore | ||
784 | * copy the required data before sending */ | ||
785 | batman_if = orig_node->batman_if; | ||
786 | memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); | ||
787 | spin_unlock_irqrestore(&orig_hash_lock, flags); | ||
788 | |||
789 | /* create a copy of the skb, if needed, to modify it. */ | ||
790 | if (!skb_clone_writable(skb, sizeof(struct icmp_packet))) { | ||
791 | skb_old = skb; | ||
792 | skb = skb_copy(skb, GFP_ATOMIC); | ||
793 | if (!skb) | ||
794 | return NET_RX_DROP; | ||
795 | icmp_packet = (struct icmp_packet *) skb->data; | ||
796 | kfree_skb(skb_old); | ||
797 | } | ||
798 | |||
741 | /* decrement ttl */ | 799 | /* decrement ttl */ |
742 | icmp_packet->ttl--; | 800 | icmp_packet->ttl--; |
743 | 801 | ||
744 | /* route it */ | 802 | /* route it */ |
745 | send_raw_packet(packet_buff + sizeof(struct ethhdr), | 803 | send_skb_packet(skb, batman_if, dstaddr); |
746 | result - sizeof(struct ethhdr), | 804 | ret = NET_RX_SUCCESS; |
747 | orig_node->batman_if, | 805 | |
748 | orig_node->router->addr); | 806 | } else |
749 | } | 807 | spin_unlock_irqrestore(&orig_hash_lock, flags); |
750 | spin_unlock(&orig_hash_lock); | 808 | |
809 | return ret; | ||
751 | } | 810 | } |
752 | 811 | ||
753 | static void recv_unicast_packet(struct ethhdr *ethhdr, | 812 | int recv_unicast_packet(struct sk_buff *skb) |
754 | unsigned char *packet_buff, | ||
755 | int result, | ||
756 | struct batman_if *batman_if) | ||
757 | { | 813 | { |
758 | struct unicast_packet *unicast_packet; | 814 | struct unicast_packet *unicast_packet; |
759 | unsigned char src_str[ETH_STR_LEN], dst_str[ETH_STR_LEN]; | 815 | unsigned char src_str[ETH_STR_LEN], dst_str[ETH_STR_LEN]; |
760 | struct orig_node *orig_node; | 816 | struct orig_node *orig_node; |
761 | int hdr_size = sizeof(struct ethhdr) + sizeof(struct unicast_packet); | 817 | struct ethhdr *ethhdr; |
818 | struct batman_if *batman_if; | ||
819 | struct sk_buff *skb_old; | ||
820 | uint8_t dstaddr[ETH_ALEN]; | ||
821 | int hdr_size = sizeof(struct unicast_packet); | ||
822 | int ret; | ||
823 | unsigned long flags; | ||
824 | |||
825 | /* drop packet if it has not necessary minimum size */ | ||
826 | if (skb_headlen(skb) < hdr_size) | ||
827 | return NET_RX_DROP; | ||
828 | |||
829 | ethhdr = (struct ethhdr *) skb_mac_header(skb); | ||
762 | 830 | ||
763 | /* packet with unicast indication but broadcast recipient */ | 831 | /* packet with unicast indication but broadcast recipient */ |
764 | if (is_bcast(ethhdr->h_dest)) | 832 | if (is_bcast(ethhdr->h_dest)) |
765 | return; | 833 | return NET_RX_DROP; |
766 | 834 | ||
767 | /* packet with broadcast sender address */ | 835 | /* packet with broadcast sender address */ |
768 | if (is_bcast(ethhdr->h_source)) | 836 | if (is_bcast(ethhdr->h_source)) |
769 | return; | 837 | return NET_RX_DROP; |
770 | 838 | ||
771 | /* not for me */ | 839 | /* not for me */ |
772 | if (!is_my_mac(ethhdr->h_dest)) | 840 | if (!is_my_mac(ethhdr->h_dest)) |
773 | return; | 841 | return NET_RX_DROP; |
774 | |||
775 | /* drop packet if it has not necessary minimum size */ | ||
776 | if (result < hdr_size) | ||
777 | return; | ||
778 | 842 | ||
779 | unicast_packet = (struct unicast_packet *) | 843 | unicast_packet = (struct unicast_packet *) skb->data; |
780 | (packet_buff + sizeof(struct ethhdr)); | ||
781 | 844 | ||
782 | /* packet for me */ | 845 | /* packet for me */ |
783 | if (is_my_mac(unicast_packet->dest)) { | 846 | if (is_my_mac(unicast_packet->dest)) { |
784 | interface_rx(soft_device, packet_buff + hdr_size, | 847 | interface_rx(skb, hdr_size); |
785 | result - hdr_size); | 848 | return NET_RX_SUCCESS; |
786 | return; | ||
787 | |||
788 | } | 849 | } |
789 | 850 | ||
790 | /* TTL exceeded */ | 851 | /* TTL exceeded */ |
791 | if (unicast_packet->ttl < 2) { | 852 | if (unicast_packet->ttl < 2) { |
792 | addr_to_string(src_str, ((struct ethhdr *) | 853 | addr_to_string(src_str, ethhdr->h_source); |
793 | (unicast_packet + 1))->h_source); | 854 | addr_to_string(dst_str, ethhdr->h_dest); |
794 | addr_to_string(dst_str, unicast_packet->dest); | ||
795 | 855 | ||
796 | printk(KERN_WARNING "batman-adv:Warning - can't send packet from %s to %s: ttl exceeded\n", src_str, dst_str); | 856 | printk(KERN_WARNING "batman-adv:Warning - can't send packet from %s to %s: ttl exceeded\n", src_str, dst_str); |
797 | return; | 857 | return NET_RX_DROP; |
798 | } | 858 | } |
799 | 859 | ||
860 | ret = NET_RX_DROP; | ||
800 | /* get routing information */ | 861 | /* get routing information */ |
801 | spin_lock(&orig_hash_lock); | 862 | spin_lock_irqsave(&orig_hash_lock, flags); |
802 | orig_node = ((struct orig_node *) | 863 | orig_node = ((struct orig_node *) |
803 | hash_find(orig_hash, unicast_packet->dest)); | 864 | hash_find(orig_hash, unicast_packet->dest)); |
804 | 865 | ||
805 | if ((orig_node != NULL) && | 866 | if ((orig_node != NULL) && |
806 | (orig_node->batman_if != NULL) && | 867 | (orig_node->batman_if != NULL) && |
807 | (orig_node->router != NULL)) { | 868 | (orig_node->router != NULL)) { |
869 | |||
870 | /* don't lock while sending the packets ... we therefore | ||
871 | * copy the required data before sending */ | ||
872 | batman_if = orig_node->batman_if; | ||
873 | memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); | ||
874 | spin_unlock_irqrestore(&orig_hash_lock, flags); | ||
875 | |||
876 | /* create a copy of the skb, if needed, to modify it. */ | ||
877 | if (!skb_clone_writable(skb, sizeof(struct unicast_packet))) { | ||
878 | skb_old = skb; | ||
879 | skb = skb_copy(skb, GFP_ATOMIC); | ||
880 | if (!skb) | ||
881 | return NET_RX_DROP; | ||
882 | unicast_packet = (struct unicast_packet *) skb->data; | ||
883 | kfree_skb(skb_old); | ||
884 | } | ||
808 | /* decrement ttl */ | 885 | /* decrement ttl */ |
809 | unicast_packet->ttl--; | 886 | unicast_packet->ttl--; |
810 | 887 | ||
811 | /* route it */ | 888 | /* route it */ |
812 | send_raw_packet(packet_buff + sizeof(struct ethhdr), | 889 | send_skb_packet(skb, batman_if, dstaddr); |
813 | result - sizeof(struct ethhdr), | 890 | ret = NET_RX_SUCCESS; |
814 | orig_node->batman_if, | 891 | |
815 | orig_node->router->addr); | 892 | } else |
816 | } | 893 | spin_unlock_irqrestore(&orig_hash_lock, flags); |
817 | spin_unlock(&orig_hash_lock); | 894 | |
895 | return ret; | ||
818 | } | 896 | } |
819 | 897 | ||
820 | 898 | ||
821 | static void recv_bcast_packet(struct ethhdr *ethhdr, | 899 | int recv_bcast_packet(struct sk_buff *skb) |
822 | unsigned char *packet_buff, | ||
823 | int result, | ||
824 | struct batman_if *batman_if) | ||
825 | { | 900 | { |
826 | struct orig_node *orig_node; | 901 | struct orig_node *orig_node; |
827 | struct bcast_packet *bcast_packet; | 902 | struct bcast_packet *bcast_packet; |
828 | int hdr_size = sizeof(struct ethhdr) + sizeof(struct bcast_packet); | 903 | struct ethhdr *ethhdr; |
904 | int hdr_size = sizeof(struct bcast_packet); | ||
905 | unsigned long flags; | ||
906 | |||
907 | /* drop packet if it has not necessary minimum size */ | ||
908 | if (skb_headlen(skb) < hdr_size) | ||
909 | return NET_RX_DROP; | ||
910 | |||
911 | ethhdr = (struct ethhdr *)skb_mac_header(skb); | ||
829 | 912 | ||
830 | /* packet with broadcast indication but unicast recipient */ | 913 | /* packet with broadcast indication but unicast recipient */ |
831 | if (!is_bcast(ethhdr->h_dest)) | 914 | if (!is_bcast(ethhdr->h_dest)) |
832 | return; | 915 | return NET_RX_DROP; |
833 | 916 | ||
834 | /* packet with broadcast sender address */ | 917 | /* packet with broadcast sender address */ |
835 | if (is_bcast(ethhdr->h_source)) | 918 | if (is_bcast(ethhdr->h_source)) |
836 | return; | 919 | return NET_RX_DROP; |
837 | |||
838 | /* drop packet if it has not necessary minimum size */ | ||
839 | if (result < hdr_size) | ||
840 | return; | ||
841 | 920 | ||
842 | /* ignore broadcasts sent by myself */ | 921 | /* ignore broadcasts sent by myself */ |
843 | if (is_my_mac(ethhdr->h_source)) | 922 | if (is_my_mac(ethhdr->h_source)) |
844 | return; | 923 | return NET_RX_DROP; |
845 | 924 | ||
846 | bcast_packet = (struct bcast_packet *) | 925 | bcast_packet = (struct bcast_packet *) skb->data; |
847 | (packet_buff + sizeof(struct ethhdr)); | ||
848 | 926 | ||
849 | /* ignore broadcasts originated by myself */ | 927 | /* ignore broadcasts originated by myself */ |
850 | if (is_my_mac(bcast_packet->orig)) | 928 | if (is_my_mac(bcast_packet->orig)) |
851 | return; | 929 | return NET_RX_DROP; |
852 | 930 | ||
853 | spin_lock(&orig_hash_lock); | 931 | spin_lock_irqsave(&orig_hash_lock, flags); |
854 | orig_node = ((struct orig_node *) | 932 | orig_node = ((struct orig_node *) |
855 | hash_find(orig_hash, bcast_packet->orig)); | 933 | hash_find(orig_hash, bcast_packet->orig)); |
856 | 934 | ||
857 | if (orig_node == NULL) { | 935 | if (orig_node == NULL) { |
858 | spin_unlock(&orig_hash_lock); | 936 | spin_unlock_irqrestore(&orig_hash_lock, flags); |
859 | return; | 937 | return NET_RX_DROP; |
860 | } | 938 | } |
861 | 939 | ||
862 | /* check flood history */ | 940 | /* check flood history */ |
863 | if (get_bit_status(orig_node->bcast_bits, | 941 | if (get_bit_status(orig_node->bcast_bits, |
864 | orig_node->last_bcast_seqno, | 942 | orig_node->last_bcast_seqno, |
865 | ntohs(bcast_packet->seqno))) { | 943 | ntohs(bcast_packet->seqno))) { |
866 | spin_unlock(&orig_hash_lock); | 944 | spin_unlock_irqrestore(&orig_hash_lock, flags); |
867 | return; | 945 | return NET_RX_DROP; |
868 | } | 946 | } |
869 | 947 | ||
870 | /* mark broadcast in flood history */ | 948 | /* mark broadcast in flood history */ |
@@ -873,211 +951,58 @@ static void recv_bcast_packet(struct ethhdr *ethhdr, | |||
873 | orig_node->last_bcast_seqno, 1)) | 951 | orig_node->last_bcast_seqno, 1)) |
874 | orig_node->last_bcast_seqno = ntohs(bcast_packet->seqno); | 952 | orig_node->last_bcast_seqno = ntohs(bcast_packet->seqno); |
875 | 953 | ||
876 | spin_unlock(&orig_hash_lock); | 954 | spin_unlock_irqrestore(&orig_hash_lock, flags); |
955 | |||
956 | /* rebroadcast packet */ | ||
957 | add_bcast_packet_to_list(skb); | ||
877 | 958 | ||
878 | /* broadcast for me */ | 959 | /* broadcast for me */ |
879 | interface_rx(soft_device, packet_buff + hdr_size, result - hdr_size); | 960 | interface_rx(skb, hdr_size); |
880 | 961 | ||
881 | /* rebroadcast packet */ | 962 | return NET_RX_SUCCESS; |
882 | add_bcast_packet_to_list(packet_buff + sizeof(struct ethhdr), | ||
883 | result - sizeof(struct ethhdr)); | ||
884 | } | 963 | } |
885 | 964 | ||
886 | static void recv_vis_packet(struct ethhdr *ethhdr, | 965 | int recv_vis_packet(struct sk_buff *skb) |
887 | unsigned char *packet_buff, | ||
888 | int result) | ||
889 | { | 966 | { |
890 | struct vis_packet *vis_packet; | 967 | struct vis_packet *vis_packet; |
891 | int hdr_size = sizeof(struct ethhdr) + sizeof(struct vis_packet); | 968 | struct ethhdr *ethhdr; |
892 | int vis_info_len; | 969 | int hdr_size = sizeof(struct vis_packet); |
970 | int ret; | ||
893 | 971 | ||
894 | /* drop if too short. */ | 972 | if (skb_headlen(skb) < hdr_size) |
895 | if (result < hdr_size) | 973 | return NET_RX_DROP; |
896 | return; | 974 | |
975 | vis_packet = (struct vis_packet *) skb->data; | ||
976 | ethhdr = (struct ethhdr *)skb_mac_header(skb); | ||
897 | 977 | ||
898 | /* not for me */ | 978 | /* not for me */ |
899 | if (!is_my_mac(ethhdr->h_dest)) | 979 | if (!is_my_mac(ethhdr->h_dest)) |
900 | return; | 980 | return NET_RX_DROP; |
901 | |||
902 | vis_packet = (struct vis_packet *)(packet_buff + sizeof(struct ethhdr)); | ||
903 | vis_info_len = result - hdr_size; | ||
904 | 981 | ||
905 | /* ignore own packets */ | 982 | /* ignore own packets */ |
906 | if (is_my_mac(vis_packet->vis_orig)) | 983 | if (is_my_mac(vis_packet->vis_orig)) |
907 | return; | 984 | return NET_RX_DROP; |
908 | 985 | ||
909 | if (is_my_mac(vis_packet->sender_orig)) | 986 | if (is_my_mac(vis_packet->sender_orig)) |
910 | return; | 987 | return NET_RX_DROP; |
911 | 988 | ||
912 | switch (vis_packet->vis_type) { | 989 | switch (vis_packet->vis_type) { |
913 | case VIS_TYPE_SERVER_SYNC: | 990 | case VIS_TYPE_SERVER_SYNC: |
914 | receive_server_sync_packet(vis_packet, vis_info_len); | 991 | /* TODO: handle fragmented skbs properly */ |
992 | receive_server_sync_packet(vis_packet, skb_headlen(skb)); | ||
993 | ret = NET_RX_SUCCESS; | ||
915 | break; | 994 | break; |
916 | 995 | ||
917 | case VIS_TYPE_CLIENT_UPDATE: | 996 | case VIS_TYPE_CLIENT_UPDATE: |
918 | receive_client_update_packet(vis_packet, vis_info_len); | 997 | /* TODO: handle fragmented skbs properly */ |
998 | receive_client_update_packet(vis_packet, skb_headlen(skb)); | ||
999 | ret = NET_RX_SUCCESS; | ||
919 | break; | 1000 | break; |
920 | 1001 | ||
921 | default: /* ignore unknown packet */ | 1002 | default: /* ignore unknown packet */ |
1003 | ret = NET_RX_DROP; | ||
922 | break; | 1004 | break; |
923 | } | 1005 | } |
924 | } | 1006 | return ret; |
925 | |||
926 | static int recv_one_packet(struct batman_if *batman_if, | ||
927 | unsigned char *packet_buff) | ||
928 | { | ||
929 | int result; | ||
930 | struct ethhdr *ethhdr; | ||
931 | struct batman_packet *batman_packet; | ||
932 | |||
933 | result = receive_raw_packet(batman_if->raw_sock, packet_buff, | ||
934 | PACKBUFF_SIZE); | ||
935 | if (result <= 0) | ||
936 | return result; | ||
937 | |||
938 | if (result < sizeof(struct ethhdr) + 2) | ||
939 | return 0; | ||
940 | |||
941 | ethhdr = (struct ethhdr *)packet_buff; | ||
942 | batman_packet = (struct batman_packet *) | ||
943 | (packet_buff + sizeof(struct ethhdr)); | ||
944 | |||
945 | if (batman_packet->version != COMPAT_VERSION) { | ||
946 | bat_dbg(DBG_BATMAN, | ||
947 | "Drop packet: incompatible batman version (%i)\n", | ||
948 | batman_packet->version); | ||
949 | return 0; | ||
950 | } | ||
951 | |||
952 | switch (batman_packet->packet_type) { | ||
953 | /* batman originator packet */ | ||
954 | case BAT_PACKET: | ||
955 | recv_bat_packet(ethhdr, packet_buff, result, batman_if); | ||
956 | break; | ||
957 | |||
958 | /* batman icmp packet */ | ||
959 | case BAT_ICMP: | ||
960 | recv_icmp_packet(ethhdr, packet_buff, result, batman_if); | ||
961 | break; | ||
962 | |||
963 | /* unicast packet */ | ||
964 | case BAT_UNICAST: | ||
965 | recv_unicast_packet(ethhdr, packet_buff, result, batman_if); | ||
966 | break; | ||
967 | |||
968 | /* broadcast packet */ | ||
969 | case BAT_BCAST: | ||
970 | recv_bcast_packet(ethhdr, | ||
971 | packet_buff, result, batman_if); | ||
972 | break; | ||
973 | |||
974 | /* vis packet */ | ||
975 | case BAT_VIS: | ||
976 | recv_vis_packet(ethhdr, packet_buff, result); | ||
977 | break; | ||
978 | } | ||
979 | return 0; | ||
980 | } | ||
981 | |||
982 | |||
983 | static int discard_one_packet(struct batman_if *batman_if, | ||
984 | unsigned char *packet_buff) | ||
985 | { | ||
986 | int result = -EAGAIN; | ||
987 | |||
988 | if (batman_if->raw_sock) { | ||
989 | result = receive_raw_packet(batman_if->raw_sock, | ||
990 | packet_buff, | ||
991 | PACKBUFF_SIZE); | ||
992 | } | ||
993 | return result; | ||
994 | } | ||
995 | |||
996 | |||
997 | static bool is_interface_active(struct batman_if *batman_if) | ||
998 | { | ||
999 | if (batman_if->if_active != IF_ACTIVE) | ||
1000 | return false; | ||
1001 | |||
1002 | return true; | ||
1003 | } | ||
1004 | |||
1005 | static void service_interface(struct batman_if *batman_if, | ||
1006 | unsigned char *packet_buff) | ||
1007 | |||
1008 | { | ||
1009 | int result; | ||
1010 | |||
1011 | do { | ||
1012 | if (is_interface_active(batman_if)) | ||
1013 | result = recv_one_packet(batman_if, packet_buff); | ||
1014 | else | ||
1015 | result = discard_one_packet(batman_if, packet_buff); | ||
1016 | } while (result >= 0); | ||
1017 | |||
1018 | /* we perform none blocking reads, so EAGAIN indicates there | ||
1019 | are no more packets to read. Anything else is a real | ||
1020 | error.*/ | ||
1021 | |||
1022 | if ((result < 0) && (result != -EAGAIN)) | ||
1023 | printk(KERN_ERR "batman-adv:Could not receive packet from interface %s: %i\n", batman_if->dev, result); | ||
1024 | } | ||
1025 | |||
1026 | static void service_interfaces(unsigned char *packet_buffer) | ||
1027 | { | ||
1028 | struct batman_if *batman_if; | ||
1029 | rcu_read_lock(); | ||
1030 | list_for_each_entry_rcu(batman_if, &if_list, list) { | ||
1031 | rcu_read_unlock(); | ||
1032 | service_interface(batman_if, packet_buffer); | ||
1033 | rcu_read_lock(); | ||
1034 | } | ||
1035 | rcu_read_unlock(); | ||
1036 | } | ||
1037 | |||
1038 | |||
1039 | int packet_recv_thread(void *data) | ||
1040 | { | ||
1041 | unsigned char *packet_buff; | ||
1042 | |||
1043 | atomic_set(&data_ready_cond, 0); | ||
1044 | atomic_set(&exit_cond, 0); | ||
1045 | packet_buff = kmalloc(PACKBUFF_SIZE, GFP_KERNEL); | ||
1046 | if (!packet_buff) { | ||
1047 | printk(KERN_ERR"batman-adv:Could allocate memory for the packet buffer. :(\n"); | ||
1048 | return -1; | ||
1049 | } | ||
1050 | |||
1051 | while ((!kthread_should_stop()) && (!atomic_read(&exit_cond))) { | ||
1052 | |||
1053 | wait_event_interruptible(thread_wait, | ||
1054 | (atomic_read(&data_ready_cond) || | ||
1055 | atomic_read(&exit_cond))); | ||
1056 | |||
1057 | atomic_set(&data_ready_cond, 0); | ||
1058 | |||
1059 | if (kthread_should_stop() || atomic_read(&exit_cond)) | ||
1060 | break; | ||
1061 | |||
1062 | service_interfaces(packet_buff); | ||
1063 | } | ||
1064 | kfree(packet_buff); | ||
1065 | |||
1066 | /* do not exit until kthread_stop() is actually called, | ||
1067 | * otherwise it will wait for us forever. */ | ||
1068 | while (!kthread_should_stop()) | ||
1069 | schedule(); | ||
1070 | |||
1071 | return 0; | ||
1072 | } | ||
1073 | |||
1074 | void batman_data_ready(struct sock *sk, int len) | ||
1075 | { | ||
1076 | void (*data_ready)(struct sock *, int) = sk->sk_user_data; | ||
1077 | |||
1078 | data_ready(sk, len); | ||
1079 | |||
1080 | atomic_set(&data_ready_cond, 1); | ||
1081 | wake_up_interruptible(&thread_wait); | ||
1082 | } | 1007 | } |
1083 | 1008 | ||