Blame view

net/batman-adv/icmp_socket.c 9.95 KB
7db7d9f36   Sven Eckelmann   batman-adv: Add S...
1
  // SPDX-License-Identifier: GPL-2.0
7a79d717e   Sven Eckelmann   batman-adv: Updat...
2
  /* Copyright (C) 2007-2019  B.A.T.M.A.N. contributors:
c6c8fea29   Sven Eckelmann   net: Add batman-a...
3
4
   *
   * Marek Lindner
c6c8fea29   Sven Eckelmann   net: Add batman-a...
5
   */
1e2c2a4fe   Sven Eckelmann   batman-adv: Add r...
6
  #include "icmp_socket.h"
c6c8fea29   Sven Eckelmann   net: Add batman-a...
7
  #include "main.h"
1e2c2a4fe   Sven Eckelmann   batman-adv: Add r...
8
9
10
  
  #include <linux/atomic.h>
  #include <linux/compiler.h>
c6c8fea29   Sven Eckelmann   net: Add batman-a...
11
  #include <linux/debugfs.h>
1e2c2a4fe   Sven Eckelmann   batman-adv: Add r...
12
13
  #include <linux/errno.h>
  #include <linux/etherdevice.h>
48881ed56   Sven Eckelmann   batman-adv: Add m...
14
  #include <linux/eventpoll.h>
1e2c2a4fe   Sven Eckelmann   batman-adv: Add r...
15
16
17
  #include <linux/export.h>
  #include <linux/fcntl.h>
  #include <linux/fs.h>
b92b94ac7   Sven Eckelmann   batman-adv: inclu...
18
  #include <linux/gfp.h>
1e2c2a4fe   Sven Eckelmann   batman-adv: Add r...
19
20
21
22
23
24
25
26
27
28
  #include <linux/if_ether.h>
  #include <linux/kernel.h>
  #include <linux/list.h>
  #include <linux/module.h>
  #include <linux/netdevice.h>
  #include <linux/pkt_sched.h>
  #include <linux/poll.h>
  #include <linux/printk.h>
  #include <linux/sched.h> /* for linux/wait.h */
  #include <linux/skbuff.h>
c6c8fea29   Sven Eckelmann   net: Add batman-a...
29
  #include <linux/slab.h>
1e2c2a4fe   Sven Eckelmann   batman-adv: Add r...
30
  #include <linux/spinlock.h>
1e2c2a4fe   Sven Eckelmann   batman-adv: Add r...
31
32
33
34
  #include <linux/stddef.h>
  #include <linux/string.h>
  #include <linux/uaccess.h>
  #include <linux/wait.h>
fec149f5d   Sven Eckelmann   batman-adv: Conve...
35
  #include <uapi/linux/batadv_packet.h>
1e2c2a4fe   Sven Eckelmann   batman-adv: Add r...
36

00caf6a2b   Sven Eckelmann   batman-adv: Mark ...
37
  #include "debugfs.h"
c6c8fea29   Sven Eckelmann   net: Add batman-a...
38
  #include "hard-interface.h"
ba412080f   Sven Eckelmann   batman-adv: Conso...
39
  #include "log.h"
1e2c2a4fe   Sven Eckelmann   batman-adv: Add r...
40
  #include "originator.h"
1e2c2a4fe   Sven Eckelmann   batman-adv: Add r...
41
  #include "send.h"
c6c8fea29   Sven Eckelmann   net: Add batman-a...
42

56303d34a   Sven Eckelmann   batman-adv: Prefi...
43
  static struct batadv_socket_client *batadv_socket_client_hash[256];
c6c8fea29   Sven Eckelmann   net: Add batman-a...
44

56303d34a   Sven Eckelmann   batman-adv: Prefi...
45
  static void batadv_socket_add_packet(struct batadv_socket_client *socket_client,
da6b8c20a   Simon Wunderlich   batman-adv: gener...
46
  				     struct batadv_icmp_header *icmph,
af4447f62   Sven Eckelmann   batman-adv: Prefi...
47
  				     size_t icmp_len);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
48

ff15c27c9   Sven Eckelmann   batman-adv: Add k...
49
50
51
  /**
   * batadv_socket_init() - Initialize soft interface independent socket data
   */
