aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorVille Nuorvala <vnuorval@tcs.hut.fi>2006-11-24 20:06:27 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-03 00:30:24 -0500
commit09c6bbf090ecb52c8d670fa4d5730be134a8ec8b (patch)
tree3ae488ac005b0847aeab4a03c4fdd38607c38d71 /net/ipv6
parent567131a722ca064c917c0b06e4bcf07d47602103 (diff)
[IPV6]: Do mandatory IPv6 tunnel endpoint checks in realtime
Doing the mandatory tunnel endpoint checks when the tunnel is set up isn't enough as interfaces can go up or down and addresses can be added or deleted after this. The checks need to be done realtime when the tunnel is processing a packet. Signed-off-by: Ville Nuorvala <vnuorval@tcs.hut.fi> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/ip6_tunnel.c96
1 files changed, 62 insertions, 34 deletions
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index fdf1a2fa3a3d..22debbf28b8a 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -494,6 +494,27 @@ static inline void ip6ip6_ecn_decapsulate(struct ipv6hdr *outer_iph,
494 if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph))) 494 if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph)))
495 IP6_ECN_set_ce(inner_iph); 495 IP6_ECN_set_ce(inner_iph);
496} 496}
497static inline int ip6_tnl_rcv_ctl(struct ip6_tnl *t)
498{
499 struct ip6_tnl_parm *p = &t->parms;
500 int ret = 0;
501
502 if (p->flags & IP6_TNL_F_CAP_RCV) {
503 struct net_device *ldev = NULL;
504
505 if (p->link)
506 ldev = dev_get_by_index(p->link);
507
508 if ((ipv6_addr_is_multicast(&p->laddr) ||
509 likely(ipv6_chk_addr(&p->laddr, ldev, 0))) &&
510 likely(!ipv6_chk_addr(&p->raddr, NULL, 0)))
511 ret = 1;
512
513 if (ldev)
514 dev_put(ldev);
515 }
516 return ret;
517}
497 518
498/** 519/**
499 * ip6ip6_rcv - decapsulate IPv6 packet and retransmit it locally 520 * ip6ip6_rcv - decapsulate IPv6 packet and retransmit it locally
@@ -518,7 +539,7 @@ ip6ip6_rcv(struct sk_buff *skb)
518 goto discard; 539 goto discard;
519 } 540 }
520 541
521 if (!(t->parms.flags & IP6_TNL_F_CAP_RCV)) { 542 if (!ip6_tnl_rcv_ctl(t)) {
522 t->stat.rx_dropped++; 543 t->stat.rx_dropped++;
523 read_unlock(&ip6ip6_lock); 544 read_unlock(&ip6ip6_lock);
524 goto discard; 545 goto discard;
@@ -597,6 +618,34 @@ ip6ip6_tnl_addr_conflict(struct ip6_tnl *t, struct ipv6hdr *hdr)
597 return ipv6_addr_equal(&t->parms.raddr, &hdr->saddr); 618 return ipv6_addr_equal(&t->parms.raddr, &hdr->saddr);
598} 619}
599 620
621static inline int ip6_tnl_xmit_ctl(struct ip6_tnl *t)
622{
623 struct ip6_tnl_parm *p = &t->parms;
624 int ret = 0;
625
626 if (p->flags & IP6_TNL_F_CAP_XMIT) {
627 struct net_device *ldev = NULL;
628
629 if (p->link)
630 ldev = dev_get_by_index(p->link);
631
632 if (unlikely(!ipv6_chk_addr(&p->laddr, ldev, 0)))
633 printk(KERN_WARNING
634 "%s xmit: Local address not yet configured!\n",
635 p->name);
636 else if (!ipv6_addr_is_multicast(&p->raddr) &&
637 unlikely(ipv6_chk_addr(&p->raddr, NULL, 0)))
638 printk(KERN_WARNING
639 "%s xmit: Routing loop! "
640 "Remote address found on this node!\n",
641 p->name);
642 else
643 ret = 1;
644 if (ldev)
645 dev_put(ldev);
646 }
647 return ret;
648}
600/** 649/**
601 * ip6ip6_tnl_xmit - encapsulate packet and send 650 * ip6ip6_tnl_xmit - encapsulate packet and send
602 * @skb: the outgoing socket buffer 651 * @skb: the outgoing socket buffer
@@ -634,10 +683,9 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
634 goto tx_err; 683 goto tx_err;
635 } 684 }
636 if (skb->protocol != htons(ETH_P_IPV6) || 685 if (skb->protocol != htons(ETH_P_IPV6) ||
637 !(t->parms.flags & IP6_TNL_F_CAP_XMIT) || 686 !ip6_tnl_xmit_ctl(t) || ip6ip6_tnl_addr_conflict(t, ipv6h))
638 ip6ip6_tnl_addr_conflict(t, ipv6h)) {
639 goto tx_err; 687 goto tx_err;
640 } 688
641 if ((offset = parse_tlv_tnl_enc_lim(skb, skb->nh.raw)) > 0) { 689 if ((offset = parse_tlv_tnl_enc_lim(skb, skb->nh.raw)) > 0) {
642 struct ipv6_tlv_tnl_enc_lim *tel; 690 struct ipv6_tlv_tnl_enc_lim *tel;
643 tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->nh.raw[offset]; 691 tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->nh.raw[offset];
@@ -768,39 +816,19 @@ tx_err:
768static void ip6_tnl_set_cap(struct ip6_tnl *t) 816static void ip6_tnl_set_cap(struct ip6_tnl *t)
769{ 817{
770 struct ip6_tnl_parm *p = &t->parms; 818 struct ip6_tnl_parm *p = &t->parms;
771 struct in6_addr *laddr = &p->laddr; 819 int ltype = ipv6_addr_type(&p->laddr);
772 struct in6_addr *raddr = &p->raddr; 820 int rtype = ipv6_addr_type(&p->raddr);
773 int ltype = ipv6_addr_type(laddr);
774 int rtype = ipv6_addr_type(raddr);
775 821
776 p->flags &= ~(IP6_TNL_F_CAP_XMIT|IP6_TNL_F_CAP_RCV); 822 p->flags &= ~(IP6_TNL_F_CAP_XMIT|IP6_TNL_F_CAP_RCV);
777 823
778 if (ltype != IPV6_ADDR_ANY && rtype != IPV6_ADDR_ANY && 824 if (ltype & (IPV6_ADDR_UNICAST|IPV6_ADDR_MULTICAST) &&
779 ((ltype|rtype) & 825 rtype & (IPV6_ADDR_UNICAST|IPV6_ADDR_MULTICAST) &&
780 (IPV6_ADDR_UNICAST| 826 !((ltype|rtype) & IPV6_ADDR_LOOPBACK) &&
781 IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL| 827 !((ltype|rtype) & IPV6_ADDR_LINKLOCAL)) {
782 IPV6_ADDR_MAPPED|IPV6_ADDR_RESERVED)) == IPV6_ADDR_UNICAST) { 828 if (ltype&IPV6_ADDR_UNICAST)
783 struct net_device *ldev = NULL; 829 p->flags |= IP6_TNL_F_CAP_XMIT;
784 int l_ok = 1; 830 if (rtype&IPV6_ADDR_UNICAST)
785 int r_ok = 1; 831 p->flags |= IP6_TNL_F_CAP_RCV;
786
787 if (p->link)
788 ldev = dev_get_by_index(p->link);
789
790 if (ltype&IPV6_ADDR_UNICAST && !ipv6_chk_addr(laddr, ldev, 0))
791 l_ok = 0;
792
793 if (rtype&IPV6_ADDR_UNICAST && ipv6_chk_addr(raddr, NULL, 0))
794 r_ok = 0;
795
796 if (l_ok && r_ok) {
797 if (ltype&IPV6_ADDR_UNICAST)
798 p->flags |= IP6_TNL_F_CAP_XMIT;
799 if (rtype&IPV6_ADDR_UNICAST)
800 p->flags |= IP6_TNL_F_CAP_RCV;
801 }
802 if (ldev)
803 dev_put(ldev);
804 } 832 }
805} 833}
806 834