aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorAntonio Quartulli <ordex@autistici.org>2011-06-02 06:29:51 -0400
committerAntonio Quartulli <ordex@autistici.org>2012-11-07 14:00:20 -0500
commit5c3a0e5535933349a5d6e6bc8b704e0611f21d3f (patch)
treed94e306819e2dee3e3af5b413bb78e45d2b42e46 /net
parent2f1dfbe185075a50dc8f0490a136377af53a1c62 (diff)
batman-adv: Distributed ARP Table - add ARP parsing functions
ARP messages are now parsed to make it possible to trigger special actions depending on their types (snooping). Signed-off-by: Antonio Quartulli <ordex@autistici.org>
Diffstat (limited to 'net')
-rw-r--r--net/batman-adv/Kconfig4
-rw-r--r--net/batman-adv/distributed-arp-table.c202
-rw-r--r--net/batman-adv/distributed-arp-table.h2
-rw-r--r--net/batman-adv/packet.h8
4 files changed, 213 insertions, 3 deletions
diff --git a/net/batman-adv/Kconfig b/net/batman-adv/Kconfig
index 53f5244e28f8..e77f805d38da 100644
--- a/net/batman-adv/Kconfig
+++ b/net/batman-adv/Kconfig
@@ -4,7 +4,7 @@
4 4
5config BATMAN_ADV 5config BATMAN_ADV
6 tristate "B.A.T.M.A.N. Advanced Meshing Protocol" 6 tristate "B.A.T.M.A.N. Advanced Meshing Protocol"
7 depends on NET 7 depends on NET && INET
8 select CRC16 8 select CRC16
9 default n 9 default n
10 help 10 help
@@ -16,7 +16,7 @@ config BATMAN_ADV
16 16
17config BATMAN_ADV_BLA 17config BATMAN_ADV_BLA
18 bool "Bridge Loop Avoidance" 18 bool "Bridge Loop Avoidance"
19 depends on BATMAN_ADV && INET 19 depends on BATMAN_ADV
20 default y 20 default y
21 help 21 help
22 This option enables BLA (Bridge Loop Avoidance), a mechanism 22 This option enables BLA (Bridge Loop Avoidance), a mechanism
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
index 2ef90e3ea2c4..49a213ce2aac 100644
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@ -21,6 +21,7 @@
21#include <linux/if_arp.h> 21#include <linux/if_arp.h>
22 22
23#include "main.h" 23#include "main.h"
24#include "hash.h"
24#include "distributed-arp-table.h" 25#include "distributed-arp-table.h"
25#include "hard-interface.h" 26#include "hard-interface.h"
26#include "originator.h" 27#include "originator.h"
@@ -142,6 +143,59 @@ static int batadv_compare_dat(const struct hlist_node *node, const void *data2)
142} 143}
143 144
144/** 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
198/**
145 * batadv_hash_dat - compute the hash value for an IP address 199 * batadv_hash_dat - compute the hash value for an IP address
146 * @data: data to hash 200 * @data: data to hash
147 * @size: size of the hash table 201 * @size: size of the hash table
@@ -257,6 +311,93 @@ out:
257 batadv_dat_entry_free_ref(dat_entry); 311 batadv_dat_entry_free_ref(dat_entry);
258} 312}
259 313
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
260/** 401/**
261 * batadv_is_orig_node_eligible - check whether a node can be a DHT candidate 402 * batadv_is_orig_node_eligible - check whether a node can be a DHT candidate
262 * @res: the array with the already selected candidates 403 * @res: the array with the already selected candidates
@@ -564,3 +705,64 @@ out:
564 batadv_hardif_free_ref(primary_if); 705 batadv_hardif_free_ref(primary_if);
565 return 0; 706 return 0;
566} 707}
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}
diff --git a/net/batman-adv/distributed-arp-table.h b/net/batman-adv/distributed-arp-table.h
index 1b88303ed6c2..f4e282a6e634 100644
--- a/net/batman-adv/distributed-arp-table.h
+++ b/net/batman-adv/distributed-arp-table.h
@@ -23,6 +23,8 @@
23#include "types.h" 23#include "types.h"
24#include "originator.h" 24#include "originator.h"
25 25
26#include <linux/if_arp.h>
27
26#define BATADV_DAT_ADDR_MAX ((batadv_dat_addr_t)~(batadv_dat_addr_t)0) 28#define BATADV_DAT_ADDR_MAX ((batadv_dat_addr_t)~(batadv_dat_addr_t)0)
27 29
28/** 30/**
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index 0f8dcf337df2..df548ed196d3 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -37,9 +37,15 @@ enum batadv_packettype {
37/** 37/**
38 * enum batadv_subtype - packet subtype for unicast4addr 38 * enum batadv_subtype - packet subtype for unicast4addr
39 * @BATADV_P_DATA: user payload 39 * @BATADV_P_DATA: user payload
40 * @BATADV_P_DAT_DHT_GET: DHT request message
41 * @BATADV_P_DAT_DHT_PUT: DHT store message
42 * @BATADV_P_DAT_CACHE_REPLY: ARP reply generated by DAT
40 */ 43 */
41enum batadv_subtype { 44enum batadv_subtype {
42 BATADV_P_DATA = 0x01, 45 BATADV_P_DATA = 0x01,
46 BATADV_P_DAT_DHT_GET = 0x02,
47 BATADV_P_DAT_DHT_PUT = 0x03,
48 BATADV_P_DAT_CACHE_REPLY = 0x04,
43}; 49};
44 50
45/* this file is included by batctl which needs these defines */ 51/* this file is included by batctl which needs these defines */