summaryrefslogtreecommitdiffstats
path: root/net/ipv4/ip_vti.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/ip_vti.c')
-rw-r--r--net/ipv4/ip_vti.c26
1 files changed, 16 insertions, 10 deletions
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index 94efe148181c..0c152087ca15 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -60,12 +60,11 @@ static int vti_input(struct sk_buff *skb, int nexthdr, __be32 spi,
tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
iph->saddr, iph->daddr, 0);
- if (tunnel != NULL) {
+ if (tunnel) {
if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
goto drop;
XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = tunnel;
- skb->mark = be32_to_cpu(tunnel->parms.i_key);
return xfrm_input(skb, nexthdr, spi, encap_type);
}
@@ -91,6 +90,8 @@ static int vti_rcv_cb(struct sk_buff *skb, int err)
struct pcpu_sw_netstats *tstats;
struct xfrm_state *x;
struct ip_tunnel *tunnel = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4;
+ u32 orig_mark = skb->mark;
+ int ret;
if (!tunnel)
return 1;
@@ -107,7 +108,11 @@ static int vti_rcv_cb(struct sk_buff *skb, int err)
x = xfrm_input_state(skb);
family = x->inner_mode->afinfo->family;
- if (!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family))
+ skb->mark = be32_to_cpu(tunnel->parms.i_key);
+ ret = xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family);
+ skb->mark = orig_mark;
+
+ if (!ret)
return -EPERM;
skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(skb->dev)));
@@ -216,8 +221,6 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
memset(&fl, 0, sizeof(fl));
- skb->mark = be32_to_cpu(tunnel->parms.o_key);
-
switch (skb->protocol) {
case htons(ETH_P_IP):
xfrm_decode_session(skb, &fl, AF_INET);
@@ -233,6 +236,9 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
}
+ /* override mark with tunnel output key */
+ fl.flowi_mark = be32_to_cpu(tunnel->parms.o_key);
+
return vti_xmit(skb, dev, &fl);
}
@@ -341,6 +347,7 @@ static const struct net_device_ops vti_netdev_ops = {
.ndo_do_ioctl = vti_tunnel_ioctl,
.ndo_change_mtu = ip_tunnel_change_mtu,
.ndo_get_stats64 = ip_tunnel_get_stats64,
+ .ndo_get_iflink = ip_tunnel_get_iflink,
};
static void vti_tunnel_setup(struct net_device *dev)
@@ -361,7 +368,6 @@ static int vti_tunnel_init(struct net_device *dev)
dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr);
dev->mtu = ETH_DATA_LEN;
dev->flags = IFF_NOARP;
- dev->iflink = 0;
dev->addr_len = 4;
dev->features |= NETIF_F_LLTX;
netif_keep_dst(dev);
@@ -456,10 +462,10 @@ static void vti_netlink_parms(struct nlattr *data[],
parms->o_key = nla_get_be32(data[IFLA_VTI_OKEY]);
if (data[IFLA_VTI_LOCAL])
- parms->iph.saddr = nla_get_be32(data[IFLA_VTI_LOCAL]);
+ parms->iph.saddr = nla_get_in_addr(data[IFLA_VTI_LOCAL]);
if (data[IFLA_VTI_REMOTE])
- parms->iph.daddr = nla_get_be32(data[IFLA_VTI_REMOTE]);
+ parms->iph.daddr = nla_get_in_addr(data[IFLA_VTI_REMOTE]);
}
@@ -505,8 +511,8 @@ static int vti_fill_info(struct sk_buff *skb, const struct net_device *dev)
nla_put_u32(skb, IFLA_VTI_LINK, p->link);
nla_put_be32(skb, IFLA_VTI_IKEY, p->i_key);
nla_put_be32(skb, IFLA_VTI_OKEY, p->o_key);
- nla_put_be32(skb, IFLA_VTI_LOCAL, p->iph.saddr);
- nla_put_be32(skb, IFLA_VTI_REMOTE, p->iph.daddr);
+ nla_put_in_addr(skb, IFLA_VTI_LOCAL, p->iph.saddr);
+ nla_put_in_addr(skb, IFLA_VTI_REMOTE, p->iph.daddr);
return 0;
}