Blame view

net/batman-adv/routing.c 31.3 KB
e19f9759e   Simon Wunderlich   batman-adv: updat...
1
  /* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors:
c6c8fea29   Sven Eckelmann   net: Add batman-a...
2
3
4
5
6
7
8
9
10
11
12
13
14
   *
   * Marek Lindner, Simon Wunderlich
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of version 2 of the GNU General Public
   * License as published by the Free Software Foundation.
   *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   * General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
ebf38fb7a   Antonio Quartulli   batman-adv: remov...
15
   * along with this program; if not, see <http://www.gnu.org/licenses/>.
c6c8fea29   Sven Eckelmann   net: Add batman-a...
16
17
18
19
20
   */
  
  #include "main.h"
  #include "routing.h"
  #include "send.h"
c6c8fea29   Sven Eckelmann   net: Add batman-a...
21
22
23
24
25
  #include "soft-interface.h"
  #include "hard-interface.h"
  #include "icmp_socket.h"
  #include "translation-table.h"
  #include "originator.h"
23721387c   Simon Wunderlich   batman-adv: add b...
26
  #include "bridge_loop_avoidance.h"
c384ea3ec   Antonio Quartulli   batman-adv: Distr...
27
  #include "distributed-arp-table.h"
953324776   Martin Hundebøll   batman-adv: netwo...
28
  #include "network-coding.h"
610bfc6bc   Martin Hundebøll   batman-adv: Recei...
29
  #include "fragmentation.h"
c6c8fea29   Sven Eckelmann   net: Add batman-a...
30

c018ad3de   Antonio Quartulli   batman-adv: add t...
31
  #include <linux/if_vlan.h>
63b010371   Sven Eckelmann   batman-adv: Prefi...
32
  static int batadv_route_unicast_packet(struct sk_buff *skb,
56303d34a   Sven Eckelmann   batman-adv: Prefi...
33
  				       struct batadv_hard_iface *recv_if);
a7f6ee949   Simon Wunderlich   batman-adv: remov...
34

7351a4822   Simon Wunderlich   batman-adv: split...
35
36
37
38
39
40
41
42
43
  /**
   * _batadv_update_route - set the router for this originator
   * @bat_priv: the bat priv with all the soft interface information
   * @orig_node: orig node which is to be configured
   * @recv_if: the receive interface for which this route is set
   * @neigh_node: neighbor which should be the next router
   *
   * This function does not perform any error checks
   */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
44
45
  static void _batadv_update_route(struct batadv_priv *bat_priv,
  				 struct batadv_orig_node *orig_node,
7351a4822   Simon Wunderlich   batman-adv: split...
46
  				 struct batadv_hard_iface *recv_if,
56303d34a   Sven Eckelmann   batman-adv: Prefi...
47
  				 struct batadv_neigh_node *neigh_node)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
48
  {
7351a4822   Simon Wunderlich   batman-adv: split...
49
  	struct batadv_orig_ifinfo *orig_ifinfo;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
50
  	struct batadv_neigh_node *curr_router;
e1a5382f9   Linus Lüssing   batman-adv: Make ...
51

7351a4822   Simon Wunderlich   batman-adv: split...
52
53
54
55
56
57
58
59
60
  	orig_ifinfo = batadv_orig_ifinfo_get(orig_node, recv_if);
  	if (!orig_ifinfo)
  		return;
  
  	rcu_read_lock();
  	curr_router = rcu_dereference(orig_ifinfo->router);
  	if (curr_router && !atomic_inc_not_zero(&curr_router->refcount))
  		curr_router = NULL;
  	rcu_read_unlock();
a8e7f4bc3   Marek Lindner   batman-adv: prote...
61

c6c8fea29   Sven Eckelmann   net: Add batman-a...
62
  	/* route deleted */
e1a5382f9   Linus Lüssing   batman-adv: Make ...
63
  	if ((curr_router) && (!neigh_node)) {
39c75a51e   Sven Eckelmann   batman-adv: Prefi...
64
65
66
  		batadv_dbg(BATADV_DBG_ROUTES, bat_priv,
  			   "Deleting route towards: %pM
  ", orig_node->orig);
95fb130d6   Antonio Quartulli   batman-adv: make ...
67
  		batadv_tt_global_del_orig(bat_priv, orig_node, -1,
08c36d3e8   Sven Eckelmann   batman-adv: Prefi...
68
  					  "Deleted route towards originator");
c6c8fea29   Sven Eckelmann   net: Add batman-a...
69

e1a5382f9   Linus Lüssing   batman-adv: Make ...
70
71
  	/* route added */
  	} else if ((!curr_router) && (neigh_node)) {
39c75a51e   Sven Eckelmann   batman-adv: Prefi...
72
  		batadv_dbg(BATADV_DBG_ROUTES, bat_priv,
1eda58bfc   Sven Eckelmann   batman-adv: Prefi...
73
74
75
  			   "Adding route towards: %pM (via %pM)
  ",
  			   orig_node->orig, neigh_node->addr);
e1a5382f9   Linus Lüssing   batman-adv: Make ...
76
  	/* route changed */
bb899b89f   Sven Eckelmann   batman-adv: Ensur...
77
  	} else if (neigh_node && curr_router) {
39c75a51e   Sven Eckelmann   batman-adv: Prefi...
78
  		batadv_dbg(BATADV_DBG_ROUTES, bat_priv,
1eda58bfc   Sven Eckelmann   batman-adv: Prefi...
79
80
81
82
  			   "Changing route towards: %pM (now via %pM - was via %pM)
  ",
  			   orig_node->orig, neigh_node->addr,
  			   curr_router->addr);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
83
  	}
e1a5382f9   Linus Lüssing   batman-adv: Make ...
84
  	if (curr_router)
7d211efc5   Sven Eckelmann   batman-adv: Prefi...
85
  		batadv_neigh_node_free_ref(curr_router);
e1a5382f9   Linus Lüssing   batman-adv: Make ...
86
87
  
  	/* increase refcount of new best neighbor */
44524fcdf   Marek Lindner   batman-adv: Corre...
88
89
  	if (neigh_node && !atomic_inc_not_zero(&neigh_node->refcount))
  		neigh_node = NULL;
e1a5382f9   Linus Lüssing   batman-adv: Make ...
90
91
  
  	spin_lock_bh(&orig_node->neigh_list_lock);
7351a4822   Simon Wunderlich   batman-adv: split...
92
  	rcu_assign_pointer(orig_ifinfo->router, neigh_node);
e1a5382f9   Linus Lüssing   batman-adv: Make ...
93
  	spin_unlock_bh(&orig_node->neigh_list_lock);
7351a4822   Simon Wunderlich   batman-adv: split...
94
  	batadv_orig_ifinfo_free_ref(orig_ifinfo);
e1a5382f9   Linus Lüssing   batman-adv: Make ...
95
96
97
  
  	/* decrease refcount of previous best neighbor */
  	if (curr_router)
7d211efc5   Sven Eckelmann   batman-adv: Prefi...
98
  		batadv_neigh_node_free_ref(curr_router);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
99
  }
7351a4822   Simon Wunderlich   batman-adv: split...
100
101
102
103
104
105
106
  /**
   * batadv_update_route - set the router for this originator
   * @bat_priv: the bat priv with all the soft interface information
   * @orig_node: orig node which is to be configured
   * @recv_if: the receive interface for which this route is set
   * @neigh_node: neighbor which should be the next router
   */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
107
108
  void batadv_update_route(struct batadv_priv *bat_priv,
  			 struct batadv_orig_node *orig_node,
7351a4822   Simon Wunderlich   batman-adv: split...
109
  			 struct batadv_hard_iface *recv_if,
56303d34a   Sven Eckelmann   batman-adv: Prefi...
110
  			 struct batadv_neigh_node *neigh_node)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
111
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
112
  	struct batadv_neigh_node *router = NULL;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
113
114
  
  	if (!orig_node)
e1a5382f9   Linus Lüssing   batman-adv: Make ...
115
  		goto out;
7351a4822   Simon Wunderlich   batman-adv: split...
116
  	router = batadv_orig_router_get(orig_node, recv_if);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
117

e1a5382f9   Linus Lüssing   batman-adv: Make ...
118
  	if (router != neigh_node)
7351a4822   Simon Wunderlich   batman-adv: split...
119
  		_batadv_update_route(bat_priv, orig_node, recv_if, neigh_node);
e1a5382f9   Linus Lüssing   batman-adv: Make ...
120
121
122
  
  out:
  	if (router)
7d211efc5   Sven Eckelmann   batman-adv: Prefi...
123
  		batadv_neigh_node_free_ref(router);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
124
  }
