OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright 2010 Hauke Mehrtens <hauke@hauke-m.de> |
| 3 * |
| 4 * This program is free software; you can redistribute it and/or modify |
| 5 * it under the terms of the GNU General Public License version 2 as |
| 6 * published by the Free Software Foundation. |
| 7 * |
| 8 * Compatibility file for Linux wireless for kernels 2.6.37. |
| 9 */ |
| 10 |
| 11 #include <linux/compat.h> |
| 12 #include <linux/netdevice.h> |
| 13 #include <net/sock.h> |
| 14 #include <linux/nsproxy.h> |
| 15 |
| 16 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) |
| 17 static const void *net_current_ns(void) |
| 18 { |
| 19 return current->nsproxy->net_ns; |
| 20 } |
| 21 |
| 22 static const void *net_initial_ns(void) |
| 23 { |
| 24 return &init_net; |
| 25 } |
| 26 |
| 27 static const void *net_netlink_ns(struct sock *sk) |
| 28 { |
| 29 return sock_net(sk); |
| 30 } |
| 31 |
| 32 struct kobj_ns_type_operations net_ns_type_operations = { |
| 33 .type = KOBJ_NS_TYPE_NET, |
| 34 .current_ns = net_current_ns, |
| 35 .netlink_ns = net_netlink_ns, |
| 36 .initial_ns = net_initial_ns, |
| 37 }; |
| 38 EXPORT_SYMBOL_GPL(net_ns_type_operations); |
| 39 |
| 40 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)*/ |
| 41 |
| 42 #undef genl_info |
| 43 #undef genl_unregister_family |
| 44 |
| 45 static LIST_HEAD(compat_nl_fam); |
| 46 |
| 47 static struct genl_ops *genl_get_cmd(u8 cmd, struct genl_family *family) |
| 48 { |
| 49 struct genl_ops *ops; |
| 50 |
| 51 list_for_each_entry(ops, &family->family.ops_list, ops.ops_list) |
| 52 if (ops->cmd == cmd) |
| 53 return ops; |
| 54 |
| 55 return NULL; |
| 56 } |
| 57 |
| 58 |
| 59 static int nl_doit_wrapper(struct sk_buff *skb, struct genl_info *info) |
| 60 { |
| 61 struct compat_genl_info compat_info; |
| 62 struct genl_family *family; |
| 63 struct genl_ops *ops; |
| 64 int err; |
| 65 |
| 66 list_for_each_entry(family, &compat_nl_fam, list) { |
| 67 if (family->id == info->nlhdr->nlmsg_type) |
| 68 goto found; |
| 69 } |
| 70 return -ENOENT; |
| 71 |
| 72 found: |
| 73 ops = genl_get_cmd(info->genlhdr->cmd, family); |
| 74 if (!ops) |
| 75 return -ENOENT; |
| 76 |
| 77 memset(&compat_info.user_ptr, 0, sizeof(compat_info.user_ptr)); |
| 78 compat_info.info = info; |
| 79 #define __copy(_field) compat_info._field = info->_field |
| 80 __copy(snd_seq); |
| 81 __copy(snd_pid); |
| 82 __copy(genlhdr); |
| 83 __copy(attrs); |
| 84 #undef __copy |
| 85 if (family->pre_doit) { |
| 86 err = family->pre_doit(ops, skb, &compat_info); |
| 87 if (err) |
| 88 return err; |
| 89 } |
| 90 |
| 91 err = ops->doit(skb, &compat_info); |
| 92 |
| 93 if (family->post_doit) |
| 94 family->post_doit(ops, skb, &compat_info); |
| 95 |
| 96 return err; |
| 97 } |
| 98 |
| 99 int compat_genl_register_family_with_ops(struct genl_family *family, |
| 100 struct genl_ops *ops, size_t n_ops) |
| 101 { |
| 102 int i, ret; |
| 103 |
| 104 #define __copy(_field) family->family._field = family->_field |
| 105 __copy(id); |
| 106 __copy(hdrsize); |
| 107 __copy(version); |
| 108 __copy(maxattr); |
| 109 strncpy(family->family.name, family->name, sizeof(family->family.name)); |
| 110 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)) |
| 111 __copy(netnsok); |
| 112 #endif |
| 113 #undef __copy |
| 114 |
| 115 ret = genl_register_family(&family->family); |
| 116 if (ret < 0) |
| 117 return ret; |
| 118 |
| 119 family->attrbuf = family->family.attrbuf; |
| 120 family->id = family->family.id; |
| 121 |
| 122 for (i = 0; i < n_ops; i++) { |
| 123 #define __copy(_field) ops[i].ops._field = ops[i]._field |
| 124 __copy(cmd); |
| 125 __copy(flags); |
| 126 __copy(policy); |
| 127 __copy(dumpit); |
| 128 __copy(done); |
| 129 #undef __copy |
| 130 if (ops[i].doit) |
| 131 ops[i].ops.doit = nl_doit_wrapper; |
| 132 ret = genl_register_ops(&family->family, &ops[i].ops); |
| 133 if (ret < 0) |
| 134 goto error_ops; |
| 135 } |
| 136 list_add(&family->list, &compat_nl_fam); |
| 137 |
| 138 return ret; |
| 139 |
| 140 error_ops: |
| 141 compat_genl_unregister_family(family); |
| 142 return ret; |
| 143 } |
| 144 EXPORT_SYMBOL(compat_genl_register_family_with_ops); |
| 145 |
| 146 int compat_genl_unregister_family(struct genl_family *family) |
| 147 { |
| 148 int err; |
| 149 err = genl_unregister_family(&family->family); |
| 150 list_del(&family->list); |
| 151 return err; |
| 152 } |
| 153 EXPORT_SYMBOL(compat_genl_unregister_family); |
| 154 |
OLD | NEW |