Skip to content

Commit 09c6bbf

Browse files
Ville NuorvalaDavid S. Miller
Ville Nuorvala
authored and
David S. Miller
committed
[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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 567131a commit 09c6bbf

File tree

1 file changed

+62
-34
lines changed

1 file changed

+62
-34
lines changed

net/ipv6/ip6_tunnel.c

Lines changed: 62 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,27 @@ static inline void ip6ip6_ecn_decapsulate(struct ipv6hdr *outer_iph,
494494
if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph)))
495495
IP6_ECN_set_ce(inner_iph);
496496
}
497+
static 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+
}
497518

498519
/**
499520
* ip6ip6_rcv - decapsulate IPv6 packet and retransmit it locally
@@ -518,7 +539,7 @@ ip6ip6_rcv(struct sk_buff *skb)
518539
goto discard;
519540
}
520541

521-
if (!(t->parms.flags & IP6_TNL_F_CAP_RCV)) {
542+
if (!ip6_tnl_rcv_ctl(t)) {
522543
t->stat.rx_dropped++;
523544
read_unlock(&ip6ip6_lock);
524545
goto discard;
@@ -597,6 +618,34 @@ ip6ip6_tnl_addr_conflict(struct ip6_tnl *t, struct ipv6hdr *hdr)
597618
return ipv6_addr_equal(&t->parms.raddr, &hdr->saddr);
598619
}
599620

621+
static 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+
}
600649
/**
601650
* ip6ip6_tnl_xmit - encapsulate packet and send
602651
* @skb: the outgoing socket buffer
@@ -634,10 +683,9 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
634683
goto tx_err;
635684
}
636685
if (skb->protocol != htons(ETH_P_IPV6) ||
637-
!(t->parms.flags & IP6_TNL_F_CAP_XMIT) ||
638-
ip6ip6_tnl_addr_conflict(t, ipv6h)) {
686+
!ip6_tnl_xmit_ctl(t) || ip6ip6_tnl_addr_conflict(t, ipv6h))
639687
goto tx_err;
640-
}
688+
641689
if ((offset = parse_tlv_tnl_enc_lim(skb, skb->nh.raw)) > 0) {
642690
struct ipv6_tlv_tnl_enc_lim *tel;
643691
tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->nh.raw[offset];
@@ -768,39 +816,19 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
768816
static void ip6_tnl_set_cap(struct ip6_tnl *t)
769817
{
770818
struct ip6_tnl_parm *p = &t->parms;
771-
struct in6_addr *laddr = &p->laddr;
772-
struct in6_addr *raddr = &p->raddr;
773-
int ltype = ipv6_addr_type(laddr);
774-
int rtype = ipv6_addr_type(raddr);
819+
int ltype = ipv6_addr_type(&p->laddr);
820+
int rtype = ipv6_addr_type(&p->raddr);
775821

776822
p->flags &= ~(IP6_TNL_F_CAP_XMIT|IP6_TNL_F_CAP_RCV);
777823

778-
if (ltype != IPV6_ADDR_ANY && rtype != IPV6_ADDR_ANY &&
779-
((ltype|rtype) &
780-
(IPV6_ADDR_UNICAST|
781-
IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL|
782-
IPV6_ADDR_MAPPED|IPV6_ADDR_RESERVED)) == IPV6_ADDR_UNICAST) {
783-
struct net_device *ldev = NULL;
784-
int l_ok = 1;
785-
int r_ok = 1;
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);
824+
if (ltype & (IPV6_ADDR_UNICAST|IPV6_ADDR_MULTICAST) &&
825+
rtype & (IPV6_ADDR_UNICAST|IPV6_ADDR_MULTICAST) &&
826+
!((ltype|rtype) & IPV6_ADDR_LOOPBACK) &&
827+
!((ltype|rtype) & IPV6_ADDR_LINKLOCAL)) {
828+
if (ltype&IPV6_ADDR_UNICAST)
829+
p->flags |= IP6_TNL_F_CAP_XMIT;
830+
if (rtype&IPV6_ADDR_UNICAST)
831+
p->flags |= IP6_TNL_F_CAP_RCV;
804832
}
805833
}
806834

0 commit comments

Comments
 (0)