c6c8fea29   Sven Eckelmann   net: Add batman-a...
125
126
127
128
129
  /* checks whether the host restarted and is in the protection time.
   * returns:
   *  0 if the packet is to be accepted
   *  1 if the packet is to be ignored.
   */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
130
  int batadv_window_protected(struct batadv_priv *bat_priv, int32_t seq_num_diff,
30d3c5113   Sven Eckelmann   batman-adv: Prefi...
131
  			    unsigned long *last_reset)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
132
  {
42d0b044b   Sven Eckelmann   batman-adv: Prefi...
133
134
135
136
  	if (seq_num_diff <= -BATADV_TQ_LOCAL_WINDOW_SIZE ||
  	    seq_num_diff >= BATADV_EXPECTED_SEQNO_RANGE) {
  		if (!batadv_has_timed_out(*last_reset,
  					  BATADV_RESET_PROTECTION_MS))
c6c8fea29   Sven Eckelmann   net: Add batman-a...
137
  			return 1;
8c7bf248a   Marek Lindner   batman-adv: refac...
138
139
  
  		*last_reset = jiffies;
39c75a51e   Sven Eckelmann   batman-adv: Prefi...
140
  		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1eda58bfc   Sven Eckelmann   batman-adv: Prefi...
141
142
  			   "old packet received, start protection
  ");
c6c8fea29   Sven Eckelmann   net: Add batman-a...
143
  	}
8c7bf248a   Marek Lindner   batman-adv: refac...
144

c6c8fea29   Sven Eckelmann   net: Add batman-a...
145
146
  	return 0;
  }
30d3c5113   Sven Eckelmann   batman-adv: Prefi...
147
  bool batadv_check_management_packet(struct sk_buff *skb,
56303d34a   Sven Eckelmann   batman-adv: Prefi...
148
  				    struct batadv_hard_iface *hard_iface,
30d3c5113   Sven Eckelmann   batman-adv: Prefi...
149
  				    int header_len)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
150
  {
c6c8fea29   Sven Eckelmann   net: Add batman-a...
151
152
153
  	struct ethhdr *ethhdr;
  
  	/* drop packet if it has not necessary minimum size */
c3e29312c   Marek Lindner   batman-adv: regis...
154
155
  	if (unlikely(!pskb_may_pull(skb, header_len)))
  		return false;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
156

7ed4be952   Antonio Quartulli   batman-adv: use e...
157
  	ethhdr = eth_hdr(skb);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
158
159
160
  
  	/* packet with broadcast indication but unicast recipient */
  	if (!is_broadcast_ether_addr(ethhdr->h_dest))
c3e29312c   Marek Lindner   batman-adv: regis...
161
  		return false;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
162
163
164
  
  	/* packet with broadcast sender address */
  	if (is_broadcast_ether_addr(ethhdr->h_source))
c3e29312c   Marek Lindner   batman-adv: regis...
165
  		return false;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
166
167
168
  
  	/* create a copy of the skb, if needed, to modify it. */
  	if (skb_cow(skb, 0) < 0)
c3e29312c   Marek Lindner   batman-adv: regis...
169
  		return false;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
170
171
172
  
  	/* keep skb linear */
  	if (skb_linearize(skb) < 0)
c3e29312c   Marek Lindner   batman-adv: regis...
173
  		return false;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
174

c3e29312c   Marek Lindner   batman-adv: regis...
175
  	return true;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
176
  }
da6b8c20a   Simon Wunderlich   batman-adv: gener...
177
178
179
180
181
182
183
184
  /**
   * batadv_recv_my_icmp_packet - receive an icmp packet locally
   * @bat_priv: the bat priv with all the soft interface information
   * @skb: icmp packet to process
   *
   * Returns NET_RX_SUCCESS if the packet has been consumed or NET_RX_DROP
   * otherwise.
   */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
185
  static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
da6b8c20a   Simon Wunderlich   batman-adv: gener...
186
  				      struct sk_buff *skb)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
187
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
188
189
  	struct batadv_hard_iface *primary_if = NULL;
  	struct batadv_orig_node *orig_node = NULL;
da6b8c20a   Simon Wunderlich   batman-adv: gener...
190
191
  	struct batadv_icmp_header *icmph;
  	int res, ret = NET_RX_DROP;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
192

da6b8c20a   Simon Wunderlich   batman-adv: gener...
193
  	icmph = (struct batadv_icmp_header *)skb->data;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
194

da6b8c20a   Simon Wunderlich   batman-adv: gener...
195
196
197
198
199
200
201
  	switch (icmph->msg_type) {
  	case BATADV_ECHO_REPLY:
  	case BATADV_DESTINATION_UNREACHABLE:
  	case BATADV_TTL_EXCEEDED:
  		/* receive the packet */
  		if (skb_linearize(skb) < 0)
  			break;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
202

da6b8c20a   Simon Wunderlich   batman-adv: gener...
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
  		batadv_socket_receive_packet(icmph, skb->len);
  		break;
  	case BATADV_ECHO_REQUEST:
  		/* answer echo request (ping) */
  		primary_if = batadv_primary_if_get_selected(bat_priv);
  		if (!primary_if)
  			goto out;
  
  		/* get routing information */
  		orig_node = batadv_orig_hash_find(bat_priv, icmph->orig);
  		if (!orig_node)
  			goto out;
  
  		/* create a copy of the skb, if needed, to modify it. */
  		if (skb_cow(skb, ETH_HLEN) < 0)
  			goto out;
  
  		icmph = (struct batadv_icmp_header *)skb->data;
8fdd01530   Antonio Quartulli   batman-adv: prefe...
221
222
  		ether_addr_copy(icmph->dst, icmph->orig);
  		ether_addr_copy(icmph->orig, primary_if->net_dev->dev_addr);
da6b8c20a   Simon Wunderlich   batman-adv: gener...
223
  		icmph->msg_type = BATADV_ECHO_REPLY;
a40d9b075   Simon Wunderlich   batman-adv: fix h...
224
  		icmph->ttl = BATADV_TTL;
da6b8c20a   Simon Wunderlich   batman-adv: gener...
225
226
227
228
229
230
231
232
  
  		res = batadv_send_skb_to_orig(skb, orig_node, NULL);
  		if (res != NET_XMIT_DROP)
  			ret = NET_RX_SUCCESS;
  
  		break;
  	default:
  		/* drop unknown type */
44524fcdf   Marek Lindner   batman-adv: Corre...
233
  		goto out;
da6b8c20a   Simon Wunderlich   batman-adv: gener...
234
  	}
44524fcdf   Marek Lindner   batman-adv: Corre...
235
  out:
32ae9b221   Marek Lindner   batman-adv: Make ...
236
  	if (primary_if)
e5d89254b   Sven Eckelmann   batman-adv: Prefi...
237
  		batadv_hardif_free_ref(primary_if);
44524fcdf   Marek Lindner   batman-adv: Corre...
238
  	if (orig_node)
7d211efc5   Sven Eckelmann   batman-adv: Prefi...
239
  		batadv_orig_node_free_ref(orig_node);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
240
241
  	return ret;
  }
56303d34a   Sven Eckelmann   batman-adv: Prefi...
242
  static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
63b010371   Sven Eckelmann   batman-adv: Prefi...
243
  					 struct sk_buff *skb)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
244
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
245
246
  	struct batadv_hard_iface *primary_if = NULL;
  	struct batadv_orig_node *orig_node = NULL;
964126901   Sven Eckelmann   batman-adv: Prefi...
247
  	struct batadv_icmp_packet *icmp_packet;
44524fcdf   Marek Lindner   batman-adv: Corre...
248
  	int ret = NET_RX_DROP;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
249

964126901   Sven Eckelmann   batman-adv: Prefi...
250
  	icmp_packet = (struct batadv_icmp_packet *)skb->data;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
251
252
  
  	/* send TTL exceeded if packet is an echo request (traceroute) */
