Skip to content

Commit 32b8a8e

Browse files
NicolasDichteldavem330
authored andcommitted
sit: add IPv4 over IPv4 support
This patch adds the support of IPv4 over Ipv4 for the module sit. The gain of this feature is to be able to have 4in4 and 6in4 over the same interface instead of having one interface for 6in4 and another for 4in4 even if encapsulation addresses are the same. To avoid conflicting with ipip module, sit IPv4 over IPv4 protocol is registered with a smaller priority. Signed-off-by: Nicolas Dichtel <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent bf3d6a8 commit 32b8a8e

File tree

2 files changed

+117
-4
lines changed

2 files changed

+117
-4
lines changed

net/ipv4/xfrm4_tunnel.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ static int xfrm_tunnel_err(struct sk_buff *skb, u32 info)
6363
static struct xfrm_tunnel xfrm_tunnel_handler __read_mostly = {
6464
.handler = xfrm_tunnel_rcv,
6565
.err_handler = xfrm_tunnel_err,
66-
.priority = 2,
66+
.priority = 3,
6767
};
6868

6969
#if IS_ENABLED(CONFIG_IPV6)

net/ipv6/sit.c

Lines changed: 116 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,10 @@ static int ipip6_rcv(struct sk_buff *skb)
577577
if (tunnel != NULL) {
578578
struct pcpu_tstats *tstats;
579579

580+
if (tunnel->parms.iph.protocol != IPPROTO_IPV6 &&
581+
tunnel->parms.iph.protocol != 0)
582+
goto out;
583+
580584
secpath_reset(skb);
581585
skb->mac_header = skb->network_header;
582586
skb_reset_network_header(skb);
@@ -629,6 +633,35 @@ static int ipip6_rcv(struct sk_buff *skb)
629633
return 0;
630634
}
631635

636+
static const struct tnl_ptk_info tpi = {
637+
/* no tunnel info required for ipip. */
638+
.proto = htons(ETH_P_IP),
639+
};
640+
641+
static int ipip_rcv(struct sk_buff *skb)
642+
{
643+
const struct iphdr *iph = ip_hdr(skb);
644+
struct ip_tunnel *tunnel;
645+
646+
tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev,
647+
iph->saddr, iph->daddr);
648+
if (tunnel != NULL) {
649+
if (tunnel->parms.iph.protocol != IPPROTO_IPIP &&
650+
tunnel->parms.iph.protocol != 0)
651+
goto drop;
652+
653+
if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
654+
goto drop;
655+
return ip_tunnel_rcv(tunnel, skb, &tpi, log_ecn_error);
656+
}
657+
658+
return 1;
659+
660+
drop:
661+
kfree_skb(skb);
662+
return 0;
663+
}
664+
632665
/*
633666
* If the IPv6 address comes from 6rd / 6to4 (RFC 3056) addr space this function
634667
* stores the embedded IPv4 address in v4dst and returns true.
@@ -877,6 +910,43 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
877910
return NETDEV_TX_OK;
878911
}
879912

913+
static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
914+
{
915+
struct ip_tunnel *tunnel = netdev_priv(dev);
916+
const struct iphdr *tiph = &tunnel->parms.iph;
917+
918+
if (likely(!skb->encapsulation)) {
919+
skb_reset_inner_headers(skb);
920+
skb->encapsulation = 1;
921+
}
922+
923+
ip_tunnel_xmit(skb, dev, tiph, IPPROTO_IPIP);
924+
return NETDEV_TX_OK;
925+
}
926+
927+
static netdev_tx_t sit_tunnel_xmit(struct sk_buff *skb,
928+
struct net_device *dev)
929+
{
930+
switch (skb->protocol) {
931+
case htons(ETH_P_IP):
932+
ipip_tunnel_xmit(skb, dev);
933+
break;
934+
case htons(ETH_P_IPV6):
935+
ipip6_tunnel_xmit(skb, dev);
936+
break;
937+
default:
938+
goto tx_err;
939+
}
940+
941+
return NETDEV_TX_OK;
942+
943+
tx_err:
944+
dev->stats.tx_errors++;
945+
dev_kfree_skb(skb);
946+
return NETDEV_TX_OK;
947+
948+
}
949+
880950
static void ipip6_tunnel_bind_dev(struct net_device *dev)
881951
{
882952
struct net_device *tdev = NULL;
@@ -1027,7 +1097,11 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
10271097
goto done;
10281098

10291099
err = -EINVAL;
1030-
if (p.iph.version != 4 || p.iph.protocol != IPPROTO_IPV6 ||
1100+
if (p.iph.protocol != IPPROTO_IPV6 &&
1101+
p.iph.protocol != IPPROTO_IPIP &&
1102+
p.iph.protocol != 0)
1103+
goto done;
1104+
if (p.iph.version != 4 ||
10311105
p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)))
10321106
goto done;
10331107
if (p.iph.ttl)
@@ -1164,7 +1238,7 @@ static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu)
11641238

11651239
static const struct net_device_ops ipip6_netdev_ops = {
11661240
.ndo_uninit = ipip6_tunnel_uninit,
1167-
.ndo_start_xmit = ipip6_tunnel_xmit,
1241+
.ndo_start_xmit = sit_tunnel_xmit,
11681242
.ndo_do_ioctl = ipip6_tunnel_ioctl,
11691243
.ndo_change_mtu = ipip6_tunnel_change_mtu,
11701244
.ndo_get_stats64 = ip_tunnel_get_stats64,
@@ -1232,6 +1306,22 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev)
12321306
return 0;
12331307
}
12341308

1309+
static int ipip6_validate(struct nlattr *tb[], struct nlattr *data[])
1310+
{
1311+
u8 proto;
1312+
1313+
if (!data)
1314+
return 0;
1315+
1316+
proto = nla_get_u8(data[IFLA_IPTUN_PROTO]);
1317+
if (proto != IPPROTO_IPV6 &&
1318+
proto != IPPROTO_IPIP &&
1319+
proto != 0)
1320+
return -EINVAL;
1321+
1322+
return 0;
1323+
}
1324+
12351325
static void ipip6_netlink_parms(struct nlattr *data[],
12361326
struct ip_tunnel_parm *parms)
12371327
{
@@ -1268,6 +1358,10 @@ static void ipip6_netlink_parms(struct nlattr *data[],
12681358

12691359
if (data[IFLA_IPTUN_FLAGS])
12701360
parms->i_flags = nla_get_be16(data[IFLA_IPTUN_FLAGS]);
1361+
1362+
if (data[IFLA_IPTUN_PROTO])
1363+
parms->iph.protocol = nla_get_u8(data[IFLA_IPTUN_PROTO]);
1364+
12711365
}
12721366

12731367
#ifdef CONFIG_IPV6_SIT_6RD
@@ -1391,6 +1485,8 @@ static size_t ipip6_get_size(const struct net_device *dev)
13911485
nla_total_size(1) +
13921486
/* IFLA_IPTUN_FLAGS */
13931487
nla_total_size(2) +
1488+
/* IFLA_IPTUN_PROTO */
1489+
nla_total_size(1) +
13941490
#ifdef CONFIG_IPV6_SIT_6RD
13951491
/* IFLA_IPTUN_6RD_PREFIX */
13961492
nla_total_size(sizeof(struct in6_addr)) +
@@ -1416,6 +1512,7 @@ static int ipip6_fill_info(struct sk_buff *skb, const struct net_device *dev)
14161512
nla_put_u8(skb, IFLA_IPTUN_TOS, parm->iph.tos) ||
14171513
nla_put_u8(skb, IFLA_IPTUN_PMTUDISC,
14181514
!!(parm->iph.frag_off & htons(IP_DF))) ||
1515+
nla_put_u8(skb, IFLA_IPTUN_PROTO, parm->iph.protocol) ||
14191516
nla_put_be16(skb, IFLA_IPTUN_FLAGS, parm->i_flags))
14201517
goto nla_put_failure;
14211518

