aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/batman-adv
diff options
context:
space:
mode:
authorSven Eckelmann <sven.eckelmann@gmx.de>2010-06-21 19:25:42 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-06-22 17:05:03 -0400
commitc41214328a7635dc35aa81d89ea579c8a2eb2769 (patch)
treef93b668db3fd0270e06eff9a84a136fa34736f3f /drivers/staging/batman-adv
parent1bd2c2159a32313ae1f872b6225601aed397524c (diff)
Staging: batman-adv: Move device for icmp injection to debugfs
batctl uses /dev/batman-adv to send special batman-adv icmp packets to other nodes in the mesh. To get it working with multiple batX devices we must ensure that every mesh device can have their own socket which is used to inject those packets in exactly one mesh. The current implementation still doesn't allow to use complete separated meshes as we rely on structures which are not part of the private data of a batman device. Signed-off-by: Sven Eckelmann <sven.eckelmann@gmx.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/batman-adv')
-rw-r--r--drivers/staging/batman-adv/Makefile2
-rw-r--r--drivers/staging/batman-adv/bat_debugfs.c77
-rw-r--r--drivers/staging/batman-adv/bat_debugfs.h33
-rw-r--r--drivers/staging/batman-adv/device.c354
-rw-r--r--drivers/staging/batman-adv/icmp_socket.c328
-rw-r--r--drivers/staging/batman-adv/icmp_socket.h (renamed from drivers/staging/batman-adv/device.h)18
-rw-r--r--drivers/staging/batman-adv/main.c21
-rw-r--r--drivers/staging/batman-adv/routing.c4
-rw-r--r--drivers/staging/batman-adv/types.h5
9 files changed, 463 insertions, 379 deletions
diff --git a/drivers/staging/batman-adv/Makefile b/drivers/staging/batman-adv/Makefile
index f25068c0fae..654c4d2b972 100644
--- a/drivers/staging/batman-adv/Makefile
+++ b/drivers/staging/batman-adv/Makefile
@@ -19,4 +19,4 @@
19# 19#
20 20
21obj-m += batman-adv.o 21obj-m += batman-adv.o
22batman-adv-objs := main.o send.o routing.o soft-interface.o device.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o bat_sysfs.o 22batman-adv-objs := main.o bat_debugfs.o bat_sysfs.o send.o routing.o soft-interface.o icmp_socket.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o
diff --git a/drivers/staging/batman-adv/bat_debugfs.c b/drivers/staging/batman-adv/bat_debugfs.c
new file mode 100644
index 00000000000..d5b28eb1c69
--- /dev/null
+++ b/drivers/staging/batman-adv/bat_debugfs.c
@@ -0,0 +1,77 @@
1/*
2 * Copyright (C) 2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#include <linux/debugfs.h>
23
24#include "main.h"
25#include "bat_debugfs.h"
26#include "translation-table.h"
27#include "originator.h"
28#include "hard-interface.h"
29#include "vis.h"
30#include "icmp_socket.h"
31
32static struct dentry *bat_debugfs;
33
34void debugfs_init(void)
35{
36 bat_debugfs = debugfs_create_dir(DEBUGFS_BAT_SUBDIR, NULL);
37}
38
39void debugfs_destroy(void)
40{
41 if (bat_debugfs) {
42 debugfs_remove_recursive(bat_debugfs);
43 bat_debugfs = NULL;
44 }
45}
46
47int debugfs_add_meshif(struct net_device *dev)
48{
49 struct bat_priv *bat_priv = netdev_priv(dev);
50
51 if (!bat_debugfs)
52 goto out;
53
54 bat_priv->debug_dir = debugfs_create_dir(dev->name, bat_debugfs);
55 if (!bat_priv->debug_dir)
56 goto out;
57
58 bat_socket_setup(bat_priv);
59
60 return 0;
61out:
62#ifdef CONFIG_DEBUG_FS
63 return -ENOMEM;
64#else
65 return 0;
66#endif /* CONFIG_DEBUG_FS */
67}
68
69void debugfs_del_meshif(struct net_device *dev)
70{
71 struct bat_priv *bat_priv = netdev_priv(dev);
72
73 if (bat_debugfs) {
74 debugfs_remove_recursive(bat_priv->debug_dir);
75 bat_priv->debug_dir = NULL;
76 }
77}
diff --git a/drivers/staging/batman-adv/bat_debugfs.h b/drivers/staging/batman-adv/bat_debugfs.h
new file mode 100644
index 00000000000..5cdd3327d98
--- /dev/null
+++ b/drivers/staging/batman-adv/bat_debugfs.h
@@ -0,0 +1,33 @@
1/*
2 * Copyright (C) 2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22
23#ifndef BAT_DEBUGFS_H
24#define BAT_DEBUGFS_H
25
26#define DEBUGFS_BAT_SUBDIR "batman_adv"
27
28void debugfs_init(void);
29void debugfs_destroy(void);
30int debugfs_add_meshif(struct net_device *dev);
31void debugfs_del_meshif(struct net_device *dev);
32
33#endif
diff --git a/drivers/staging/batman-adv/device.c b/drivers/staging/batman-adv/device.c
deleted file mode 100644
index 32204b5572d..00000000000
--- a/drivers/staging/batman-adv/device.c
+++ /dev/null
@@ -1,354 +0,0 @@
1/*
2 * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#include <linux/device.h>
23#include <linux/slab.h>
24#include "main.h"
25#include "device.h"
26#include "send.h"
27#include "types.h"
28#include "hash.h"
29#include "hard-interface.h"
30
31static struct class *batman_class;
32
33static int Major; /* Major number assigned to our device driver */
34
35static const struct file_operations fops = {
36 .open = bat_device_open,
37 .release = bat_device_release,
38 .read = bat_device_read,
39 .write = bat_device_write,
40 .poll = bat_device_poll,
41};
42
43static struct device_client *device_client_hash[256];
44
45void bat_device_init(void)
46{
47 memset(device_client_hash, 0, sizeof(device_client_hash));
48}
49
50int bat_device_setup(void)
51{
52 int tmp_major;
53
54 if (Major)
55 return 1;
56
57 /* register our device - kernel assigns a free major number */
58 tmp_major = register_chrdev(0, DRIVER_DEVICE, &fops);
59 if (tmp_major < 0) {
60 printk(KERN_ERR "batman-adv:"
61 "Registering the character device failed with %d\n",
62 tmp_major);
63 return 0;
64 }
65
66 batman_class = class_create(THIS_MODULE, "batman-adv");
67
68 if (IS_ERR(batman_class)) {
69 printk(KERN_ERR "batman-adv:"
70 "Could not register class 'batman-adv'\n");
71 return 0;
72 }
73
74 device_create(batman_class, NULL, MKDEV(tmp_major, 0), NULL,
75 "batman-adv");
76
77 Major = tmp_major;
78 return 1;
79}
80
81void bat_device_destroy(void)
82{
83 if (!Major)
84 return;
85
86 device_destroy(batman_class, MKDEV(Major, 0));
87 class_destroy(batman_class);
88
89 /* Unregister the device */
90 unregister_chrdev(Major, DRIVER_DEVICE);
91
92 Major = 0;
93}
94
95int bat_device_open(struct inode *inode, struct file *file)
96{
97 unsigned int i;
98 struct device_client *device_client;
99
100 device_client = kmalloc(sizeof(struct device_client), GFP_KERNEL);
101
102 if (!device_client)
103 return -ENOMEM;
104
105 for (i = 0; i < ARRAY_SIZE(device_client_hash); i++) {
106 if (!device_client_hash[i]) {
107 device_client_hash[i] = device_client;
108 break;
109 }
110 }
111
112 if (i == ARRAY_SIZE(device_client_hash)) {
113 printk(KERN_ERR "batman-adv:"
114 "Error - can't add another packet client: "
115 "maximum number of clients reached\n");
116 kfree(device_client);
117 return -EXFULL;
118 }
119
120 INIT_LIST_HEAD(&device_client->queue_list);
121 device_client->queue_len = 0;
122 device_client->index = i;
123 spin_lock_init(&device_client->lock);
124 init_waitqueue_head(&device_client->queue_wait);
125
126 file->private_data = device_client;
127
128 inc_module_count();
129 return 0;
130}
131
132int bat_device_release(struct inode *inode, struct file *file)
133{
134 struct device_client *device_client =
135 (struct device_client *)file->private_data;
136 struct device_packet *device_packet;
137 struct list_head *list_pos, *list_pos_tmp;
138 unsigned long flags;
139
140 spin_lock_irqsave(&device_client->lock, flags);
141
142 /* for all packets in the queue ... */
143 list_for_each_safe(list_pos, list_pos_tmp, &device_client->queue_list) {
144 device_packet = list_entry(list_pos,
145 struct device_packet, list);
146
147 list_del(list_pos);
148 kfree(device_packet);
149 }
150
151 device_client_hash[device_client->index] = NULL;
152 spin_unlock_irqrestore(&device_client->lock, flags);
153
154 kfree(device_client);
155 dec_module_count();
156
157 return 0;
158}
159
160ssize_t bat_device_read(struct file *file, char __user *buf, size_t count,
161 loff_t *ppos)
162{
163 struct device_client *device_client =
164 (struct device_client *)file->private_data;
165 struct device_packet *device_packet;
166 int error;
167 unsigned long flags;
168
169 if ((file->f_flags & O_NONBLOCK) && (device_client->queue_len == 0))
170 return -EAGAIN;
171
172 if ((!buf) || (count < sizeof(struct icmp_packet)))
173 return -EINVAL;
174
175 if (!access_ok(VERIFY_WRITE, buf, count))
176 return -EFAULT;
177
178 error = wait_event_interruptible(device_client->queue_wait,
179 device_client->queue_len);
180
181 if (error)
182 return error;
183
184 spin_lock_irqsave(&device_client->lock, flags);
185
186 device_packet = list_first_entry(&device_client->queue_list,
187 struct device_packet, list);
188 list_del(&device_packet->list);
189 device_client->queue_len--;
190
191 spin_unlock_irqrestore(&device_client->lock, flags);
192
193 error = __copy_to_user(buf, &device_packet->icmp_packet,
194 sizeof(struct icmp_packet));
195
196 kfree(device_packet);
197
198 if (error)
199 return -EFAULT;
200
201 return sizeof(struct icmp_packet);
202}
203
204ssize_t bat_device_write(struct file *file, const char __user *buff,
205 size_t len, loff_t *off)
206{
207 struct device_client *device_client =
208 (struct device_client *)file->private_data;
209 struct icmp_packet icmp_packet;
210 struct orig_node *orig_node;
211 struct batman_if *batman_if;
212 uint8_t dstaddr[ETH_ALEN];
213 unsigned long flags;
214
215 if (len < sizeof(struct icmp_packet)) {
216 bat_dbg(DBG_BATMAN, "batman-adv:"
217 "Error - can't send packet from char device: "
218 "invalid packet size\n");
219 return -EINVAL;
220 }
221
222 if (!access_ok(VERIFY_READ, buff, sizeof(struct icmp_packet)))
223 return -EFAULT;
224
225 if (__copy_from_user(&icmp_packet, buff, sizeof(icmp_packet)))
226 return -EFAULT;
227
228 if (icmp_packet.packet_type != BAT_ICMP) {
229 bat_dbg(DBG_BATMAN, "batman-adv:"
230 "Error - can't send packet from char device: "
231 "got bogus packet type (expected: BAT_ICMP)\n");
232 return -EINVAL;
233 }
234
235 if (icmp_packet.msg_type != ECHO_REQUEST) {
236 bat_dbg(DBG_BATMAN, "batman-adv:"
237 "Error - can't send packet from char device: "
238 "got bogus message type (expected: ECHO_REQUEST)\n");
239 return -EINVAL;
240 }
241
242 icmp_packet.uid = device_client->index;
243
244 if (icmp_packet.version != COMPAT_VERSION) {
245 icmp_packet.msg_type = PARAMETER_PROBLEM;
246 icmp_packet.ttl = COMPAT_VERSION;
247 bat_device_add_packet(device_client, &icmp_packet);
248 goto out;
249 }
250
251 if (atomic_read(&module_state) != MODULE_ACTIVE)
252 goto dst_unreach;
253
254 spin_lock_irqsave(&orig_hash_lock, flags);
255 orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet.dst));
256
257 if (!orig_node)
258 goto unlock;
259
260 if (!orig_node->router)
261 goto unlock;
262
263 batman_if = orig_node->router->if_incoming;
264 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
265
266 spin_unlock_irqrestore(&orig_hash_lock, flags);
267
268 if (!batman_if)
269 goto dst_unreach;
270
271 if (batman_if->if_status != IF_ACTIVE)
272 goto dst_unreach;
273
274 memcpy(icmp_packet.orig,
275 batman_if->net_dev->dev_addr,
276 ETH_ALEN);
277
278 send_raw_packet((unsigned char *)&icmp_packet,
279 sizeof(struct icmp_packet),
280 batman_if, dstaddr);
281
282 goto out;
283
284unlock:
285 spin_unlock_irqrestore(&orig_hash_lock, flags);
286dst_unreach:
287 icmp_packet.msg_type = DESTINATION_UNREACHABLE;
288 bat_device_add_packet(device_client, &icmp_packet);
289out:
290 return len;
291}
292
293unsigned int bat_device_poll(struct file *file, poll_table *wait)
294{
295 struct device_client *device_client =
296 (struct device_client *)file->private_data;
297
298 poll_wait(file, &device_client->queue_wait, wait);
299
300 if (device_client->queue_len > 0)
301 return POLLIN | POLLRDNORM;
302
303 return 0;
304}
305
306void bat_device_add_packet(struct device_client *device_client,
307 struct icmp_packet *icmp_packet)
308{
309 struct device_packet *device_packet;
310 unsigned long flags;
311
312 device_packet = kmalloc(sizeof(struct device_packet), GFP_ATOMIC);
313
314 if (!device_packet)
315 return;
316
317 INIT_LIST_HEAD(&device_packet->list);
318 memcpy(&device_packet->icmp_packet, icmp_packet,
319 sizeof(struct icmp_packet));
320
321 spin_lock_irqsave(&device_client->lock, flags);
322
323 /* while waiting for the lock the device_client could have been
324 * deleted */
325 if (!device_client_hash[icmp_packet->uid]) {
326 spin_unlock_irqrestore(&device_client->lock, flags);
327 kfree(device_packet);
328 return;
329 }
330
331 list_add_tail(&device_packet->list, &device_client->queue_list);
332 device_client->queue_len++;
333
334 if (device_client->queue_len > 100) {
335 device_packet = list_first_entry(&device_client->queue_list,
336 struct device_packet, list);
337
338 list_del(&device_packet->list);
339 kfree(device_packet);
340 device_client->queue_len--;
341 }
342
343 spin_unlock_irqrestore(&device_client->lock, flags);
344
345 wake_up(&device_client->queue_wait);
346}
347
348void bat_device_receive_packet(struct icmp_packet *icmp_packet)
349{
350 struct device_client *hash = device_client_hash[icmp_packet->uid];
351
352 if (hash)
353 bat_device_add_packet(hash, icmp_packet);
354}
diff --git a/drivers/staging/batman-adv/icmp_socket.c b/drivers/staging/batman-adv/icmp_socket.c
new file mode 100644
index 00000000000..d4411cbe350
--- /dev/null
+++ b/drivers/staging/batman-adv/icmp_socket.c
@@ -0,0 +1,328 @@
1/*
2 * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#include <linux/debugfs.h>
23#include <linux/slab.h>
24#include "main.h"
25#include "icmp_socket.h"
26#include "send.h"
27#include "types.h"
28#include "hash.h"
29#include "hard-interface.h"
30
31
32static struct socket_client *socket_client_hash[256];
33
34static void bat_socket_add_packet(struct socket_client *socket_client,
35 struct icmp_packet *icmp_packet);
36
37void bat_socket_init(void)
38{
39 memset(socket_client_hash, 0, sizeof(socket_client_hash));
40}
41
42static int bat_socket_open(struct inode *inode, struct file *file)
43{
44 unsigned int i;
45 struct socket_client *socket_client;
46
47 socket_client = kmalloc(sizeof(struct socket_client), GFP_KERNEL);
48
49 if (!socket_client)
50 return -ENOMEM;
51
52 for (i = 0; i < ARRAY_SIZE(socket_client_hash); i++) {
53 if (!socket_client_hash[i]) {
54 socket_client_hash[i] = socket_client;
55 break;
56 }
57 }
58
59 if (i == ARRAY_SIZE(socket_client_hash)) {
60 printk(KERN_ERR "batman-adv:"
61 "Error - can't add another packet client: "
62 "maximum number of clients reached\n");
63 kfree(socket_client);
64 return -EXFULL;
65 }
66
67 INIT_LIST_HEAD(&socket_client->queue_list);
68 socket_client->queue_len = 0;
69 socket_client->index = i;
70 spin_lock_init(&socket_client->lock);
71 init_waitqueue_head(&socket_client->queue_wait);
72
73 file->private_data = socket_client;
74
75 inc_module_count();
76 return 0;
77}
78
79static int bat_socket_release(struct inode *inode, struct file *file)
80{
81 struct socket_client *socket_client =
82 (struct socket_client *)file->private_data;
83 struct socket_packet *socket_packet;
84 struct list_head *list_pos, *list_pos_tmp;
85 unsigned long flags;
86
87 spin_lock_irqsave(&socket_client->lock, flags);
88
89 /* for all packets in the queue ... */
90 list_for_each_safe(list_pos, list_pos_tmp, &socket_client->queue_list) {
91 socket_packet = list_entry(list_pos,
92 struct socket_packet, list);
93
94 list_del(list_pos);
95 kfree(socket_packet);
96 }
97
98 socket_client_hash[socket_client->index] = NULL;
99 spin_unlock_irqrestore(&socket_client->lock, flags);
100
101 kfree(socket_client);
102 dec_module_count();
103
104 return 0;
105}
106
107static ssize_t bat_socket_read(struct file *file, char __user *buf,
108 size_t count, loff_t *ppos)
109{
110 struct socket_client *socket_client =
111 (struct socket_client *)file->private_data;
112 struct socket_packet *socket_packet;
113 int error;
114 unsigned long flags;
115
116 if ((file->f_flags & O_NONBLOCK) && (socket_client->queue_len == 0))
117 return -EAGAIN;
118
119 if ((!buf) || (count < sizeof(struct icmp_packet)))
120 return -EINVAL;
121
122 if (!access_ok(VERIFY_WRITE, buf, count))
123 return -EFAULT;
124
125 error = wait_event_interruptible(socket_client->queue_wait,
126 socket_client->queue_len);
127
128 if (error)
129 return error;
130
131 spin_lock_irqsave(&socket_client->lock, flags);
132
133 socket_packet = list_first_entry(&socket_client->queue_list,
134 struct socket_packet, list);
135 list_del(&socket_packet->list);
136 socket_client->queue_len--;
137
138 spin_unlock_irqrestore(&socket_client->lock, flags);
139
140 error = __copy_to_user(buf, &socket_packet->icmp_packet,
141 sizeof(struct icmp_packet));
142
143 kfree(socket_packet);
144
145 if (error)
146 return -EFAULT;
147
148 return sizeof(struct icmp_packet);
149}
150
151static ssize_t bat_socket_write(struct file *file, const char __user *buff,
152 size_t len, loff_t *off)
153{
154 struct socket_client *socket_client =
155 (struct socket_client *)file->private_data;
156 struct icmp_packet icmp_packet;
157 struct orig_node *orig_node;
158 struct batman_if *batman_if;
159 uint8_t dstaddr[ETH_ALEN];
160 unsigned long flags;
161
162 if (len < sizeof(struct icmp_packet)) {
163 bat_dbg(DBG_BATMAN, "batman-adv:"
164 "Error - can't send packet from char device: "
165 "invalid packet size\n");
166 return -EINVAL;
167 }
168
169 if (!access_ok(VERIFY_READ, buff, sizeof(struct icmp_packet)))
170 return -EFAULT;
171
172 if (__copy_from_user(&icmp_packet, buff, sizeof(icmp_packet)))
173 return -EFAULT;
174
175 if (icmp_packet.packet_type != BAT_ICMP) {
176 bat_dbg(DBG_BATMAN, "batman-adv:"
177 "Error - can't send packet from char device: "
178 "got bogus packet type (expected: BAT_ICMP)\n");
179 return -EINVAL;
180 }
181
182 if (icmp_packet.msg_type != ECHO_REQUEST) {
183 bat_dbg(DBG_BATMAN, "batman-adv:"
184 "Error - can't send packet from char device: "
185 "got bogus message type (expected: ECHO_REQUEST)\n");
186 return -EINVAL;
187 }
188
189 icmp_packet.uid = socket_client->index;
190
191 if (icmp_packet.version != COMPAT_VERSION) {
192 icmp_packet.msg_type = PARAMETER_PROBLEM;
193 icmp_packet.ttl = COMPAT_VERSION;
194 bat_socket_add_packet(socket_client, &icmp_packet);
195 goto out;
196 }
197
198 if (atomic_read(&module_state) != MODULE_ACTIVE)
199 goto dst_unreach;
200
201 spin_lock_irqsave(&orig_hash_lock, flags);
202 orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet.dst));
203
204 if (!orig_node)
205 goto unlock;
206
207 if (!orig_node->router)
208 goto unlock;
209
210 batman_if = orig_node->router->if_incoming;
211 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
212
213 spin_unlock_irqrestore(&orig_hash_lock, flags);
214
215 if (!batman_if)
216 goto dst_unreach;
217
218 if (batman_if->if_status != IF_ACTIVE)
219 goto dst_unreach;
220
221 memcpy(icmp_packet.orig,
222 batman_if->net_dev->dev_addr,
223 ETH_ALEN);
224
225 send_raw_packet((unsigned char *)&icmp_packet,
226 sizeof(struct icmp_packet),
227 batman_if, dstaddr);
228
229 goto out;
230
231unlock:
232 spin_unlock_irqrestore(&orig_hash_lock, flags);
233dst_unreach:
234 icmp_packet.msg_type = DESTINATION_UNREACHABLE;
235 bat_socket_add_packet(socket_client, &icmp_packet);
236out:
237 return len;
238}
239
240static unsigned int bat_socket_poll(struct file *file, poll_table *wait)
241{
242 struct socket_client *socket_client =
243 (struct socket_client *)file->private_data;
244
245 poll_wait(file, &socket_client->queue_wait, wait);
246
247 if (socket_client->queue_len > 0)
248 return POLLIN | POLLRDNORM;
249
250 return 0;
251}
252
253static const struct file_operations fops = {
254 .owner = THIS_MODULE,
255 .open = bat_socket_open,
256 .release = bat_socket_release,
257 .read = bat_socket_read,
258 .write = bat_socket_write,
259 .poll = bat_socket_poll,
260};
261
262int bat_socket_setup(struct bat_priv *bat_priv)
263{
264 struct dentry *d;
265
266 if (!bat_priv->debug_dir)
267 goto err;
268
269 d = debugfs_create_file(ICMP_SOCKET, S_IFREG | S_IWUSR | S_IRUSR,
270 bat_priv->debug_dir, NULL, &fops);
271 if (d)
272 goto err;
273
274 return 0;
275
276err:
277 return 1;
278}
279
280static void bat_socket_add_packet(struct socket_client *socket_client,
281 struct icmp_packet *icmp_packet)
282{
283 struct socket_packet *socket_packet;
284 unsigned long flags;
285
286 socket_packet = kmalloc(sizeof(struct socket_packet), GFP_ATOMIC);
287
288 if (!socket_packet)
289 return;
290
291 INIT_LIST_HEAD(&socket_packet->list);
292 memcpy(&socket_packet->icmp_packet, icmp_packet,
293 sizeof(struct icmp_packet));
294
295 spin_lock_irqsave(&socket_client->lock, flags);
296
297 /* while waiting for the lock the socket_client could have been
298 * deleted */
299 if (!socket_client_hash[icmp_packet->uid]) {
300 spin_unlock_irqrestore(&socket_client->lock, flags);
301 kfree(socket_packet);
302 return;
303 }
304
305 list_add_tail(&socket_packet->list, &socket_client->queue_list);
306 socket_client->queue_len++;
307
308 if (socket_client->queue_len > 100) {
309 socket_packet = list_first_entry(&socket_client->queue_list,
310 struct socket_packet, list);
311
312 list_del(&socket_packet->list);
313 kfree(socket_packet);
314 socket_client->queue_len--;
315 }
316
317 spin_unlock_irqrestore(&socket_client->lock, flags);
318
319 wake_up(&socket_client->queue_wait);
320}
321
322void bat_socket_receive_packet(struct icmp_packet *icmp_packet)
323{
324 struct socket_client *hash = socket_client_hash[icmp_packet->uid];
325
326 if (hash)
327 bat_socket_add_packet(hash, icmp_packet);
328}
diff --git a/drivers/staging/batman-adv/device.h b/drivers/staging/batman-adv/icmp_socket.h
index eb14b371cea..5ad73daa08c 100644
--- a/drivers/staging/batman-adv/device.h
+++ b/drivers/staging/batman-adv/icmp_socket.h
@@ -21,16 +21,8 @@
21 21
22#include "types.h" 22#include "types.h"
23 23
24void bat_device_init(void); 24#define ICMP_SOCKET "socket"
25int bat_device_setup(void); 25
26void bat_device_destroy(void); 26void bat_socket_init(void);
27int bat_device_open(struct inode *inode, struct file *file); 27int bat_socket_setup(struct bat_priv *bat_priv);
28int bat_device_release(struct inode *inode, struct file *file); 28void bat_socket_receive_packet(struct icmp_packet *icmp_packet);
29ssize_t bat_device_read(struct file *file, char __user *buf, size_t count,
30 loff_t *ppos);
31ssize_t bat_device_write(struct file *file, const char __user *buff,
32 size_t len, loff_t *off);
33unsigned int bat_device_poll(struct file *file, poll_table *wait);
34void bat_device_add_packet(struct device_client *device_client,
35 struct icmp_packet *icmp_packet);
36void bat_device_receive_packet(struct icmp_packet *icmp_packet);
diff --git a/drivers/staging/batman-adv/main.c b/drivers/staging/batman-adv/main.c
index 14ab4a0a880..ed18b08e704 100644
--- a/drivers/staging/batman-adv/main.c
+++ b/drivers/staging/batman-adv/main.c
@@ -21,11 +21,12 @@
21 21
22#include "main.h" 22#include "main.h"
23#include "bat_sysfs.h" 23#include "bat_sysfs.h"
24#include "bat_debugfs.h"
24#include "routing.h" 25#include "routing.h"
25#include "send.h" 26#include "send.h"
26#include "originator.h" 27#include "originator.h"
27#include "soft-interface.h" 28#include "soft-interface.h"
28#include "device.h" 29#include "icmp_socket.h"
29#include "translation-table.h" 30#include "translation-table.h"
30#include "hard-interface.h" 31#include "hard-interface.h"
31#include "types.h" 32#include "types.h"
@@ -89,7 +90,8 @@ int init_module(void)
89 if (!bat_event_workqueue) 90 if (!bat_event_workqueue)
90 return -ENOMEM; 91 return -ENOMEM;
91 92
92 bat_device_init(); 93 bat_socket_init();
94 debugfs_init();
93 95
94 /* initialize layer 2 interface */ 96 /* initialize layer 2 interface */
95 soft_device = alloc_netdev(sizeof(struct bat_priv) , "bat%d", 97 soft_device = alloc_netdev(sizeof(struct bat_priv) , "bat%d",
@@ -114,6 +116,11 @@ int init_module(void)
114 if (retval < 0) 116 if (retval < 0)
115 goto unreg_soft_device; 117 goto unreg_soft_device;
116 118
119 retval = debugfs_add_meshif(soft_device);
120
121 if (retval < 0)
122 goto unreg_sysfs;
123
117 register_netdevice_notifier(&hard_if_notifier); 124 register_netdevice_notifier(&hard_if_notifier);
118 dev_add_pack(&batman_adv_packet_type); 125 dev_add_pack(&batman_adv_packet_type);
119 126
@@ -123,6 +130,8 @@ int init_module(void)
123 130
124 return 0; 131 return 0;
125 132
133unreg_sysfs:
134 sysfs_del_meshif(soft_device);
126unreg_soft_device: 135unreg_soft_device:
127 unregister_netdev(soft_device); 136 unregister_netdev(soft_device);
128 soft_device = NULL; 137 soft_device = NULL;
@@ -143,6 +152,7 @@ void cleanup_module(void)
143 hardif_remove_interfaces(); 152 hardif_remove_interfaces();
144 153
145 if (soft_device) { 154 if (soft_device) {
155 debugfs_del_meshif(soft_device);
146 sysfs_del_meshif(soft_device); 156 sysfs_del_meshif(soft_device);
147 unregister_netdev(soft_device); 157 unregister_netdev(soft_device);
148 soft_device = NULL; 158 soft_device = NULL;
@@ -154,7 +164,7 @@ void cleanup_module(void)
154 bat_event_workqueue = NULL; 164 bat_event_workqueue = NULL;
155} 165}
156 166
157/* activates the module, creates bat device, starts timer ... */ 167/* activates the module, starts timer ... */
158void activate_module(void) 168void activate_module(void)
159{ 169{
160 if (originator_init() < 1) 170 if (originator_init() < 1)
@@ -168,9 +178,6 @@ void activate_module(void)
168 178
169 hna_local_add(soft_device->dev_addr); 179 hna_local_add(soft_device->dev_addr);
170 180
171 if (bat_device_setup() < 1)
172 goto end;
173
174 if (vis_init() < 1) 181 if (vis_init() < 1)
175 goto err; 182 goto err;
176 183
@@ -205,7 +212,7 @@ void deactivate_module(void)
205 hna_global_free(); 212 hna_global_free();
206 213
207 synchronize_net(); 214 synchronize_net();
208 bat_device_destroy(); 215 debugfs_destroy();
209 216
210 synchronize_rcu(); 217 synchronize_rcu();
211 atomic_set(&module_state, MODULE_INACTIVE); 218 atomic_set(&module_state, MODULE_INACTIVE);
diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c
index 066dc8b3881..d4bdca9c126 100644
--- a/drivers/staging/batman-adv/routing.c
+++ b/drivers/staging/batman-adv/routing.c
@@ -25,7 +25,7 @@
25#include "hash.h" 25#include "hash.h"
26#include "soft-interface.h" 26#include "soft-interface.h"
27#include "hard-interface.h" 27#include "hard-interface.h"
28#include "device.h" 28#include "icmp_socket.h"
29#include "translation-table.h" 29#include "translation-table.h"
30#include "originator.h" 30#include "originator.h"
31#include "types.h" 31#include "types.h"
@@ -668,7 +668,7 @@ static int recv_my_icmp_packet(struct sk_buff *skb)
668 668
669 /* add data to device queue */ 669 /* add data to device queue */
670 if (icmp_packet->msg_type != ECHO_REQUEST) { 670 if (icmp_packet->msg_type != ECHO_REQUEST) {
671 bat_device_receive_packet(icmp_packet); 671 bat_socket_receive_packet(icmp_packet);
672 return NET_RX_DROP; 672 return NET_RX_DROP;
673 } 673 }
674 674
diff --git a/drivers/staging/batman-adv/types.h b/drivers/staging/batman-adv/types.h
index 86007c7eb44..751cd632281 100644
--- a/drivers/staging/batman-adv/types.h
+++ b/drivers/staging/batman-adv/types.h
@@ -106,9 +106,10 @@ struct bat_priv {
106 char num_ifaces; 106 char num_ifaces;
107 struct batman_if *primary_if; 107 struct batman_if *primary_if;
108 struct kobject *mesh_obj; 108 struct kobject *mesh_obj;
109 struct dentry *debug_dir;
109}; 110};
110 111
111struct device_client { 112struct socket_client {
112 struct list_head queue_list; 113 struct list_head queue_list;
113 unsigned int queue_len; 114 unsigned int queue_len;
114 unsigned char index; 115 unsigned char index;
@@ -116,7 +117,7 @@ struct device_client {
116 wait_queue_head_t queue_wait; 117 wait_queue_head_t queue_wait;
117}; 118};
118 119
119struct device_packet { 120struct socket_packet {
120 struct list_head list; 121 struct list_head list;
121 struct icmp_packet icmp_packet; 122 struct icmp_packet icmp_packet;
122}; 123};