27a417e6b   Antonio Quartulli   batman-adv: fix s...
253
  	if (icmp_packet->msg_type != BATADV_ECHO_REQUEST) {
86ceb3605   Sven Eckelmann   batman-adv: Ignor...
254
255
  		pr_debug("Warning - can't forward icmp packet from %pM to %pM: ttl exceeded
  ",
27a417e6b   Antonio Quartulli   batman-adv: fix s...
256
  			 icmp_packet->orig, icmp_packet->dst);
44524fcdf   Marek Lindner   batman-adv: Corre...
257
  		goto out;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
258
  	}
e5d89254b   Sven Eckelmann   batman-adv: Prefi...
259
  	primary_if = batadv_primary_if_get_selected(bat_priv);
32ae9b221   Marek Lindner   batman-adv: Make ...
260
  	if (!primary_if)
44524fcdf   Marek Lindner   batman-adv: Corre...
261
  		goto out;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
262
263
  
  	/* get routing information */
27a417e6b   Antonio Quartulli   batman-adv: fix s...
264
  	orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->orig);
44524fcdf   Marek Lindner   batman-adv: Corre...
265
  	if (!orig_node)
e1a5382f9   Linus Lüssing   batman-adv: Make ...
266
  		goto out;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
267

44524fcdf   Marek Lindner   batman-adv: Corre...
268
  	/* create a copy of the skb, if needed, to modify it. */
0d125074e   Antonio Quartulli   batman-adv: use E...
269
  	if (skb_cow(skb, ETH_HLEN) < 0)
44524fcdf   Marek Lindner   batman-adv: Corre...
270
  		goto out;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
271

964126901   Sven Eckelmann   batman-adv: Prefi...
272
  	icmp_packet = (struct batadv_icmp_packet *)skb->data;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
273

8fdd01530   Antonio Quartulli   batman-adv: prefe...
274
275
  	ether_addr_copy(icmp_packet->dst, icmp_packet->orig);
  	ether_addr_copy(icmp_packet->orig, primary_if->net_dev->dev_addr);
27a417e6b   Antonio Quartulli   batman-adv: fix s...
276
277
  	icmp_packet->msg_type = BATADV_TTL_EXCEEDED;
  	icmp_packet->ttl = BATADV_TTL;
44524fcdf   Marek Lindner   batman-adv: Corre...
278

e91ecfc64   Martin Hundebøll   batman-adv: Move ...
279
  	if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
bb351ba0b   Martin Hundebøll   batman-adv: Add w...
280
  		ret = NET_RX_SUCCESS;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
281

44524fcdf   Marek Lindner   batman-adv: Corre...
282
  out:
32ae9b221   Marek Lindner   batman-adv: Make ...
283
  	if (primary_if)
e5d89254b   Sven Eckelmann   batman-adv: Prefi...
284
  		batadv_hardif_free_ref(primary_if);
44524fcdf   Marek Lindner   batman-adv: Corre...
285
  	if (orig_node)
7d211efc5   Sven Eckelmann   batman-adv: Prefi...
286
  		batadv_orig_node_free_ref(orig_node);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
287
288
  	return ret;
  }
56303d34a   Sven Eckelmann   batman-adv: Prefi...
289
290
  int batadv_recv_icmp_packet(struct sk_buff *skb,
  			    struct batadv_hard_iface *recv_if)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
291
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
292
  	struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
da6b8c20a   Simon Wunderlich   batman-adv: gener...
293
294
  	struct batadv_icmp_header *icmph;
  	struct batadv_icmp_packet_rr *icmp_packet_rr;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
295
  	struct ethhdr *ethhdr;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
296
  	struct batadv_orig_node *orig_node = NULL;
da6b8c20a   Simon Wunderlich   batman-adv: gener...
297
  	int hdr_size = sizeof(struct batadv_icmp_header);
44524fcdf   Marek Lindner   batman-adv: Corre...
298
  	int ret = NET_RX_DROP;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
299

c6c8fea29   Sven Eckelmann   net: Add batman-a...
300
301
  	/* drop packet if it has not necessary minimum size */
  	if (unlikely(!pskb_may_pull(skb, hdr_size)))
44524fcdf   Marek Lindner   batman-adv: Corre...
302
  		goto out;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
303

7ed4be952   Antonio Quartulli   batman-adv: use e...
304
  	ethhdr = eth_hdr(skb);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
305
306
307
  
  	/* packet with unicast indication but broadcast recipient */
  	if (is_broadcast_ether_addr(ethhdr->h_dest))
44524fcdf   Marek Lindner   batman-adv: Corre...
308
  		goto out;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
309
310
311
  
  	/* packet with broadcast sender address */
  	if (is_broadcast_ether_addr(ethhdr->h_source))
44524fcdf   Marek Lindner   batman-adv: Corre...
312
  		goto out;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
313
314
  
  	/* not for me */
fe8a93b95   Antonio Quartulli   batman-adv: make ...
315
  	if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest))
44524fcdf   Marek Lindner   batman-adv: Corre...
316
  		goto out;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
317

da6b8c20a   Simon Wunderlich   batman-adv: gener...
318
  	icmph = (struct batadv_icmp_header *)skb->data;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
319
320
  
  	/* add record route information if not full */
da6b8c20a   Simon Wunderlich   batman-adv: gener...
321
322
323
324
325
326
327
328
329
330
331
332
333
334
  	if ((icmph->msg_type == BATADV_ECHO_REPLY ||
  	     icmph->msg_type == BATADV_ECHO_REQUEST) &&
  	    (skb->len >= sizeof(struct batadv_icmp_packet_rr))) {
  		if (skb_linearize(skb) < 0)
  			goto out;
  
  		/* create a copy of the skb, if needed, to modify it. */
  		if (skb_cow(skb, ETH_HLEN) < 0)
  			goto out;
  
  		icmph = (struct batadv_icmp_header *)skb->data;
  		icmp_packet_rr = (struct batadv_icmp_packet_rr *)icmph;
  		if (icmp_packet_rr->rr_cur >= BATADV_RR_LEN)
  			goto out;
8fdd01530   Antonio Quartulli   batman-adv: prefe...
335
336
  		ether_addr_copy(icmp_packet_rr->rr[icmp_packet_rr->rr_cur],
  				ethhdr->h_dest);
da6b8c20a   Simon Wunderlich   batman-adv: gener...
337
  		icmp_packet_rr->rr_cur++;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
338
339
340
  	}
  
  	/* packet for me */
da6b8c20a   Simon Wunderlich   batman-adv: gener...
341
342
  	if (batadv_is_my_mac(bat_priv, icmph->dst))
  		return batadv_recv_my_icmp_packet(bat_priv, skb);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
343
344
  
  	/* TTL exceeded */
a40d9b075   Simon Wunderlich   batman-adv: fix h...
345
  	if (icmph->ttl < 2)
63b010371   Sven Eckelmann   batman-adv: Prefi...
346
  		return batadv_recv_icmp_ttl_exceeded(bat_priv, skb);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
347

c6c8fea29   Sven Eckelmann   net: Add batman-a...
348
  	/* get routing information */
da6b8c20a   Simon Wunderlich   batman-adv: gener...
349
  	orig_node = batadv_orig_hash_find(bat_priv, icmph->dst);
44524fcdf   Marek Lindner   batman-adv: Corre...
350
  	if (!orig_node)
e1a5382f9   Linus Lüssing   batman-adv: Make ...
351
  		goto out;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
352

44524fcdf   Marek Lindner   batman-adv: Corre...
353
  	/* create a copy of the skb, if needed, to modify it. */
0d125074e   Antonio Quartulli   batman-adv: use E...
354
  	if (skb_cow(skb, ETH_HLEN) < 0)
44524fcdf   Marek Lindner   batman-adv: Corre...
355
  		goto out;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
356

da6b8c20a   Simon Wunderlich   batman-adv: gener...
357
  	icmph = (struct batadv_icmp_header *)skb->data;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
358

44524fcdf   Marek Lindner   batman-adv: Corre...
359
  	/* decrement ttl */
a40d9b075   Simon Wunderlich   batman-adv: fix h...
360
  	icmph->ttl--;
44524fcdf   Marek Lindner   batman-adv: Corre...
361
362
  
  	/* route it */
e91ecfc64   Martin Hundebøll   batman-adv: Move ...
363
  	if (batadv_send_skb_to_orig(skb, orig_node, recv_if) != NET_XMIT_DROP)
