#include "spectrum_ipip.h"
 #include "reg.h"
 
-struct ip_tunnel_parm
+struct ip_tunnel_parm_kern
 mlxsw_sp_ipip_netdev_parms4(const struct net_device *ol_dev)
 {
        struct ip_tunnel *tun = netdev_priv(ol_dev);
        return tun->parms;
 }
 
-static bool mlxsw_sp_ipip_parms4_has_ikey(const struct ip_tunnel_parm *parms)
+static bool
+mlxsw_sp_ipip_parms4_has_ikey(const struct ip_tunnel_parm_kern *parms)
 {
        return !!(parms->i_flags & TUNNEL_KEY);
 }
        return !!(parms->i_flags & TUNNEL_KEY);
 }
 
-static bool mlxsw_sp_ipip_parms4_has_okey(const struct ip_tunnel_parm *parms)
+static bool
+mlxsw_sp_ipip_parms4_has_okey(const struct ip_tunnel_parm_kern *parms)
 {
        return !!(parms->o_flags & TUNNEL_KEY);
 }
        return !!(parms->o_flags & TUNNEL_KEY);
 }
 
-static u32 mlxsw_sp_ipip_parms4_ikey(const struct ip_tunnel_parm *parms)
+static u32 mlxsw_sp_ipip_parms4_ikey(const struct ip_tunnel_parm_kern *parms)
 {
        return mlxsw_sp_ipip_parms4_has_ikey(parms) ?
                be32_to_cpu(parms->i_key) : 0;
                be32_to_cpu(parms->i_key) : 0;
 }
 
-static u32 mlxsw_sp_ipip_parms4_okey(const struct ip_tunnel_parm *parms)
+static u32 mlxsw_sp_ipip_parms4_okey(const struct ip_tunnel_parm_kern *parms)
 {
        return mlxsw_sp_ipip_parms4_has_okey(parms) ?
                be32_to_cpu(parms->o_key) : 0;
 }
 
 static union mlxsw_sp_l3addr
-mlxsw_sp_ipip_parms4_saddr(const struct ip_tunnel_parm *parms)
+mlxsw_sp_ipip_parms4_saddr(const struct ip_tunnel_parm_kern *parms)
 {
        return (union mlxsw_sp_l3addr) { .addr4 = parms->iph.saddr };
 }
 }
 
 static union mlxsw_sp_l3addr
