diff options
-rw-r--r-- | net/ipv4/xfrm4_tunnel.c | 2 | ||||
-rw-r--r-- | net/ipv6/sit.c | 119 |
2 files changed, 117 insertions, 4 deletions
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c index 05a5df2febc9..06347dbd32c1 100644 --- a/net/ipv4/xfrm4_tunnel.c +++ b/net/ipv4/xfrm4_tunnel.c | |||
@@ -63,7 +63,7 @@ static int xfrm_tunnel_err(struct sk_buff *skb, u32 info) | |||
63 | static struct xfrm_tunnel xfrm_tunnel_handler __read_mostly = { | 63 | static struct xfrm_tunnel xfrm_tunnel_handler __read_mostly = { |
64 | .handler = xfrm_tunnel_rcv, | 64 | .handler = xfrm_tunnel_rcv, |
65 | .err_handler = xfrm_tunnel_err, | 65 | .err_handler = xfrm_tunnel_err, |
66 | .priority = 2, | 66 | .priority = 3, |
67 | }; | 67 | }; |
68 | 68 | ||
69 | #if IS_ENABLED(CONFIG_IPV6) | 69 | #if IS_ENABLED(CONFIG_IPV6) |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 335363478bbf..6b9c1f128eaf 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -577,6 +577,10 @@ static int ipip6_rcv(struct sk_buff *skb) | |||
577 | if (tunnel != NULL) { | 577 | if (tunnel != NULL) { |
578 | struct pcpu_tstats *tstats; | 578 | struct pcpu_tstats *tstats; |
579 | 579 | ||
580 | if (tunnel->parms.iph.protocol != IPPROTO_IPV6 && | ||
581 | tunnel->parms.iph.protocol != 0) | ||
582 | goto out; | ||
583 | |||
580 | secpath_reset(skb); | 584 | secpath_reset(skb); |
581 | skb->mac_header = skb->network_header; | 585 | skb->mac_header = skb->network_header; |
582 | skb_reset_network_header(skb); | 586 | skb_reset_network_header(skb); |
@@ -629,6 +633,35 @@ out: | |||
629 | return 0; | 633 | return 0; |
630 | } | 634 | } |
631 | 635 | ||
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 | |||
632 | /* | 665 | /* |
633 | * If the IPv6 address comes from 6rd / 6to4 (RFC 3056) addr space this function | 666 | * If the IPv6 address comes from 6rd / 6to4 (RFC 3056) addr space this function |
634 | * stores the embedded IPv4 address in v4dst and returns true. | 667 | * stores the embedded IPv4 address in v4dst and returns true. |
@@ -877,6 +910,43 @@ tx_error: | |||
877 | return NETDEV_TX_OK; | 910 | return NETDEV_TX_OK; |
878 | } | 911 | } |
879 | 912 | ||
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 | |||
880 | static void ipip6_tunnel_bind_dev(struct net_device *dev) | 950 | static void ipip6_tunnel_bind_dev(struct net_device *dev) |
881 | { | 951 | { |
882 | struct net_device *tdev = NULL; | 952 | struct net_device *tdev = NULL; |
@@ -1027,7 +1097,11 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1027 | goto done; | 1097 | goto done; |
1028 | 1098 | ||
1029 | err = -EINVAL; | 1099 | 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 || | ||
1031 | p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF))) | 1105 | p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF))) |
1032 | goto done; | 1106 | goto done; |
1033 | if (p.iph.ttl) | 1107 | if (p.iph.ttl) |
@@ -1164,7 +1238,7 @@ static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu) | |||
1164 | 1238 | ||
1165 | static const struct net_device_ops ipip6_netdev_ops = { | 1239 | static const struct net_device_ops ipip6_netdev_ops = { |
1166 | .ndo_uninit = ipip6_tunnel_uninit, | 1240 | .ndo_uninit = ipip6_tunnel_uninit, |
1167 | .ndo_start_xmit = ipip6_tunnel_xmit, | 1241 | .ndo_start_xmit = sit_tunnel_xmit, |
1168 | .ndo_do_ioctl = ipip6_tunnel_ioctl, | 1242 | .ndo_do_ioctl = ipip6_tunnel_ioctl, |
1169 | .ndo_change_mtu = ipip6_tunnel_change_mtu, | 1243 | .ndo_change_mtu = ipip6_tunnel_change_mtu, |
1170 | .ndo_get_stats64 = ip_tunnel_get_stats64, | 1244 | .ndo_get_stats64 = ip_tunnel_get_stats64, |
@@ -1232,6 +1306,22 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev) | |||
1232 | return 0; | 1306 | return 0; |
1233 | } | 1307 | } |
1234 | 1308 | ||
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 | |||
1235 | static void ipip6_netlink_parms(struct nlattr *data[], | 1325 | static void ipip6_netlink_parms(struct nlattr *data[], |
1236 | struct ip_tunnel_parm *parms) | 1326 | struct ip_tunnel_parm *parms) |
1237 | { | 1327 | { |
@@ -1268,6 +1358,10 @@ static void ipip6_netlink_parms(struct nlattr *data[], | |||
1268 | 1358 | ||
1269 | if (data[IFLA_IPTUN_FLAGS]) | 1359 | if (data[IFLA_IPTUN_FLAGS]) |
1270 | parms->i_flags = nla_get_be16(data[IFLA_IPTUN_FLAGS]); | 1360 | 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 | |||
1271 | } | 1365 | } |
1272 | 1366 | ||
1273 | #ifdef CONFIG_IPV6_SIT_6RD | 1367 | #ifdef CONFIG_IPV6_SIT_6RD |
@@ -1391,6 +1485,8 @@ static size_t ipip6_get_size(const struct net_device *dev) | |||
1391 | nla_total_size(1) + | 1485 | nla_total_size(1) + |
1392 | /* IFLA_IPTUN_FLAGS */ | 1486 | /* IFLA_IPTUN_FLAGS */ |
1393 | nla_total_size(2) + | 1487 | nla_total_size(2) + |
1488 | /* IFLA_IPTUN_PROTO */ | ||
1489 | nla_total_size(1) + | ||
1394 | #ifdef CONFIG_IPV6_SIT_6RD | 1490 | #ifdef CONFIG_IPV6_SIT_6RD |
1395 | /* IFLA_IPTUN_6RD_PREFIX */ | 1491 | /* IFLA_IPTUN_6RD_PREFIX */ |
1396 | nla_total_size(sizeof(struct in6_addr)) + | 1492 | 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) | |||
1416 | nla_put_u8(skb, IFLA_IPTUN_TOS, parm->iph.tos) || | 1512 | nla_put_u8(skb, IFLA_IPTUN_TOS, parm->iph.tos) || |
1417 | nla_put_u8(skb, IFLA_IPTUN_PMTUDISC, | 1513 | nla_put_u8(skb, IFLA_IPTUN_PMTUDISC, |
1418 | !!(parm->iph.frag_off & htons(IP_DF))) || | 1514 | !!(parm->iph.frag_off & htons(IP_DF))) || |
1515 | nla_put_u8(skb, IFLA_IPTUN_PROTO, parm->iph.protocol) || | ||
1419 | nla_put_be16(skb, IFLA_IPTUN_FLAGS, parm->i_flags)) | 1516 | nla_put_be16(skb, IFLA_IPTUN_FLAGS, parm->i_flags)) |
1420 | goto nla_put_failure; | 1517 | goto nla_put_failure; |
1421 | 1518 | ||
@@ -1445,6 +1542,7 @@ static const struct nla_policy ipip6_policy[IFLA_IPTUN_MAX + 1] = { | |||
1445 | [IFLA_IPTUN_TOS] = { .type = NLA_U8 }, | 1542 | [IFLA_IPTUN_TOS] = { .type = NLA_U8 }, |
1446 | [IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 }, | 1543 | [IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 }, |
1447 | [IFLA_IPTUN_FLAGS] = { .type = NLA_U16 }, | 1544 | [IFLA_IPTUN_FLAGS] = { .type = NLA_U16 }, |
1545 | [IFLA_IPTUN_PROTO] = { .type = NLA_U8 }, | ||
1448 | #ifdef CONFIG_IPV6_SIT_6RD | 1546 | #ifdef CONFIG_IPV6_SIT_6RD |
1449 | [IFLA_IPTUN_6RD_PREFIX] = { .len = sizeof(struct in6_addr) }, | 1547 | [IFLA_IPTUN_6RD_PREFIX] = { .len = sizeof(struct in6_addr) }, |
1450 | [IFLA_IPTUN_6RD_RELAY_PREFIX] = { .type = NLA_U32 }, | 1548 | [IFLA_IPTUN_6RD_RELAY_PREFIX] = { .type = NLA_U32 }, |
@@ -1459,6 +1557,7 @@ static struct rtnl_link_ops sit_link_ops __read_mostly = { | |||
1459 | .policy = ipip6_policy, | 1557 | .policy = ipip6_policy, |
1460 | .priv_size = sizeof(struct ip_tunnel), | 1558 | .priv_size = sizeof(struct ip_tunnel), |
1461 | .setup = ipip6_tunnel_setup, | 1559 | .setup = ipip6_tunnel_setup, |
1560 | .validate = ipip6_validate, | ||
1462 | .newlink = ipip6_newlink, | 1561 | .newlink = ipip6_newlink, |
1463 | .changelink = ipip6_changelink, | 1562 | .changelink = ipip6_changelink, |
1464 | .get_size = ipip6_get_size, | 1563 | .get_size = ipip6_get_size, |
@@ -1471,6 +1570,12 @@ static struct xfrm_tunnel sit_handler __read_mostly = { | |||
1471 | .priority = 1, | 1570 | .priority = 1, |
1472 | }; | 1571 | }; |
1473 | 1572 | ||
1573 | static struct xfrm_tunnel ipip_handler __read_mostly = { | ||
1574 | .handler = ipip_rcv, | ||
1575 | .err_handler = ipip6_err, | ||
1576 | .priority = 2, | ||
1577 | }; | ||
1578 | |||
1474 | static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_head *head) | 1579 | static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_head *head) |
1475 | { | 1580 | { |
1476 | int prio; | 1581 | int prio; |
@@ -1553,6 +1658,7 @@ static void __exit sit_cleanup(void) | |||
1553 | { | 1658 | { |
1554 | rtnl_link_unregister(&sit_link_ops); | 1659 | rtnl_link_unregister(&sit_link_ops); |
1555 | xfrm4_tunnel_deregister(&sit_handler, AF_INET6); | 1660 | xfrm4_tunnel_deregister(&sit_handler, AF_INET6); |
1661 | xfrm4_tunnel_deregister(&ipip_handler, AF_INET); | ||
1556 | 1662 | ||
1557 | unregister_pernet_device(&sit_net_ops); | 1663 | unregister_pernet_device(&sit_net_ops); |
1558 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ | 1664 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ |
@@ -1569,9 +1675,14 @@ static int __init sit_init(void) | |||
1569 | return err; | 1675 | return err; |
1570 | err = xfrm4_tunnel_register(&sit_handler, AF_INET6); | 1676 | err = xfrm4_tunnel_register(&sit_handler, AF_INET6); |
1571 | if (err < 0) { | 1677 | if (err < 0) { |
1572 | pr_info("%s: can't add protocol\n", __func__); | 1678 | pr_info("%s: can't register ip6ip4\n", __func__); |
1573 | goto xfrm_tunnel_failed; | 1679 | goto xfrm_tunnel_failed; |
1574 | } | 1680 | } |
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 | } | ||
1575 | err = rtnl_link_register(&sit_link_ops); | 1686 | err = rtnl_link_register(&sit_link_ops); |
1576 | if (err < 0) | 1687 | if (err < 0) |
1577 | goto rtnl_link_failed; | 1688 | goto rtnl_link_failed; |
@@ -1580,6 +1691,8 @@ out: | |||
1580 | return err; | 1691 | return err; |
1581 | 1692 | ||
1582 | rtnl_link_failed: | 1693 | rtnl_link_failed: |
1694 | xfrm4_tunnel_deregister(&ipip_handler, AF_INET); | ||
1695 | xfrm_tunnel4_failed: | ||
1583 | xfrm4_tunnel_deregister(&sit_handler, AF_INET6); | 1696 | xfrm4_tunnel_deregister(&sit_handler, AF_INET6); |
1584 | xfrm_tunnel_failed: | 1697 | xfrm_tunnel_failed: |
1585 | unregister_pernet_device(&sit_net_ops); | 1698 | unregister_pernet_device(&sit_net_ops); |