bb351ba0b   Martin Hundebøll   batman-adv: Add w...
364
  		ret = NET_RX_SUCCESS;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
365

44524fcdf   Marek Lindner   batman-adv: Corre...
366
  out:
44524fcdf   Marek Lindner   batman-adv: Corre...
367
  	if (orig_node)
7d211efc5   Sven Eckelmann   batman-adv: Prefi...
368
  		batadv_orig_node_free_ref(orig_node);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
369
370
  	return ret;
  }
f86ce0ad1   Martin Hundebøll   batman-adv: Retur...
371
372
  /**
   * batadv_check_unicast_packet - Check for malformed unicast packets
6e0895c2e   David S. Miller   Merge git://git.k...
373
   * @bat_priv: the bat priv with all the soft interface information
f86ce0ad1   Martin Hundebøll   batman-adv: Retur...
374
375
376
377
378
379
380
381
   * @skb: packet to check
   * @hdr_size: size of header to pull
   *
   * Check for short header and bad addresses in given packet. Returns negative
   * value when check fails and 0 otherwise. The negative value depends on the
   * reason: -ENODATA for bad header, -EBADR for broadcast destination or source,
   * and -EREMOTE for non-local (other host) destination.
   */
fe8a93b95   Antonio Quartulli   batman-adv: make ...
382
383
  static int batadv_check_unicast_packet(struct batadv_priv *bat_priv,
  				       struct sk_buff *skb, int hdr_size)
ff51fd70a   Martin Hundebøll   batman-adv: Move ...
384
385
386
387
388
  {
  	struct ethhdr *ethhdr;
  
  	/* drop packet if it has not necessary minimum size */
  	if (unlikely(!pskb_may_pull(skb, hdr_size)))
f86ce0ad1   Martin Hundebøll   batman-adv: Retur...
389
  		return -ENODATA;
ff51fd70a   Martin Hundebøll   batman-adv: Move ...
390

7ed4be952   Antonio Quartulli   batman-adv: use e...
391
  	ethhdr = eth_hdr(skb);
ff51fd70a   Martin Hundebøll   batman-adv: Move ...
392
393
394
  
  	/* packet with unicast indication but broadcast recipient */
  	if (is_broadcast_ether_addr(ethhdr->h_dest))
f86ce0ad1   Martin Hundebøll   batman-adv: Retur...
395
  		return -EBADR;
ff51fd70a   Martin Hundebøll   batman-adv: Move ...
396
397
398
  
  	/* packet with broadcast sender address */
  	if (is_broadcast_ether_addr(ethhdr->h_source))
f86ce0ad1   Martin Hundebøll   batman-adv: Retur...
399
  		return -EBADR;
ff51fd70a   Martin Hundebøll   batman-adv: Move ...
400
401
  
  	/* not for me */
fe8a93b95   Antonio Quartulli   batman-adv: make ...
402
  	if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest))
f86ce0ad1   Martin Hundebøll   batman-adv: Retur...
403
  		return -EREMOTE;
ff51fd70a   Martin Hundebøll   batman-adv: Move ...
404
405
406
  
  	return 0;
  }
f6c8b7117   Simon Wunderlich   batman-adv: remov...
407
408
409
410
411
412
413
414
  /**
   * batadv_find_router - find a suitable router for this originator
   * @bat_priv: the bat priv with all the soft interface information
   * @orig_node: the destination node
   * @recv_if: pointer to interface this packet was received on
   *
   * Returns the router which should be used for this orig_node on
   * this interface, or NULL if not available.
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
415
   */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
416
417
418
  struct batadv_neigh_node *
  batadv_find_router(struct batadv_priv *bat_priv,
  		   struct batadv_orig_node *orig_node,
f3b3d9018   Simon Wunderlich   batman-adv: add b...
419
  		   struct batadv_hard_iface *recv_if)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
420
  {
f3b3d9018   Simon Wunderlich   batman-adv: add b...
421
422
423
424
425
426
427
428
429
  	struct batadv_algo_ops *bao = bat_priv->bat_algo_ops;
  	struct batadv_neigh_node *first_candidate_router = NULL;
  	struct batadv_neigh_node *next_candidate_router = NULL;
  	struct batadv_neigh_node *router, *cand_router = NULL;
  	struct batadv_neigh_node *last_cand_router = NULL;
  	struct batadv_orig_ifinfo *cand, *first_candidate = NULL;
  	struct batadv_orig_ifinfo *next_candidate = NULL;
  	struct batadv_orig_ifinfo *last_candidate;
  	bool last_candidate_found = false;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
430
431
432
  
  	if (!orig_node)
  		return NULL;
7351a4822   Simon Wunderlich   batman-adv: split...
433
  	router = batadv_orig_router_get(orig_node, recv_if);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
434

f3b3d9018   Simon Wunderlich   batman-adv: add b...
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
  	/* only consider bonding for recv_if == BATADV_IF_DEFAULT (first hop)
  	 * and if activated.
  	 */
  	if (recv_if == BATADV_IF_DEFAULT || !atomic_read(&bat_priv->bonding) ||
  	    !router)
  		return router;
  
  	/* bonding: loop through the list of possible routers found
  	 * for the various outgoing interfaces and find a candidate after
  	 * the last chosen bonding candidate (next_candidate). If no such
  	 * router is found, use the first candidate found (the previously
  	 * chosen bonding candidate might have been the last one in the list).
  	 * If this can't be found either, return the previously choosen
  	 * router - obviously there are no other candidates.
  	 */
  	rcu_read_lock();
  	last_candidate = orig_node->last_bonding_candidate;
  	if (last_candidate)
  		last_cand_router = rcu_dereference(last_candidate->router);
  
  	hlist_for_each_entry_rcu(cand, &orig_node->ifinfo_list, list) {
  		/* acquire some structures and references ... */
  		if (!atomic_inc_not_zero(&cand->refcount))
  			continue;
  
  		cand_router = rcu_dereference(cand->router);
  		if (!cand_router)
  			goto next;
  
  		if (!atomic_inc_not_zero(&cand_router->refcount)) {
  			cand_router = NULL;
  			goto next;
  		}
  
  		/* alternative candidate should be good enough to be
  		 * considered
  		 */
  		if (!bao->bat_neigh_is_equiv_or_better(cand_router,
  						       cand->if_outgoing,
  						       router, recv_if))
  			goto next;
  
  		/* don't use the same router twice */
  		if (last_cand_router == cand_router)
  			goto next;
  
  		/* mark the first possible candidate */
  		if (!first_candidate) {
  			atomic_inc(&cand_router->refcount);
  			atomic_inc(&cand->refcount);
  			first_candidate = cand;
  			first_candidate_router = cand_router;
  		}
  
  		/* check if the loop has already passed the previously selected
  		 * candidate ... this function should select the next candidate
  		 * AFTER the previously used bonding candidate.
  		 */
  		if (!last_candidate || last_candidate_found) {
  			next_candidate = cand;
  			next_candidate_router = cand_router;
  			break;
  		}
  
  		if (last_candidate == cand)
  			last_candidate_found = true;
  next:
  		/* free references */
  		if (cand_router) {
  			batadv_neigh_node_free_ref(cand_router);
  			cand_router = NULL;
  		}
  		batadv_orig_ifinfo_free_ref(cand);
  	}
  	rcu_read_unlock();
  
  	/* last_bonding_candidate is reset below, remove the old reference. */
  	if (orig_node->last_bonding_candidate)
  		batadv_orig_ifinfo_free_ref(orig_node->last_bonding_candidate);
  
  	/* After finding candidates, handle the three cases:
  	 * 1) there is a next candidate, use that
  	 * 2) there is no next candidate, use the first of the list
  	 * 3) there is no candidate at all, return the default router
  	 */
  	if (next_candidate) {
  		batadv_neigh_node_free_ref(router);
  
  		/* remove references to first candidate, we don't need it. */
  		if (first_candidate) {
  			batadv_neigh_node_free_ref(first_candidate_router);
  			batadv_orig_ifinfo_free_ref(first_candidate);
  		}
  		router = next_candidate_router;
  		orig_node->last_bonding_candidate = next_candidate;
  	} else if (first_candidate) {
  		batadv_neigh_node_free_ref(router);
  
  		/* refcounting has already been done in the loop above. */
  		router = first_candidate_router;
  		orig_node->last_bonding_candidate = first_candidate;
  	} else {
  		orig_node->last_bonding_candidate = NULL;
  	}
f6c8b7117   Simon Wunderlich   batman-adv: remov...
539

c6c8fea29   Sven Eckelmann   net: Add batman-a...
540
541
  	return router;
  }
