static struct ip_tunnel * ipip6_tunnel_locate(struct net *net, struct ip_tunnel_parm *parms, int create) { __be32 remote = parms->iph.daddr; __be32 local = parms->iph.saddr; struct ip_tunnel *t, **tp, *nt; struct net_device *dev; char name[IFNAMSIZ]; struct sit_net *sitn = net_generic(net, sit_net_id); for (tp = __ipip6_bucket(sitn, parms); (t = *tp) != NULL; tp = &t->next) { if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr && parms->link == t->parms.link) { if (create) return NULL; else return t; } } if (!create) goto failed; if (parms->name[0]) strlcpy(name, parms->name, IFNAMSIZ); else sprintf(name, "sit%%d"); dev = alloc_netdev(sizeof(*t), name, ipip6_tunnel_setup); if (dev == NULL) return NULL; dev_net_set(dev, net); if (strchr(name, '%')) { if (dev_alloc_name(dev, name) < 0) goto failed_free; } nt = netdev_priv(dev); nt->parms = *parms; ipip6_tunnel_init(dev); if (parms->i_flags & SIT_ISATAP) dev->priv_flags |= IFF_ISATAP; if (register_netdevice(dev) < 0) goto failed_free; dev_hold(dev); ipip6_tunnel_link(sitn, nt); return nt; failed_free: free_netdev(dev); failed: return NULL; }
static int sit_rst(loff_t start, struct cpt_netdev_image *di, struct rst_ops *ops, struct cpt_context *ctx) { int err = -ENODEV; struct cpt_tunnel_image v; struct net_device *dev; struct ip_tunnel *t; loff_t pos; int fbdev; struct sit_net *sitn; sitn = net_generic(get_exec_env()->ve_netns, sit_net_id); if (sitn == NULL) return -EOPNOTSUPP; pos = start + di->cpt_hdrlen; err = ops->get_object(CPT_OBJ_NET_IPIP_TUNNEL, pos, &v, sizeof(v), ctx); if (err) return err; /* some sanity */ if (v.cpt_content != CPT_CONTENT_VOID) return -EINVAL; if (!(v.cpt_tnl_flags & CPT_TUNNEL_SIT)) return 1; if (v.cpt_tnl_flags & CPT_TUNNEL_FBDEV) { fbdev = 1; err = 0; dev = sitn->fb_tunnel_dev; } else { fbdev = 0; err = -ENOMEM; dev = alloc_netdev(sizeof(struct ip_tunnel), di->cpt_name, ipip6_tunnel_setup); if (!dev) goto out; } t = netdev_priv(dev); t->parms.i_flags = v.cpt_i_flags; t->parms.o_flags = v.cpt_o_flags; t->parms.i_key = v.cpt_i_key; t->parms.o_key = v.cpt_o_key; BUILD_BUG_ON(sizeof(v.cpt_iphdr) != sizeof(t->parms.iph)); memcpy(&t->parms.iph, &v.cpt_iphdr, sizeof(t->parms.iph)); if (!fbdev) { ipip6_tunnel_init(dev); err = register_netdevice(dev); if (err) { free_netdev(dev); goto out; } dev_hold(dev); ipip6_tunnel_link(sitn, t); } out: return err; }