Blame view
net/batman-adv/routing.c
29.3 KB
c6c8fea29 net: Add batman-a... |
1 |
/* |
64afe3539 batman-adv: Updat... |
2 |
* Copyright (C) 2007-2011 B.A.T.M.A.N. contributors: |
c6c8fea29 net: Add batman-a... |
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
* * 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 * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA * */ #include "main.h" #include "routing.h" #include "send.h" |
c6c8fea29 net: Add batman-a... |
25 26 27 28 29 |
#include "soft-interface.h" #include "hard-interface.h" #include "icmp_socket.h" #include "translation-table.h" #include "originator.h" |
c6c8fea29 net: Add batman-a... |
30 |
#include "vis.h" |
c6c8fea29 net: Add batman-a... |
31 |
#include "unicast.h" |
fc9572756 batman-adv: agglo... |
32 |
#include "bat_ogm.h" |
c6c8fea29 net: Add batman-a... |
33 |
|
e6c10f433 batman-adv: renam... |
34 |
void slide_own_bcast_window(struct hard_iface *hard_iface) |
c6c8fea29 net: Add batman-a... |
35 |
{ |
e6c10f433 batman-adv: renam... |
36 |
struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); |
c6c8fea29 net: Add batman-a... |
37 |
struct hashtable_t *hash = bat_priv->orig_hash; |
7aadf889e batman-adv: remov... |
38 |
struct hlist_node *node; |
c6c8fea29 net: Add batman-a... |
39 |
struct hlist_head *head; |
c6c8fea29 net: Add batman-a... |
40 41 |
struct orig_node *orig_node; unsigned long *word; |
c90681b85 batman-adv: fixed... |
42 |
uint32_t i; |
c6c8fea29 net: Add batman-a... |
43 |
size_t word_index; |
c6c8fea29 net: Add batman-a... |
44 45 |
for (i = 0; i < hash->size; i++) { head = &hash->table[i]; |
fb778ea17 batman-adv: prote... |
46 |
rcu_read_lock(); |
7aadf889e batman-adv: remov... |
47 |
hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { |
2ae2daf6c batman-adv: prote... |
48 |
spin_lock_bh(&orig_node->ogm_cnt_lock); |
e6c10f433 batman-adv: renam... |
49 |
word_index = hard_iface->if_num * NUM_WORDS; |
c6c8fea29 net: Add batman-a... |
50 51 52 |
word = &(orig_node->bcast_own[word_index]); bit_get_packet(bat_priv, word, 1, 0); |
e6c10f433 batman-adv: renam... |
53 |
orig_node->bcast_own_sum[hard_iface->if_num] = |
c6c8fea29 net: Add batman-a... |
54 |
bit_packet_count(word); |
2ae2daf6c batman-adv: prote... |
55 |
spin_unlock_bh(&orig_node->ogm_cnt_lock); |
c6c8fea29 net: Add batman-a... |
56 |
} |
fb778ea17 batman-adv: prote... |
57 |
rcu_read_unlock(); |
c6c8fea29 net: Add batman-a... |
58 |
} |
c6c8fea29 net: Add batman-a... |
59 |
} |
fc9572756 batman-adv: agglo... |
60 61 62 |
static void _update_route(struct bat_priv *bat_priv, struct orig_node *orig_node, struct neigh_node *neigh_node) |
c6c8fea29 net: Add batman-a... |
63 |
{ |
e1a5382f9 batman-adv: Make ... |
64 65 66 |
struct neigh_node *curr_router; curr_router = orig_node_get_router(orig_node); |
a8e7f4bc3 batman-adv: prote... |
67 |
|
c6c8fea29 net: Add batman-a... |
68 |
/* route deleted */ |
e1a5382f9 batman-adv: Make ... |
69 |
if ((curr_router) && (!neigh_node)) { |
c6c8fea29 net: Add batman-a... |
70 71 72 |
bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM ", orig_node->orig); |
2dafb49d8 batman-adv: renam... |
73 |
tt_global_del_orig(bat_priv, orig_node, |
a73105b8d batman-adv: impro... |
74 |
"Deleted route towards originator"); |
c6c8fea29 net: Add batman-a... |
75 |
|
e1a5382f9 batman-adv: Make ... |
76 77 |
/* route added */ } else if ((!curr_router) && (neigh_node)) { |
c6c8fea29 net: Add batman-a... |
78 79 80 81 82 |
bat_dbg(DBG_ROUTES, bat_priv, "Adding route towards: %pM (via %pM) ", orig_node->orig, neigh_node->addr); |
e1a5382f9 batman-adv: Make ... |
83 |
/* route changed */ |
bb899b89f batman-adv: Ensur... |
84 |
} else if (neigh_node && curr_router) { |
c6c8fea29 net: Add batman-a... |
85 86 87 88 89 |
bat_dbg(DBG_ROUTES, bat_priv, "Changing route towards: %pM " "(now via %pM - was via %pM) ", orig_node->orig, neigh_node->addr, |
e1a5382f9 batman-adv: Make ... |
90 |
curr_router->addr); |
c6c8fea29 net: Add batman-a... |
91 |
} |
e1a5382f9 batman-adv: Make ... |
92 93 94 95 |
if (curr_router) neigh_node_free_ref(curr_router); /* increase refcount of new best neighbor */ |
44524fcdf batman-adv: Corre... |
96 97 |
if (neigh_node && !atomic_inc_not_zero(&neigh_node->refcount)) neigh_node = NULL; |
e1a5382f9 batman-adv: Make ... |
98 99 100 101 102 103 104 105 |
spin_lock_bh(&orig_node->neigh_list_lock); rcu_assign_pointer(orig_node->router, neigh_node); spin_unlock_bh(&orig_node->neigh_list_lock); /* decrease refcount of previous best neighbor */ if (curr_router) neigh_node_free_ref(curr_router); |
c6c8fea29 net: Add batman-a... |
106 |
} |
fc9572756 batman-adv: agglo... |
107 108 |
void update_route(struct bat_priv *bat_priv, struct orig_node *orig_node, struct neigh_node *neigh_node) |
c6c8fea29 net: Add batman-a... |
109 |
{ |
e1a5382f9 batman-adv: Make ... |
110 |
struct neigh_node *router = NULL; |
c6c8fea29 net: Add batman-a... |
111 112 |
if (!orig_node) |
e1a5382f9 batman-adv: Make ... |
113 114 115 |
goto out; router = orig_node_get_router(orig_node); |
c6c8fea29 net: Add batman-a... |
116 |
|
e1a5382f9 batman-adv: Make ... |
117 |
if (router != neigh_node) |
fc9572756 batman-adv: agglo... |
118 |
_update_route(bat_priv, orig_node, neigh_node); |
e1a5382f9 batman-adv: Make ... |
119 120 121 122 |
out: if (router) neigh_node_free_ref(router); |
c6c8fea29 net: Add batman-a... |
123 |
} |
a4c135c56 batman-adv: prote... |
124 125 126 127 128 129 130 131 132 |
/* caller must hold the neigh_list_lock */ void bonding_candidate_del(struct orig_node *orig_node, struct neigh_node *neigh_node) { /* this neighbor is not part of our candidate list */ if (list_empty(&neigh_node->bonding_list)) goto out; list_del_rcu(&neigh_node->bonding_list); |
a4c135c56 batman-adv: prote... |
133 |
INIT_LIST_HEAD(&neigh_node->bonding_list); |
44524fcdf batman-adv: Corre... |
134 |
neigh_node_free_ref(neigh_node); |
a4c135c56 batman-adv: prote... |
135 136 137 138 139 |
atomic_dec(&orig_node->bond_candidates); out: return; } |
fc9572756 batman-adv: agglo... |
140 141 |
void bonding_candidate_add(struct orig_node *orig_node, struct neigh_node *neigh_node) |
a4c135c56 batman-adv: prote... |
142 143 |
{ struct hlist_node *node; |
e1a5382f9 batman-adv: Make ... |
144 145 |
struct neigh_node *tmp_neigh_node, *router = NULL; uint8_t interference_candidate = 0; |
a4c135c56 batman-adv: prote... |
146 147 148 149 |
spin_lock_bh(&orig_node->neigh_list_lock); /* only consider if it has the same primary address ... */ |
39901e716 batman-adv: separ... |
150 151 |
if (!compare_eth(orig_node->orig, neigh_node->orig_node->primary_addr)) |
a4c135c56 batman-adv: prote... |
152 |
goto candidate_del; |
e1a5382f9 batman-adv: Make ... |
153 154 |
router = orig_node_get_router(orig_node); if (!router) |
a4c135c56 batman-adv: prote... |
155 |
goto candidate_del; |
a4c135c56 batman-adv: prote... |
156 |
/* ... and is good enough to be considered */ |
e1a5382f9 batman-adv: Make ... |
157 |
if (neigh_node->tq_avg < router->tq_avg - BONDING_TQ_THRESHOLD) |
a4c135c56 batman-adv: prote... |
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
goto candidate_del; /** * check if we have another candidate with the same mac address or * interface. If we do, we won't select this candidate because of * possible interference. */ hlist_for_each_entry_rcu(tmp_neigh_node, node, &orig_node->neigh_list, list) { if (tmp_neigh_node == neigh_node) continue; /* we only care if the other candidate is even * considered as candidate. */ if (list_empty(&tmp_neigh_node->bonding_list)) continue; if ((neigh_node->if_incoming == tmp_neigh_node->if_incoming) || |
39901e716 batman-adv: separ... |
177 |
(compare_eth(neigh_node->addr, tmp_neigh_node->addr))) { |
a4c135c56 batman-adv: prote... |
178 179 180 181 182 183 184 185 186 187 188 189 |
interference_candidate = 1; break; } } /* don't care further if it is an interference candidate */ if (interference_candidate) goto candidate_del; /* this neighbor already is part of our candidate list */ if (!list_empty(&neigh_node->bonding_list)) goto out; |
44524fcdf batman-adv: Corre... |
190 191 |
if (!atomic_inc_not_zero(&neigh_node->refcount)) goto out; |
a4c135c56 batman-adv: prote... |
192 |
list_add_rcu(&neigh_node->bonding_list, &orig_node->bond_list); |
a4c135c56 batman-adv: prote... |
193 194 195 196 197 198 199 200 |
atomic_inc(&orig_node->bond_candidates); goto out; candidate_del: bonding_candidate_del(orig_node, neigh_node); out: spin_unlock_bh(&orig_node->neigh_list_lock); |
e1a5382f9 batman-adv: Make ... |
201 202 203 |
if (router) neigh_node_free_ref(router); |
a4c135c56 batman-adv: prote... |
204 205 206 |
} /* copy primary address for bonding */ |
fc9572756 batman-adv: agglo... |
207 208 209 |
void bonding_save_primary(const struct orig_node *orig_node, struct orig_node *orig_neigh_node, const struct batman_ogm_packet *batman_ogm_packet) |
a4c135c56 batman-adv: prote... |
210 |
{ |
b6da4bf5d batman-adv: renam... |
211 |
if (!(batman_ogm_packet->flags & PRIMARIES_FIRST_HOP)) |
a4c135c56 batman-adv: prote... |
212 213 214 215 |
return; memcpy(orig_neigh_node->primary_addr, orig_node->orig, ETH_ALEN); } |
c6c8fea29 net: Add batman-a... |
216 217 218 219 220 |
/* 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. */ |
fc9572756 batman-adv: agglo... |
221 222 |
int window_protected(struct bat_priv *bat_priv, int32_t seq_num_diff, unsigned long *last_reset) |
c6c8fea29 net: Add batman-a... |
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
{ if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE) || (seq_num_diff >= EXPECTED_SEQNO_RANGE)) { if (time_after(jiffies, *last_reset + msecs_to_jiffies(RESET_PROTECTION_MS))) { *last_reset = jiffies; bat_dbg(DBG_BATMAN, bat_priv, "old packet received, start protection "); return 0; } else return 1; } return 0; } |
fc9572756 batman-adv: agglo... |
240 |
int recv_bat_ogm_packet(struct sk_buff *skb, struct hard_iface *hard_iface) |
c6c8fea29 net: Add batman-a... |
241 |
{ |
c6c8fea29 net: Add batman-a... |
242 243 244 |
struct ethhdr *ethhdr; /* drop packet if it has not necessary minimum size */ |
b6da4bf5d batman-adv: renam... |
245 |
if (unlikely(!pskb_may_pull(skb, BATMAN_OGM_LEN))) |
c6c8fea29 net: Add batman-a... |
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 |
return NET_RX_DROP; ethhdr = (struct ethhdr *)skb_mac_header(skb); /* packet with broadcast indication but unicast recipient */ if (!is_broadcast_ether_addr(ethhdr->h_dest)) return NET_RX_DROP; /* packet with broadcast sender address */ if (is_broadcast_ether_addr(ethhdr->h_source)) return NET_RX_DROP; /* create a copy of the skb, if needed, to modify it. */ if (skb_cow(skb, 0) < 0) return NET_RX_DROP; /* keep skb linear */ if (skb_linearize(skb) < 0) return NET_RX_DROP; ethhdr = (struct ethhdr *)skb_mac_header(skb); |
fc9572756 batman-adv: agglo... |
267 |
bat_ogm_receive(ethhdr, skb->data, skb_headlen(skb), hard_iface); |
c6c8fea29 net: Add batman-a... |
268 269 270 271 272 273 274 275 |
kfree_skb(skb); return NET_RX_SUCCESS; } static int recv_my_icmp_packet(struct bat_priv *bat_priv, struct sk_buff *skb, size_t icmp_len) { |
32ae9b221 batman-adv: Make ... |
276 |
struct hard_iface *primary_if = NULL; |
44524fcdf batman-adv: Corre... |
277 |
struct orig_node *orig_node = NULL; |
e1a5382f9 batman-adv: Make ... |
278 |
struct neigh_node *router = NULL; |
c6c8fea29 net: Add batman-a... |
279 |
struct icmp_packet_rr *icmp_packet; |
44524fcdf batman-adv: Corre... |
280 |
int ret = NET_RX_DROP; |
c6c8fea29 net: Add batman-a... |
281 282 |
icmp_packet = (struct icmp_packet_rr *)skb->data; |
c6c8fea29 net: Add batman-a... |
283 284 285 286 |
/* add data to device queue */ if (icmp_packet->msg_type != ECHO_REQUEST) { bat_socket_receive_packet(icmp_packet, icmp_len); |
44524fcdf batman-adv: Corre... |
287 |
goto out; |
c6c8fea29 net: Add batman-a... |
288 |
} |
32ae9b221 batman-adv: Make ... |
289 290 |
primary_if = primary_if_get_selected(bat_priv); if (!primary_if) |
44524fcdf batman-adv: Corre... |
291 |
goto out; |
c6c8fea29 net: Add batman-a... |
292 293 294 |
/* answer echo request (ping) */ /* get routing information */ |
7aadf889e batman-adv: remov... |
295 |
orig_node = orig_hash_find(bat_priv, icmp_packet->orig); |
44524fcdf batman-adv: Corre... |
296 |
if (!orig_node) |
e1a5382f9 batman-adv: Make ... |
297 |
goto out; |
c6c8fea29 net: Add batman-a... |
298 |
|
e1a5382f9 batman-adv: Make ... |
299 300 301 |
router = orig_node_get_router(orig_node); if (!router) goto out; |
c6c8fea29 net: Add batman-a... |
302 |
|
44524fcdf batman-adv: Corre... |
303 304 305 306 307 308 309 |
/* create a copy of the skb, if needed, to modify it. */ if (skb_cow(skb, sizeof(struct ethhdr)) < 0) goto out; icmp_packet = (struct icmp_packet_rr *)skb->data; memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); |
32ae9b221 batman-adv: Make ... |
310 |
memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN); |
44524fcdf batman-adv: Corre... |
311 312 |
icmp_packet->msg_type = ECHO_REPLY; icmp_packet->ttl = TTL; |
e1a5382f9 batman-adv: Make ... |
313 |
send_skb_packet(skb, router->if_incoming, router->addr); |
44524fcdf batman-adv: Corre... |
314 |
ret = NET_RX_SUCCESS; |
c6c8fea29 net: Add batman-a... |
315 |
|
44524fcdf batman-adv: Corre... |
316 |
out: |
32ae9b221 batman-adv: Make ... |
317 318 |
if (primary_if) hardif_free_ref(primary_if); |
e1a5382f9 batman-adv: Make ... |
319 320 |
if (router) neigh_node_free_ref(router); |
44524fcdf batman-adv: Corre... |
321 |
if (orig_node) |
7b36e8eef batman-adv: Corre... |
322 |
orig_node_free_ref(orig_node); |
c6c8fea29 net: Add batman-a... |
323 324 325 326 |
return ret; } static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, |
74ef11535 batman-adv: remov... |
327 |
struct sk_buff *skb) |
c6c8fea29 net: Add batman-a... |
328 |
{ |
32ae9b221 batman-adv: Make ... |
329 |
struct hard_iface *primary_if = NULL; |
44524fcdf batman-adv: Corre... |
330 |
struct orig_node *orig_node = NULL; |
e1a5382f9 batman-adv: Make ... |
331 |
struct neigh_node *router = NULL; |
c6c8fea29 net: Add batman-a... |
332 |
struct icmp_packet *icmp_packet; |
44524fcdf batman-adv: Corre... |
333 |
int ret = NET_RX_DROP; |
c6c8fea29 net: Add batman-a... |
334 335 |
icmp_packet = (struct icmp_packet *)skb->data; |
c6c8fea29 net: Add batman-a... |
336 337 338 339 340 341 342 |
/* send TTL exceeded if packet is an echo request (traceroute) */ if (icmp_packet->msg_type != ECHO_REQUEST) { pr_debug("Warning - can't forward icmp packet from %pM to " "%pM: ttl exceeded ", icmp_packet->orig, icmp_packet->dst); |
44524fcdf batman-adv: Corre... |
343 |
goto out; |
c6c8fea29 net: Add batman-a... |
344 |
} |
32ae9b221 batman-adv: Make ... |
345 346 |
primary_if = primary_if_get_selected(bat_priv); if (!primary_if) |
44524fcdf batman-adv: Corre... |
347 |
goto out; |
c6c8fea29 net: Add batman-a... |
348 349 |
/* get routing information */ |
7aadf889e batman-adv: remov... |
350 |
orig_node = orig_hash_find(bat_priv, icmp_packet->orig); |
44524fcdf batman-adv: Corre... |
351 |
if (!orig_node) |
e1a5382f9 batman-adv: Make ... |
352 |
goto out; |
c6c8fea29 net: Add batman-a... |
353 |
|
e1a5382f9 batman-adv: Make ... |
354 355 356 |
router = orig_node_get_router(orig_node); if (!router) goto out; |
c6c8fea29 net: Add batman-a... |
357 |
|
44524fcdf batman-adv: Corre... |
358 359 360 |
/* create a copy of the skb, if needed, to modify it. */ if (skb_cow(skb, sizeof(struct ethhdr)) < 0) goto out; |
c6c8fea29 net: Add batman-a... |
361 |
|
44524fcdf batman-adv: Corre... |
362 |
icmp_packet = (struct icmp_packet *)skb->data; |
c6c8fea29 net: Add batman-a... |
363 |
|
44524fcdf batman-adv: Corre... |
364 |
memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); |
32ae9b221 batman-adv: Make ... |
365 |
memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN); |
44524fcdf batman-adv: Corre... |
366 367 |
icmp_packet->msg_type = TTL_EXCEEDED; icmp_packet->ttl = TTL; |
e1a5382f9 batman-adv: Make ... |
368 |
send_skb_packet(skb, router->if_incoming, router->addr); |
44524fcdf batman-adv: Corre... |
369 |
ret = NET_RX_SUCCESS; |
c6c8fea29 net: Add batman-a... |
370 |
|
44524fcdf batman-adv: Corre... |
371 |
out: |
32ae9b221 batman-adv: Make ... |
372 373 |
if (primary_if) hardif_free_ref(primary_if); |
e1a5382f9 batman-adv: Make ... |
374 375 |
if (router) neigh_node_free_ref(router); |
44524fcdf batman-adv: Corre... |
376 |
if (orig_node) |
7b36e8eef batman-adv: Corre... |
377 |
orig_node_free_ref(orig_node); |
c6c8fea29 net: Add batman-a... |
378 379 |
return ret; } |
e6c10f433 batman-adv: renam... |
380 |
int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if) |
c6c8fea29 net: Add batman-a... |
381 382 383 384 |
{ struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); struct icmp_packet_rr *icmp_packet; struct ethhdr *ethhdr; |
44524fcdf batman-adv: Corre... |
385 |
struct orig_node *orig_node = NULL; |
e1a5382f9 batman-adv: Make ... |
386 |
struct neigh_node *router = NULL; |
c6c8fea29 net: Add batman-a... |
387 |
int hdr_size = sizeof(struct icmp_packet); |
44524fcdf batman-adv: Corre... |
388 |
int ret = NET_RX_DROP; |
c6c8fea29 net: Add batman-a... |
389 390 391 392 393 394 395 396 397 |
/** * we truncate all incoming icmp packets if they don't match our size */ if (skb->len >= sizeof(struct icmp_packet_rr)) hdr_size = sizeof(struct icmp_packet_rr); /* drop packet if it has not necessary minimum size */ if (unlikely(!pskb_may_pull(skb, hdr_size))) |
44524fcdf batman-adv: Corre... |
398 |
goto out; |
c6c8fea29 net: Add batman-a... |
399 400 401 402 403 |
ethhdr = (struct ethhdr *)skb_mac_header(skb); /* packet with unicast indication but broadcast recipient */ if (is_broadcast_ether_addr(ethhdr->h_dest)) |
44524fcdf batman-adv: Corre... |
404 |
goto out; |
c6c8fea29 net: Add batman-a... |
405 406 407 |
/* packet with broadcast sender address */ if (is_broadcast_ether_addr(ethhdr->h_source)) |
44524fcdf batman-adv: Corre... |
408 |
goto out; |
c6c8fea29 net: Add batman-a... |
409 410 411 |
/* not for me */ if (!is_my_mac(ethhdr->h_dest)) |
44524fcdf batman-adv: Corre... |
412 |
goto out; |
c6c8fea29 net: Add batman-a... |
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 |
icmp_packet = (struct icmp_packet_rr *)skb->data; /* add record route information if not full */ if ((hdr_size == sizeof(struct icmp_packet_rr)) && (icmp_packet->rr_cur < BAT_RR_LEN)) { memcpy(&(icmp_packet->rr[icmp_packet->rr_cur]), ethhdr->h_dest, ETH_ALEN); icmp_packet->rr_cur++; } /* packet for me */ if (is_my_mac(icmp_packet->dst)) return recv_my_icmp_packet(bat_priv, skb, hdr_size); /* TTL exceeded */ if (icmp_packet->ttl < 2) |
74ef11535 batman-adv: remov... |
430 |
return recv_icmp_ttl_exceeded(bat_priv, skb); |
c6c8fea29 net: Add batman-a... |
431 |
|
c6c8fea29 net: Add batman-a... |
432 |
/* get routing information */ |
7aadf889e batman-adv: remov... |
433 |
orig_node = orig_hash_find(bat_priv, icmp_packet->dst); |
44524fcdf batman-adv: Corre... |
434 |
if (!orig_node) |
e1a5382f9 batman-adv: Make ... |
435 |
goto out; |
c6c8fea29 net: Add batman-a... |
436 |
|
e1a5382f9 batman-adv: Make ... |
437 438 439 |
router = orig_node_get_router(orig_node); if (!router) goto out; |
c6c8fea29 net: Add batman-a... |
440 |
|
44524fcdf batman-adv: Corre... |
441 442 443 |
/* create a copy of the skb, if needed, to modify it. */ if (skb_cow(skb, sizeof(struct ethhdr)) < 0) goto out; |
c6c8fea29 net: Add batman-a... |
444 |
|
44524fcdf batman-adv: Corre... |
445 |
icmp_packet = (struct icmp_packet_rr *)skb->data; |
c6c8fea29 net: Add batman-a... |
446 |
|
44524fcdf batman-adv: Corre... |
447 448 449 450 |
/* decrement ttl */ icmp_packet->ttl--; /* route it */ |
e1a5382f9 batman-adv: Make ... |
451 |
send_skb_packet(skb, router->if_incoming, router->addr); |
44524fcdf batman-adv: Corre... |
452 |
ret = NET_RX_SUCCESS; |
c6c8fea29 net: Add batman-a... |
453 |
|
44524fcdf batman-adv: Corre... |
454 |
out: |
e1a5382f9 batman-adv: Make ... |
455 456 |
if (router) neigh_node_free_ref(router); |
44524fcdf batman-adv: Corre... |
457 |
if (orig_node) |
7b36e8eef batman-adv: Corre... |
458 |
orig_node_free_ref(orig_node); |
c6c8fea29 net: Add batman-a... |
459 460 |
return ret; } |
551586292 batman-adv: Move ... |
461 462 463 464 465 466 |
/* In the bonding case, send the packets in a round * robin fashion over the remaining interfaces. * * This method rotates the bonding list and increases the * returned router's refcount. */ static struct neigh_node *find_bond_router(struct orig_node *primary_orig, |
747e4221a batman-adv: Add c... |
467 |
const struct hard_iface *recv_if) |
551586292 batman-adv: Move ... |
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 |
{ struct neigh_node *tmp_neigh_node; struct neigh_node *router = NULL, *first_candidate = NULL; rcu_read_lock(); list_for_each_entry_rcu(tmp_neigh_node, &primary_orig->bond_list, bonding_list) { if (!first_candidate) first_candidate = tmp_neigh_node; /* recv_if == NULL on the first node. */ if (tmp_neigh_node->if_incoming == recv_if) continue; if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) continue; router = tmp_neigh_node; break; } /* use the first candidate if nothing was found. */ if (!router && first_candidate && atomic_inc_not_zero(&first_candidate->refcount)) router = first_candidate; if (!router) goto out; /* selected should point to the next element * after the current router */ spin_lock_bh(&primary_orig->neigh_list_lock); /* this is a list_move(), which unfortunately * does not exist as rcu version */ list_del_rcu(&primary_orig->bond_list); list_add_rcu(&primary_orig->bond_list, &router->bonding_list); spin_unlock_bh(&primary_orig->neigh_list_lock); out: rcu_read_unlock(); return router; } /* Interface Alternating: Use the best of the * remaining candidates which are not using * this interface. * * Increases the returned router's refcount */ static struct neigh_node *find_ifalter_router(struct orig_node *primary_orig, |
747e4221a batman-adv: Add c... |
518 |
const struct hard_iface *recv_if) |
551586292 batman-adv: Move ... |
519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 |
{ struct neigh_node *tmp_neigh_node; struct neigh_node *router = NULL, *first_candidate = NULL; rcu_read_lock(); list_for_each_entry_rcu(tmp_neigh_node, &primary_orig->bond_list, bonding_list) { if (!first_candidate) first_candidate = tmp_neigh_node; /* recv_if == NULL on the first node. */ if (tmp_neigh_node->if_incoming == recv_if) continue; if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) continue; /* if we don't have a router yet * or this one is better, choose it. */ if ((!router) || (tmp_neigh_node->tq_avg > router->tq_avg)) { /* decrement refcount of * previously selected router */ if (router) neigh_node_free_ref(router); router = tmp_neigh_node; atomic_inc_not_zero(&router->refcount); } neigh_node_free_ref(tmp_neigh_node); } /* use the first candidate if nothing was found. */ if (!router && first_candidate && atomic_inc_not_zero(&first_candidate->refcount)) router = first_candidate; rcu_read_unlock(); return router; } |
a73105b8d batman-adv: impro... |
560 561 562 563 |
int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if) { struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); struct tt_query_packet *tt_query; |
8b7342d67 batman-adv: check... |
564 |
uint16_t tt_len; |
a73105b8d batman-adv: impro... |
565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 |
struct ethhdr *ethhdr; /* drop packet if it has not necessary minimum size */ if (unlikely(!pskb_may_pull(skb, sizeof(struct tt_query_packet)))) goto out; /* I could need to modify it */ if (skb_cow(skb, sizeof(struct tt_query_packet)) < 0) goto out; ethhdr = (struct ethhdr *)skb_mac_header(skb); /* packet with unicast indication but broadcast recipient */ if (is_broadcast_ether_addr(ethhdr->h_dest)) goto out; /* packet with broadcast sender address */ if (is_broadcast_ether_addr(ethhdr->h_source)) goto out; tt_query = (struct tt_query_packet *)skb->data; tt_query->tt_data = ntohs(tt_query->tt_data); switch (tt_query->flags & TT_QUERY_TYPE_MASK) { case TT_REQUEST: /* If we cannot provide an answer the tt_request is * forwarded */ if (!send_tt_response(bat_priv, tt_query)) { bat_dbg(DBG_TT, bat_priv, "Routing TT_REQUEST to %pM [%c] ", tt_query->dst, (tt_query->flags & TT_FULL_TABLE ? 'F' : '.')); tt_query->tt_data = htons(tt_query->tt_data); return route_unicast_packet(skb, recv_if); } break; case TT_RESPONSE: |
dc58fe32e batman-adv: linea... |
604 605 606 607 608 |
if (is_my_mac(tt_query->dst)) { /* packet needs to be linearized to access the TT * changes */ if (skb_linearize(skb) < 0) goto out; |
a73105b8d batman-adv: impro... |
609 |
|
8b7342d67 batman-adv: check... |
610 611 612 613 |
tt_len = tt_query->tt_data * sizeof(struct tt_change); /* Ensure we have all the claimed data */ if (unlikely(skb_headlen(skb) < |
69497c17c batman-adv: forma... |
614 |
sizeof(struct tt_query_packet) + tt_len)) |
8b7342d67 batman-adv: check... |
615 |
goto out; |
a73105b8d batman-adv: impro... |
616 |
handle_tt_response(bat_priv, tt_query); |
dc58fe32e batman-adv: linea... |
617 |
} else { |
a73105b8d batman-adv: impro... |
618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 |
bat_dbg(DBG_TT, bat_priv, "Routing TT_RESPONSE to %pM [%c] ", tt_query->dst, (tt_query->flags & TT_FULL_TABLE ? 'F' : '.')); tt_query->tt_data = htons(tt_query->tt_data); return route_unicast_packet(skb, recv_if); } break; } out: /* returning NET_RX_DROP will make the caller function kfree the skb */ return NET_RX_DROP; } |
cc47f66e6 batman-adv: impro... |
633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 |
int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if) { struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); struct roam_adv_packet *roam_adv_packet; struct orig_node *orig_node; struct ethhdr *ethhdr; /* drop packet if it has not necessary minimum size */ if (unlikely(!pskb_may_pull(skb, sizeof(struct roam_adv_packet)))) goto out; ethhdr = (struct ethhdr *)skb_mac_header(skb); /* packet with unicast indication but broadcast recipient */ if (is_broadcast_ether_addr(ethhdr->h_dest)) goto out; /* packet with broadcast sender address */ if (is_broadcast_ether_addr(ethhdr->h_source)) goto out; roam_adv_packet = (struct roam_adv_packet *)skb->data; if (!is_my_mac(roam_adv_packet->dst)) return route_unicast_packet(skb, recv_if); orig_node = orig_hash_find(bat_priv, roam_adv_packet->src); if (!orig_node) goto out; bat_dbg(DBG_TT, bat_priv, "Received ROAMING_ADV from %pM " "(client %pM) ", roam_adv_packet->src, roam_adv_packet->client); tt_global_add(bat_priv, orig_node, roam_adv_packet->client, |
bc2790808 batman-adv: detec... |
669 |
atomic_read(&orig_node->last_ttvn) + 1, true, false); |
cc47f66e6 batman-adv: impro... |
670 671 672 673 674 675 676 677 678 679 680 |
/* Roaming phase starts: I have new information but the ttvn has not * been incremented yet. This flag will make me check all the incoming * packets for the correct destination. */ bat_priv->tt_poss_change = true; orig_node_free_ref(orig_node); out: /* returning NET_RX_DROP will make the caller function kfree the skb */ return NET_RX_DROP; } |
c6c8fea29 net: Add batman-a... |
681 |
/* find a suitable router for this originator, and use |
a4c135c56 batman-adv: prote... |
682 683 |
* bonding if possible. increases the found neighbors * refcount.*/ |
c6c8fea29 net: Add batman-a... |
684 685 |
struct neigh_node *find_router(struct bat_priv *bat_priv, struct orig_node *orig_node, |
747e4221a batman-adv: Add c... |
686 |
const struct hard_iface *recv_if) |
c6c8fea29 net: Add batman-a... |
687 688 689 |
{ struct orig_node *primary_orig_node; struct orig_node *router_orig; |
551586292 batman-adv: Move ... |
690 |
struct neigh_node *router; |
c6c8fea29 net: Add batman-a... |
691 692 693 694 695 |
static uint8_t zero_mac[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; int bonding_enabled; if (!orig_node) return NULL; |
e1a5382f9 batman-adv: Make ... |
696 697 |
router = orig_node_get_router(orig_node); if (!router) |
01df2b65e batman-adv: Fix r... |
698 |
goto err; |
c6c8fea29 net: Add batman-a... |
699 700 701 |
/* without bonding, the first node should * always choose the default router. */ |
c6c8fea29 net: Add batman-a... |
702 |
bonding_enabled = atomic_read(&bat_priv->bonding); |
a4c135c56 batman-adv: prote... |
703 704 |
rcu_read_lock(); /* select default router to output */ |
e1a5382f9 batman-adv: Make ... |
705 |
router_orig = router->orig_node; |
01df2b65e batman-adv: Fix r... |
706 707 |
if (!router_orig) goto err_unlock; |
a4c135c56 batman-adv: prote... |
708 |
|
a4c135c56 batman-adv: prote... |
709 710 |
if ((!recv_if) && (!bonding_enabled)) goto return_router; |
c6c8fea29 net: Add batman-a... |
711 712 713 |
/* if we have something in the primary_addr, we can search * for a potential bonding candidate. */ |
39901e716 batman-adv: separ... |
714 |
if (compare_eth(router_orig->primary_addr, zero_mac)) |
a4c135c56 batman-adv: prote... |
715 |
goto return_router; |
c6c8fea29 net: Add batman-a... |
716 717 718 |
/* find the orig_node which has the primary interface. might * even be the same as our router_orig in many cases */ |
39901e716 batman-adv: separ... |
719 |
if (compare_eth(router_orig->primary_addr, router_orig->orig)) { |
c6c8fea29 net: Add batman-a... |
720 721 |
primary_orig_node = router_orig; } else { |
7aadf889e batman-adv: remov... |
722 723 |
primary_orig_node = orig_hash_find(bat_priv, router_orig->primary_addr); |
c6c8fea29 net: Add batman-a... |
724 |
if (!primary_orig_node) |
a4c135c56 batman-adv: prote... |
725 |
goto return_router; |
7aadf889e batman-adv: remov... |
726 |
|
7b36e8eef batman-adv: Corre... |
727 |
orig_node_free_ref(primary_orig_node); |
c6c8fea29 net: Add batman-a... |
728 729 730 731 |
} /* with less than 2 candidates, we can't do any * bonding and prefer the original router. */ |
a4c135c56 batman-adv: prote... |
732 733 |
if (atomic_read(&primary_orig_node->bond_candidates) < 2) goto return_router; |
c6c8fea29 net: Add batman-a... |
734 |
|
c6c8fea29 net: Add batman-a... |
735 736 737 |
/* all nodes between should choose a candidate which * is is not on the interface where the packet came * in. */ |
a4c135c56 batman-adv: prote... |
738 |
|
44524fcdf batman-adv: Corre... |
739 |
neigh_node_free_ref(router); |
c6c8fea29 net: Add batman-a... |
740 |
|
551586292 batman-adv: Move ... |
741 742 743 744 |
if (bonding_enabled) router = find_bond_router(primary_orig_node, recv_if); else router = find_ifalter_router(primary_orig_node, recv_if); |
c6c8fea29 net: Add batman-a... |
745 |
|
a4c135c56 batman-adv: prote... |
746 |
return_router: |
e2cbc11c0 batman-adv: move ... |
747 748 |
if (router && router->if_incoming->if_status != IF_ACTIVE) goto err_unlock; |
a4c135c56 batman-adv: prote... |
749 |
rcu_read_unlock(); |
c6c8fea29 net: Add batman-a... |
750 |
return router; |
01df2b65e batman-adv: Fix r... |
751 752 753 754 755 756 |
err_unlock: rcu_read_unlock(); err: if (router) neigh_node_free_ref(router); return NULL; |
c6c8fea29 net: Add batman-a... |
757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 |
} static int check_unicast_packet(struct sk_buff *skb, int hdr_size) { struct ethhdr *ethhdr; /* drop packet if it has not necessary minimum size */ if (unlikely(!pskb_may_pull(skb, hdr_size))) return -1; ethhdr = (struct ethhdr *)skb_mac_header(skb); /* packet with unicast indication but broadcast recipient */ if (is_broadcast_ether_addr(ethhdr->h_dest)) return -1; /* packet with broadcast sender address */ if (is_broadcast_ether_addr(ethhdr->h_source)) return -1; /* not for me */ if (!is_my_mac(ethhdr->h_dest)) return -1; return 0; } |
7cefb149a batman-adv: Remov... |
783 |
int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if) |
c6c8fea29 net: Add batman-a... |
784 785 |
{ struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); |
44524fcdf batman-adv: Corre... |
786 787 |
struct orig_node *orig_node = NULL; struct neigh_node *neigh_node = NULL; |
c6c8fea29 net: Add batman-a... |
788 789 |
struct unicast_packet *unicast_packet; struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb); |
44524fcdf batman-adv: Corre... |
790 |
int ret = NET_RX_DROP; |
c6c8fea29 net: Add batman-a... |
791 792 793 794 795 796 797 798 799 800 |
struct sk_buff *new_skb; unicast_packet = (struct unicast_packet *)skb->data; /* TTL exceeded */ if (unicast_packet->ttl < 2) { pr_debug("Warning - can't forward unicast packet from %pM to " "%pM: ttl exceeded ", ethhdr->h_source, unicast_packet->dest); |
44524fcdf batman-adv: Corre... |
801 |
goto out; |
c6c8fea29 net: Add batman-a... |
802 803 804 |
} /* get routing information */ |
7aadf889e batman-adv: remov... |
805 |
orig_node = orig_hash_find(bat_priv, unicast_packet->dest); |
44524fcdf batman-adv: Corre... |
806 |
if (!orig_node) |
b5a6f69c5 batman-adv: orig_... |
807 |
goto out; |
c6c8fea29 net: Add batman-a... |
808 |
|
a4c135c56 batman-adv: prote... |
809 |
/* find_router() increases neigh_nodes refcount if found. */ |
44524fcdf batman-adv: Corre... |
810 |
neigh_node = find_router(bat_priv, orig_node, recv_if); |
c6c8fea29 net: Add batman-a... |
811 |
|
d0072609b batman-adv: remov... |
812 |
if (!neigh_node) |
44524fcdf batman-adv: Corre... |
813 |
goto out; |
c6c8fea29 net: Add batman-a... |
814 815 816 |
/* create a copy of the skb, if needed, to modify it. */ if (skb_cow(skb, sizeof(struct ethhdr)) < 0) |
44524fcdf batman-adv: Corre... |
817 |
goto out; |
c6c8fea29 net: Add batman-a... |
818 819 820 821 822 |
unicast_packet = (struct unicast_packet *)skb->data; if (unicast_packet->packet_type == BAT_UNICAST && atomic_read(&bat_priv->fragmentation) && |
d0072609b batman-adv: remov... |
823 824 825 826 827 |
skb->len > neigh_node->if_incoming->net_dev->mtu) { ret = frag_send_skb(skb, bat_priv, neigh_node->if_incoming, neigh_node->addr); goto out; } |
c6c8fea29 net: Add batman-a... |
828 829 |
if (unicast_packet->packet_type == BAT_UNICAST_FRAG && |
d0072609b batman-adv: remov... |
830 |
frag_can_reassemble(skb, neigh_node->if_incoming->net_dev->mtu)) { |
c6c8fea29 net: Add batman-a... |
831 832 833 834 |
ret = frag_reassemble_skb(skb, bat_priv, &new_skb); if (ret == NET_RX_DROP) |
44524fcdf batman-adv: Corre... |
835 |
goto out; |
c6c8fea29 net: Add batman-a... |
836 837 |
/* packet was buffered for late merge */ |
44524fcdf batman-adv: Corre... |
838 839 840 841 |
if (!new_skb) { ret = NET_RX_SUCCESS; goto out; } |
c6c8fea29 net: Add batman-a... |
842 843 844 845 846 847 848 849 850 |
skb = new_skb; unicast_packet = (struct unicast_packet *)skb->data; } /* decrement ttl */ unicast_packet->ttl--; /* route it */ |
d0072609b batman-adv: remov... |
851 |
send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); |
44524fcdf batman-adv: Corre... |
852 |
ret = NET_RX_SUCCESS; |
c6c8fea29 net: Add batman-a... |
853 |
|
44524fcdf batman-adv: Corre... |
854 855 856 857 |
out: if (neigh_node) neigh_node_free_ref(neigh_node); if (orig_node) |
7b36e8eef batman-adv: Corre... |
858 |
orig_node_free_ref(orig_node); |
44524fcdf batman-adv: Corre... |
859 |
return ret; |
c6c8fea29 net: Add batman-a... |
860 |
} |
a73105b8d batman-adv: impro... |
861 862 863 864 865 866 867 |
static int check_unicast_ttvn(struct bat_priv *bat_priv, struct sk_buff *skb) { uint8_t curr_ttvn; struct orig_node *orig_node; struct ethhdr *ethhdr; struct hard_iface *primary_if; struct unicast_packet *unicast_packet; |
cc47f66e6 batman-adv: impro... |
868 |
bool tt_poss_change; |
a73105b8d batman-adv: impro... |
869 870 871 872 873 874 |
/* I could need to modify it */ if (skb_cow(skb, sizeof(struct unicast_packet)) < 0) return 0; unicast_packet = (struct unicast_packet *)skb->data; |
cc47f66e6 batman-adv: impro... |
875 876 |
if (is_my_mac(unicast_packet->dest)) { tt_poss_change = bat_priv->tt_poss_change; |
a73105b8d batman-adv: impro... |
877 |
curr_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn); |
cc47f66e6 batman-adv: impro... |
878 |
} else { |
a73105b8d batman-adv: impro... |
879 880 881 882 883 884 |
orig_node = orig_hash_find(bat_priv, unicast_packet->dest); if (!orig_node) return 0; curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); |
cc47f66e6 batman-adv: impro... |
885 |
tt_poss_change = orig_node->tt_poss_change; |
a73105b8d batman-adv: impro... |
886 887 888 889 |
orig_node_free_ref(orig_node); } /* Check whether I have to reroute the packet */ |
cc47f66e6 batman-adv: impro... |
890 |
if (seq_before(unicast_packet->ttvn, curr_ttvn) || tt_poss_change) { |
a73105b8d batman-adv: impro... |
891 892 893 894 895 896 |
/* Linearize the skb before accessing it */ if (skb_linearize(skb) < 0) return 0; ethhdr = (struct ethhdr *)(skb->data + sizeof(struct unicast_packet)); |
3d393e473 batman-adv: imple... |
897 |
orig_node = transtable_search(bat_priv, NULL, ethhdr->h_dest); |
a73105b8d batman-adv: impro... |
898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 |
if (!orig_node) { if (!is_my_client(bat_priv, ethhdr->h_dest)) return 0; primary_if = primary_if_get_selected(bat_priv); if (!primary_if) return 0; memcpy(unicast_packet->dest, primary_if->net_dev->dev_addr, ETH_ALEN); hardif_free_ref(primary_if); } else { memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN); curr_ttvn = (uint8_t) atomic_read(&orig_node->last_ttvn); orig_node_free_ref(orig_node); } bat_dbg(DBG_ROUTES, bat_priv, "TTVN mismatch (old_ttvn %u " "new_ttvn %u)! Rerouting unicast packet (for %pM) to " "%pM ", unicast_packet->ttvn, curr_ttvn, ethhdr->h_dest, unicast_packet->dest); unicast_packet->ttvn = curr_ttvn; } return 1; } |
e6c10f433 batman-adv: renam... |
926 |
int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if) |
c6c8fea29 net: Add batman-a... |
927 |
{ |
a73105b8d batman-adv: impro... |
928 |
struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); |
c6c8fea29 net: Add batman-a... |
929 |
struct unicast_packet *unicast_packet; |
704509b8d batman-adv: Calcu... |
930 |
int hdr_size = sizeof(*unicast_packet); |
c6c8fea29 net: Add batman-a... |
931 932 933 |
if (check_unicast_packet(skb, hdr_size) < 0) return NET_RX_DROP; |
a73105b8d batman-adv: impro... |
934 935 |
if (!check_unicast_ttvn(bat_priv, skb)) return NET_RX_DROP; |
c6c8fea29 net: Add batman-a... |
936 937 938 939 940 941 942 |
unicast_packet = (struct unicast_packet *)skb->data; /* packet for me */ if (is_my_mac(unicast_packet->dest)) { interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size); return NET_RX_SUCCESS; } |
7cefb149a batman-adv: Remov... |
943 |
return route_unicast_packet(skb, recv_if); |
c6c8fea29 net: Add batman-a... |
944 |
} |
e6c10f433 batman-adv: renam... |
945 |
int recv_ucast_frag_packet(struct sk_buff *skb, struct hard_iface *recv_if) |
c6c8fea29 net: Add batman-a... |
946 947 948 |
{ struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); struct unicast_frag_packet *unicast_packet; |
704509b8d batman-adv: Calcu... |
949 |
int hdr_size = sizeof(*unicast_packet); |
c6c8fea29 net: Add batman-a... |
950 951 952 953 954 |
struct sk_buff *new_skb = NULL; int ret; if (check_unicast_packet(skb, hdr_size) < 0) return NET_RX_DROP; |
a73105b8d batman-adv: impro... |
955 956 |
if (!check_unicast_ttvn(bat_priv, skb)) return NET_RX_DROP; |
c6c8fea29 net: Add batman-a... |
957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 |
unicast_packet = (struct unicast_frag_packet *)skb->data; /* packet for me */ if (is_my_mac(unicast_packet->dest)) { ret = frag_reassemble_skb(skb, bat_priv, &new_skb); if (ret == NET_RX_DROP) return NET_RX_DROP; /* packet was buffered for late merge */ if (!new_skb) return NET_RX_SUCCESS; interface_rx(recv_if->soft_iface, new_skb, recv_if, sizeof(struct unicast_packet)); return NET_RX_SUCCESS; } |
7cefb149a batman-adv: Remov... |
975 |
return route_unicast_packet(skb, recv_if); |
c6c8fea29 net: Add batman-a... |
976 |
} |
e6c10f433 batman-adv: renam... |
977 |
int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if) |
c6c8fea29 net: Add batman-a... |
978 979 |
{ struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); |
f3e0008f0 batman-adv: make ... |
980 |
struct orig_node *orig_node = NULL; |
c6c8fea29 net: Add batman-a... |
981 982 |
struct bcast_packet *bcast_packet; struct ethhdr *ethhdr; |
704509b8d batman-adv: Calcu... |
983 |
int hdr_size = sizeof(*bcast_packet); |
f3e0008f0 batman-adv: make ... |
984 |
int ret = NET_RX_DROP; |
c6c8fea29 net: Add batman-a... |
985 986 987 988 |
int32_t seq_diff; /* drop packet if it has not necessary minimum size */ if (unlikely(!pskb_may_pull(skb, hdr_size))) |
f3e0008f0 batman-adv: make ... |
989 |
goto out; |
c6c8fea29 net: Add batman-a... |
990 991 992 993 994 |
ethhdr = (struct ethhdr *)skb_mac_header(skb); /* packet with broadcast indication but unicast recipient */ if (!is_broadcast_ether_addr(ethhdr->h_dest)) |
f3e0008f0 batman-adv: make ... |
995 |
goto out; |
c6c8fea29 net: Add batman-a... |
996 997 998 |
/* packet with broadcast sender address */ if (is_broadcast_ether_addr(ethhdr->h_source)) |
f3e0008f0 batman-adv: make ... |
999 |
goto out; |
c6c8fea29 net: Add batman-a... |
1000 1001 1002 |
/* ignore broadcasts sent by myself */ if (is_my_mac(ethhdr->h_source)) |
f3e0008f0 batman-adv: make ... |
1003 |
goto out; |
c6c8fea29 net: Add batman-a... |
1004 1005 1006 1007 1008 |
bcast_packet = (struct bcast_packet *)skb->data; /* ignore broadcasts originated by myself */ if (is_my_mac(bcast_packet->orig)) |
f3e0008f0 batman-adv: make ... |
1009 |
goto out; |
c6c8fea29 net: Add batman-a... |
1010 1011 |
if (bcast_packet->ttl < 2) |
f3e0008f0 batman-adv: make ... |
1012 |
goto out; |
c6c8fea29 net: Add batman-a... |
1013 |
|
7aadf889e batman-adv: remov... |
1014 |
orig_node = orig_hash_find(bat_priv, bcast_packet->orig); |
f3e0008f0 batman-adv: make ... |
1015 1016 |
if (!orig_node) |
b5a6f69c5 batman-adv: orig_... |
1017 |
goto out; |
c6c8fea29 net: Add batman-a... |
1018 |
|
f3e0008f0 batman-adv: make ... |
1019 |
spin_lock_bh(&orig_node->bcast_seqno_lock); |
c6c8fea29 net: Add batman-a... |
1020 1021 |
/* check whether the packet is a duplicate */ |
f3e0008f0 batman-adv: make ... |
1022 1023 1024 |
if (get_bit_status(orig_node->bcast_bits, orig_node->last_bcast_seqno, ntohl(bcast_packet->seqno))) goto spin_unlock; |
c6c8fea29 net: Add batman-a... |
1025 1026 1027 1028 1029 |
seq_diff = ntohl(bcast_packet->seqno) - orig_node->last_bcast_seqno; /* check whether the packet is old and the host just restarted. */ if (window_protected(bat_priv, seq_diff, |
f3e0008f0 batman-adv: make ... |
1030 1031 |
&orig_node->bcast_seqno_reset)) goto spin_unlock; |
c6c8fea29 net: Add batman-a... |
1032 1033 1034 1035 1036 |
/* mark broadcast in flood history, update window position * if required. */ if (bit_get_packet(bat_priv, orig_node->bcast_bits, seq_diff, 1)) orig_node->last_bcast_seqno = ntohl(bcast_packet->seqno); |
f3e0008f0 batman-adv: make ... |
1037 |
spin_unlock_bh(&orig_node->bcast_seqno_lock); |
f3e0008f0 batman-adv: make ... |
1038 |
|
c6c8fea29 net: Add batman-a... |
1039 |
/* rebroadcast packet */ |
8698529d2 batman-adv: add_b... |
1040 |
add_bcast_packet_to_list(bat_priv, skb, 1); |
c6c8fea29 net: Add batman-a... |
1041 1042 1043 |
/* broadcast for me */ interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size); |
f3e0008f0 batman-adv: make ... |
1044 1045 |
ret = NET_RX_SUCCESS; goto out; |
c6c8fea29 net: Add batman-a... |
1046 |
|
f3e0008f0 batman-adv: make ... |
1047 1048 |
spin_unlock: spin_unlock_bh(&orig_node->bcast_seqno_lock); |
f3e0008f0 batman-adv: make ... |
1049 1050 |
out: if (orig_node) |
7b36e8eef batman-adv: Corre... |
1051 |
orig_node_free_ref(orig_node); |
f3e0008f0 batman-adv: make ... |
1052 |
return ret; |
c6c8fea29 net: Add batman-a... |
1053 |
} |
e6c10f433 batman-adv: renam... |
1054 |
int recv_vis_packet(struct sk_buff *skb, struct hard_iface *recv_if) |
c6c8fea29 net: Add batman-a... |
1055 1056 1057 1058 |
{ struct vis_packet *vis_packet; struct ethhdr *ethhdr; struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); |
704509b8d batman-adv: Calcu... |
1059 |
int hdr_size = sizeof(*vis_packet); |
c6c8fea29 net: Add batman-a... |
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 |
/* keep skb linear */ if (skb_linearize(skb) < 0) return NET_RX_DROP; if (unlikely(!pskb_may_pull(skb, hdr_size))) return NET_RX_DROP; vis_packet = (struct vis_packet *)skb->data; ethhdr = (struct ethhdr *)skb_mac_header(skb); /* not for me */ if (!is_my_mac(ethhdr->h_dest)) return NET_RX_DROP; /* ignore own packets */ if (is_my_mac(vis_packet->vis_orig)) return NET_RX_DROP; if (is_my_mac(vis_packet->sender_orig)) return NET_RX_DROP; switch (vis_packet->vis_type) { case VIS_TYPE_SERVER_SYNC: receive_server_sync_packet(bat_priv, vis_packet, skb_headlen(skb)); break; case VIS_TYPE_CLIENT_UPDATE: receive_client_update_packet(bat_priv, vis_packet, skb_headlen(skb)); break; default: /* ignore unknown packet */ break; } /* We take a copy of the data in the packet, so we should always free the skbuf. */ return NET_RX_DROP; } |