63b010371   Sven Eckelmann   batman-adv: Prefi...
542
  static int batadv_route_unicast_packet(struct sk_buff *skb,
56303d34a   Sven Eckelmann   batman-adv: Prefi...
543
  				       struct batadv_hard_iface *recv_if)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
544
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
545
546
  	struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
  	struct batadv_orig_node *orig_node = NULL;
964126901   Sven Eckelmann   batman-adv: Prefi...
547
  	struct batadv_unicast_packet *unicast_packet;
7ed4be952   Antonio Quartulli   batman-adv: use e...
548
  	struct ethhdr *ethhdr = eth_hdr(skb);
c54f38c9a   Simon Wunderlich   batman-adv: set s...
549
  	int res, hdr_len, ret = NET_RX_DROP;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
550

964126901   Sven Eckelmann   batman-adv: Prefi...
551
  	unicast_packet = (struct batadv_unicast_packet *)skb->data;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
552
553
  
  	/* TTL exceeded */
a40d9b075   Simon Wunderlich   batman-adv: fix h...
554
  	if (unicast_packet->ttl < 2) {
86ceb3605   Sven Eckelmann   batman-adv: Ignor...
555
556
557
  		pr_debug("Warning - can't forward unicast packet from %pM to %pM: ttl exceeded
  ",
  			 ethhdr->h_source, unicast_packet->dest);
44524fcdf   Marek Lindner   batman-adv: Corre...
558
  		goto out;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
559
560
561
  	}
  
  	/* get routing information */
da641193d   Sven Eckelmann   batman-adv: Prefi...
562
  	orig_node = batadv_orig_hash_find(bat_priv, unicast_packet->dest);
7aadf889e   Marek Lindner   batman-adv: remov...
563

44524fcdf   Marek Lindner   batman-adv: Corre...
564
  	if (!orig_node)
b5a6f69c5   Antonio Quartulli   batman-adv: orig_...
565
  		goto out;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
566

c6c8fea29   Sven Eckelmann   net: Add batman-a...
567
  	/* create a copy of the skb, if needed, to modify it. */
0d125074e   Antonio Quartulli   batman-adv: use E...
568
  	if (skb_cow(skb, ETH_HLEN) < 0)
44524fcdf   Marek Lindner   batman-adv: Corre...
569
  		goto out;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
570

c6c8fea29   Sven Eckelmann   net: Add batman-a...
571
  	/* decrement ttl */
f097e25db   Martin Hundebøll   batman-adv: Remov...
572
  	unicast_packet = (struct batadv_unicast_packet *)skb->data;
a40d9b075   Simon Wunderlich   batman-adv: fix h...
573
  	unicast_packet->ttl--;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
574

a40d9b075   Simon Wunderlich   batman-adv: fix h...
575
  	switch (unicast_packet->packet_type) {
c54f38c9a   Simon Wunderlich   batman-adv: set s...
576
577
578
579
580
581
582
583
584
585
586
587
588
589
  	case BATADV_UNICAST_4ADDR:
  		hdr_len = sizeof(struct batadv_unicast_4addr_packet);
  		break;
  	case BATADV_UNICAST:
  		hdr_len = sizeof(struct batadv_unicast_packet);
  		break;
  	default:
  		/* other packet types not supported - yet */
  		hdr_len = -1;
  		break;
  	}
  
  	if (hdr_len > 0)
  		batadv_skb_set_priority(skb, hdr_len);
e91ecfc64   Martin Hundebøll   batman-adv: Move ...
590
  	res = batadv_send_skb_to_orig(skb, orig_node, recv_if);
953324776   Martin Hundebøll   batman-adv: netwo...
591

e91ecfc64   Martin Hundebøll   batman-adv: Move ...
592
593
594
  	/* translate transmit result into receive result */
  	if (res == NET_XMIT_SUCCESS) {
  		/* skb was transmitted and consumed */
953324776   Martin Hundebøll   batman-adv: netwo...
595
596
597
  		batadv_inc_counter(bat_priv, BATADV_CNT_FORWARD);
  		batadv_add_counter(bat_priv, BATADV_CNT_FORWARD_BYTES,
  				   skb->len + ETH_HLEN);
e91ecfc64   Martin Hundebøll   batman-adv: Move ...
598
599
600
601
602
  
  		ret = NET_RX_SUCCESS;
  	} else if (res == NET_XMIT_POLICED) {
  		/* skb was buffered and consumed */
  		ret = NET_RX_SUCCESS;
953324776   Martin Hundebøll   batman-adv: netwo...
603
  	}
c6c8fea29   Sven Eckelmann   net: Add batman-a...
604

44524fcdf   Marek Lindner   batman-adv: Corre...
605
  out:
44524fcdf   Marek Lindner   batman-adv: Corre...
606
  	if (orig_node)
7d211efc5   Sven Eckelmann   batman-adv: Prefi...
607
  		batadv_orig_node_free_ref(orig_node);
44524fcdf   Marek Lindner   batman-adv: Corre...
608
  	return ret;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
609
  }
7c1fd91da   Antonio Quartulli   batman-adv: subst...
610
611
612
613
614
  /**
   * batadv_reroute_unicast_packet - update the unicast header for re-routing
   * @bat_priv: the bat priv with all the soft interface information
   * @unicast_packet: the unicast header to be updated
   * @dst_addr: the payload destination
c018ad3de   Antonio Quartulli   batman-adv: add t...
615
   * @vid: VLAN identifier
7c1fd91da   Antonio Quartulli   batman-adv: subst...
616
617
618
619
620
621
622
623
624
625
   *
   * Search the translation table for dst_addr and update the unicast header with
   * the new corresponding information (originator address where the destination
   * client currently is and its known TTVN)
   *
   * Returns true if the packet header has been updated, false otherwise
   */
  static bool
  batadv_reroute_unicast_packet(struct batadv_priv *bat_priv,
  			      struct batadv_unicast_packet *unicast_packet,
c018ad3de   Antonio Quartulli   batman-adv: add t...
626
  			      uint8_t *dst_addr, unsigned short vid)
7c1fd91da   Antonio Quartulli   batman-adv: subst...
627
628
629
630
631
  {
  	struct batadv_orig_node *orig_node = NULL;
  	struct batadv_hard_iface *primary_if = NULL;
  	bool ret = false;
  	uint8_t *orig_addr, orig_ttvn;
c018ad3de   Antonio Quartulli   batman-adv: add t...
632
  	if (batadv_is_my_client(bat_priv, dst_addr, vid)) {
7c1fd91da   Antonio Quartulli   batman-adv: subst...
633
634
635
636
637
638
  		primary_if = batadv_primary_if_get_selected(bat_priv);
  		if (!primary_if)
  			goto out;
  		orig_addr = primary_if->net_dev->dev_addr;
  		orig_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
  	} else {
c018ad3de   Antonio Quartulli   batman-adv: add t...
639
640
  		orig_node = batadv_transtable_search(bat_priv, NULL, dst_addr,
  						     vid);
7c1fd91da   Antonio Quartulli   batman-adv: subst...
641
642
643
644
645
646
647
648
649
650
651
  		if (!orig_node)
  			goto out;
  
  		if (batadv_compare_eth(orig_node->orig, unicast_packet->dest))
  			goto out;
  
  		orig_addr = orig_node->orig;
  		orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
  	}
  
  	/* update the packet header */
8fdd01530   Antonio Quartulli   batman-adv: prefe...
652
  	ether_addr_copy(unicast_packet->dest, orig_addr);
7c1fd91da   Antonio Quartulli   batman-adv: subst...
653
654
655
656
657
658
659
660
661
662
663
  	unicast_packet->ttvn = orig_ttvn;
  
  	ret = true;
  out:
  	if (primary_if)
  		batadv_hardif_free_ref(primary_if);
  	if (orig_node)
  		batadv_orig_node_free_ref(orig_node);
  
  	return ret;
  }
56303d34a   Sven Eckelmann   batman-adv: Prefi...
664
  static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
