diff options
-rw-r--r-- | include/uapi/linux/if_tunnel.h | 11 | ||||
-rw-r--r-- | net/ipv4/ipip.c | 57 |
2 files changed, 67 insertions, 1 deletions
diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h index 5db5942575fe..ccb21d585bf4 100644 --- a/include/uapi/linux/if_tunnel.h +++ b/include/uapi/linux/if_tunnel.h | |||
@@ -37,6 +37,17 @@ struct ip_tunnel_parm { | |||
37 | struct iphdr iph; | 37 | struct iphdr iph; |
38 | }; | 38 | }; |
39 | 39 | ||
40 | enum { | ||
41 | IFLA_IPTUN_UNSPEC, | ||
42 | IFLA_IPTUN_LINK, | ||
43 | IFLA_IPTUN_LOCAL, | ||
44 | IFLA_IPTUN_REMOTE, | ||
45 | IFLA_IPTUN_TTL, | ||
46 | IFLA_IPTUN_TOS, | ||
47 | __IFLA_IPTUN_MAX, | ||
48 | }; | ||
49 | #define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1) | ||
50 | |||
40 | /* SIT-mode i_flags */ | 51 | /* SIT-mode i_flags */ |
41 | #define SIT_ISATAP 0x0001 | 52 | #define SIT_ISATAP 0x0001 |
42 | 53 | ||
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index cc49cc1ff3b9..720855e41100 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c | |||
@@ -138,6 +138,7 @@ struct ipip_net { | |||
138 | static int ipip_tunnel_init(struct net_device *dev); | 138 | static int ipip_tunnel_init(struct net_device *dev); |
139 | static void ipip_tunnel_setup(struct net_device *dev); | 139 | static void ipip_tunnel_setup(struct net_device *dev); |
140 | static void ipip_dev_free(struct net_device *dev); | 140 | static void ipip_dev_free(struct net_device *dev); |
141 | static struct rtnl_link_ops ipip_link_ops __read_mostly; | ||
141 | 142 | ||
142 | /* | 143 | /* |
143 | * Locking : hash tables are protected by RCU and RTNL | 144 | * Locking : hash tables are protected by RCU and RTNL |
@@ -305,6 +306,7 @@ static struct ip_tunnel *ipip_tunnel_locate(struct net *net, | |||
305 | goto failed_free; | 306 | goto failed_free; |
306 | 307 | ||
307 | strcpy(nt->parms.name, dev->name); | 308 | strcpy(nt->parms.name, dev->name); |
309 | dev->rtnl_link_ops = &ipip_link_ops; | ||
308 | 310 | ||
309 | dev_hold(dev); | 311 | dev_hold(dev); |
310 | ipip_tunnel_link(ipn, nt); | 312 | ipip_tunnel_link(ipn, nt); |
@@ -841,6 +843,47 @@ static int __net_init ipip_fb_tunnel_init(struct net_device *dev) | |||
841 | return 0; | 843 | return 0; |
842 | } | 844 | } |
843 | 845 | ||
846 | static size_t ipip_get_size(const struct net_device *dev) | ||
847 | { | ||
848 | return | ||
849 | /* IFLA_IPTUN_LINK */ | ||
850 | nla_total_size(4) + | ||
851 | /* IFLA_IPTUN_LOCAL */ | ||
852 | nla_total_size(4) + | ||
853 | /* IFLA_IPTUN_REMOTE */ | ||
854 | nla_total_size(4) + | ||
855 | /* IFLA_IPTUN_TTL */ | ||
856 | nla_total_size(1) + | ||
857 | /* IFLA_IPTUN_TOS */ | ||
858 | nla_total_size(1) + | ||
859 | 0; | ||
860 | } | ||
861 | |||
862 | static int ipip_fill_info(struct sk_buff *skb, const struct net_device *dev) | ||
863 | { | ||
864 | struct ip_tunnel *tunnel = netdev_priv(dev); | ||
865 | struct ip_tunnel_parm *parm = &tunnel->parms; | ||
866 | |||
867 | if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) || | ||
868 | nla_put_be32(skb, IFLA_IPTUN_LOCAL, parm->iph.saddr) || | ||
869 | nla_put_be32(skb, IFLA_IPTUN_REMOTE, parm->iph.daddr) || | ||
870 | nla_put_u8(skb, IFLA_IPTUN_TTL, parm->iph.ttl) || | ||
871 | nla_put_u8(skb, IFLA_IPTUN_TOS, parm->iph.tos)) | ||
872 | goto nla_put_failure; | ||
873 | return 0; | ||
874 | |||
875 | nla_put_failure: | ||
876 | return -EMSGSIZE; | ||
877 | } | ||
878 | |||
879 | static struct rtnl_link_ops ipip_link_ops __read_mostly = { | ||
880 | .kind = "ipip", | ||
881 | .maxtype = IFLA_IPTUN_MAX, | ||
882 | .priv_size = sizeof(struct ip_tunnel), | ||
883 | .get_size = ipip_get_size, | ||
884 | .fill_info = ipip_fill_info, | ||
885 | }; | ||
886 | |||
844 | static struct xfrm_tunnel ipip_handler __read_mostly = { | 887 | static struct xfrm_tunnel ipip_handler __read_mostly = { |
845 | .handler = ipip_rcv, | 888 | .handler = ipip_rcv, |
846 | .err_handler = ipip_err, | 889 | .err_handler = ipip_err, |
@@ -937,14 +980,26 @@ static int __init ipip_init(void) | |||
937 | return err; | 980 | return err; |
938 | err = xfrm4_tunnel_register(&ipip_handler, AF_INET); | 981 | err = xfrm4_tunnel_register(&ipip_handler, AF_INET); |
939 | if (err < 0) { | 982 | if (err < 0) { |
940 | unregister_pernet_device(&ipip_net_ops); | ||
941 | pr_info("%s: can't register tunnel\n", __func__); | 983 | pr_info("%s: can't register tunnel\n", __func__); |
984 | goto xfrm_tunnel_failed; | ||
942 | } | 985 | } |
986 | err = rtnl_link_register(&ipip_link_ops); | ||
987 | if (err < 0) | ||
988 | goto rtnl_link_failed; | ||
989 | |||
990 | out: | ||
943 | return err; | 991 | return err; |
992 | |||
993 | rtnl_link_failed: | ||
994 | xfrm4_tunnel_deregister(&ipip_handler, AF_INET); | ||
995 | xfrm_tunnel_failed: | ||
996 | unregister_pernet_device(&ipip_net_ops); | ||
997 | goto out; | ||
944 | } | 998 | } |
945 | 999 | ||
946 | static void __exit ipip_fini(void) | 1000 | static void __exit ipip_fini(void) |
947 | { | 1001 | { |
1002 | rtnl_link_unregister(&ipip_link_ops); | ||
948 | if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET)) | 1003 | if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET)) |
949 | pr_info("%s: can't deregister tunnel\n", __func__); | 1004 | pr_info("%s: can't deregister tunnel\n", __func__); |
950 | 1005 | ||