9039dc7e8   Sven Eckelmann   batman-adv: Prefi...
52
  void batadv_socket_init(void)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
53
  {
af4447f62   Sven Eckelmann   batman-adv: Prefi...
54
  	memset(batadv_socket_client_hash, 0, sizeof(batadv_socket_client_hash));
c6c8fea29   Sven Eckelmann   net: Add batman-a...
55
  }
af4447f62   Sven Eckelmann   batman-adv: Prefi...
56
  static int batadv_socket_open(struct inode *inode, struct file *file)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
57
58
  {
  	unsigned int i;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
59
  	struct batadv_socket_client *socket_client;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
60

bd5b80d51   Sven Eckelmann   batman-adv: Check...
61
62
  	if (!try_module_get(THIS_MODULE))
  		return -EBUSY;
00caf6a2b   Sven Eckelmann   batman-adv: Mark ...
63
  	batadv_debugfs_deprecated(file, "");
c5bf68fe0   Kirill Smelkov   *: convert stream...
64
  	stream_open(inode, file);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
65

704509b8d   Sven Eckelmann   batman-adv: Calcu...
66
  	socket_client = kmalloc(sizeof(*socket_client), GFP_KERNEL);
bd5b80d51   Sven Eckelmann   batman-adv: Check...
67
68
  	if (!socket_client) {
  		module_put(THIS_MODULE);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
69
  		return -ENOMEM;
bd5b80d51   Sven Eckelmann   batman-adv: Check...
70
  	}
c6c8fea29   Sven Eckelmann   net: Add batman-a...
71

af4447f62   Sven Eckelmann   batman-adv: Prefi...
72
73
74
  	for (i = 0; i < ARRAY_SIZE(batadv_socket_client_hash); i++) {
  		if (!batadv_socket_client_hash[i]) {
  			batadv_socket_client_hash[i] = socket_client;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
75
76
77
  			break;
  		}
  	}
af4447f62   Sven Eckelmann   batman-adv: Prefi...
78
  	if (i == ARRAY_SIZE(batadv_socket_client_hash)) {
86ceb3605   Sven Eckelmann   batman-adv: Ignor...
79
80
  		pr_err("Error - can't add another packet client: maximum number of clients reached
  ");
c6c8fea29   Sven Eckelmann   net: Add batman-a...
81
  		kfree(socket_client);
bd5b80d51   Sven Eckelmann   batman-adv: Check...
82
  		module_put(THIS_MODULE);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
83
84
85
86
87
88
89
90
91
92
93
  		return -EXFULL;
  	}
  
  	INIT_LIST_HEAD(&socket_client->queue_list);
  	socket_client->queue_len = 0;
  	socket_client->index = i;
  	socket_client->bat_priv = inode->i_private;
  	spin_lock_init(&socket_client->lock);
  	init_waitqueue_head(&socket_client->queue_wait);
  
  	file->private_data = socket_client;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
94
95
  	return 0;
  }
af4447f62   Sven Eckelmann   batman-adv: Prefi...
96
  static int batadv_socket_release(struct inode *inode, struct file *file)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
97
  {
fb1f23eab   Geliang Tang   batman-adv: use l...
98
99
  	struct batadv_socket_client *client = file->private_data;
  	struct batadv_socket_packet *packet, *tmp;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
100

fb1f23eab   Geliang Tang   batman-adv: use l...
101
  	spin_lock_bh(&client->lock);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
102
103
  
  	/* for all packets in the queue ... */
fb1f23eab   Geliang Tang   batman-adv: use l...
104
105
106
  	list_for_each_entry_safe(packet, tmp, &client->queue_list, list) {
  		list_del(&packet->list);
  		kfree(packet);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
107
  	}
fb1f23eab   Geliang Tang   batman-adv: use l...
108
109
  	batadv_socket_client_hash[client->index] = NULL;
  	spin_unlock_bh(&client->lock);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
110

fb1f23eab   Geliang Tang   batman-adv: use l...
111
  	kfree(client);
bd5b80d51   Sven Eckelmann   batman-adv: Check...
112
  	module_put(THIS_MODULE);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
113
114
115
  
  	return 0;
  }
af4447f62   Sven Eckelmann   batman-adv: Prefi...
116
117
  static ssize_t batadv_socket_read(struct file *file, char __user *buf,
  				  size_t count, loff_t *ppos)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
118
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
119
120
  	struct batadv_socket_client *socket_client = file->private_data;
  	struct batadv_socket_packet *socket_packet;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
121
122
  	size_t packet_len;
  	int error;
825ffe1f7   Sven Eckelmann   batman-adv: Remov...
123
  	if ((file->f_flags & O_NONBLOCK) && socket_client->queue_len == 0)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
124
  		return -EAGAIN;
825ffe1f7   Sven Eckelmann   batman-adv: Remov...
125
  	if (!buf || count < sizeof(struct batadv_icmp_packet))
c6c8fea29   Sven Eckelmann   net: Add batman-a...
126
  		return -EINVAL;
96d4f267e   Linus Torvalds   Remove 'type' arg...
127
  	if (!access_ok(buf, count))
c6c8fea29   Sven Eckelmann   net: Add batman-a...
128
129
130
131
132
133
134
135
136
137
138
  		return -EFAULT;
  
  	error = wait_event_interruptible(socket_client->queue_wait,
  					 socket_client->queue_len);
  
  	if (error)
  		return error;
  
  	spin_lock_bh(&socket_client->lock);
  
  	socket_packet = list_first_entry(&socket_client->queue_list,
56303d34a   Sven Eckelmann   batman-adv: Prefi...
139
  					 struct batadv_socket_packet, list);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
140
141
142
143
  	list_del(&socket_packet->list);
  	socket_client->queue_len--;
  
  	spin_unlock_bh(&socket_client->lock);
b5a1eeef0   Sven Eckelmann   batman-adv: Only ...
144
145
  	packet_len = min(count, socket_packet->icmp_len);
  	error = copy_to_user(buf, &socket_packet->icmp_packet, packet_len);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
146

c6c8fea29   Sven Eckelmann   net: Add batman-a...
147
148
149
150
151
152
153
  	kfree(socket_packet);
  
  	if (error)
  		return -EFAULT;
  
  	return packet_len;
  }