dd981ab09   Antonio Quartulli   batman-adv: use t...
665
  				     struct sk_buff *skb, int hdr_len) {
c018ad3de   Antonio Quartulli   batman-adv: add t...
666
667
  	struct batadv_unicast_packet *unicast_packet;
  	struct batadv_hard_iface *primary_if;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
668
  	struct batadv_orig_node *orig_node;
c018ad3de   Antonio Quartulli   batman-adv: add t...
669
  	uint8_t curr_ttvn, old_ttvn;
a73105b8d   Antonio Quartulli   batman-adv: impro...
670
  	struct ethhdr *ethhdr;
c018ad3de   Antonio Quartulli   batman-adv: add t...
671
  	unsigned short vid;
3e34819e0   Sven Eckelmann   batman-adv: Prefi...
672
  	int is_old_ttvn;
a73105b8d   Antonio Quartulli   batman-adv: impro...
673

b8fcfa42e   Antonio Quartulli   batman-adv: check...
674
  	/* check if there is enough data before accessing it */
f1791425c   Antonio Quartulli   batman-adv: prope...
675
  	if (!pskb_may_pull(skb, hdr_len + ETH_HLEN))
b8fcfa42e   Antonio Quartulli   batman-adv: check...
676
677
678
679
  		return 0;
  
  	/* create a copy of the skb (in case of for re-routing) to modify it. */
  	if (skb_cow(skb, sizeof(*unicast_packet)) < 0)
a73105b8d   Antonio Quartulli   batman-adv: impro...
680
  		return 0;
964126901   Sven Eckelmann   batman-adv: Prefi...
681
  	unicast_packet = (struct batadv_unicast_packet *)skb->data;
c018ad3de   Antonio Quartulli   batman-adv: add t...
682
  	vid = batadv_get_vid(skb, hdr_len);
dd981ab09   Antonio Quartulli   batman-adv: use t...
683
  	ethhdr = (struct ethhdr *)(skb->data + hdr_len);
a73105b8d   Antonio Quartulli   batman-adv: impro...
684

7c1fd91da   Antonio Quartulli   batman-adv: subst...
685
686
687
688
689
  	/* check if the destination client was served by this node and it is now
  	 * roaming. In this case, it means that the node has got a ROAM_ADV
  	 * message and that it knows the new destination in the mesh to re-route
  	 * the packet to
  	 */
c018ad3de   Antonio Quartulli   batman-adv: add t...
690
  	if (batadv_tt_local_client_is_roaming(bat_priv, ethhdr->h_dest, vid)) {
7c1fd91da   Antonio Quartulli   batman-adv: subst...
691
  		if (batadv_reroute_unicast_packet(bat_priv, unicast_packet,
c018ad3de   Antonio Quartulli   batman-adv: add t...
692
  						  ethhdr->h_dest, vid))
7c1fd91da   Antonio Quartulli   batman-adv: subst...
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
  			net_ratelimited_function(batadv_dbg, BATADV_DBG_TT,
  						 bat_priv,
  						 "Rerouting unicast packet to %pM (dst=%pM): Local Roaming
  ",
  						 unicast_packet->dest,
  						 ethhdr->h_dest);
  		/* at this point the mesh destination should have been
  		 * substituted with the originator address found in the global
  		 * table. If not, let the packet go untouched anyway because
  		 * there is nothing the node can do
  		 */
  		return 1;
  	}
  
  	/* retrieve the TTVN known by this node for the packet destination. This
  	 * value is used later to check if the node which sent (or re-routed
  	 * last time) the packet had an updated information or not
  	 */
  	curr_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
fe8a93b95   Antonio Quartulli   batman-adv: make ...
712
  	if (!batadv_is_my_mac(bat_priv, unicast_packet->dest)) {
da641193d   Sven Eckelmann   batman-adv: Prefi...
713
714
  		orig_node = batadv_orig_hash_find(bat_priv,
  						  unicast_packet->dest);
7c1fd91da   Antonio Quartulli   batman-adv: subst...
715
716
717
718
  		/* if it is not possible to find the orig_node representing the
  		 * destination, the packet can immediately be dropped as it will
  		 * not be possible to deliver it
  		 */
a73105b8d   Antonio Quartulli   batman-adv: impro...
719
720
721
722
  		if (!orig_node)
  			return 0;
  
  		curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
7d211efc5   Sven Eckelmann   batman-adv: Prefi...
723
  		batadv_orig_node_free_ref(orig_node);
a73105b8d   Antonio Quartulli   batman-adv: impro...
724
  	}
7c1fd91da   Antonio Quartulli   batman-adv: subst...
725
726
727
  	/* check if the TTVN contained in the packet is fresher than what the
  	 * node knows
  	 */
3e34819e0   Sven Eckelmann   batman-adv: Prefi...
728
  	is_old_ttvn = batadv_seq_before(unicast_packet->ttvn, curr_ttvn);
7c1fd91da   Antonio Quartulli   batman-adv: subst...
729
730
  	if (!is_old_ttvn)
  		return 1;
a73105b8d   Antonio Quartulli   batman-adv: impro...
731

7c1fd91da   Antonio Quartulli   batman-adv: subst...
732
733
734
735
736
737
  	old_ttvn = unicast_packet->ttvn;
  	/* the packet was forged based on outdated network information. Its
  	 * destination can possibly be updated and forwarded towards the new
  	 * target host
  	 */
  	if (batadv_reroute_unicast_packet(bat_priv, unicast_packet,
c018ad3de   Antonio Quartulli   batman-adv: add t...
738
  					  ethhdr->h_dest, vid)) {
7c1fd91da   Antonio Quartulli   batman-adv: subst...
739
740
741
742
743
744
745
  		net_ratelimited_function(batadv_dbg, BATADV_DBG_TT, bat_priv,
  					 "Rerouting unicast packet to %pM (dst=%pM): TTVN mismatch old_ttvn=%u new_ttvn=%u
  ",
  					 unicast_packet->dest, ethhdr->h_dest,
  					 old_ttvn, curr_ttvn);
  		return 1;
  	}
3275e7cc8   Antonio Quartulli   batman-adv: impro...
746

7c1fd91da   Antonio Quartulli   batman-adv: subst...
747
748
749
750
  	/* the packet has not been re-routed: either the destination is
  	 * currently served by this node or there is no destination at all and
  	 * it is possible to drop the packet
  	 */
c018ad3de   Antonio Quartulli   batman-adv: add t...
751
  	if (!batadv_is_my_client(bat_priv, ethhdr->h_dest, vid))
7c1fd91da   Antonio Quartulli   batman-adv: subst...
752
  		return 0;
3275e7cc8   Antonio Quartulli   batman-adv: impro...
753

7c1fd91da   Antonio Quartulli   batman-adv: subst...
754
755
756
757
758
759
  	/* update the header in order to let the packet be delivered to this
  	 * node's soft interface
  	 */
  	primary_if = batadv_primary_if_get_selected(bat_priv);
  	if (!primary_if)
  		return 0;
a73105b8d   Antonio Quartulli   batman-adv: impro...
760

8fdd01530   Antonio Quartulli   batman-adv: prefe...
761
  	ether_addr_copy(unicast_packet->dest, primary_if->net_dev->dev_addr);
7c1fd91da   Antonio Quartulli   batman-adv: subst...
762
763
764
765
  
  	batadv_hardif_free_ref(primary_if);
  
  	unicast_packet->ttvn = curr_ttvn;
a73105b8d   Antonio Quartulli   batman-adv: impro...
766

a73105b8d   Antonio Quartulli   batman-adv: impro...
767
768
  	return 1;
  }
a1f1ac5c4   Simon Wunderlich   batman-adv: reord...
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
  /**
   * batadv_recv_unhandled_unicast_packet - receive and process packets which
   *	are in the unicast number space but not yet known to the implementation
   * @skb: unicast tvlv packet to process
   * @recv_if: pointer to interface this packet was received on
   *
   * Returns NET_RX_SUCCESS if the packet has been consumed or NET_RX_DROP
   * otherwise.
   */
  int batadv_recv_unhandled_unicast_packet(struct sk_buff *skb,
  					 struct batadv_hard_iface *recv_if)
  {
  	struct batadv_unicast_packet *unicast_packet;
  	struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
  	int check, hdr_size = sizeof(*unicast_packet);
  
  	check = batadv_check_unicast_packet(bat_priv, skb, hdr_size);
  	if (check < 0)
  		return NET_RX_DROP;
  
  	/* we don't know about this type, drop it. */
  	unicast_packet = (struct batadv_unicast_packet *)skb->data;
  	if (batadv_is_my_mac(bat_priv, unicast_packet->dest))
  		return NET_RX_DROP;
  
  	return batadv_route_unicast_packet(skb, recv_if);
  }