-mlxsw_sp_ipip_parms4_daddr(const struct ip_tunnel_parm *parms)
+mlxsw_sp_ipip_parms4_daddr(const struct ip_tunnel_parm_kern *parms)
 {
        return (union mlxsw_sp_l3addr) { .addr4 = parms->iph.daddr };
 }
 mlxsw_sp_ipip_netdev_saddr(enum mlxsw_sp_l3proto proto,
                           const struct net_device *ol_dev)
 {
-       struct ip_tunnel_parm parms4;
+       struct ip_tunnel_parm_kern parms4;
        struct __ip6_tnl_parm parms6;
 
        switch (proto) {
 static __be32 mlxsw_sp_ipip_netdev_daddr4(const struct net_device *ol_dev)
 {
 
-       struct ip_tunnel_parm parms4 = mlxsw_sp_ipip_netdev_parms4(ol_dev);
+       struct ip_tunnel_parm_kern parms4;
+
+       parms4 = mlxsw_sp_ipip_netdev_parms4(ol_dev);
 
        return mlxsw_sp_ipip_parms4_daddr(&parms4).addr4;
 }
 mlxsw_sp_ipip_netdev_daddr(enum mlxsw_sp_l3proto proto,
                           const struct net_device *ol_dev)
 {
-       struct ip_tunnel_parm parms4;
+       struct ip_tunnel_parm_kern parms4;
        struct __ip6_tnl_parm parms6;
 
        switch (proto) {
 static struct mlxsw_sp_ipip_parms
 mlxsw_sp_ipip_netdev_parms_init_gre4(const struct net_device *ol_dev)
 {
-       struct ip_tunnel_parm parms = mlxsw_sp_ipip_netdev_parms4(ol_dev);
+       struct ip_tunnel_parm_kern parms = mlxsw_sp_ipip_netdev_parms4(ol_dev);
 
        return (struct mlxsw_sp_ipip_parms) {
                .proto = MLXSW_SP_L3_PROTO_IPV4,
 {
        u16 rif_index = mlxsw_sp_ipip_lb_rif_index(ipip_entry->ol_lb);
        u16 ul_rif_id = mlxsw_sp_ipip_lb_ul_rif_id(ipip_entry->ol_lb);
+       struct ip_tunnel_parm_kern parms;
        char rtdp_pl[MLXSW_REG_RTDP_LEN];
-       struct ip_tunnel_parm parms;
        unsigned int type_check;
        bool has_ikey;
        u32 daddr4;
 mlxsw_sp_ipip_ol_loopback_config_gre4(struct mlxsw_sp *mlxsw_sp,
                                      const struct net_device *ol_dev)
 {
-       struct ip_tunnel_parm parms = mlxsw_sp_ipip_netdev_parms4(ol_dev);
+       struct ip_tunnel_parm_kern parms = mlxsw_sp_ipip_netdev_parms4(ol_dev);
        enum mlxsw_reg_ritr_loopback_ipip_type lb_ipipt;
 
        lb_ipipt = mlxsw_sp_ipip_parms4_has_okey(&parms) ?
 
 #include <linux/if_tunnel.h>
 #include <net/ip6_tunnel.h>
 
-struct ip_tunnel_parm
+struct ip_tunnel_parm_kern
 mlxsw_sp_ipip_netdev_parms4(const struct net_device *ol_dev);
 struct __ip6_tnl_parm
 mlxsw_sp_ipip_netdev_parms6(const struct net_device *ol_dev);
 
                            __be32 *saddrp, __be32 *daddrp)
 {
        struct ip_tunnel *tun = netdev_priv(to_dev);
+       struct ip_tunnel_parm_kern parms;
        struct net_device *dev = NULL;
-       struct ip_tunnel_parm parms;
        struct rtable *rt = NULL;
        struct flowi4 fl4;
 
                                  const struct net_device *to_dev,
                                  struct mlxsw_sp_span_parms *sparmsp)
 {
-       struct ip_tunnel_parm tparm = mlxsw_sp_ipip_netdev_parms4(to_dev);
+       struct ip_tunnel_parm_kern tparm = mlxsw_sp_ipip_netdev_parms4(to_dev);
        union mlxsw_sp_l3addr saddr = { .addr4 = tparm.iph.saddr };
        union mlxsw_sp_l3addr daddr = { .addr4 = tparm.iph.daddr };
        bool inherit_tos = tparm.iph.tos & 0x1;
 
 struct kernel_hwtstamp_config;
 struct phy_device;
 struct dsa_port;
-struct ip_tunnel_parm;
+struct ip_tunnel_parm_kern;
 struct macsec_context;
 struct macsec_ops;
 struct netdev_name_node;
  *     queue id bound to an AF_XDP socket. The flags field specifies if
  *     only RX, only Tx, or both should be woken up using the flags
  *     XDP_WAKEUP_RX and XDP_WAKEUP_TX.
- * int (*ndo_tunnel_ctl)(struct net_device *dev, struct ip_tunnel_parm *p,
+ * int (*ndo_tunnel_ctl)(struct net_device *dev, struct ip_tunnel_parm_kern *p,
  *                      int cmd);
  *     Add, change, delete or get information on an IPv4 tunnel.
  * struct net_device *(*ndo_get_peer_dev)(struct net_device *dev);
        int                     (*ndo_xsk_wakeup)(struct net_device *dev,
                                                  u32 queue_id, u32 flags);
        int                     (*ndo_tunnel_ctl)(struct net_device *dev,
-                                                 struct ip_tunnel_parm *p, int cmd);
+                                                 struct ip_tunnel_parm_kern *p,
+                                                 int cmd);
        struct net_device *     (*ndo_get_peer_dev)(struct net_device *dev);
        int                     (*ndo_fill_forward_path)(struct net_device_path_ctx *ctx,
                                                          struct net_device_path *path);
 
 
 struct metadata_dst;
 
+/* Kernel-side copy of ip_tunnel_parm */
+struct ip_tunnel_parm_kern {
+       char                    name[IFNAMSIZ];
+       int                     link;
+       __be16                  i_flags;
+       __be16                  o_flags;
+       __be32                  i_key;
+       __be32                  o_key;
+       struct iphdr            iph;
+};
+
 struct ip_tunnel {
        struct ip_tunnel __rcu  *next;
        struct hlist_node hash_node;
 
        struct dst_cache dst_cache;
 
-       struct ip_tunnel_parm parms;
+       struct ip_tunnel_parm_kern parms;
 
        int             mlink;
        int             encap_hlen;     /* Encap header length (FOU,GUE) */
                    const struct iphdr *tnl_params, const u8 protocol);
 void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
                       const u8 proto, int tunnel_hlen);
-int ip_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd);
+int ip_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm_kern *p,
+                 int cmd);
+bool ip_tunnel_parm_from_user(struct ip_tunnel_parm_kern *kp,
+                             const void __user *data);
+bool ip_tunnel_parm_to_user(void __user *data, struct ip_tunnel_parm_kern *kp);
 int ip_tunnel_siocdevprivate(struct net_device *dev, struct ifreq *ifr,
                             void __user *data, int cmd);
 int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict);
                  const struct tnl_ptk_info *tpi, struct metadata_dst *tun_dst,
                  bool log_ecn_error);
 int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
-                        struct ip_tunnel_parm *p, __u32 fwmark);
+                        struct ip_tunnel_parm_kern *p, __u32 fwmark);
 int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[],
-                     struct ip_tunnel_parm *p, __u32 fwmark);
+                     struct ip_tunnel_parm_kern *p, __u32 fwmark);
 void ip_tunnel_setup(struct net_device *dev, unsigned int net_id);
 
 bool ip_tunnel_netlink_encap_parms(struct nlattr *data[],
                                   struct ip_tunnel_encap *encap);
 
 void ip_tunnel_netlink_parms(struct nlattr *data[],
-                            struct ip_tunnel_parm *parms);
+                            struct ip_tunnel_parm_kern *parms);
 
 extern const struct header_ops ip_tunnel_header_ops;
 __be16 ip_tunnel_parse_protocol(const struct sk_buff *skb);
 
        }
 }
 
