mac80211: fix netlink backport for 2.6.31 and below
[openwrt.git] / package / mac80211 / patches / 020-nl80211_backport.patch
1 --- a/include/linux/compat-2.6.37.h
2 +++ b/include/linux/compat-2.6.37.h
3 @@ -45,6 +45,71 @@ static inline void skb_checksum_none_ass
4  
5  #define pcmcia_enable_device(link)     pcmcia_request_configuration(link, &link->conf)
6  
7 +#include <net/genetlink.h>
8 +
9 +struct compat_genl_info {
10 +       struct genl_info *info;
11 +
12 +       u32 snd_seq;
13 +       u32 snd_pid;
14 +       struct genlmsghdr *genlhdr;
15 +       struct nlattr **attrs;
16 +       void *user_ptr[2];
17 +};
18 +#define genl_info compat_genl_info
19 +
20 +struct compat_genl_ops {
21 +       struct genl_ops ops;
22 +
23 +       u8 cmd;
24 +       u8 internal_flags;
25 +       unsigned int flags;
26 +       const struct nla_policy *policy;
27 +
28 +       int (*doit)(struct sk_buff *skb, struct genl_info *info);
29 +       int (*dumpit)(struct sk_buff *skb, struct netlink_callback *cb);
30 +       int (*done)(struct netlink_callback *cb);
31 +};
32 +#define genl_ops compat_genl_ops
33 +
34 +struct compat_genl_family {
35 +       struct genl_family family;
36 +
37 +       struct list_head list;
38 +
39 +       unsigned int id, hdrsize, version, maxattr;
40 +       const char *name;
41 +       bool netnsok;
42 +
43 +       struct nlattr **attrbuf;
44 +
45 +       int (*pre_doit)(struct genl_ops *ops, struct sk_buff *skb,
46 +                       struct genl_info *info);
47 +
48 +       void (*post_doit)(struct genl_ops *ops, struct sk_buff *skb,
49 +                         struct genl_info *info);
50 +};
51 +
52 +#define genl_family compat_genl_family
53 +
54 +#define genl_register_family_with_ops compat_genl_register_family_with_ops
55 +
56 +int genl_register_family_with_ops(struct genl_family *family,
57 +                                 struct genl_ops *ops, size_t n_ops);
58 +
59 +#define genl_unregister_family compat_genl_unregister_family
60 +
61 +int genl_unregister_family(struct genl_family *family);
62 +
63 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32))
64 +#define genl_info_net(_info) genl_info_net((_info)->info)
65 +#endif
66 +
67 +#define genlmsg_reply(_msg, _info) genlmsg_reply(_msg, (_info)->info)
68 +#define genlmsg_put(_skb, _pid, _seq, _fam, _flags, _cmd) genlmsg_put(_skb, _pid, _seq, &(_fam)->family, _flags, _cmd)
69 +#define genl_register_mc_group(_fam, _grp) genl_register_mc_group(&(_fam)->family, _grp)
70 +#define genl_unregister_mc_group(_fam, _grp) genl_unregister_mc_group(&(_fam)->family, _grp)
71 +
72  #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)) */
73  
74  #endif /* LINUX_26_37_COMPAT_H */
75 --- a/compat/compat-2.6.37.c
76 +++ b/compat/compat-2.6.37.c
77 @@ -42,4 +42,116 @@ EXPORT_SYMBOL_GPL(net_ns_type_operations
78  
79  #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)*/ 
80  
81 +#undef genl_info
82 +#undef genl_unregister_family
83 +
84 +static LIST_HEAD(compat_nl_fam);
85 +
86 +static struct genl_ops *genl_get_cmd(u8 cmd, struct genl_family *family)
87 +{
88 +       struct genl_ops *ops;
89 +
90 +       list_for_each_entry(ops, &family->family.ops_list, ops.ops_list)
91 +               if (ops->cmd == cmd)
92 +                       return ops;
93 +
94 +       return NULL;
95 +}
96 +
97 +
98 +static int nl_doit_wrapper(struct sk_buff *skb, struct genl_info *info)
99 +{
100 +       struct compat_genl_info compat_info;
101 +       struct genl_family *family;
102 +       struct genl_ops *ops;
103 +       int err;
104 +
105 +       list_for_each_entry(family, &compat_nl_fam, list) {
106 +               if (family->id == info->nlhdr->nlmsg_type)
107 +                       goto found;
108 +       }
109 +       return -ENOENT;
110 +
111 +found:
112 +       ops = genl_get_cmd(info->genlhdr->cmd, family);
113 +       if (!ops)
114 +               return -ENOENT;
115 +
116 +       memset(&compat_info.user_ptr, 0, sizeof(compat_info.user_ptr));
117 +       compat_info.info = info;
118 +#define __copy(_field) compat_info._field = info->_field
119 +       __copy(snd_seq);
120 +       __copy(snd_pid);
121 +       __copy(genlhdr);
122 +       __copy(attrs);
123 +#undef __copy
124 +       if (family->pre_doit) {
125 +               err = family->pre_doit(ops, skb, &compat_info);
126 +               if (err)
127 +                       return err;
128 +       }
129 +
130 +       err = ops->doit(skb, &compat_info);
131 +
132 +       if (family->post_doit)
133 +               family->post_doit(ops, skb, &compat_info);
134 +
135 +       return err;
136 +}
137 +
138 +int compat_genl_register_family_with_ops(struct genl_family *family,
139 +                                        struct genl_ops *ops, size_t n_ops)
140 +{
141 +       int i, ret;
142 +
143 +#define __copy(_field) family->family._field = family->_field
144 +       __copy(id);
145 +       __copy(hdrsize);
146 +       __copy(version);
147 +       __copy(maxattr);
148 +       strncpy(family->family.name, family->name, sizeof(family->family.name));
149 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32))
150 +       __copy(netnsok);
151 +#endif
152 +#undef __copy
153 +
154 +       ret = genl_register_family(&family->family);
155 +       if (ret < 0)
156 +               return ret;
157 +
158 +       family->attrbuf = family->family.attrbuf;
159 +       family->id = family->family.id;
160 +
161 +       for (i = 0; i < n_ops; i++) {
162 +#define __copy(_field) ops[i].ops._field = ops[i]._field
163 +               __copy(cmd);
164 +               __copy(flags);
165 +               __copy(policy);
166 +               __copy(dumpit);
167 +               __copy(done);
168 +#undef __copy
169 +               ops[i].ops.doit = nl_doit_wrapper;
170 +               ret = genl_register_ops(&family->family, &ops[i].ops);
171 +               if (ret < 0)
172 +                       goto error_ops;
173 +       }
174 +       list_add(&family->list, &compat_nl_fam);
175 +
176 +       return ret;
177 +
178 +error_ops:
179 +       compat_genl_unregister_family(family);
180 +       return ret;
181 +}
182 +EXPORT_SYMBOL(compat_genl_register_family_with_ops);
183 +
184 +int compat_genl_unregister_family(struct genl_family *family)
185 +{
186 +       int err;
187 +       err = genl_unregister_family(&family->family);
188 +       list_del(&family->list);
189 +       return err;
190 +}
191 +EXPORT_SYMBOL(compat_genl_unregister_family);
192 +
193  #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) */
194 --- a/compat/compat-2.6.31.c
195 +++ /dev/null
196 @@ -1,64 +0,0 @@
197 -/*
198 - * Copyright 2007      Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
199 - *
200 - * This program is free software; you can redistribute it and/or modify
201 - * it under the terms of the GNU General Public License version 2 as
202 - * published by the Free Software Foundation.
203 - *
204 - * Compatibility file for Linux wireless for kernels 2.6.31.
205 - */
206 -
207 -#include <linux/compat.h>
208 -
209 -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31))
210 -
211 -#include <linux/netdevice.h>
212 -
213 -/**
214 - * genl_register_family_with_ops - register a generic netlink family
215 - * @family: generic netlink family
216 - * @ops: operations to be registered
217 - * @n_ops: number of elements to register
218 - *
219 - * Registers the specified family and operations from the specified table.
220 - * Only one family may be registered with the same family name or identifier.
221 - *
222 - * The family id may equal GENL_ID_GENERATE causing an unique id to
223 - * be automatically generated and assigned.
224 - *
225 - * Either a doit or dumpit callback must be specified for every registered
226 - * operation or the function will fail. Only one operation structure per
227 - * command identifier may be registered.
228 - *
229 - * See include/net/genetlink.h for more documenation on the operations
230 - * structure.
231 - *
232 - * This is equivalent to calling genl_register_family() followed by
233 - * genl_register_ops() for every operation entry in the table taking
234 - * care to unregister the family on error path.
235 - *
236 - * Return 0 on success or a negative error code.
237 - */
238 -int genl_register_family_with_ops(struct genl_family *family,
239 -       struct genl_ops *ops, size_t n_ops)
240 -{
241 -       int err, i;
242 -
243 -       err = genl_register_family(family);
244 -       if (err)
245 -               return err;
246 -
247 -       for (i = 0; i < n_ops; ++i, ++ops) {
248 -               err = genl_register_ops(family, ops);
249 -               if (err)
250 -                       goto err_out;
251 -       }
252 -       return 0;
253 -err_out:
254 -       genl_unregister_family(family);
255 -       return err;
256 -}
257 -EXPORT_SYMBOL(genl_register_family_with_ops);
258 -
259 -#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)) */
260 -
261 --- a/include/linux/compat-2.6.31.h
262 +++ b/include/linux/compat-2.6.31.h
263 @@ -114,10 +114,6 @@ static inline struct rtable *skb_rtable(
264         return (struct rtable *)skb_dst(skb);
265  }
266  
267 -extern int genl_register_family_with_ops(struct genl_family *family,
268 -       struct genl_ops *ops, size_t n_ops);
269 -
270 -
271  /* Backport threaded IRQ support */
272  
273  static inline
274 --- a/compat/Makefile
275 +++ b/compat/Makefile
276 @@ -23,7 +23,6 @@ compat-$(CONFIG_COMPAT_KERNEL_27) += com
277  compat-$(CONFIG_COMPAT_KERNEL_28) += compat-2.6.28.o
278  compat-$(CONFIG_COMPAT_KERNEL_29) += compat-2.6.29.o
279  compat-$(CONFIG_COMPAT_KERNEL_30) += compat-2.6.30.o
280 -compat-$(CONFIG_COMPAT_KERNEL_31) += compat-2.6.31.o
281  compat-$(CONFIG_COMPAT_KERNEL_32) += compat-2.6.32.o
282  compat-$(CONFIG_COMPAT_KERNEL_33) += compat-2.6.33.o
283  compat-$(CONFIG_COMPAT_KERNEL_35) += compat-2.6.35.o