56303d34a   Sven Eckelmann   batman-adv: Prefi...
796
797
  int batadv_recv_unicast_packet(struct sk_buff *skb,
  			       struct batadv_hard_iface *recv_if)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
798
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
799
  	struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
964126901   Sven Eckelmann   batman-adv: Prefi...
800
  	struct batadv_unicast_packet *unicast_packet;
4046b24af   Martin Hundebøll   batman-adv: Add g...
801
  	struct batadv_unicast_4addr_packet *unicast_4addr_packet;
9affec6be   Antonio Quartulli   batman-adv: enabl...
802
803
  	uint8_t *orig_addr;
  	struct batadv_orig_node *orig_node = NULL;
612d2b4fe   Martin Hundebøll   batman-adv: netwo...
804
  	int check, hdr_size = sizeof(*unicast_packet);
c384ea3ec   Antonio Quartulli   batman-adv: Distr...
805
  	bool is4addr;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
806

7cdcf6ddd   Antonio Quartulli   batman-adv: add U...
807
  	unicast_packet = (struct batadv_unicast_packet *)skb->data;
4046b24af   Martin Hundebøll   batman-adv: Add g...
808
  	unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
7cdcf6ddd   Antonio Quartulli   batman-adv: add U...
809

a40d9b075   Simon Wunderlich   batman-adv: fix h...
810
  	is4addr = unicast_packet->packet_type == BATADV_UNICAST_4ADDR;
7cdcf6ddd   Antonio Quartulli   batman-adv: add U...
811
  	/* the caller function should have already pulled 2 bytes */
c384ea3ec   Antonio Quartulli   batman-adv: Distr...
812
  	if (is4addr)
4046b24af   Martin Hundebøll   batman-adv: Add g...
813
  		hdr_size = sizeof(*unicast_4addr_packet);
7cdcf6ddd   Antonio Quartulli   batman-adv: add U...
814

612d2b4fe   Martin Hundebøll   batman-adv: netwo...
815
  	/* function returns -EREMOTE for promiscuous packets */
6e0895c2e   David S. Miller   Merge git://git.k...
816
  	check = batadv_check_unicast_packet(bat_priv, skb, hdr_size);
612d2b4fe   Martin Hundebøll   batman-adv: netwo...
817
818
819
820
821
822
823
824
  
  	/* Even though the packet is not for us, we might save it to use for
  	 * decoding a later received coded packet
  	 */
  	if (check == -EREMOTE)
  		batadv_nc_skb_store_sniffed_unicast(bat_priv, skb);
  
  	if (check < 0)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
825
  		return NET_RX_DROP;
dd981ab09   Antonio Quartulli   batman-adv: use t...
826
  	if (!batadv_check_unicast_ttvn(bat_priv, skb, hdr_size))
a73105b8d   Antonio Quartulli   batman-adv: impro...
827
  		return NET_RX_DROP;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
828
  	/* packet for me */
fe8a93b95   Antonio Quartulli   batman-adv: make ...
829
  	if (batadv_is_my_mac(bat_priv, unicast_packet->dest)) {
9affec6be   Antonio Quartulli   batman-adv: enabl...
830
  		if (is4addr) {
4046b24af   Martin Hundebøll   batman-adv: Add g...
831
832
  			batadv_dat_inc_counter(bat_priv,
  					       unicast_4addr_packet->subtype);
9affec6be   Antonio Quartulli   batman-adv: enabl...
833
834
835
  			orig_addr = unicast_4addr_packet->src;
  			orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
  		}
4046b24af   Martin Hundebøll   batman-adv: Add g...
836

c384ea3ec   Antonio Quartulli   batman-adv: Distr...
837
838
839
840
841
842
  		if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb,
  							  hdr_size))
  			goto rx_success;
  		if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb,
  							hdr_size))
  			goto rx_success;
371351731   Antonio Quartulli   batman-adv: chang...
843
  		batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size,
9affec6be   Antonio Quartulli   batman-adv: enabl...
844
  				    orig_node);
371351731   Antonio Quartulli   batman-adv: chang...
845

c384ea3ec   Antonio Quartulli   batman-adv: Distr...
846
  rx_success:
9affec6be   Antonio Quartulli   batman-adv: enabl...
847
848
  		if (orig_node)
  			batadv_orig_node_free_ref(orig_node);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
849
850
  		return NET_RX_SUCCESS;
  	}
63b010371   Sven Eckelmann   batman-adv: Prefi...
851
  	return batadv_route_unicast_packet(skb, recv_if);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
852
  }
ef2615774   Marek Lindner   batman-adv: tvlv ...
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
  /**
   * batadv_recv_unicast_tvlv - receive and process unicast tvlv packets
   * @skb: unicast tvlv packet to process
   * @recv_if: pointer to interface this packet was received on
   * @dst_addr: the payload destination
   *
   * Returns NET_RX_SUCCESS if the packet has been consumed or NET_RX_DROP
   * otherwise.
   */
  int batadv_recv_unicast_tvlv(struct sk_buff *skb,
  			     struct batadv_hard_iface *recv_if)
  {
  	struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
  	struct batadv_unicast_tvlv_packet *unicast_tvlv_packet;
  	unsigned char *tvlv_buff;
  	uint16_t tvlv_buff_len;
  	int hdr_size = sizeof(*unicast_tvlv_packet);
  	int ret = NET_RX_DROP;
  
  	if (batadv_check_unicast_packet(bat_priv, skb, hdr_size) < 0)
  		return NET_RX_DROP;
  
  	/* the header is likely to be modified while forwarding */
  	if (skb_cow(skb, hdr_size) < 0)
  		return NET_RX_DROP;
  
  	/* packet needs to be linearized to access the tvlv content */
  	if (skb_linearize(skb) < 0)
  		return NET_RX_DROP;
  
  	unicast_tvlv_packet = (struct batadv_unicast_tvlv_packet *)skb->data;
  
  	tvlv_buff = (unsigned char *)(skb->data + hdr_size);
  	tvlv_buff_len = ntohs(unicast_tvlv_packet->tvlv_len);
  
  	if (tvlv_buff_len > skb->len - hdr_size)
  		return NET_RX_DROP;
  
  	ret = batadv_tvlv_containers_process(bat_priv, false, NULL,
  					     unicast_tvlv_packet->src,
  					     unicast_tvlv_packet->dst,
  					     tvlv_buff, tvlv_buff_len);
  
  	if (ret != NET_RX_SUCCESS)
  		ret = batadv_route_unicast_packet(skb, recv_if);
05c3c8a63   Antonio Quartulli   batman-adv: free ...
898
899
  	else
  		consume_skb(skb);
ef2615774   Marek Lindner   batman-adv: tvlv ...
900
901
902
  
  	return ret;
  }
c6c8fea29   Sven Eckelmann   net: Add batman-a...
903

610bfc6bc   Martin Hundebøll   batman-adv: Recei...
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
  /**
   * batadv_recv_frag_packet - process received fragment
   * @skb: the received fragment
   * @recv_if: interface that the skb is received on
   *
   * This function does one of the three following things: 1) Forward fragment, if
   * the assembled packet will exceed our MTU; 2) Buffer fragment, if we till
   * lack further fragments; 3) Merge fragments, if we have all needed parts.
   *
   * Return NET_RX_DROP if the skb is not consumed, NET_RX_SUCCESS otherwise.
   */
  int batadv_recv_frag_packet(struct sk_buff *skb,
  			    struct batadv_hard_iface *recv_if)
  {
  	struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
  	struct batadv_orig_node *orig_node_src = NULL;
  	struct batadv_frag_packet *frag_packet;
  	int ret = NET_RX_DROP;
  
  	if (batadv_check_unicast_packet(bat_priv, skb,
  					sizeof(*frag_packet)) < 0)
  		goto out;
  
  	frag_packet = (struct batadv_frag_packet *)skb->data;
  	orig_node_src = batadv_orig_hash_find(bat_priv, frag_packet->orig);
  	if (!orig_node_src)
  		goto out;
  
  	/* Route the fragment if it is not for us and too big to be merged. */
  	if (!batadv_is_my_mac(bat_priv, frag_packet->dest) &&
  	    batadv_frag_skb_fwd(skb, recv_if, orig_node_src)) {
  		ret = NET_RX_SUCCESS;
  		goto out;
  	}
  
  	batadv_inc_counter(bat_priv, BATADV_CNT_FRAG_RX);
  	batadv_add_counter(bat_priv, BATADV_CNT_FRAG_RX_BYTES, skb->len);
  
  	/* Add fragment to buffer and merge if possible. */
  	if (!batadv_frag_skb_buffer(&skb, orig_node_src))
  		goto out;
  
  	/* Deliver merged packet to the appropriate handler, if it was
  	 * merged
  	 */
  	if (skb)
  		batadv_batman_skb_recv(skb, recv_if->net_dev,
  				       &recv_if->batman_adv_ptype, NULL);
  
  	ret = NET_RX_SUCCESS;
  
  out:
  	if (orig_node_src)
  		batadv_orig_node_free_ref(orig_node_src);
  
  	return ret;
  }
