diff options
Diffstat (limited to 'net/ipv4/ip_gre.c')
-rw-r--r-- | net/ipv4/ip_gre.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index a85ae2f7a21c..303012adf9e6 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -750,6 +750,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev | |||
750 | int gre_hlen; | 750 | int gre_hlen; |
751 | __be32 dst; | 751 | __be32 dst; |
752 | int mtu; | 752 | int mtu; |
753 | u8 ttl; | ||
753 | 754 | ||
754 | if (skb->ip_summed == CHECKSUM_PARTIAL && | 755 | if (skb->ip_summed == CHECKSUM_PARTIAL && |
755 | skb_checksum_help(skb)) | 756 | skb_checksum_help(skb)) |
@@ -760,7 +761,10 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev | |||
760 | 761 | ||
761 | if (dev->header_ops && dev->type == ARPHRD_IPGRE) { | 762 | if (dev->header_ops && dev->type == ARPHRD_IPGRE) { |
762 | gre_hlen = 0; | 763 | gre_hlen = 0; |
763 | tiph = (const struct iphdr *)skb->data; | 764 | if (skb->protocol == htons(ETH_P_IP)) |
765 | tiph = (const struct iphdr *)skb->data; | ||
766 | else | ||
767 | tiph = &tunnel->parms.iph; | ||
764 | } else { | 768 | } else { |
765 | gre_hlen = tunnel->hlen; | 769 | gre_hlen = tunnel->hlen; |
766 | tiph = &tunnel->parms.iph; | 770 | tiph = &tunnel->parms.iph; |
@@ -812,6 +816,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev | |||
812 | goto tx_error; | 816 | goto tx_error; |
813 | } | 817 | } |
814 | 818 | ||
819 | ttl = tiph->ttl; | ||
815 | tos = tiph->tos; | 820 | tos = tiph->tos; |
816 | if (tos == 1) { | 821 | if (tos == 1) { |
817 | tos = 0; | 822 | tos = 0; |
@@ -904,11 +909,12 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev | |||
904 | dev_kfree_skb(skb); | 909 | dev_kfree_skb(skb); |
905 | skb = new_skb; | 910 | skb = new_skb; |
906 | old_iph = ip_hdr(skb); | 911 | old_iph = ip_hdr(skb); |
912 | /* Warning : tiph value might point to freed memory */ | ||
907 | } | 913 | } |
908 | 914 | ||
909 | skb_reset_transport_header(skb); | ||
910 | skb_push(skb, gre_hlen); | 915 | skb_push(skb, gre_hlen); |
911 | skb_reset_network_header(skb); | 916 | skb_reset_network_header(skb); |
917 | skb_set_transport_header(skb, sizeof(*iph)); | ||
912 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); | 918 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); |
913 | IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | | 919 | IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | |
914 | IPSKB_REROUTED); | 920 | IPSKB_REROUTED); |
@@ -927,8 +933,9 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev | |||
927 | iph->tos = ipgre_ecn_encapsulate(tos, old_iph, skb); | 933 | iph->tos = ipgre_ecn_encapsulate(tos, old_iph, skb); |
928 | iph->daddr = fl4.daddr; | 934 | iph->daddr = fl4.daddr; |
929 | iph->saddr = fl4.saddr; | 935 | iph->saddr = fl4.saddr; |
936 | iph->ttl = ttl; | ||
930 | 937 | ||
931 | if ((iph->ttl = tiph->ttl) == 0) { | 938 | if (ttl == 0) { |
932 | if (skb->protocol == htons(ETH_P_IP)) | 939 | if (skb->protocol == htons(ETH_P_IP)) |
933 | iph->ttl = old_iph->ttl; | 940 | iph->ttl = old_iph->ttl; |
934 | #if IS_ENABLED(CONFIG_IPV6) | 941 | #if IS_ENABLED(CONFIG_IPV6) |