示例#1
0
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;
}
示例#2
0
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;
}