aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/ipv6/sit.c54
1 files changed, 41 insertions, 13 deletions
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 98fe53694a65..02f96dcbcf02 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -72,6 +72,8 @@ MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
72static int ipip6_tunnel_init(struct net_device *dev); 72static int ipip6_tunnel_init(struct net_device *dev);
73static void ipip6_tunnel_setup(struct net_device *dev); 73static void ipip6_tunnel_setup(struct net_device *dev);
74static void ipip6_dev_free(struct net_device *dev); 74static void ipip6_dev_free(struct net_device *dev);
75static bool check_6rd(struct ip_tunnel *tunnel, const struct in6_addr *v6dst,
76 __be32 *v4dst);
75static struct rtnl_link_ops sit_link_ops __read_mostly; 77static struct rtnl_link_ops sit_link_ops __read_mostly;
76 78
77static int sit_net_id __read_mostly; 79static int sit_net_id __read_mostly;
@@ -590,6 +592,15 @@ out:
590 return err; 592 return err;
591} 593}
592 594
595static inline bool is_spoofed_6rd(struct ip_tunnel *tunnel, const __be32 v4addr,
596 const struct in6_addr *v6addr)
597{
598 __be32 v4embed = 0;
599 if (check_6rd(tunnel, v6addr, &v4embed) && v4addr != v4embed)
600 return true;
601 return false;
602}
603
593static int ipip6_rcv(struct sk_buff *skb) 604static int ipip6_rcv(struct sk_buff *skb)
594{ 605{
595 const struct iphdr *iph = ip_hdr(skb); 606 const struct iphdr *iph = ip_hdr(skb);
@@ -608,10 +619,19 @@ static int ipip6_rcv(struct sk_buff *skb)
608 skb->protocol = htons(ETH_P_IPV6); 619 skb->protocol = htons(ETH_P_IPV6);
609 skb->pkt_type = PACKET_HOST; 620 skb->pkt_type = PACKET_HOST;
610 621
611 if ((tunnel->dev->priv_flags & IFF_ISATAP) && 622 if (tunnel->dev->priv_flags & IFF_ISATAP) {
612 !isatap_chksrc(skb, iph, tunnel)) { 623 if (!isatap_chksrc(skb, iph, tunnel)) {
613 tunnel->dev->stats.rx_errors++; 624 tunnel->dev->stats.rx_errors++;
614 goto out; 625 goto out;
626 }
627 } else {
628 if (is_spoofed_6rd(tunnel, iph->saddr,
629 &ipv6_hdr(skb)->saddr) ||
630 is_spoofed_6rd(tunnel, iph->daddr,
631 &ipv6_hdr(skb)->daddr)) {
632 tunnel->dev->stats.rx_errors++;
633 goto out;
634 }
615 } 635 }
616 636
617 __skb_tunnel_rx(skb, tunnel->dev); 637 __skb_tunnel_rx(skb, tunnel->dev);
@@ -645,14 +665,12 @@ out:
645} 665}
646 666
647/* 667/*
648 * Returns the embedded IPv4 address if the IPv6 address 668 * If the IPv6 address comes from 6rd / 6to4 (RFC 3056) addr space this function
649 * comes from 6rd / 6to4 (RFC 3056) addr space. 669 * stores the embedded IPv4 address in v4dst and returns true.
650 */ 670 */
651static inline 671static bool check_6rd(struct ip_tunnel *tunnel, const struct in6_addr *v6dst,
652__be32 try_6rd(const struct in6_addr *v6dst, struct ip_tunnel *tunnel) 672 __be32 *v4dst)
653{ 673{
654 __be32 dst = 0;
655
656#ifdef CONFIG_IPV6_SIT_6RD 674#ifdef CONFIG_IPV6_SIT_6RD
657 if (ipv6_prefix_equal(v6dst, &tunnel->ip6rd.prefix, 675 if (ipv6_prefix_equal(v6dst, &tunnel->ip6rd.prefix,
658 tunnel->ip6rd.prefixlen)) { 676 tunnel->ip6rd.prefixlen)) {
@@ -671,14 +689,24 @@ __be32 try_6rd(const struct in6_addr *v6dst, struct ip_tunnel *tunnel)
671 d |= ntohl(v6dst->s6_addr32[pbw0 + 1]) >> 689 d |= ntohl(v6dst->s6_addr32[pbw0 + 1]) >>
672 (32 - pbi1); 690 (32 - pbi1);
673 691
674 dst = tunnel->ip6rd.relay_prefix | htonl(d); 692 *v4dst = tunnel->ip6rd.relay_prefix | htonl(d);
693 return true;
675 } 694 }
676#else 695#else
677 if (v6dst->s6_addr16[0] == htons(0x2002)) { 696 if (v6dst->s6_addr16[0] == htons(0x2002)) {
678 /* 6to4 v6 addr has 16 bits prefix, 32 v4addr, 16 SLA, ... */ 697 /* 6to4 v6 addr has 16 bits prefix, 32 v4addr, 16 SLA, ... */
679 memcpy(&dst, &v6dst->s6_addr16[1], 4); 698 memcpy(v4dst, &v6dst->s6_addr16[1], 4);
699 return true;
680 } 700 }
681#endif 701#endif
702 return false;
703}
704
705static inline __be32 try_6rd(struct ip_tunnel *tunnel,
706 const struct in6_addr *v6dst)
707{
708 __be32 dst = 0;
709 check_6rd(tunnel, v6dst, &dst);
682 return dst; 710 return dst;
683} 711}
684 712
@@ -739,7 +767,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
739 } 767 }
740 768
741 if (!dst) 769 if (!dst)
742 dst = try_6rd(&iph6->daddr, tunnel); 770 dst = try_6rd(tunnel, &iph6->daddr);
743 771
744 if (!dst) { 772 if (!dst) {
745 struct neighbour *neigh = NULL; 773 struct neighbour *neigh = NULL;