This source file includes following definitions.
- wimax_msg_alloc
- wimax_msg_data_len
- wimax_msg_data
- wimax_msg_len
- wimax_msg_send
- wimax_msg
- wimax_gnl_doit_msg_from_user
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 #include <linux/device.h>
60 #include <linux/slab.h>
61 #include <net/genetlink.h>
62 #include <linux/netdevice.h>
63 #include <linux/wimax.h>
64 #include <linux/security.h>
65 #include <linux/export.h>
66 #include "wimax-internal.h"
67
68
69 #define D_SUBMODULE op_msg
70 #include "debug-levels.h"
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105 struct sk_buff *wimax_msg_alloc(struct wimax_dev *wimax_dev,
106 const char *pipe_name,
107 const void *msg, size_t size,
108 gfp_t gfp_flags)
109 {
110 int result;
111 struct device *dev = wimax_dev_to_dev(wimax_dev);
112 size_t msg_size;
113 void *genl_msg;
114 struct sk_buff *skb;
115
116 msg_size = nla_total_size(size)
117 + nla_total_size(sizeof(u32))
118 + (pipe_name ? nla_total_size(strlen(pipe_name)) : 0);
119 result = -ENOMEM;
120 skb = genlmsg_new(msg_size, gfp_flags);
121 if (skb == NULL)
122 goto error_new;
123 genl_msg = genlmsg_put(skb, 0, 0, &wimax_gnl_family,
124 0, WIMAX_GNL_OP_MSG_TO_USER);
125 if (genl_msg == NULL) {
126 dev_err(dev, "no memory to create generic netlink message\n");
127 goto error_genlmsg_put;
128 }
129 result = nla_put_u32(skb, WIMAX_GNL_MSG_IFIDX,
130 wimax_dev->net_dev->ifindex);
131 if (result < 0) {
132 dev_err(dev, "no memory to add ifindex attribute\n");
133 goto error_nla_put;
134 }
135 if (pipe_name) {
136 result = nla_put_string(skb, WIMAX_GNL_MSG_PIPE_NAME,
137 pipe_name);
138 if (result < 0) {
139 dev_err(dev, "no memory to add pipe_name attribute\n");
140 goto error_nla_put;
141 }
142 }
143 result = nla_put(skb, WIMAX_GNL_MSG_DATA, size, msg);
144 if (result < 0) {
145 dev_err(dev, "no memory to add payload (msg %p size %zu) in "
146 "attribute: %d\n", msg, size, result);
147 goto error_nla_put;
148 }
149 genlmsg_end(skb, genl_msg);
150 return skb;
151
152 error_nla_put:
153 error_genlmsg_put:
154 error_new:
155 nlmsg_free(skb);
156 return ERR_PTR(result);
157 }
158 EXPORT_SYMBOL_GPL(wimax_msg_alloc);
159
160
161
162
163
164
165
166
167
168
169 const void *wimax_msg_data_len(struct sk_buff *msg, size_t *size)
170 {
171 struct nlmsghdr *nlh = (void *) msg->head;
172 struct nlattr *nla;
173
174 nla = nlmsg_find_attr(nlh, sizeof(struct genlmsghdr),
175 WIMAX_GNL_MSG_DATA);
176 if (nla == NULL) {
177 pr_err("Cannot find attribute WIMAX_GNL_MSG_DATA\n");
178 return NULL;
179 }
180 *size = nla_len(nla);
181 return nla_data(nla);
182 }
183 EXPORT_SYMBOL_GPL(wimax_msg_data_len);
184
185
186
187
188
189
190
191 const void *wimax_msg_data(struct sk_buff *msg)
192 {
193 struct nlmsghdr *nlh = (void *) msg->head;
194 struct nlattr *nla;
195
196 nla = nlmsg_find_attr(nlh, sizeof(struct genlmsghdr),
197 WIMAX_GNL_MSG_DATA);
198 if (nla == NULL) {
199 pr_err("Cannot find attribute WIMAX_GNL_MSG_DATA\n");
200 return NULL;
201 }
202 return nla_data(nla);
203 }
204 EXPORT_SYMBOL_GPL(wimax_msg_data);
205
206
207
208
209
210
211
212 ssize_t wimax_msg_len(struct sk_buff *msg)
213 {
214 struct nlmsghdr *nlh = (void *) msg->head;
215 struct nlattr *nla;
216
217 nla = nlmsg_find_attr(nlh, sizeof(struct genlmsghdr),
218 WIMAX_GNL_MSG_DATA);
219 if (nla == NULL) {
220 pr_err("Cannot find attribute WIMAX_GNL_MSG_DATA\n");
221 return -EINVAL;
222 }
223 return nla_len(nla);
224 }
225 EXPORT_SYMBOL_GPL(wimax_msg_len);
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258 int wimax_msg_send(struct wimax_dev *wimax_dev, struct sk_buff *skb)
259 {
260 struct device *dev = wimax_dev_to_dev(wimax_dev);
261 void *msg = skb->data;
262 size_t size = skb->len;
263 might_sleep();
264
265 d_printf(1, dev, "CTX: wimax msg, %zu bytes\n", size);
266 d_dump(2, dev, msg, size);
267 genlmsg_multicast(&wimax_gnl_family, skb, 0, 0, GFP_KERNEL);
268 d_printf(1, dev, "CTX: genl multicast done\n");
269 return 0;
270 }
271 EXPORT_SYMBOL_GPL(wimax_msg_send);
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294 int wimax_msg(struct wimax_dev *wimax_dev, const char *pipe_name,
295 const void *buf, size_t size, gfp_t gfp_flags)
296 {
297 int result = -ENOMEM;
298 struct sk_buff *skb;
299
300 skb = wimax_msg_alloc(wimax_dev, pipe_name, buf, size, gfp_flags);
301 if (IS_ERR(skb))
302 result = PTR_ERR(skb);
303 else
304 result = wimax_msg_send(wimax_dev, skb);
305 return result;
306 }
307 EXPORT_SYMBOL_GPL(wimax_msg);
308
309
310
311
312
313
314
315
316
317 int wimax_gnl_doit_msg_from_user(struct sk_buff *skb, struct genl_info *info)
318 {
319 int result, ifindex;
320 struct wimax_dev *wimax_dev;
321 struct device *dev;
322 struct nlmsghdr *nlh = info->nlhdr;
323 char *pipe_name;
324 void *msg_buf;
325 size_t msg_len;
326
327 might_sleep();
328 d_fnstart(3, NULL, "(skb %p info %p)\n", skb, info);
329 result = -ENODEV;
330 if (info->attrs[WIMAX_GNL_MSG_IFIDX] == NULL) {
331 pr_err("WIMAX_GNL_MSG_FROM_USER: can't find IFIDX attribute\n");
332 goto error_no_wimax_dev;
333 }
334 ifindex = nla_get_u32(info->attrs[WIMAX_GNL_MSG_IFIDX]);
335 wimax_dev = wimax_dev_get_by_genl_info(info, ifindex);
336 if (wimax_dev == NULL)
337 goto error_no_wimax_dev;
338 dev = wimax_dev_to_dev(wimax_dev);
339
340
341 result = -EINVAL;
342 if (info->attrs[WIMAX_GNL_MSG_DATA] == NULL) {
343 dev_err(dev, "WIMAX_GNL_MSG_FROM_USER: can't find MSG_DATA "
344 "attribute\n");
345 goto error_no_data;
346 }
347 msg_buf = nla_data(info->attrs[WIMAX_GNL_MSG_DATA]);
348 msg_len = nla_len(info->attrs[WIMAX_GNL_MSG_DATA]);
349
350 if (info->attrs[WIMAX_GNL_MSG_PIPE_NAME] == NULL)
351 pipe_name = NULL;
352 else {
353 struct nlattr *attr = info->attrs[WIMAX_GNL_MSG_PIPE_NAME];
354 size_t attr_len = nla_len(attr);
355
356 result = -ENOMEM;
357 pipe_name = kstrndup(nla_data(attr), attr_len + 1, GFP_KERNEL);
358 if (pipe_name == NULL)
359 goto error_alloc;
360 pipe_name[attr_len] = 0;
361 }
362 mutex_lock(&wimax_dev->mutex);
363 result = wimax_dev_is_ready(wimax_dev);
364 if (result == -ENOMEDIUM)
365 result = 0;
366 if (result < 0)
367 goto error_not_ready;
368 result = -ENOSYS;
369 if (wimax_dev->op_msg_from_user == NULL)
370 goto error_noop;
371
372 d_printf(1, dev,
373 "CRX: nlmsghdr len %u type %u flags 0x%04x seq 0x%x pid %u\n",
374 nlh->nlmsg_len, nlh->nlmsg_type, nlh->nlmsg_flags,
375 nlh->nlmsg_seq, nlh->nlmsg_pid);
376 d_printf(1, dev, "CRX: wimax message %zu bytes\n", msg_len);
377 d_dump(2, dev, msg_buf, msg_len);
378
379 result = wimax_dev->op_msg_from_user(wimax_dev, pipe_name,
380 msg_buf, msg_len, info);
381 error_noop:
382 error_not_ready:
383 mutex_unlock(&wimax_dev->mutex);
384 error_alloc:
385 kfree(pipe_name);
386 error_no_data:
387 dev_put(wimax_dev->net_dev);
388 error_no_wimax_dev:
389 d_fnend(3, NULL, "(skb %p info %p) = %d\n", skb, info, result);
390 return result;
391 }