-static int ipgre_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm *p,
+static int ipgre_tunnel_ctl(struct net_device *dev,
+                           struct ip_tunnel_parm_kern *p,
                            int cmd)
 {
        int err;
 static int ipgre_netlink_parms(struct net_device *dev,
                                struct nlattr *data[],
                                struct nlattr *tb[],
-                               struct ip_tunnel_parm *parms,
+                               struct ip_tunnel_parm_kern *parms,
                                __u32 *fwmark)
 {
        struct ip_tunnel *t = netdev_priv(dev);
 static int erspan_netlink_parms(struct net_device *dev,
                                struct nlattr *data[],
                                struct nlattr *tb[],
-                               struct ip_tunnel_parm *parms,
+                               struct ip_tunnel_parm_kern *parms,
                                __u32 *fwmark)
 {
        struct ip_tunnel *t = netdev_priv(dev);
                         struct nlattr *tb[], struct nlattr *data[],
                         struct netlink_ext_ack *extack)
 {
-       struct ip_tunnel_parm p;
+       struct ip_tunnel_parm_kern p;
        __u32 fwmark = 0;
        int err;
 
                          struct nlattr *tb[], struct nlattr *data[],
                          struct netlink_ext_ack *extack)
 {
-       struct ip_tunnel_parm p;
+       struct ip_tunnel_parm_kern p;
        __u32 fwmark = 0;
        int err;
 
                            struct netlink_ext_ack *extack)
 {
        struct ip_tunnel *t = netdev_priv(dev);
+       struct ip_tunnel_parm_kern p;
        __u32 fwmark = t->fwmark;
-       struct ip_tunnel_parm p;
        int err;
 
        err = ipgre_newlink_encap_setup(dev, data);
                             struct netlink_ext_ack *extack)
 {
        struct ip_tunnel *t = netdev_priv(dev);
+       struct ip_tunnel_parm_kern p;
        __u32 fwmark = t->fwmark;
-       struct ip_tunnel_parm p;
        int err;
 
        err = ipgre_newlink_encap_setup(dev, data);
 static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
 {
        struct ip_tunnel *t = netdev_priv(dev);
-       struct ip_tunnel_parm *p = &t->parms;
+       struct ip_tunnel_parm_kern *p = &t->parms;
        __be16 o_flags = p->o_flags;
 
        if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
 
                         IP_TNL_HASH_BITS);
 }
 
-static bool ip_tunnel_key_match(const struct ip_tunnel_parm *p,
+static bool ip_tunnel_key_match(const struct ip_tunnel_parm_kern *p,
                                __be16 flags, __be32 key)
 {
        if (p->i_flags & TUNNEL_KEY) {
 EXPORT_SYMBOL_GPL(ip_tunnel_lookup);
 
 static struct hlist_head *ip_bucket(struct ip_tunnel_net *itn,
-                                   struct ip_tunnel_parm *parms)
+                                   struct ip_tunnel_parm_kern *parms)
 {
        unsigned int h;
        __be32 remote;
 }
 
 static struct ip_tunnel *ip_tunnel_find(struct ip_tunnel_net *itn,
-                                       struct ip_tunnel_parm *parms,
+                                       struct ip_tunnel_parm_kern *parms,
                                        int type)
 {
        __be32 remote = parms->iph.daddr;
 
 static struct net_device *__ip_tunnel_create(struct net *net,
                                             const struct rtnl_link_ops *ops,
-                                            struct ip_tunnel_parm *parms)
+                                            struct ip_tunnel_parm_kern *parms)
 {
        int err;
        struct ip_tunnel *tunnel;
 
 static struct ip_tunnel *ip_tunnel_create(struct net *net,
                                          struct ip_tunnel_net *itn,
-                                         struct ip_tunnel_parm *parms)
+                                         struct ip_tunnel_parm_kern *parms)
 {
        struct ip_tunnel *nt;
        struct net_device *dev;
 static void ip_tunnel_update(struct ip_tunnel_net *itn,
                             struct ip_tunnel *t,
                             struct net_device *dev,
-                            struct ip_tunnel_parm *p,
+                            struct ip_tunnel_parm_kern *p,
                             bool set_mtu,
                             __u32 fwmark)
 {
        netdev_state_change(dev);
 }
 
-int ip_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd)
+int ip_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm_kern *p,
+                 int cmd)
 {
        int err = 0;
        struct ip_tunnel *t = netdev_priv(dev);
 }
 EXPORT_SYMBOL_GPL(ip_tunnel_ctl);
 
+bool ip_tunnel_parm_from_user(struct ip_tunnel_parm_kern *kp,
+                             const void __user *data)
+{
+       struct ip_tunnel_parm p;
+
+       if (copy_from_user(&p, data, sizeof(p)))
+               return false;
+
+       strscpy(kp->name, p.name);
+       kp->link = p.link;
+       kp->i_flags = p.i_flags;
+       kp->o_flags = p.o_flags;
+       kp->i_key = p.i_key;
+       kp->o_key = p.o_key;
+       memcpy(&kp->iph, &p.iph, min(sizeof(kp->iph), sizeof(p.iph)));
+
+       return true;
+}
+EXPORT_SYMBOL_GPL(ip_tunnel_parm_from_user);
+
+bool ip_tunnel_parm_to_user(void __user *data, struct ip_tunnel_parm_kern *kp)
+{
+       struct ip_tunnel_parm p;
+
+       strscpy(p.name, kp->name);
+       p.link = kp->link;
+       p.i_flags = kp->i_flags;
+       p.o_flags = kp->o_flags;
+       p.i_key = kp->i_key;
+       p.o_key = kp->o_key;
+       memcpy(&p.iph, &kp->iph, min(sizeof(p.iph), sizeof(kp->iph)));
+
+       return !copy_to_user(data, &p, sizeof(p));
+}
+EXPORT_SYMBOL_GPL(ip_tunnel_parm_to_user);
+
 int ip_tunnel_siocdevprivate(struct net_device *dev, struct ifreq *ifr,
                             void __user *data, int cmd)
 {
-       struct ip_tunnel_parm p;
+       struct ip_tunnel_parm_kern p;
        int err;
 
-       if (copy_from_user(&p, data, sizeof(p)))
+       if (!ip_tunnel_parm_from_user(&p, data))
                return -EFAULT;
        err = dev->netdev_ops->ndo_tunnel_ctl(dev, &p, cmd);
-       if (!err && copy_to_user(data, &p, sizeof(p)))
+       if (!err && !ip_tunnel_parm_to_user(data, &p))
                return -EFAULT;
        return err;
 }
                                  struct rtnl_link_ops *ops, char *devname)
 {
        struct ip_tunnel_net *itn = net_generic(net, ip_tnl_net_id);
-       struct ip_tunnel_parm parms;
+       struct ip_tunnel_parm_kern parms;
        unsigned int i;
 
        itn->rtnl_link_ops = ops;
 EXPORT_SYMBOL_GPL(ip_tunnel_delete_nets);
 
 int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[],
-                     struct ip_tunnel_parm *p, __u32 fwmark)
+                     struct ip_tunnel_parm_kern *p, __u32 fwmark)
 {
        struct ip_tunnel *nt;
        struct net *net = dev_net(dev);
 EXPORT_SYMBOL_GPL(ip_tunnel_newlink);
 
 int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
-                        struct ip_tunnel_parm *p, __u32 fwmark)
+                        struct ip_tunnel_parm_kern *p, __u32 fwmark)
 {
        struct ip_tunnel *t;
        struct ip_tunnel *tunnel = netdev_priv(dev);
 
 EXPORT_SYMBOL_GPL(ip_tunnel_netlink_encap_parms);
 
 void ip_tunnel_netlink_parms(struct nlattr *data[],
-                            struct ip_tunnel_parm *parms)
+                            struct ip_tunnel_parm_kern *parms)
 {
        if (data[IFLA_IPTUN_LINK])
                parms->link = nla_get_u32(data[IFLA_IPTUN_LINK]);
 
                            struct flowi *fl)
 {
        struct ip_tunnel *tunnel = netdev_priv(dev);
-       struct ip_tunnel_parm *parms = &tunnel->parms;
+       struct ip_tunnel_parm_kern *parms = &tunnel->parms;
        struct dst_entry *dst = skb_dst(skb);
        struct net_device *tdev;        /* Device to other host */
        int pkt_len = skb->len;
 }
 
 static int
