batman-adv: Distributed ARP Table - add ARP parsing functions
[linux-2.6-block.git] / net / batman-adv / distributed-arp-table.c
CommitLineData
785ea114
AQ
1/* Copyright (C) 2011-2012 B.A.T.M.A.N. contributors:
2 *
3 * Antonio Quartulli
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of version 2 of the GNU General Public
7 * License as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA
18 */
19
20#include <linux/if_ether.h>
21#include <linux/if_arp.h>
22
23#include "main.h"
5c3a0e55 24#include "hash.h"
785ea114
AQ
25#include "distributed-arp-table.h"
26#include "hard-interface.h"
27#include "originator.h"
28#include "send.h"
29#include "types.h"
30#include "unicast.h"
31
2f1dfbe1
AQ
32static void batadv_dat_purge(struct work_struct *work);
33
34/**
35 * batadv_dat_start_timer - initialise the DAT periodic worker
36 * @bat_priv: the bat priv with all the soft interface information
37 */
38static void batadv_dat_start_timer(struct batadv_priv *bat_priv)
39{
40 INIT_DELAYED_WORK(&bat_priv->dat.work, batadv_dat_purge);
41 queue_delayed_work(batadv_event_workqueue, &bat_priv->dat.work,
42 msecs_to_jiffies(10000));
43}
44
45/**
46 * batadv_dat_entry_free_ref - decrements the dat_entry refcounter and possibly
47 * free it
48 * @dat_entry: the oentry to free
49 */
50static void batadv_dat_entry_free_ref(struct batadv_dat_entry *dat_entry)
51{
52 if (atomic_dec_and_test(&dat_entry->refcount))
53 kfree_rcu(dat_entry, rcu);
54}
55
56/**
57 * batadv_dat_to_purge - checks whether a dat_entry has to be purged or not
58 * @dat_entry: the entry to check
59 *
60 * Returns true if the entry has to be purged now, false otherwise
61 */
62static bool batadv_dat_to_purge(struct batadv_dat_entry *dat_entry)
63{
64 return batadv_has_timed_out(dat_entry->last_update,
65 BATADV_DAT_ENTRY_TIMEOUT);
66}
67
68/**
69 * __batadv_dat_purge - delete entries from the DAT local storage
70 * @bat_priv: the bat priv with all the soft interface information
71 * @to_purge: function in charge to decide whether an entry has to be purged or
72 * not. This function takes the dat_entry as argument and has to
73 * returns a boolean value: true is the entry has to be deleted,
74 * false otherwise
75 *
76 * Loops over each entry in the DAT local storage and delete it if and only if
77 * the to_purge function passed as argument returns true
78 */
79static void __batadv_dat_purge(struct batadv_priv *bat_priv,
80 bool (*to_purge)(struct batadv_dat_entry *))
81{
82 spinlock_t *list_lock; /* protects write access to the hash lists */
83 struct batadv_dat_entry *dat_entry;
84 struct hlist_node *node, *node_tmp;
85 struct hlist_head *head;
86 uint32_t i;
87
88 if (!bat_priv->dat.hash)
89 return;
90
91 for (i = 0; i < bat_priv->dat.hash->size; i++) {
92 head = &bat_priv->dat.hash->table[i];
93 list_lock = &bat_priv->dat.hash->list_locks[i];
94
95 spin_lock_bh(list_lock);
96 hlist_for_each_entry_safe(dat_entry, node, node_tmp, head,
97 hash_entry) {
98 /* if an helper function has been passed as parameter,
99 * ask it if the entry has to be purged or not
100 */
101 if (to_purge && !to_purge(dat_entry))
102 continue;
103
104 hlist_del_rcu(node);
105 batadv_dat_entry_free_ref(dat_entry);
106 }
107 spin_unlock_bh(list_lock);
108 }
109}
110
111/**
112 * batadv_dat_purge - periodic task that deletes old entries from the local DAT
113 * hash table
114 * @work: kernel work struct
115 */
116static void batadv_dat_purge(struct work_struct *work)
117{
118 struct delayed_work *delayed_work;
119 struct batadv_priv_dat *priv_dat;
120 struct batadv_priv *bat_priv;
121
122 delayed_work = container_of(work, struct delayed_work, work);
123 priv_dat = container_of(delayed_work, struct batadv_priv_dat, work);
124 bat_priv = container_of(priv_dat, struct batadv_priv, dat);
125
126 __batadv_dat_purge(bat_priv, batadv_dat_to_purge);
127 batadv_dat_start_timer(bat_priv);
128}
129
130/**
131 * batadv_compare_dat - comparing function used in the local DAT hash table
132 * @node: node in the local table
133 * @data2: second object to compare the node to
134 *
135 * Returns 1 if the two entry are the same, 0 otherwise
136 */
137static int batadv_compare_dat(const struct hlist_node *node, const void *data2)
138{
139 const void *data1 = container_of(node, struct batadv_dat_entry,
140 hash_entry);
141
142 return (memcmp(data1, data2, sizeof(__be32)) == 0 ? 1 : 0);
143}
144
5c3a0e55
AQ
145/**
146 * batadv_arp_hw_src - extract the hw_src field from an ARP packet
147 * @skb: ARP packet
148 * @hdr_size: size of the possible header before the ARP packet
149 *
150 * Returns the value of the hw_src field in the ARP packet
151 */
152static uint8_t *batadv_arp_hw_src(struct sk_buff *skb, int hdr_size)
153{
154 uint8_t *addr;
155
156 addr = (uint8_t *)(skb->data + hdr_size);
157 addr += ETH_HLEN + sizeof(struct arphdr);
158
159 return addr;
160}
161
162/**
163 * batadv_arp_ip_src - extract the ip_src field from an ARP packet
164 * @skb: ARP packet
165 * @hdr_size: size of the possible header before the ARP packet
166 *
167 * Returns the value of the ip_src field in the ARP packet
168 */
169static __be32 batadv_arp_ip_src(struct sk_buff *skb, int hdr_size)
170{
171 return *(__be32 *)(batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN);
172}
173
174/**
175 * batadv_arp_hw_dst - extract the hw_dst field from an ARP packet
176 * @skb: ARP packet
177 * @hdr_size: size of the possible header before the ARP packet
178 *
179 * Returns the value of the hw_dst field in the ARP packet
180 */
181static uint8_t *batadv_arp_hw_dst(struct sk_buff *skb, int hdr_size)
182{
183 return batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN + 4;
184}
185
186/**
187 * batadv_arp_ip_dst - extract the ip_dst field from an ARP packet
188 * @skb: ARP packet
189 * @hdr_size: size of the possible header before the ARP packet
190 *
191 * Returns the value of the ip_dst field in the ARP packet
192 */
193static __be32 batadv_arp_ip_dst(struct sk_buff *skb, int hdr_size)
194{
195 return *(__be32 *)(batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN * 2 + 4);
196}
197
785ea114
AQ
198/**
199 * batadv_hash_dat - compute the hash value for an IP address
200 * @data: data to hash
201 * @size: size of the hash table
202 *
203 * Returns the selected index in the hash table for the given data
204 */
205static uint32_t batadv_hash_dat(const void *data, uint32_t size)
206{
207 const unsigned char *key = data;
208 uint32_t hash = 0;
209 size_t i;
210
211 for (i = 0; i < 4; i++) {
212 hash += key[i];
213 hash += (hash << 10);
214 hash ^= (hash >> 6);
215 }
216
217 hash += (hash << 3);
218 hash ^= (hash >> 11);
219 hash += (hash << 15);
220
221 return hash % size;
222}
223
2f1dfbe1
AQ
224/**
225 * batadv_dat_entry_hash_find - looks for a given dat_entry in the local hash
226 * table
227 * @bat_priv: the bat priv with all the soft interface information
228 * @ip: search key
229 *
230 * Returns the dat_entry if found, NULL otherwise
231 */
232static struct batadv_dat_entry *
233batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, __be32 ip)
234{
235 struct hlist_head *head;
236 struct hlist_node *node;
237 struct batadv_dat_entry *dat_entry, *dat_entry_tmp = NULL;
238 struct batadv_hashtable *hash = bat_priv->dat.hash;
239 uint32_t index;
240
241 if (!hash)
242 return NULL;
243
244 index = batadv_hash_dat(&ip, hash->size);
245 head = &hash->table[index];
246
247 rcu_read_lock();
248 hlist_for_each_entry_rcu(dat_entry, node, head, hash_entry) {
249 if (dat_entry->ip != ip)
250 continue;
251
252 if (!atomic_inc_not_zero(&dat_entry->refcount))
253 continue;
254
255 dat_entry_tmp = dat_entry;
256 break;
257 }
258 rcu_read_unlock();
259
260 return dat_entry_tmp;
261}
262
263/**
264 * batadv_dat_entry_add - add a new dat entry or update it if already exists
265 * @bat_priv: the bat priv with all the soft interface information
266 * @ip: ipv4 to add/edit
267 * @mac_addr: mac address to assign to the given ipv4
268 */
269static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
270 uint8_t *mac_addr)
271{
272 struct batadv_dat_entry *dat_entry;
273 int hash_added;
274
275 dat_entry = batadv_dat_entry_hash_find(bat_priv, ip);
276 /* if this entry is already known, just update it */
277 if (dat_entry) {
278 if (!batadv_compare_eth(dat_entry->mac_addr, mac_addr))
279 memcpy(dat_entry->mac_addr, mac_addr, ETH_ALEN);
280 dat_entry->last_update = jiffies;
281 batadv_dbg(BATADV_DBG_DAT, bat_priv,
282 "Entry updated: %pI4 %pM\n", &dat_entry->ip,
283 dat_entry->mac_addr);
284 goto out;
285 }
286
287 dat_entry = kmalloc(sizeof(*dat_entry), GFP_ATOMIC);
288 if (!dat_entry)
289 goto out;
290
291 dat_entry->ip = ip;
292 memcpy(dat_entry->mac_addr, mac_addr, ETH_ALEN);
293 dat_entry->last_update = jiffies;
294 atomic_set(&dat_entry->refcount, 2);
295
296 hash_added = batadv_hash_add(bat_priv->dat.hash, batadv_compare_dat,
297 batadv_hash_dat, &dat_entry->ip,
298 &dat_entry->hash_entry);
299
300 if (unlikely(hash_added != 0)) {
301 /* remove the reference for the hash */
302 batadv_dat_entry_free_ref(dat_entry);
303 goto out;
304 }
305
306 batadv_dbg(BATADV_DBG_DAT, bat_priv, "New entry added: %pI4 %pM\n",
307 &dat_entry->ip, dat_entry->mac_addr);
308
309out:
310 if (dat_entry)
311 batadv_dat_entry_free_ref(dat_entry);
312}
313
5c3a0e55
AQ
314#ifdef CONFIG_BATMAN_ADV_DEBUG
315
316/**
317 * batadv_dbg_arp - print a debug message containing all the ARP packet details
318 * @bat_priv: the bat priv with all the soft interface information
319 * @skb: ARP packet
320 * @type: ARP type
321 * @hdr_size: size of the possible header before the ARP packet
322 * @msg: message to print together with the debugging information
323 */
324static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
325 uint16_t type, int hdr_size, char *msg)
326{
327 struct batadv_unicast_4addr_packet *unicast_4addr_packet;
328 struct batadv_bcast_packet *bcast_pkt;
329 uint8_t *orig_addr;
330 __be32 ip_src, ip_dst;
331
332 if (msg)
333 batadv_dbg(BATADV_DBG_DAT, bat_priv, "%s\n", msg);
334
335 ip_src = batadv_arp_ip_src(skb, hdr_size);
336 ip_dst = batadv_arp_ip_dst(skb, hdr_size);
337 batadv_dbg(BATADV_DBG_DAT, bat_priv,
338 "ARP MSG = [src: %pM-%pI4 dst: %pM-%pI4]\n",
339 batadv_arp_hw_src(skb, hdr_size), &ip_src,
340 batadv_arp_hw_dst(skb, hdr_size), &ip_dst);
341
342 if (hdr_size == 0)
343 return;
344
345 /* if the ARP packet is encapsulated in a batman packet, let's print
346 * some debug messages
347 */
348 unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
349
350 switch (unicast_4addr_packet->u.header.packet_type) {
351 case BATADV_UNICAST:
352 batadv_dbg(BATADV_DBG_DAT, bat_priv,
353 "* encapsulated within a UNICAST packet\n");
354 break;
355 case BATADV_UNICAST_4ADDR:
356 batadv_dbg(BATADV_DBG_DAT, bat_priv,
357 "* encapsulated within a UNICAST_4ADDR packet (src: %pM)\n",
358 unicast_4addr_packet->src);
359 switch (unicast_4addr_packet->subtype) {
360 case BATADV_P_DAT_DHT_PUT:
361 batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: DAT_DHT_PUT\n");
362 break;
363 case BATADV_P_DAT_DHT_GET:
364 batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: DAT_DHT_GET\n");
365 break;
366 case BATADV_P_DAT_CACHE_REPLY:
367 batadv_dbg(BATADV_DBG_DAT, bat_priv,
368 "* type: DAT_CACHE_REPLY\n");
369 break;
370 case BATADV_P_DATA:
371 batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: DATA\n");
372 break;
373 default:
374 batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: Unknown (%u)!\n",
375 unicast_4addr_packet->u.header.packet_type);
376 }
377 break;
378 case BATADV_BCAST:
379 bcast_pkt = (struct batadv_bcast_packet *)unicast_4addr_packet;
380 orig_addr = bcast_pkt->orig;
381 batadv_dbg(BATADV_DBG_DAT, bat_priv,
382 "* encapsulated within a BCAST packet (src: %pM)\n",
383 orig_addr);
384 break;
385 default:
386 batadv_dbg(BATADV_DBG_DAT, bat_priv,
387 "* encapsulated within an unknown packet type (0x%x)\n",
388 unicast_4addr_packet->u.header.packet_type);
389 }
390}
391
392#else
393
394static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
395 uint16_t type, int hdr_size, char *msg)
396{
397}
398
399#endif /* CONFIG_BATMAN_ADV_DEBUG */
400
785ea114
AQ
401/**
402 * batadv_is_orig_node_eligible - check whether a node can be a DHT candidate
403 * @res: the array with the already selected candidates
404 * @select: number of already selected candidates
405 * @tmp_max: address of the currently evaluated node
406 * @max: current round max address
407 * @last_max: address of the last selected candidate
408 * @candidate: orig_node under evaluation
409 * @max_orig_node: last selected candidate
410 *
411 * Returns true if the node has been elected as next candidate or false othrwise
412 */
413static bool batadv_is_orig_node_eligible(struct batadv_dat_candidate *res,
414 int select, batadv_dat_addr_t tmp_max,
415 batadv_dat_addr_t max,
416 batadv_dat_addr_t last_max,
417 struct batadv_orig_node *candidate,
418 struct batadv_orig_node *max_orig_node)
419{
420 bool ret = false;
421 int j;
422
423 /* Check if this node has already been selected... */
424 for (j = 0; j < select; j++)
425 if (res[j].orig_node == candidate)
426 break;
427 /* ..and possibly skip it */
428 if (j < select)
429 goto out;
430 /* sanity check: has it already been selected? This should not happen */
431 if (tmp_max > last_max)
432 goto out;
433 /* check if during this iteration an originator with a closer dht
434 * address has already been found
435 */
436 if (tmp_max < max)
437 goto out;
438 /* this is an hash collision with the temporary selected node. Choose
439 * the one with the lowest address
440 */
441 if ((tmp_max == max) &&
442 (batadv_compare_eth(candidate->orig, max_orig_node->orig) > 0))
443 goto out;
444
445 ret = true;
446out:
447 return ret;
448}
449
450/**
451 * batadv_choose_next_candidate - select the next DHT candidate
452 * @bat_priv: the bat priv with all the soft interface information
453 * @cands: candidates array
454 * @select: number of candidates already present in the array
455 * @ip_key: key to look up in the DHT
456 * @last_max: pointer where the address of the selected candidate will be saved
457 */
458static void batadv_choose_next_candidate(struct batadv_priv *bat_priv,
459 struct batadv_dat_candidate *cands,
460 int select, batadv_dat_addr_t ip_key,
461 batadv_dat_addr_t *last_max)
462{
463 batadv_dat_addr_t max = 0, tmp_max = 0;
464 struct batadv_orig_node *orig_node, *max_orig_node = NULL;
465 struct batadv_hashtable *hash = bat_priv->orig_hash;
466 struct hlist_node *node;
467 struct hlist_head *head;
468 int i;
469
470 /* if no node is eligible as candidate, leave the candidate type as
471 * NOT_FOUND
472 */
473 cands[select].type = BATADV_DAT_CANDIDATE_NOT_FOUND;
474
475 /* iterate over the originator list and find the node with closest
476 * dat_address which has not been selected yet
477 */
478 for (i = 0; i < hash->size; i++) {
479 head = &hash->table[i];
480
481 rcu_read_lock();
482 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
483 /* the dht space is a ring and addresses are unsigned */
484 tmp_max = BATADV_DAT_ADDR_MAX - orig_node->dat_addr +
485 ip_key;
486
487 if (!batadv_is_orig_node_eligible(cands, select,
488 tmp_max, max,
489 *last_max, orig_node,
490 max_orig_node))
491 continue;
492
493 if (!atomic_inc_not_zero(&orig_node->refcount))
494 continue;
495
496 max = tmp_max;
497 if (max_orig_node)
498 batadv_orig_node_free_ref(max_orig_node);
499 max_orig_node = orig_node;
500 }
501 rcu_read_unlock();
502 }
503 if (max_orig_node) {
504 cands[select].type = BATADV_DAT_CANDIDATE_ORIG;
505 cands[select].orig_node = max_orig_node;
506 batadv_dbg(BATADV_DBG_DAT, bat_priv,
507 "dat_select_candidates() %d: selected %pM addr=%u dist=%u\n",
508 select, max_orig_node->orig, max_orig_node->dat_addr,
509 max);
510 }
511 *last_max = max;
512}
513
514/**
515 * batadv_dat_select_candidates - selects the nodes which the DHT message has to
516 * be sent to
517 * @bat_priv: the bat priv with all the soft interface information
518 * @ip_dst: ipv4 to look up in the DHT
519 *
520 * An originator O is selected if and only if its DHT_ID value is one of three
521 * closest values (from the LEFT, with wrap around if needed) then the hash
522 * value of the key. ip_dst is the key.
523 *
524 * Returns the candidate array of size BATADV_DAT_CANDIDATE_NUM
525 */
526static struct batadv_dat_candidate *
527batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
528{
529 int select;
530 batadv_dat_addr_t last_max = BATADV_DAT_ADDR_MAX, ip_key;
531 struct batadv_dat_candidate *res;
532
533 if (!bat_priv->orig_hash)
534 return NULL;
535
536 res = kmalloc(BATADV_DAT_CANDIDATES_NUM * sizeof(*res), GFP_ATOMIC);
537 if (!res)
538 return NULL;
539
540 ip_key = (batadv_dat_addr_t)batadv_hash_dat(&ip_dst,
541 BATADV_DAT_ADDR_MAX);
542
543 batadv_dbg(BATADV_DBG_DAT, bat_priv,
544 "dat_select_candidates(): IP=%pI4 hash(IP)=%u\n", &ip_dst,
545 ip_key);
546
547 for (select = 0; select < BATADV_DAT_CANDIDATES_NUM; select++)
548 batadv_choose_next_candidate(bat_priv, res, select, ip_key,
549 &last_max);
550
551 return res;
552}
553
554/**
555 * batadv_dat_send_data - send a payload to the selected candidates
556 * @bat_priv: the bat priv with all the soft interface information
557 * @skb: payload to send
558 * @ip: the DHT key
559 * @packet_subtype: unicast4addr packet subtype to use
560 *
561 * In this function the skb is copied by means of pskb_copy() and is sent as
562 * unicast packet to each of the selected candidates
563 *
564 * Returns true if the packet is sent to at least one candidate, false otherwise
565 */
566static bool batadv_dat_send_data(struct batadv_priv *bat_priv,
567 struct sk_buff *skb, __be32 ip,
568 int packet_subtype)
569{
570 int i;
571 bool ret = false;
572 int send_status;
573 struct batadv_neigh_node *neigh_node = NULL;
574 struct sk_buff *tmp_skb;
575 struct batadv_dat_candidate *cand;
576
577 cand = batadv_dat_select_candidates(bat_priv, ip);
578 if (!cand)
579 goto out;
580
581 batadv_dbg(BATADV_DBG_DAT, bat_priv, "DHT_SEND for %pI4\n", &ip);
582
583 for (i = 0; i < BATADV_DAT_CANDIDATES_NUM; i++) {
584 if (cand[i].type == BATADV_DAT_CANDIDATE_NOT_FOUND)
585 continue;
586
587 neigh_node = batadv_orig_node_get_router(cand[i].orig_node);
588 if (!neigh_node)
589 goto free_orig;
590
591 tmp_skb = pskb_copy(skb, GFP_ATOMIC);
592 if (!batadv_unicast_4addr_prepare_skb(bat_priv, tmp_skb,
593 cand[i].orig_node,
594 packet_subtype)) {
595 kfree_skb(tmp_skb);
596 goto free_neigh;
597 }
598
599 send_status = batadv_send_skb_packet(tmp_skb,
600 neigh_node->if_incoming,
601 neigh_node->addr);
602 if (send_status == NET_XMIT_SUCCESS)
603 /* packet sent to a candidate: return true */
604 ret = true;
605free_neigh:
606 batadv_neigh_node_free_ref(neigh_node);
607free_orig:
608 batadv_orig_node_free_ref(cand[i].orig_node);
609 }
610
611out:
612 kfree(cand);
613 return ret;
614}
2f1dfbe1
AQ
615
616/**
617 * batadv_dat_hash_free - free the local DAT hash table
618 * @bat_priv: the bat priv with all the soft interface information
619 */
620static void batadv_dat_hash_free(struct batadv_priv *bat_priv)
621{
622 __batadv_dat_purge(bat_priv, NULL);
623
624 batadv_hash_destroy(bat_priv->dat.hash);
625
626 bat_priv->dat.hash = NULL;
627}
628
629/**
630 * batadv_dat_init - initialise the DAT internals
631 * @bat_priv: the bat priv with all the soft interface information
632 */
633int batadv_dat_init(struct batadv_priv *bat_priv)
634{
635 if (bat_priv->dat.hash)
636 return 0;
637
638 bat_priv->dat.hash = batadv_hash_new(1024);
639
640 if (!bat_priv->dat.hash)
641 return -ENOMEM;
642
643 batadv_dat_start_timer(bat_priv);
644
645 return 0;
646}
647
648/**
649 * batadv_dat_free - free the DAT internals
650 * @bat_priv: the bat priv with all the soft interface information
651 */
652void batadv_dat_free(struct batadv_priv *bat_priv)
653{
654 cancel_delayed_work_sync(&bat_priv->dat.work);
655
656 batadv_dat_hash_free(bat_priv);
657}
658
659/**
660 * batadv_dat_cache_seq_print_text - print the local DAT hash table
661 * @seq: seq file to print on
662 * @offset: not used
663 */
664int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset)
665{
666 struct net_device *net_dev = (struct net_device *)seq->private;
667 struct batadv_priv *bat_priv = netdev_priv(net_dev);
668 struct batadv_hashtable *hash = bat_priv->dat.hash;
669 struct batadv_dat_entry *dat_entry;
670 struct batadv_hard_iface *primary_if;
671 struct hlist_node *node;
672 struct hlist_head *head;
673 unsigned long last_seen_jiffies;
674 int last_seen_msecs, last_seen_secs, last_seen_mins;
675 uint32_t i;
676
677 primary_if = batadv_seq_print_text_primary_if_get(seq);
678 if (!primary_if)
679 goto out;
680
681 seq_printf(seq, "Distributed ARP Table (%s):\n", net_dev->name);
682 seq_printf(seq, " %-7s %-13s %5s\n", "IPv4", "MAC",
683 "last-seen");
684
685 for (i = 0; i < hash->size; i++) {
686 head = &hash->table[i];
687
688 rcu_read_lock();
689 hlist_for_each_entry_rcu(dat_entry, node, head, hash_entry) {
690 last_seen_jiffies = jiffies - dat_entry->last_update;
691 last_seen_msecs = jiffies_to_msecs(last_seen_jiffies);
692 last_seen_mins = last_seen_msecs / 60000;
693 last_seen_msecs = last_seen_msecs % 60000;
694 last_seen_secs = last_seen_msecs / 1000;
695
696 seq_printf(seq, " * %15pI4 %14pM %6i:%02i\n",
697 &dat_entry->ip, dat_entry->mac_addr,
698 last_seen_mins, last_seen_secs);
699 }
700 rcu_read_unlock();
701 }
702
703out:
704 if (primary_if)
705 batadv_hardif_free_ref(primary_if);
706 return 0;
707}
5c3a0e55
AQ
708
709/**
710 * batadv_arp_get_type - parse an ARP packet and gets the type
711 * @bat_priv: the bat priv with all the soft interface information
712 * @skb: packet to analyse
713 * @hdr_size: size of the possible header before the ARP packet in the skb
714 *
715 * Returns the ARP type if the skb contains a valid ARP packet, 0 otherwise
716 */
717static uint16_t batadv_arp_get_type(struct batadv_priv *bat_priv,
718 struct sk_buff *skb, int hdr_size)
719{
720 struct arphdr *arphdr;
721 struct ethhdr *ethhdr;
722 __be32 ip_src, ip_dst;
723 uint16_t type = 0;
724
725 /* pull the ethernet header */
726 if (unlikely(!pskb_may_pull(skb, hdr_size + ETH_HLEN)))
727 goto out;
728
729 ethhdr = (struct ethhdr *)(skb->data + hdr_size);
730
731 if (ethhdr->h_proto != htons(ETH_P_ARP))
732 goto out;
733
734 /* pull the ARP payload */
735 if (unlikely(!pskb_may_pull(skb, hdr_size + ETH_HLEN +
736 arp_hdr_len(skb->dev))))
737 goto out;
738
739 arphdr = (struct arphdr *)(skb->data + hdr_size + ETH_HLEN);
740
741 /* Check whether the ARP packet carries a valid
742 * IP information
743 */
744 if (arphdr->ar_hrd != htons(ARPHRD_ETHER))
745 goto out;
746
747 if (arphdr->ar_pro != htons(ETH_P_IP))
748 goto out;
749
750 if (arphdr->ar_hln != ETH_ALEN)
751 goto out;
752
753 if (arphdr->ar_pln != 4)
754 goto out;
755
756 /* Check for bad reply/request. If the ARP message is not sane, DAT
757 * will simply ignore it
758 */
759 ip_src = batadv_arp_ip_src(skb, hdr_size);
760 ip_dst = batadv_arp_ip_dst(skb, hdr_size);
761 if (ipv4_is_loopback(ip_src) || ipv4_is_multicast(ip_src) ||
762 ipv4_is_loopback(ip_dst) || ipv4_is_multicast(ip_dst))
763 goto out;
764
765 type = ntohs(arphdr->ar_op);
766out:
767 return type;
768}