aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/udp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/udp.c')
-rw-r--r--net/ipv6/udp.c131
1 files changed, 63 insertions, 68 deletions
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 7092ff78fd84..4836af8f582d 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -79,7 +79,6 @@ static unsigned int udp6_ehashfn(struct net *net,
79int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) 79int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2)
80{ 80{
81 const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2); 81 const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2);
82 int sk_ipv6only = ipv6_only_sock(sk);
83 int sk2_ipv6only = inet_v6_ipv6only(sk2); 82 int sk2_ipv6only = inet_v6_ipv6only(sk2);
84 int addr_type = ipv6_addr_type(&sk->sk_v6_rcv_saddr); 83 int addr_type = ipv6_addr_type(&sk->sk_v6_rcv_saddr);
85 int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED; 84 int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED;
@@ -95,7 +94,7 @@ int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2)
95 return 1; 94 return 1;
96 95
97 if (addr_type == IPV6_ADDR_ANY && 96 if (addr_type == IPV6_ADDR_ANY &&
98 !(sk_ipv6only && addr_type2 == IPV6_ADDR_MAPPED)) 97 !(ipv6_only_sock(sk) && addr_type2 == IPV6_ADDR_MAPPED))
99 return 1; 98 return 1;
100 99
101 if (sk2_rcv_saddr6 && 100 if (sk2_rcv_saddr6 &&
@@ -473,7 +472,7 @@ try_again:
473 sin6->sin6_addr = ipv6_hdr(skb)->saddr; 472 sin6->sin6_addr = ipv6_hdr(skb)->saddr;
474 sin6->sin6_scope_id = 473 sin6->sin6_scope_id =
475 ipv6_iface_scope_id(&sin6->sin6_addr, 474 ipv6_iface_scope_id(&sin6->sin6_addr,
476 IP6CB(skb)->iif); 475 inet6_iif(skb));
477 } 476 }
478 *addr_len = sizeof(*sin6); 477 *addr_len = sizeof(*sin6);
479 } 478 }
@@ -534,11 +533,15 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
534 struct udphdr *uh = (struct udphdr*)(skb->data+offset); 533 struct udphdr *uh = (struct udphdr*)(skb->data+offset);
535 struct sock *sk; 534 struct sock *sk;
536 int err; 535 int err;
536 struct net *net = dev_net(skb->dev);
537 537
538 sk = __udp6_lib_lookup(dev_net(skb->dev), daddr, uh->dest, 538 sk = __udp6_lib_lookup(net, daddr, uh->dest,
539 saddr, uh->source, inet6_iif(skb), udptable); 539 saddr, uh->source, inet6_iif(skb), udptable);
540 if (sk == NULL) 540 if (sk == NULL) {
541 ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev),
542 ICMP6_MIB_INERRORS);
541 return; 543 return;
544 }
542 545
543 if (type == ICMPV6_PKT_TOOBIG) { 546 if (type == ICMPV6_PKT_TOOBIG) {
544 if (!ip6_sk_accept_pmtu(sk)) 547 if (!ip6_sk_accept_pmtu(sk))
@@ -674,7 +677,7 @@ int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
674 goto csum_error; 677 goto csum_error;
675 } 678 }
676 679
677 if (sk_rcvqueues_full(sk, skb, sk->sk_rcvbuf)) { 680 if (sk_rcvqueues_full(sk, sk->sk_rcvbuf)) {
678 UDP6_INC_STATS_BH(sock_net(sk), 681 UDP6_INC_STATS_BH(sock_net(sk),
679 UDP_MIB_RCVBUFERRORS, is_udplite); 682 UDP_MIB_RCVBUFERRORS, is_udplite);
680 goto drop; 683 goto drop;
@@ -703,43 +706,26 @@ drop:
703 return -1; 706 return -1;
704} 707}
705 708
706static struct sock *udp_v6_mcast_next(struct net *net, struct sock *sk, 709static bool __udp_v6_is_mcast_sock(struct net *net, struct sock *sk,
707 __be16 loc_port, const struct in6_addr *loc_addr, 710 __be16 loc_port, const struct in6_addr *loc_addr,
708 __be16 rmt_port, const struct in6_addr *rmt_addr, 711 __be16 rmt_port, const struct in6_addr *rmt_addr,
709 int dif) 712 int dif, unsigned short hnum)
710{ 713{
711 struct hlist_nulls_node *node; 714 struct inet_sock *inet = inet_sk(sk);
712 unsigned short num = ntohs(loc_port);
713
714 sk_nulls_for_each_from(sk, node) {
715 struct inet_sock *inet = inet_sk(sk);
716
717 if (!net_eq(sock_net(sk), net))
718 continue;
719
720 if (udp_sk(sk)->udp_port_hash == num &&
721 sk->sk_family == PF_INET6) {
722 if (inet->inet_dport) {
723 if (inet->inet_dport != rmt_port)
724 continue;
725 }
726 if (!ipv6_addr_any(&sk->sk_v6_daddr) &&
727 !ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr))
728 continue;
729
730 if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif)
731 continue;
732 715
733 if (!ipv6_addr_any(&sk->sk_v6_rcv_saddr)) { 716 if (!net_eq(sock_net(sk), net))
734 if (!ipv6_addr_equal(&sk->sk_v6_rcv_saddr, loc_addr)) 717 return false;
735 continue; 718
736 } 719 if (udp_sk(sk)->udp_port_hash != hnum ||
737 if (!inet6_mc_check(sk, loc_addr, rmt_addr)) 720 sk->sk_family != PF_INET6 ||
738 continue; 721 (inet->inet_dport && inet->inet_dport != rmt_port) ||
739 return sk; 722 (!ipv6_addr_any(&sk->sk_v6_daddr) &&
740 } 723 !ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr)) ||
741 } 724 (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif))
742 return NULL; 725 return false;
726 if (!inet6_mc_check(sk, loc_addr, rmt_addr))
727 return false;
728 return true;
743} 729}
744 730
745static void flush_stack(struct sock **stack, unsigned int count, 731static void flush_stack(struct sock **stack, unsigned int count,
@@ -763,6 +749,7 @@ static void flush_stack(struct sock **stack, unsigned int count,
763 749
764 if (skb1 && udpv6_queue_rcv_skb(sk, skb1) <= 0) 750 if (skb1 && udpv6_queue_rcv_skb(sk, skb1) <= 0)
765 skb1 = NULL; 751 skb1 = NULL;
752 sock_put(sk);
766 } 753 }
767 if (unlikely(skb1)) 754 if (unlikely(skb1))
768 kfree_skb(skb1); 755 kfree_skb(skb1);
@@ -788,43 +775,51 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
788{ 775{
789 struct sock *sk, *stack[256 / sizeof(struct sock *)]; 776 struct sock *sk, *stack[256 / sizeof(struct sock *)];
790 const struct udphdr *uh = udp_hdr(skb); 777 const struct udphdr *uh = udp_hdr(skb);
791 struct udp_hslot *hslot = udp_hashslot(udptable, net, ntohs(uh->dest)); 778 struct hlist_nulls_node *node;
792 int dif; 779 unsigned short hnum = ntohs(uh->dest);
793 unsigned int i, count = 0; 780 struct udp_hslot *hslot = udp_hashslot(udptable, net, hnum);
781 int dif = inet6_iif(skb);
782 unsigned int count = 0, offset = offsetof(typeof(*sk), sk_nulls_node);
783 unsigned int hash2 = 0, hash2_any = 0, use_hash2 = (hslot->count > 10);
784
785 if (use_hash2) {
786 hash2_any = udp6_portaddr_hash(net, &in6addr_any, hnum) &
787 udp_table.mask;
788 hash2 = udp6_portaddr_hash(net, daddr, hnum) & udp_table.mask;
789start_lookup:
790 hslot = &udp_table.hash2[hash2];
791 offset = offsetof(typeof(*sk), __sk_common.skc_portaddr_node);
792 }
794 793
795 spin_lock(&hslot->lock); 794 spin_lock(&hslot->lock);
796 sk = sk_nulls_head(&hslot->head); 795 sk_nulls_for_each_entry_offset(sk, node, &hslot->head, offset) {
797 dif = inet6_iif(skb); 796 if (__udp_v6_is_mcast_sock(net, sk,
798 sk = udp_v6_mcast_next(net, sk, uh->dest, daddr, uh->source, saddr, dif); 797 uh->dest, daddr,
799 while (sk) { 798 uh->source, saddr,
800 /* If zero checksum and no_check is not on for 799 dif, hnum) &&
801 * the socket then skip it. 800 /* If zero checksum and no_check is not on for
802 */ 801 * the socket then skip it.
803 if (uh->check || udp_sk(sk)->no_check6_rx) 802 */
803 (uh->check || udp_sk(sk)->no_check6_rx)) {
804 if (unlikely(count == ARRAY_SIZE(stack))) {
805 flush_stack(stack, count, skb, ~0);
806 count = 0;
807 }
804 stack[count++] = sk; 808 stack[count++] = sk;
805 809 sock_hold(sk);
806 sk = udp_v6_mcast_next(net, sk_nulls_next(sk), uh->dest, daddr,
807 uh->source, saddr, dif);
808 if (unlikely(count == ARRAY_SIZE(stack))) {
809 if (!sk)
810 break;
811 flush_stack(stack, count, skb, ~0);
812 count = 0;
813 } 810 }
814 } 811 }
815 /*
816 * before releasing the lock, we must take reference on sockets
817 */
818 for (i = 0; i < count; i++)
819 sock_hold(stack[i]);
820 812
821 spin_unlock(&hslot->lock); 813 spin_unlock(&hslot->lock);
822 814
815 /* Also lookup *:port if we are using hash2 and haven't done so yet. */
816 if (use_hash2 && hash2 != hash2_any) {
817 hash2 = hash2_any;
818 goto start_lookup;
819 }
820
823 if (count) { 821 if (count) {
824 flush_stack(stack, count, skb, count - 1); 822 flush_stack(stack, count, skb, count - 1);
825
826 for (i = 0; i < count; i++)
827 sock_put(stack[i]);
828 } else { 823 } else {
829 kfree_skb(skb); 824 kfree_skb(skb);
830 } 825 }