diff options
author | Antonio Quartulli <ordex@autistici.org> | 2011-06-02 06:29:51 -0400 |
---|---|---|
committer | Antonio Quartulli <ordex@autistici.org> | 2012-11-07 14:00:20 -0500 |
commit | 5c3a0e5535933349a5d6e6bc8b704e0611f21d3f (patch) | |
tree | d94e306819e2dee3e3af5b413bb78e45d2b42e46 /net | |
parent | 2f1dfbe185075a50dc8f0490a136377af53a1c62 (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/Kconfig | 4 | ||||
-rw-r--r-- | net/batman-adv/distributed-arp-table.c | 202 | ||||
-rw-r--r-- | net/batman-adv/distributed-arp-table.h | 2 | ||||
-rw-r--r-- | net/batman-adv/packet.h | 8 |
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 | ||
5 | config BATMAN_ADV | 5 | config 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 | ||
17 | config BATMAN_ADV_BLA | 17 | config 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 | */ | ||
152 | static 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 | */ | ||
169 | static __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 | */ | ||
181 | static 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 | */ | ||
193 | static __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 | */ | ||
324 | static 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 | |||
394 | static 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 | */ | ||
717 | static 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); | ||
766 | out: | ||
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 | */ |
41 | enum batadv_subtype { | 44 | enum 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 */ |