af4447f62   Sven Eckelmann   batman-adv: Prefi...
154
155
  static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
  				   size_t len, loff_t *off)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
156
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
157
158
159
  	struct batadv_socket_client *socket_client = file->private_data;
  	struct batadv_priv *bat_priv = socket_client->bat_priv;
  	struct batadv_hard_iface *primary_if = NULL;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
160
  	struct sk_buff *skb;
da6b8c20a   Simon Wunderlich   batman-adv: gener...
161
162
  	struct batadv_icmp_packet_rr *icmp_packet_rr;
  	struct batadv_icmp_header *icmp_header;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
163
164
  	struct batadv_orig_node *orig_node = NULL;
  	struct batadv_neigh_node *neigh_node = NULL;
964126901   Sven Eckelmann   batman-adv: Prefi...
165
  	size_t packet_len = sizeof(struct batadv_icmp_packet);
6b5e971a2   Sven Eckelmann   batman-adv: Repla...
166
  	u8 *addr;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
167

da6b8c20a   Simon Wunderlich   batman-adv: gener...
168
  	if (len < sizeof(struct batadv_icmp_header)) {
39c75a51e   Sven Eckelmann   batman-adv: Prefi...
169
  		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1eda58bfc   Sven Eckelmann   batman-adv: Prefi...
170
171
  			   "Error - can't send packet from char device: invalid packet size
  ");
c6c8fea29   Sven Eckelmann   net: Add batman-a...
172
173
  		return -EINVAL;
  	}
e5d89254b   Sven Eckelmann   batman-adv: Prefi...
174
  	primary_if = batadv_primary_if_get_selected(bat_priv);
32ae9b221   Marek Lindner   batman-adv: Make ...
175
176
177
178
179
  
  	if (!primary_if) {
  		len = -EFAULT;
  		goto out;
  	}
c6c8fea29   Sven Eckelmann   net: Add batman-a...
180

