#define __NET_NAMESPACE_WRAPPER_H 1
#include <linux/version.h>
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
#include_next <net/net_namespace.h>
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
struct net;
-struct pernet_operations {
+struct extended_pernet_operations {
struct list_head list;
int (*init)(struct net *net);
void (*exit)(struct net *net);
+ int *id;
+ size_t size;
};
-#endif /* linux kernel < 2.6.24 */
+#define pernet_operations extended_pernet_operations
+
+#define register_pernet_device rpl_register_pernet_device
+int rpl_register_pernet_device(struct extended_pernet_operations *ops);
-extern int register_pernet_gen_device(int *id, struct pernet_operations *);
-extern void unregister_pernet_gen_device(int id, struct pernet_operations *);
+#define unregister_pernet_device rpl_unregister_pernet_device
+void rpl_unregister_pernet_device(struct extended_pernet_operations *ops);
-#endif /* linux kernel < 2.6.26 */
+#endif /* linux kernel < 2.6.33 */
#endif
#define __NET_NETNS_GENERIC_WRAPPER_H 1
#include <linux/version.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+#include_next <net/netns/generic.h>
+#endif
-struct net;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
-extern void *net_generic(struct net *net, int id);
-extern int net_assign_generic(struct net *net, int id, void *data);
+#define net_assign_generic rpl_net_assign_generic
+int rpl_net_assign_generic(struct net *net, int id, void *data);
-#else
-#include_next <net/netns/generic.h>
-#endif /* linux kernel < 2.6.26 */
+#define net_generic rpl_net_generic
+void *rpl_net_generic(struct net *net, int id);
+
+#endif /* linux kernel < 2.6.33 */
#endif
static int ipgre_init_net(struct net *net)
{
+ struct ipgre_net *ign = net_generic(net, ipgre_net_id);
int err;
- struct ipgre_net *ign;
-
- err = -ENOMEM;
- ign = kzalloc(sizeof(struct ipgre_net), GFP_KERNEL);
- if (ign == NULL)
- goto err_alloc;
-
- err = net_assign_generic(net, ipgre_net_id, ign);
- if (err < 0)
- goto err_assign;
ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), GRE_IOCTL_DEVICE,
ipgre_tunnel_setup);
err_reg_dev:
free_netdev(ign->fb_tunnel_dev);
err_alloc_dev:
- /* nothing */
-err_assign:
- kfree(ign);
-err_alloc:
return err;
}
ipgre_destroy_tunnels(ign, &list);
unregister_netdevice_many(&list);
rtnl_unlock();
- kfree(ign);
}
static struct pernet_operations ipgre_net_ops = {
.init = ipgre_init_net,
.exit = ipgre_exit_net,
+ .id = &ipgre_net_id,
+ .size = sizeof(struct ipgre_net),
};
static int ipgre_tap_init(struct net_device *dev)
return -EAGAIN;
}
- err = register_pernet_gen_device(&ipgre_net_id, &ipgre_net_ops);
+ err = register_pernet_device(&ipgre_net_ops);
if (err < 0)
goto gen_device_failed;
tap_ops_failed:
rtnl_link_unregister(&ipgre_link_ops);
rtnl_link_failed:
- unregister_pernet_gen_device(ipgre_net_id, &ipgre_net_ops);
+ unregister_pernet_device(&ipgre_net_ops);
#endif
gen_device_failed:
inet_del_protocol(&ipgre_protocol, IPPROTO_GRE);
rtnl_link_unregister(&ipgre_tap_ops);
rtnl_link_unregister(&ipgre_link_ops);
#endif
- unregister_pernet_gen_device(ipgre_net_id, &ipgre_net_ops);
+ unregister_pernet_device(&ipgre_net_ops);
if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0)
printk(KERN_INFO "ipgre close: can't remove protocol\n");
}
#include <linux/version.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
#include <linux/sched.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
+#undef pernet_operations
+#undef register_pernet_device
+#undef unregister_pernet_device
+#undef net_assign_generic
+#undef net_generic
+
/* This trivial implementation assumes that there is only a single pernet
- * generic device registered and that the caller is well behaved. It only
- * weakly attempts to check that these conditions are true. */
+ * device registered and that the caller is well behaved. It only weakly
+ * attempts to check that these conditions are true. */
-static bool device_registered;
+static struct extended_pernet_operations *dev_ops;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
static void *ng_data;
+#else
+static struct pernet_operations new_ops;
+#endif
-int register_pernet_gen_device(int *id, struct pernet_operations *ops)
+static int device_init_net(struct net *net)
{
- BUG_ON(device_registered);
+ int err;
+ if (dev_ops->id && dev_ops->size) {
+ void *data = kzalloc(dev_ops->size, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ err = rpl_net_assign_generic(net, *dev_ops->id, data);
+ if (err) {
+ kfree(data);
+ return err;
+ }
+ }
+ if (dev_ops->init)
+ return dev_ops->init(net);
+ return 0;
+}
- *id = 1;
- device_registered = true;
+static void device_exit_net(struct net *net)
+{
+ if (dev_ops->id && dev_ops->size) {
+ int id = *dev_ops->id;
+ kfree(rpl_net_generic(net, id));
+ }
- if (ops->init == NULL)
- return 0;
- return ops->init(NULL);
+ if (dev_ops->exit)
+ return dev_ops->exit(net);
}
-void unregister_pernet_gen_device(int id, struct pernet_operations *ops)
+int rpl_register_pernet_device(struct extended_pernet_operations *ops)
{
- device_registered = false;
- if (ops->exit)
- ops->exit(NULL);
+ BUG_ON(dev_ops);
+ dev_ops = ops;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+ if (dev_ops->id)
+ *dev_ops->id = 1;
+
+ return device_init_net(NULL);
+#else
+ memcpy(&new_ops, dev_ops, sizeof new_ops);
+ new_ops.init = device_init_net;
+ new_ops.exit = device_exit_net;
+
+ if (ops->id)
+ return register_pernet_gen_device(dev_ops->id, &new_ops);
+ else
+ return register_pernet_device(&new_ops);
+#endif
}
-int net_assign_generic(struct net *net, int id, void *data)
+void rpl_unregister_pernet_device(struct extended_pernet_operations *ops)
{
+ BUG_ON(!dev_ops);
+ BUG_ON(dev_ops != ops);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+ device_exit_net(NULL);
+#else
+ if (ops->id)
+ unregister_pernet_gen_device(*dev_ops->id, &new_ops);
+ else
+ unregister_pernet_device(&new_ops);
+#endif
+
+ dev_ops = NULL;
+}
+
+int rpl_net_assign_generic(struct net *net, int id, void *data)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
BUG_ON(id != 1);
ng_data = data;
return 0;
+#else
+ return net_assign_generic(net, id, data);
+#endif
}
-void *net_generic(struct net *net, int id)
+void *rpl_net_generic(struct net *net, int id)
{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
BUG_ON(id != 1);
return ng_data;
+#else
+ return net_generic(net, id);
+#endif
}
-#endif /* kernel < 2.6.26 */
+#endif /* kernel < 2.6.33 */