-vti_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd)
+vti_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm_kern *p, int cmd)
 {
        int err = 0;
 
 }
 
 static void vti_netlink_parms(struct nlattr *data[],
-                             struct ip_tunnel_parm *parms,
+                             struct ip_tunnel_parm_kern *parms,
                              __u32 *fwmark)
 {
        memset(parms, 0, sizeof(*parms));
                       struct nlattr *tb[], struct nlattr *data[],
                       struct netlink_ext_ack *extack)
 {
-       struct ip_tunnel_parm parms;
+       struct ip_tunnel_parm_kern parms;
        __u32 fwmark = 0;
 
        vti_netlink_parms(data, &parms, &fwmark);
                          struct netlink_ext_ack *extack)
 {
        struct ip_tunnel *t = netdev_priv(dev);
+       struct ip_tunnel_parm_kern p;
        __u32 fwmark = t->fwmark;
-       struct ip_tunnel_parm p;
 
        vti_netlink_parms(data, &p, &fwmark);
        return ip_tunnel_changelink(dev, tb, &p, fwmark);
 static int vti_fill_info(struct sk_buff *skb, const struct net_device *dev)
 {
        struct ip_tunnel *t = netdev_priv(dev);
-       struct ip_tunnel_parm *p = &t->parms;
+       struct ip_tunnel_parm_kern *p = &t->parms;
 
        if (nla_put_u32(skb, IFLA_VTI_LINK, p->link) ||
            nla_put_be32(skb, IFLA_VTI_IKEY, p->i_key) ||
 
 }
 
 static int
-ipip_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd)
+ipip_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm_kern *p, int cmd)
 {
        if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
                if (p->iph.version != 4 ||
 }
 
 static void ipip_netlink_parms(struct nlattr *data[],
-                              struct ip_tunnel_parm *parms, bool *collect_md,
-                              __u32 *fwmark)
+                              struct ip_tunnel_parm_kern *parms,
+                              bool *collect_md, __u32 *fwmark)
 {
        memset(parms, 0, sizeof(*parms));
 
                        struct netlink_ext_ack *extack)
 {
        struct ip_tunnel *t = netdev_priv(dev);
-       struct ip_tunnel_parm p;
        struct ip_tunnel_encap ipencap;
+       struct ip_tunnel_parm_kern p;
        __u32 fwmark = 0;
 
        if (ip_tunnel_netlink_encap_parms(data, &ipencap)) {
                           struct netlink_ext_ack *extack)
 {
        struct ip_tunnel *t = netdev_priv(dev);
-       struct ip_tunnel_parm p;
        struct ip_tunnel_encap ipencap;
+       struct ip_tunnel_parm_kern p;
        bool collect_md;
        __u32 fwmark = t->fwmark;
 
 static int ipip_fill_info(struct sk_buff *skb, const struct net_device *dev)
 {
        struct ip_tunnel *tunnel = netdev_priv(dev);
-       struct ip_tunnel_parm *parm = &tunnel->parms;
+       struct ip_tunnel_parm_kern *parm = &tunnel->parms;
 
        if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) ||
            nla_put_in_addr(skb, IFLA_IPTUN_LOCAL, parm->iph.saddr) ||
 
 static struct net_device *ipmr_new_tunnel(struct net *net, struct vifctl *v)
 {
        struct net_device *tunnel_dev, *new_dev;
-       struct ip_tunnel_parm p = { };
+       struct ip_tunnel_parm_kern p = { };
        int err;
 
        tunnel_dev = __dev_get_by_name(net, "tunl0");
 
 #include <linux/string.h>
 #include <linux/hash.h>
 
+#include <net/ip_tunnels.h>
 #include <net/net_namespace.h>
 #include <net/sock.h>
 #include <net/snmp.h>
 static int addrconf_set_sit_dstaddr(struct net *net, struct net_device *dev,
                struct in6_ifreq *ireq)
 {
-       struct ip_tunnel_parm p = { };
+       struct ip_tunnel_parm_kern p = { };
        int err;
 
        if (!(ipv6_addr_type(&ireq->ifr6_addr) & IPV6_ADDR_COMPATv4))
 
        return NULL;
 }
 
-static struct ip_tunnel __rcu **__ipip6_bucket(struct sit_net *sitn,
-               struct ip_tunnel_parm *parms)
+static struct ip_tunnel __rcu **
+__ipip6_bucket(struct sit_net *sitn, struct ip_tunnel_parm_kern *parms)
 {
        __be32 remote = parms->iph.daddr;
        __be32 local = parms->iph.saddr;
 }
 
 static struct ip_tunnel *ipip6_tunnel_locate(struct net *net,
-               struct ip_tunnel_parm *parms, int create)
+                                            struct ip_tunnel_parm_kern *parms,
+                                            int create)
 {
        __be32 remote = parms->iph.daddr;
        __be32 local = parms->iph.saddr;
        dev->needed_headroom = t_hlen + hlen;
 }
 
-static void ipip6_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p,
+static void ipip6_tunnel_update(struct ip_tunnel *t,
+                               struct ip_tunnel_parm_kern *p,
                                __u32 fwmark)
 {
        struct net *net = t->net;
 ipip6_tunnel_get6rd(struct net_device *dev, struct ip_tunnel_parm __user *data)
 {
        struct ip_tunnel *t = netdev_priv(dev);
+       struct ip_tunnel_parm_kern p;
        struct ip_tunnel_6rd ip6rd;
-       struct ip_tunnel_parm p;
 
        if (dev == dev_to_sit_net(dev)->fb_tunnel_dev) {
-               if (copy_from_user(&p, data, sizeof(p)))
+               if (!ip_tunnel_parm_from_user(&p, data))
                        return -EFAULT;
                t = ipip6_tunnel_locate(t->net, &p, 0);
        }
 }
 
 static int
-__ipip6_tunnel_ioctl_validate(struct net *net, struct ip_tunnel_parm *p)
+__ipip6_tunnel_ioctl_validate(struct net *net, struct ip_tunnel_parm_kern *p)
 {
        if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 }
 
 static int
-ipip6_tunnel_get(struct net_device *dev, struct ip_tunnel_parm *p)
+ipip6_tunnel_get(struct net_device *dev, struct ip_tunnel_parm_kern *p)
 {
        struct ip_tunnel *t = netdev_priv(dev);
 
 }
 
 static int
-ipip6_tunnel_add(struct net_device *dev, struct ip_tunnel_parm *p)
+ipip6_tunnel_add(struct net_device *dev, struct ip_tunnel_parm_kern *p)
 {
        struct ip_tunnel *t = netdev_priv(dev);
        int err;
 }
 
 static int
-ipip6_tunnel_change(struct net_device *dev, struct ip_tunnel_parm *p)
+ipip6_tunnel_change(struct net_device *dev, struct ip_tunnel_parm_kern *p)
 {
        struct ip_tunnel *t = netdev_priv(dev);
        int err;
 }
 
 static int
-ipip6_tunnel_del(struct net_device *dev, struct ip_tunnel_parm *p)
+ipip6_tunnel_del(struct net_device *dev, struct ip_tunnel_parm_kern *p)
 {
        struct ip_tunnel *t = netdev_priv(dev);
 
 }
 
 static int
-ipip6_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd)
+ipip6_tunnel_ctl(struct net_device *dev, struct ip_tunnel_parm_kern *p,
+                int cmd)
 {
        switch (cmd) {
        case SIOCGETTUNNEL:
 }
 
 static void ipip6_netlink_parms(struct nlattr *data[],
-                               struct ip_tunnel_parm *parms,
+                               struct ip_tunnel_parm_kern *parms,
                                __u32 *fwmark)
 {
        memset(parms, 0, sizeof(*parms));
                            struct netlink_ext_ack *extack)
 {
        struct ip_tunnel *t = netdev_priv(dev);
-       struct ip_tunnel_parm p;
        struct ip_tunnel_encap ipencap;
+       struct ip_tunnel_parm_kern p;
        struct net *net = t->net;
        struct sit_net *sitn = net_generic(net, sit_net_id);
 #ifdef CONFIG_IPV6_SIT_6RD
 static int ipip6_fill_info(struct sk_buff *skb, const struct net_device *dev)
 {
        struct ip_tunnel *tunnel = netdev_priv(dev);
-       struct ip_tunnel_parm *parm = &tunnel->parms;
+       struct ip_tunnel_parm_kern *parm = &tunnel->parms;
 
        if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) ||
            nla_put_in_addr(skb, IFLA_IPTUN_LOCAL, parm->iph.saddr) ||