da6b8c20a   Simon Wunderlich   batman-adv: gener...
181
182
183
184
  	if (len >= BATADV_ICMP_MAX_PACKET_SIZE)
  		packet_len = BATADV_ICMP_MAX_PACKET_SIZE;
  	else
  		packet_len = len;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
185

41ab6c489   Antonio Quartulli   batman-adv: don't...
186
  	skb = netdev_alloc_skb_ip_align(NULL, packet_len + ETH_HLEN);
32ae9b221   Marek Lindner   batman-adv: Make ...
187
188
189
190
  	if (!skb) {
  		len = -ENOMEM;
  		goto out;
  	}
c6c8fea29   Sven Eckelmann   net: Add batman-a...
191

c54f38c9a   Simon Wunderlich   batman-adv: set s...
192
  	skb->priority = TC_PRIO_CONTROL;
41ab6c489   Antonio Quartulli   batman-adv: don't...
193
  	skb_reserve(skb, ETH_HLEN);
4df864c1d   Johannes Berg   networking: make ...
194
  	icmp_header = skb_put(skb, packet_len);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
195

da6b8c20a   Simon Wunderlich   batman-adv: gener...
196
  	if (copy_from_user(icmp_header, buff, packet_len)) {
c6c8fea29   Sven Eckelmann   net: Add batman-a...
197
198
199
  		len = -EFAULT;
  		goto free_skb;
  	}
a40d9b075   Simon Wunderlich   batman-adv: fix h...
200
  	if (icmp_header->packet_type != BATADV_ICMP) {
39c75a51e   Sven Eckelmann   batman-adv: Prefi...
201
  		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1eda58bfc   Sven Eckelmann   batman-adv: Prefi...
202
203
  			   "Error - can't send packet from char device: got bogus packet type (expected: BAT_ICMP)
  ");
c6c8fea29   Sven Eckelmann   net: Add batman-a...
204
205
206
  		len = -EINVAL;
  		goto free_skb;
  	}
da6b8c20a   Simon Wunderlich   batman-adv: gener...
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
  	switch (icmp_header->msg_type) {
  	case BATADV_ECHO_REQUEST:
  		if (len < sizeof(struct batadv_icmp_packet)) {
  			batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
  				   "Error - can't send packet from char device: invalid packet size
  ");
  			len = -EINVAL;
  			goto free_skb;
  		}
  
  		if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
  			goto dst_unreach;
  
  		orig_node = batadv_orig_hash_find(bat_priv, icmp_header->dst);
  		if (!orig_node)
  			goto dst_unreach;
7351a4822   Simon Wunderlich   batman-adv: split...
223
224
  		neigh_node = batadv_orig_router_get(orig_node,
  						    BATADV_IF_DEFAULT);
da6b8c20a   Simon Wunderlich   batman-adv: gener...
225
226
227
228
229
230
231
232
233
234
  		if (!neigh_node)
  			goto dst_unreach;
  
  		if (!neigh_node->if_incoming)
  			goto dst_unreach;
  
  		if (neigh_node->if_incoming->if_status != BATADV_IF_ACTIVE)
  			goto dst_unreach;
  
  		icmp_packet_rr = (struct batadv_icmp_packet_rr *)icmp_header;
8fdd01530   Antonio Quartulli   batman-adv: prefe...
235
236
237
238
  		if (packet_len == sizeof(*icmp_packet_rr)) {
  			addr = neigh_node->if_incoming->net_dev->dev_addr;
  			ether_addr_copy(icmp_packet_rr->rr[0], addr);
  		}
da6b8c20a   Simon Wunderlich   batman-adv: gener...
239
240
241
  
  		break;
  	default:
39c75a51e   Sven Eckelmann   batman-adv: Prefi...
242
  		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
da6b8c20a   Simon Wunderlich   batman-adv: gener...
243
244
  			   "Error - can't send packet from char device: got unknown message type
  ");
c6c8fea29   Sven Eckelmann   net: Add batman-a...
245
246
247
  		len = -EINVAL;
  		goto free_skb;
  	}
da6b8c20a   Simon Wunderlich   batman-adv: gener...
248
  	icmp_header->uid = socket_client->index;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
249