56303d34a   Sven Eckelmann   batman-adv: Prefi...
961
962
  int batadv_recv_bcast_packet(struct sk_buff *skb,
  			     struct batadv_hard_iface *recv_if)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
963
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
964
965
  	struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
  	struct batadv_orig_node *orig_node = NULL;
964126901   Sven Eckelmann   batman-adv: Prefi...
966
  	struct batadv_bcast_packet *bcast_packet;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
967
  	struct ethhdr *ethhdr;
704509b8d   Sven Eckelmann   batman-adv: Calcu...
968
  	int hdr_size = sizeof(*bcast_packet);
f3e0008f0   Marek Lindner   batman-adv: make ...
969
  	int ret = NET_RX_DROP;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
970
  	int32_t seq_diff;
3fba7325b   Antonio Quartulli   batman-adv: don't...
971
  	uint32_t seqno;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
972
973
974
  
  	/* drop packet if it has not necessary minimum size */
  	if (unlikely(!pskb_may_pull(skb, hdr_size)))
f3e0008f0   Marek Lindner   batman-adv: make ...
975
  		goto out;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
976

7ed4be952   Antonio Quartulli   batman-adv: use e...
977
  	ethhdr = eth_hdr(skb);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
978
979
980
  
  	/* packet with broadcast indication but unicast recipient */
  	if (!is_broadcast_ether_addr(ethhdr->h_dest))
f3e0008f0   Marek Lindner   batman-adv: make ...
981
  		goto out;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
982
983
984
  
  	/* packet with broadcast sender address */
  	if (is_broadcast_ether_addr(ethhdr->h_source))
f3e0008f0   Marek Lindner   batman-adv: make ...
985
  		goto out;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
986
987
  
  	/* ignore broadcasts sent by myself */
fe8a93b95   Antonio Quartulli   batman-adv: make ...
988
  	if (batadv_is_my_mac(bat_priv, ethhdr->h_source))
f3e0008f0   Marek Lindner   batman-adv: make ...
989
  		goto out;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
990

964126901   Sven Eckelmann   batman-adv: Prefi...
991
  	bcast_packet = (struct batadv_bcast_packet *)skb->data;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
992
993
  
  	/* ignore broadcasts originated by myself */
fe8a93b95   Antonio Quartulli   batman-adv: make ...
994
  	if (batadv_is_my_mac(bat_priv, bcast_packet->orig))
f3e0008f0   Marek Lindner   batman-adv: make ...
995
  		goto out;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
996

a40d9b075   Simon Wunderlich   batman-adv: fix h...
997
  	if (bcast_packet->ttl < 2)
f3e0008f0   Marek Lindner   batman-adv: make ...
998
  		goto out;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
999

da641193d   Sven Eckelmann   batman-adv: Prefi...
1000
  	orig_node = batadv_orig_hash_find(bat_priv, bcast_packet->orig);
f3e0008f0   Marek Lindner   batman-adv: make ...
1001
1002
  
  	if (!orig_node)
b5a6f69c5   Antonio Quartulli   batman-adv: orig_...
1003
  		goto out;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1004

f3e0008f0   Marek Lindner   batman-adv: make ...
1005
  	spin_lock_bh(&orig_node->bcast_seqno_lock);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1006

3fba7325b   Antonio Quartulli   batman-adv: don't...
1007
  	seqno = ntohl(bcast_packet->seqno);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1008
  	/* check whether the packet is a duplicate */
9b4a1159d   Sven Eckelmann   batman-adv: Prefi...
1009
  	if (batadv_test_bit(orig_node->bcast_bits, orig_node->last_bcast_seqno,
3fba7325b   Antonio Quartulli   batman-adv: don't...
1010
  			    seqno))
f3e0008f0   Marek Lindner   batman-adv: make ...
1011
  		goto spin_unlock;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1012

3fba7325b   Antonio Quartulli   batman-adv: don't...
1013
  	seq_diff = seqno - orig_node->last_bcast_seqno;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1014
1015
  
  	/* check whether the packet is old and the host just restarted. */
30d3c5113   Sven Eckelmann   batman-adv: Prefi...
1016
1017
  	if (batadv_window_protected(bat_priv, seq_diff,
  				    &orig_node->bcast_seqno_reset))
f3e0008f0   Marek Lindner   batman-adv: make ...
1018
  		goto spin_unlock;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1019
1020
  
  	/* mark broadcast in flood history, update window position
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
1021
1022
  	 * if required.
  	 */
0f5f93226   Sven Eckelmann   batman-adv: Prefi...
1023
  	if (batadv_bit_get_packet(bat_priv, orig_node->bcast_bits, seq_diff, 1))
3fba7325b   Antonio Quartulli   batman-adv: don't...
1024
  		orig_node->last_bcast_seqno = seqno;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1025

f3e0008f0   Marek Lindner   batman-adv: make ...
1026
  	spin_unlock_bh(&orig_node->bcast_seqno_lock);
f3e0008f0   Marek Lindner   batman-adv: make ...
1027

fe2da6ff2   Simon Wunderlich   batman-adv: add b...
1028
  	/* check whether this has been sent by another originator before */
004e86fc5   Simon Wunderlich   batman-adv: Fix b...
1029
  	if (batadv_bla_check_bcast_duplist(bat_priv, skb))
fe2da6ff2   Simon Wunderlich   batman-adv: add b...
1030
  		goto out;
c54f38c9a   Simon Wunderlich   batman-adv: set s...
1031
  	batadv_skb_set_priority(skb, sizeof(struct batadv_bcast_packet));
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1032
  	/* rebroadcast packet */
9455e34cb   Sven Eckelmann   batman-adv: Prefi...
1033
  	batadv_add_bcast_packet_to_list(bat_priv, skb, 1);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1034

23721387c   Simon Wunderlich   batman-adv: add b...
1035
1036
1037
  	/* don't hand the broadcast up if it is from an originator
  	 * from the same backbone.
  	 */
08adf1512   Sven Eckelmann   batman-adv: Prefi...
1038
  	if (batadv_bla_is_backbone_gw(skb, orig_node, hdr_size))
23721387c   Simon Wunderlich   batman-adv: add b...
1039
  		goto out;
c384ea3ec   Antonio Quartulli   batman-adv: Distr...
1040
1041
1042
1043
  	if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb, hdr_size))
  		goto rx_success;
  	if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb, hdr_size))
  		goto rx_success;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1044
  	/* broadcast for me */
371351731   Antonio Quartulli   batman-adv: chang...
1045
1046
  	batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size,
  			    orig_node);
c384ea3ec   Antonio Quartulli   batman-adv: Distr...
1047
1048
  
  rx_success:
f3e0008f0   Marek Lindner   batman-adv: make ...
1049
1050
  	ret = NET_RX_SUCCESS;
  	goto out;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1051

f3e0008f0   Marek Lindner   batman-adv: make ...
1052
1053
  spin_unlock:
  	spin_unlock_bh(&orig_node->bcast_seqno_lock);
f3e0008f0   Marek Lindner   batman-adv: make ...
1054
1055
  out:
  	if (orig_node)
7d211efc5   Sven Eckelmann   batman-adv: Prefi...
1056
  		batadv_orig_node_free_ref(orig_node);
f3e0008f0   Marek Lindner   batman-adv: make ...
1057
  	return ret;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1058
  }