@@ -1445,6 +1542,7 @@ static const struct nla_policy ipip6_policy[IFLA_IPTUN_MAX + 1] = {
14451542
[IFLA_IPTUN_TOS] = { .type = NLA_U8 },
14461543
[IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 },
14471544
[IFLA_IPTUN_FLAGS] = { .type = NLA_U16 },
1545+
[IFLA_IPTUN_PROTO] = { .type = NLA_U8 },
14481546
#ifdef CONFIG_IPV6_SIT_6RD
14491547
[IFLA_IPTUN_6RD_PREFIX] = { .len = sizeof(struct in6_addr) },
14501548
[IFLA_IPTUN_6RD_RELAY_PREFIX] = { .type = NLA_U32 },
@@ -1459,6 +1557,7 @@ static struct rtnl_link_ops sit_link_ops __read_mostly = {
14591557
.policy = ipip6_policy,
14601558
.priv_size = sizeof(struct ip_tunnel),
14611559
.setup = ipip6_tunnel_setup,
1560+
.validate = ipip6_validate,
14621561
.newlink = ipip6_newlink,
14631562
.changelink = ipip6_changelink,
14641563
.get_size = ipip6_get_size,
@@ -1471,6 +1570,12 @@ static struct xfrm_tunnel sit_handler __read_mostly = {
14711570
.priority = 1,
14721571
};
14731572

1573+
static struct xfrm_tunnel ipip_handler __read_mostly = {
1574+
.handler = ipip_rcv,
1575+
.err_handler = ipip6_err,
1576+
.priority = 2,
1577+
};
1578+
14741579
static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_head *head)
14751580
{
14761581
int prio;
@@ -1553,6 +1658,7 @@ static void __exit sit_cleanup(void)
15531658
{
15541659
rtnl_link_unregister(&sit_link_ops);
15551660
xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
1661+
xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
15561662

15571663
unregister_pernet_device(&sit_net_ops);
15581664
rcu_barrier(); /* Wait for completion of call_rcu()'s */
@@ -1569,9 +1675,14 @@ static int __init sit_init(void)
15691675
return err;
15701676
err = xfrm4_tunnel_register(&sit_handler, AF_INET6);
15711677
if (err < 0) {
1572-
pr_info("%s: can't add protocol\n", __func__);
1678+
pr_info("%s: can't register ip6ip4\n", __func__);
15731679
goto xfrm_tunnel_failed;
15741680
}
1681+
err = xfrm4_tunnel_register(&ipip_handler, AF_INET);
1682+
if (err < 0) {
1683+
pr_info("%s: can't register ip4ip4\n", __func__);
1684+
goto xfrm_tunnel4_failed;
1685+
}
15751686
err = rtnl_link_register(&sit_link_ops);
15761687
if (err < 0)
15771688
goto rtnl_link_failed;
@@ -1580,6 +1691,8 @@ static int __init sit_init(void)
15801691
return err;
15811692

15821693
rtnl_link_failed:
1694+
xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
1695+
xfrm_tunnel4_failed:
15831696
xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
15841697
xfrm_tunnel_failed:
15851698
unregister_pernet_device(&sit_net_ops);

0 commit comments

Comments
 (0)