a40d9b075   Simon Wunderlich   batman-adv: fix h...
250
  	if (icmp_header->version != BATADV_COMPAT_VERSION) {
da6b8c20a   Simon Wunderlich   batman-adv: gener...
251
  		icmp_header->msg_type = BATADV_PARAMETER_PROBLEM;
a40d9b075   Simon Wunderlich   batman-adv: fix h...
252
  		icmp_header->version = BATADV_COMPAT_VERSION;
da6b8c20a   Simon Wunderlich   batman-adv: gener...
253
  		batadv_socket_add_packet(socket_client, icmp_header,
af4447f62   Sven Eckelmann   batman-adv: Prefi...
254
  					 packet_len);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
255
256
  		goto free_skb;
  	}
8fdd01530   Antonio Quartulli   batman-adv: prefe...
257
  	ether_addr_copy(icmp_header->orig, primary_if->net_dev->dev_addr);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
258

95d392784   Antonio Quartulli   batman-adv: keep ...
259
  	batadv_send_unicast_skb(skb, neigh_node);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
260
  	goto out;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
261
  dst_unreach:
da6b8c20a   Simon Wunderlich   batman-adv: gener...
262
263
  	icmp_header->msg_type = BATADV_DESTINATION_UNREACHABLE;
  	batadv_socket_add_packet(socket_client, icmp_header, packet_len);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
264
265
266
  free_skb:
  	kfree_skb(skb);
  out:
32ae9b221   Marek Lindner   batman-adv: Make ...
267
  	if (primary_if)
82047ad7f   Sven Eckelmann   batman-adv: Renam...
268
  		batadv_hardif_put(primary_if);
44524fcdf   Marek Lindner   batman-adv: Corre...
269
  	if (neigh_node)
25bb25099   Sven Eckelmann   batman-adv: Renam...
270
  		batadv_neigh_node_put(neigh_node);
44524fcdf   Marek Lindner   batman-adv: Corre...
271
  	if (orig_node)
5d9673109   Sven Eckelmann   batman-adv: Renam...
272
  		batadv_orig_node_put(orig_node);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
273
274
  	return len;
  }
ade994f4f   Al Viro   net: annotate ->p...
275
  static __poll_t batadv_socket_poll(struct file *file, poll_table *wait)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
276
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
277
  	struct batadv_socket_client *socket_client = file->private_data;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
278
279
280
281
  
  	poll_wait(file, &socket_client->queue_wait, wait);
  
  	if (socket_client->queue_len > 0)
a9a08845e   Linus Torvalds   vfs: do bulk POLL...
282
  		return EPOLLIN | EPOLLRDNORM;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
283
284
285
  
  	return 0;
  }
af4447f62   Sven Eckelmann   batman-adv: Prefi...
286
  static const struct file_operations batadv_fops = {
c6c8fea29   Sven Eckelmann   net: Add batman-a...
287
  	.owner = THIS_MODULE,
af4447f62   Sven Eckelmann   batman-adv: Prefi...
288
289
290
291
292
  	.open = batadv_socket_open,
  	.release = batadv_socket_release,
  	.read = batadv_socket_read,
  	.write = batadv_socket_write,
  	.poll = batadv_socket_poll,
c6c8fea29   Sven Eckelmann   net: Add batman-a...
293
294
  	.llseek = no_llseek,
  };
ff15c27c9   Sven Eckelmann   batman-adv: Add k...
295
296
297
  /**
   * batadv_socket_setup() - Create debugfs "socket" file
   * @bat_priv: the bat priv with all the soft interface information
ff15c27c9   Sven Eckelmann   batman-adv: Add k...
298
   */
3bcacd1e0   Greg Kroah-Hartman   batman-adv: no ne...
299
  void batadv_socket_setup(struct batadv_priv *bat_priv)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
300
  {
3bcacd1e0   Greg Kroah-Hartman   batman-adv: no ne...
301
302
  	debugfs_create_file(BATADV_ICMP_SOCKET, 0600, bat_priv->debug_dir,
  			    bat_priv, &batadv_fops);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
303
  }
