aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/uapi/linux/if_tunnel.h3
-rw-r--r--net/ipv6/ip6_tunnel.c57
2 files changed, 60 insertions, 0 deletions
diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h
index ccb21d585bf4..c1bf0b5a8da1 100644
--- a/include/uapi/linux/if_tunnel.h
+++ b/include/uapi/linux/if_tunnel.h
@@ -44,6 +44,9 @@ enum {
44 IFLA_IPTUN_REMOTE, 44 IFLA_IPTUN_REMOTE,
45 IFLA_IPTUN_TTL, 45 IFLA_IPTUN_TTL,
46 IFLA_IPTUN_TOS, 46 IFLA_IPTUN_TOS,
47 IFLA_IPTUN_ENCAP_LIMIT,
48 IFLA_IPTUN_FLOWINFO,
49 IFLA_IPTUN_FLAGS,
47 __IFLA_IPTUN_MAX, 50 __IFLA_IPTUN_MAX,
48}; 51};
49#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1) 52#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1)
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 09482f723064..424ed45ef122 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -83,6 +83,7 @@ static u32 HASH(const struct in6_addr *addr1, const struct in6_addr *addr2)
83 83
84static int ip6_tnl_dev_init(struct net_device *dev); 84static int ip6_tnl_dev_init(struct net_device *dev);
85static void ip6_tnl_dev_setup(struct net_device *dev); 85static void ip6_tnl_dev_setup(struct net_device *dev);
86static struct rtnl_link_ops ip6_link_ops __read_mostly;
86 87
87static int ip6_tnl_net_id __read_mostly; 88static int ip6_tnl_net_id __read_mostly;
88struct ip6_tnl_net { 89struct ip6_tnl_net {
@@ -299,6 +300,7 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct __ip6_tnl_parm *p)
299 goto failed_free; 300 goto failed_free;
300 301
301 strcpy(t->parms.name, dev->name); 302 strcpy(t->parms.name, dev->name);
303 dev->rtnl_link_ops = &ip6_link_ops;
302 304
303 dev_hold(dev); 305 dev_hold(dev);
304 ip6_tnl_link(ip6n, t); 306 ip6_tnl_link(ip6n, t);
@@ -1504,6 +1506,55 @@ static int __net_init ip6_fb_tnl_dev_init(struct net_device *dev)
1504 return 0; 1506 return 0;
1505} 1507}
1506 1508
1509static size_t ip6_get_size(const struct net_device *dev)
1510{
1511 return
1512 /* IFLA_IPTUN_LINK */
1513 nla_total_size(4) +
1514 /* IFLA_IPTUN_LOCAL */
1515 nla_total_size(sizeof(struct in6_addr)) +
1516 /* IFLA_IPTUN_REMOTE */
1517 nla_total_size(sizeof(struct in6_addr)) +
1518 /* IFLA_IPTUN_TTL */
1519 nla_total_size(1) +
1520 /* IFLA_IPTUN_ENCAP_LIMIT */
1521 nla_total_size(1) +
1522 /* IFLA_IPTUN_FLOWINFO */
1523 nla_total_size(4) +
1524 /* IFLA_IPTUN_FLAGS */
1525 nla_total_size(4) +
1526 0;
1527}
1528
1529static int ip6_fill_info(struct sk_buff *skb, const struct net_device *dev)
1530{
1531 struct ip6_tnl *tunnel = netdev_priv(dev);
1532 struct __ip6_tnl_parm *parm = &tunnel->parms;
1533
1534 if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) ||
1535 nla_put(skb, IFLA_IPTUN_LOCAL, sizeof(struct in6_addr),
1536 &parm->raddr) ||
1537 nla_put(skb, IFLA_IPTUN_REMOTE, sizeof(struct in6_addr),
1538 &parm->laddr) ||
1539 nla_put_u8(skb, IFLA_IPTUN_TTL, parm->hop_limit) ||
1540 nla_put_u8(skb, IFLA_IPTUN_ENCAP_LIMIT, parm->encap_limit) ||
1541 nla_put_be32(skb, IFLA_IPTUN_FLOWINFO, parm->flowinfo) ||
1542 nla_put_u32(skb, IFLA_IPTUN_FLAGS, parm->flags))
1543 goto nla_put_failure;
1544 return 0;
1545
1546nla_put_failure:
1547 return -EMSGSIZE;
1548}
1549
1550static struct rtnl_link_ops ip6_link_ops __read_mostly = {
1551 .kind = "ip6tnl",
1552 .maxtype = IFLA_IPTUN_MAX,
1553 .priv_size = sizeof(struct ip6_tnl),
1554 .get_size = ip6_get_size,
1555 .fill_info = ip6_fill_info,
1556};
1557
1507static struct xfrm6_tunnel ip4ip6_handler __read_mostly = { 1558static struct xfrm6_tunnel ip4ip6_handler __read_mostly = {
1508 .handler = ip4ip6_rcv, 1559 .handler = ip4ip6_rcv,
1509 .err_handler = ip4ip6_err, 1560 .err_handler = ip4ip6_err,
@@ -1612,9 +1663,14 @@ static int __init ip6_tunnel_init(void)
1612 pr_err("%s: can't register ip6ip6\n", __func__); 1663 pr_err("%s: can't register ip6ip6\n", __func__);
1613 goto out_ip6ip6; 1664 goto out_ip6ip6;
1614 } 1665 }
1666 err = rtnl_link_register(&ip6_link_ops);
1667 if (err < 0)
1668 goto rtnl_link_failed;
1615 1669
1616 return 0; 1670 return 0;
1617 1671
1672rtnl_link_failed:
1673 xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6);
1618out_ip6ip6: 1674out_ip6ip6:
1619 xfrm6_tunnel_deregister(&ip4ip6_handler, AF_INET); 1675 xfrm6_tunnel_deregister(&ip4ip6_handler, AF_INET);
1620out_ip4ip6: 1676out_ip4ip6:
@@ -1629,6 +1685,7 @@ out_pernet:
1629 1685
1630static void __exit ip6_tunnel_cleanup(void) 1686static void __exit ip6_tunnel_cleanup(void)
1631{ 1687{
1688 rtnl_link_unregister(&ip6_link_ops);
1632 if (xfrm6_tunnel_deregister(&ip4ip6_handler, AF_INET)) 1689 if (xfrm6_tunnel_deregister(&ip4ip6_handler, AF_INET))
1633 pr_info("%s: can't deregister ip4ip6\n", __func__); 1690 pr_info("%s: can't deregister ip4ip6\n", __func__);
1634 1691