da6b8c20a   Simon Wunderlich   batman-adv: gener...
304
  /**
7e9a8c2ce   Sven Eckelmann   batman-adv: Use p...
305
   * batadv_socket_add_packet() - schedule an icmp packet to be sent to
34473822d   Sven Eckelmann   batman-adv: Fix k...
306
   *  userspace on an icmp socket.
da6b8c20a   Simon Wunderlich   batman-adv: gener...
307
308
309
310
   * @socket_client: the socket this packet belongs to
   * @icmph: pointer to the header of the icmp packet
   * @icmp_len: total length of the icmp packet
   */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
311
  static void batadv_socket_add_packet(struct batadv_socket_client *socket_client,
da6b8c20a   Simon Wunderlich   batman-adv: gener...
312
  				     struct batadv_icmp_header *icmph,
af4447f62   Sven Eckelmann   batman-adv: Prefi...
313
  				     size_t icmp_len)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
314
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
315
  	struct batadv_socket_packet *socket_packet;
da6b8c20a   Simon Wunderlich   batman-adv: gener...
316
  	size_t len;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
317

704509b8d   Sven Eckelmann   batman-adv: Calcu...
318
  	socket_packet = kmalloc(sizeof(*socket_packet), GFP_ATOMIC);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
319
320
321
  
  	if (!socket_packet)
  		return;
da6b8c20a   Simon Wunderlich   batman-adv: gener...
322
323
324
325
  	len = icmp_len;
  	/* check the maximum length before filling the buffer */
  	if (len > sizeof(socket_packet->icmp_packet))
  		len = sizeof(socket_packet->icmp_packet);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
326
  	INIT_LIST_HEAD(&socket_packet->list);
da6b8c20a   Simon Wunderlich   batman-adv: gener...
327
328
  	memcpy(&socket_packet->icmp_packet, icmph, len);
  	socket_packet->icmp_len = len;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
329
330
331
332
  
  	spin_lock_bh(&socket_client->lock);
  
  	/* while waiting for the lock the socket_client could have been
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
333
334
  	 * deleted
  	 */
da6b8c20a   Simon Wunderlich   batman-adv: gener...
335
  	if (!batadv_socket_client_hash[icmph->uid]) {
c6c8fea29   Sven Eckelmann   net: Add batman-a...
336
337
338
339
340
341
342
343
344
345
  		spin_unlock_bh(&socket_client->lock);
  		kfree(socket_packet);
  		return;
  	}
  
  	list_add_tail(&socket_packet->list, &socket_client->queue_list);
  	socket_client->queue_len++;
  
  	if (socket_client->queue_len > 100) {
  		socket_packet = list_first_entry(&socket_client->queue_list,
56303d34a   Sven Eckelmann   batman-adv: Prefi...
346
347
  						 struct batadv_socket_packet,
  						 list);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
348
349
350
351
352
353
354
355
356
357
  
  		list_del(&socket_packet->list);
  		kfree(socket_packet);
  		socket_client->queue_len--;
  	}
  
  	spin_unlock_bh(&socket_client->lock);
  
  	wake_up(&socket_client->queue_wait);
  }
da6b8c20a   Simon Wunderlich   batman-adv: gener...
358
  /**
7e9a8c2ce   Sven Eckelmann   batman-adv: Use p...
359
   * batadv_socket_receive_packet() - schedule an icmp packet to be received
da6b8c20a   Simon Wunderlich   batman-adv: gener...
360
361
362
363
364
   *  locally and sent to userspace.
   * @icmph: pointer to the header of the icmp packet
   * @icmp_len: total length of the icmp packet
   */
  void batadv_socket_receive_packet(struct batadv_icmp_header *icmph,
9039dc7e8   Sven Eckelmann   batman-adv: Prefi...
365
  				  size_t icmp_len)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
366
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
367
  	struct batadv_socket_client *hash;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
368

da6b8c20a   Simon Wunderlich   batman-adv: gener...
369
  	hash = batadv_socket_client_hash[icmph->uid];
c6c8fea29   Sven Eckelmann   net: Add batman-a...
370
  	if (hash)
da6b8c20a   Simon Wunderlich   batman-adv: gener...
371
  		batadv_socket_add_packet(hash, icmph, icmp_len);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
372
  }