[B.A.T.M.A.N.] [PATCH 1/2] batman-adv: Fix broadcast+ogm queue purging race condition
by Linus Lüssing
So far on purging broadcast and ogm queues we temporarily give up the
spin lock of these queues to be able to cancel any scheduled forwarding
work. However this is unsafe and can lead to a general protection error
in batadv_purge_outstanding_packets().
With this patch we split the queue purging into two steps: First
removing forward packets from those queues and signaling the
cancelation. Secondly, we are actively canceling any scheduled
forwarding, wait for any running forwarding to finish and only free a
forw_packet afterwards.
Signed-off-by: Linus Lüssing <linus.luessing(a)web.de>
---
Fixes issue #168
send.c | 117 ++++++++++++++++++++++++++++++++++++++-------------------------
types.h | 1 +
2 files changed, 71 insertions(+), 47 deletions(-)
diff --git a/send.c b/send.c
index 0a0bb45..f93476b 100644
--- a/send.c
+++ b/send.c
@@ -245,6 +245,10 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
bat_priv = netdev_priv(soft_iface);
spin_lock_bh(&bat_priv->forw_bcast_list_lock);
+ if (hlist_unhashed(&forw_packet->list)) {
+ spin_unlock_bh(&bat_priv->forw_bcast_list_lock);
+ return;
+ }
hlist_del(&forw_packet->list);
spin_unlock_bh(&bat_priv->forw_bcast_list_lock);
@@ -293,6 +297,10 @@ void batadv_send_outstanding_bat_ogm_packet(struct work_struct *work)
delayed_work);
bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface);
spin_lock_bh(&bat_priv->forw_bat_list_lock);
+ if (hlist_unhashed(&forw_packet->list)) {
+ spin_unlock_bh(&bat_priv->forw_bat_list_lock);
+ return;
+ }
hlist_del(&forw_packet->list);
spin_unlock_bh(&bat_priv->forw_bat_list_lock);
@@ -316,13 +324,68 @@ out:
batadv_forw_packet_free(forw_packet);
}
+/**
+ * batadv_cancel_packets - Cancels a list of forward packets
+ * @forw_list: The to be canceled forward packets
+ * @canceled_list: The backup list.
+ *
+ * This canceles any scheduled forwarding packet tasks in the provided
+ * forw_list. The packets are being moved from the forw_list to the
+ * canceled_list afterwards to unhash the forward packet list pointer,
+ * allowing any already running task to notice the cancelation.
+ */
+static void batadv_cancel_packets(struct hlist_head *forw_list,
+ struct hlist_head *canceled_list,
+ const struct batadv_hard_iface *hard_iface)
+{
+ struct batadv_forw_packet *forw_packet;
+ struct hlist_node *tmp_node, *safe_tmp_node;
+
+ hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node,
+ forw_list, list) {
+ /* if purge_outstanding_packets() was called with an argument
+ * we delete only packets belonging to the given interface
+ */
+ if ((hard_iface) &&
+ (forw_packet->if_incoming != hard_iface))
+ continue;
+
+ hlist_del_init(&forw_packet->list);
+ hlist_add_head(&forw_packet->canceled_list, canceled_list);
+ }
+}
+
+/**
+ * batadv_canceled_packets_free - Frees canceled forward packets
+ * @head: A list of to be freed forw_packets
+ *
+ * This function canceles the scheduling of any packet in the provided list,
+ * waits for any possibly running packet forwarding thread to finish and
+ * finally, safely frees this forward packet.
+ *
+ * This function might sleep.
+ */
+static void batadv_canceled_packets_free(struct hlist_head *head)
+{
+ struct batadv_forw_packet *forw_packet;
+ struct hlist_node *tmp_node, *safe_tmp_node;
+
+ hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node, head,
+ canceled_list) {
+ cancel_delayed_work_sync(&forw_packet->delayed_work);
+
+ hlist_del(&forw_packet->canceled_list);
+ batadv_forw_packet_free(forw_packet);
+ }
+}
+
void
batadv_purge_outstanding_packets(struct batadv_priv *bat_priv,
const struct batadv_hard_iface *hard_iface)
{
- struct batadv_forw_packet *forw_packet;
- struct hlist_node *tmp_node, *safe_tmp_node;
- bool pending;
+ struct hlist_head head;
+
+ INIT_HLIST_HEAD(&head);
if (hard_iface)
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
@@ -334,53 +397,13 @@ batadv_purge_outstanding_packets(struct batadv_priv *bat_priv,
/* free bcast list */
spin_lock_bh(&bat_priv->forw_bcast_list_lock);
- hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node,
- &bat_priv->forw_bcast_list, list) {
- /* if purge_outstanding_packets() was called with an argument
- * we delete only packets belonging to the given interface
- */
- if ((hard_iface) &&
- (forw_packet->if_incoming != hard_iface))
- continue;
-
- spin_unlock_bh(&bat_priv->forw_bcast_list_lock);
-
- /* batadv_send_outstanding_bcast_packet() will lock the list to
- * delete the item from the list
- */
- pending = cancel_delayed_work_sync(&forw_packet->delayed_work);
- spin_lock_bh(&bat_priv->forw_bcast_list_lock);
-
- if (pending) {
- hlist_del(&forw_packet->list);
- batadv_forw_packet_free(forw_packet);
- }
- }
+ batadv_cancel_packets(&bat_priv->forw_bcast_list, &head, hard_iface);
spin_unlock_bh(&bat_priv->forw_bcast_list_lock);
/* free batman packet list */
spin_lock_bh(&bat_priv->forw_bat_list_lock);
- hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node,
- &bat_priv->forw_bat_list, list) {
- /* if purge_outstanding_packets() was called with an argument
- * we delete only packets belonging to the given interface
- */
- if ((hard_iface) &&
- (forw_packet->if_incoming != hard_iface))
- continue;
-
- spin_unlock_bh(&bat_priv->forw_bat_list_lock);
-
- /* send_outstanding_bat_packet() will lock the list to
- * delete the item from the list
- */
- pending = cancel_delayed_work_sync(&forw_packet->delayed_work);
- spin_lock_bh(&bat_priv->forw_bat_list_lock);
-
- if (pending) {
- hlist_del(&forw_packet->list);
- batadv_forw_packet_free(forw_packet);
- }
- }
+ batadv_cancel_packets(&bat_priv->forw_bat_list, &head, hard_iface);
spin_unlock_bh(&bat_priv->forw_bat_list_lock);
+
+ batadv_canceled_packets_free(&head);
}
diff --git a/types.h b/types.h
index aba8364..f62a35f 100644
--- a/types.h
+++ b/types.h
@@ -853,6 +853,7 @@ struct batadv_skb_cb {
*/
struct batadv_forw_packet {
struct hlist_node list;
+ struct hlist_node canceled_list;
unsigned long send_time;
uint8_t own;
struct sk_buff *skb;
--
1.7.10.4
4 years, 8 months
[B.A.T.M.A.N.] Classes and purposed classes (problem to solve)
by cmsv
Scenario:
I have recently moved 13 nodes previously using wds to batman-adv.
One problem that i am encountering is the gateway selection and its
actually defectiveness.
This problem has be seen when the client nodes are set on class 20.
The node clients in fact select the gateways that advertise better link
quality usually above 200 but at the same time some clients end up
connecting to a gateway that is either too slow or unusable either due
to routing or other factors such as distance and even clear visibility.
In one case the node connects to something that defies logic.
I thought about ways to work around this and came up with an idea that
may help which means the creation of 2 new classes.
- Preferred gateway fall-back
- Preferred fixed gateway
For Preferred gateway fall-back:
consider the gateway's advertised quality towards the gateway and stick
with the selection until the gateway disappears returning to it soon as
it returns regardless of any other data.
- Preferred fixed gateway
Manual gateway selection by the node owner or admin. (wds type)
If these classes cannot be created; maybe a plugin of some sort could
be. could be called "gordon".
I understand that this idea may sound useless the same way blocking
originators may be for someone but in some scenarios just like blocking
originators it look to me very valid.
My current problem is that the link quality seems to go up and down like
a roller coaster in a specific order which causes the clients to switch
constantly sometimes many times per hour.
While this does not seem to be an issue for most client nodes; for 2 of
them it means no internet access at all.
The solution for now seems to be having these 2 nodes forced to use 1
specific gateway.
I am quite open to any ideas that may help resolve this issue that has
been casing some "uninformed people" to become headaches.
--
Redes wireless
http://wirelesspt.net
5 years, 4 months
[B.A.T.M.A.N.] [PATCH] batman-adv: Fix general protection fault in batadv_tt_global_del_orig()
by Linus Lüssing
On shutdown a race condition where we access a just freed global TT hash
might occure:
batadv_mesh_free()->batadv_originator_free() schedules the
batadv_orig_node_free_rcu().
Before batadv_orig_node_free_rcu() is executed (which happens on the
rcu_barrier() call in batadv_exit() the latest),
batadv_mesh_free()->batadv_tt_free()->batadv_tt_global_table_free()->
batadv_hash_destroy(hash)->kfree(hash)
is called, freeing the global tt hash.
When batadv_orig_node_free_rcu()->batadv_tt_global_del_orig() now gets
executed it tries to access this just freed global tt hash, causing a
kernel panic.
This patch tries to fix this by waiting for any just scheduled
batadv_orig_node_free_rcu() to finish via an extra rcu_barrier() call
before freeing the global TT hash.
Signed-off-by: Linus Lüssing <linus.luessing(a)web.de>
---
Ref: #169
main.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/main.c b/main.c
index 62b1f89..0afc171 100644
--- a/main.c
+++ b/main.c
@@ -164,6 +164,11 @@ void batadv_mesh_free(struct net_device *soft_iface)
batadv_gw_node_purge(bat_priv);
batadv_originator_free(bat_priv);
+
+ /* Wait for any batadv_orig_node_free_rcu() to finish,
+ * they access the soon to be freed global TT hash */
+ rcu_barrier();
+
batadv_nc_free(bat_priv);
batadv_tt_free(bat_priv);
--
1.7.10.4
7 years, 11 months
[B.A.T.M.A.N.] [PATCH] batman-adv: do not silently ignore wrong condition
by Antonio Quartulli
Only one neigh_node per orig_node should match a given
neighbor address, therefore, if more than one matching
neigh_node is found, a WARNING has to be triggered to let
the user know that something is wrong in the originator
state instead of silently skipping the error.
Signed-off-by: Antonio Quartulli <ordex(a)autistici.org>
---
bat_iv_ogm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/bat_iv_ogm.c b/bat_iv_ogm.c
index 38183dc..9fbf588 100644
--- a/bat_iv_ogm.c
+++ b/bat_iv_ogm.c
@@ -669,7 +669,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
if (batadv_compare_eth(neigh_addr, ethhdr->h_source) &&
tmp_neigh_node->if_incoming == if_incoming &&
atomic_inc_not_zero(&tmp_neigh_node->refcount)) {
- if (neigh_node)
+ if (WARN(neigh_node, "too many matching neigh_nodes")
batadv_neigh_node_free_ref(neigh_node);
neigh_node = tmp_neigh_node;
continue;
--
1.8.1.5
8 years
[B.A.T.M.A.N.] [PATCH] batman-adv: don't check compat version twice
by Antonio Quartulli
From: Antonio Quartulli <antonio(a)open-mesh.com>
Compatibility version is checked upon packet reception
before calling any handler. For this reason it does need to
be checked once more in the handler itself.
Signed-off-by: Antonio Quartulli <antonio(a)open-mesh.com>
---
bat_iv_ogm.c | 7 -------
1 file changed, 7 deletions(-)
diff --git a/bat_iv_ogm.c b/bat_iv_ogm.c
index 6d62e29..38183dc 100644
--- a/bat_iv_ogm.c
+++ b/bat_iv_ogm.c
@@ -1054,13 +1054,6 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
}
rcu_read_unlock();
- if (batadv_ogm_packet->header.version != BATADV_COMPAT_VERSION) {
- batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
- "Drop packet: incompatible batman version (%i)\n",
- batadv_ogm_packet->header.version);
- return;
- }
-
if (is_my_addr) {
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"Drop packet: received my own broadcast (sender: %pM)\n",
--
1.8.1.5
8 years
[B.A.T.M.A.N.] [PATCHv2] batman-adv: don't check the source address twice
by Antonio Quartulli
From: Antonio Quartulli <antonio(a)open-mesh.com>
The source address has already been checked in
batadv_check_management_packet() upon packet reception and
therefore it does not need to be checked again in
ogm_process()
Signed-off-by: Antonio Quartulli <antonio(a)open-mesh.com>
---
v2:
- removed variable declaration
bat_iv_ogm.c | 12 +-----------
1 file changed, 1 insertion(+), 11 deletions(-)
diff --git a/bat_iv_ogm.c b/bat_iv_ogm.c
index da239c5..6d62e29 100644
--- a/bat_iv_ogm.c
+++ b/bat_iv_ogm.c
@@ -988,7 +988,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
struct batadv_neigh_node *orig_neigh_router = NULL;
int has_directlink_flag;
int is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0;
- int is_broadcast = 0, is_bidirect;
+ int is_bidirect;
bool is_single_hop_neigh = false;
bool is_from_best_next_hop = false;
int is_duplicate, sameseq, simlar_ttl;
@@ -1051,9 +1051,6 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
if (batadv_compare_eth(batadv_ogm_packet->prev_sender,
hard_iface->net_dev->dev_addr))
is_my_oldorig = 1;
-
- if (is_broadcast_ether_addr(ethhdr->h_source))
- is_broadcast = 1;
}
rcu_read_unlock();
@@ -1071,13 +1068,6 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
return;
}
- if (is_broadcast) {
- batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
- "Drop packet: ignoring all packets with broadcast source addr (sender: %pM)\n",
- ethhdr->h_source);
- return;
- }
-
if (is_my_orig) {
unsigned long *word;
int offset;
--
1.8.1.5
8 years
[B.A.T.M.A.N.] [PATCH 1/2] batman-adv: drop useless argument seqno in neighbor creation
by Antonio Quartulli
From: Antonio Quartulli <antonio(a)open-mesh.com>
the sequence number is not stored in struct neigh_node,
therefore there is no need to pass such value to the
neigh_node creation procedure.
At the moment the value is only used by a debug message, but
given the fact that the seqno is not related to the neighbor
object, it is better to print it elsewhere.
Signed-off-by: Antonio Quartulli <antonio(a)open-mesh.com>
---
do we really want to pass the seqno over every function just to print it at the
end? If this value is really important (debug? don't know) it should be printed
in a proper place, e.g. in the function that triggered the creation and that
possibly has the seqno for other purposes...
Otherwise we would not be able to create a neigh_nod unless we have a seqno to
pass.
Cheers,
bat_iv_ogm.c | 11 ++++-------
originator.c | 5 ++---
originator.h | 2 +-
3 files changed, 7 insertions(+), 11 deletions(-)
diff --git a/bat_iv_ogm.c b/bat_iv_ogm.c
index 071f288..da239c5 100644
--- a/bat_iv_ogm.c
+++ b/bat_iv_ogm.c
@@ -33,12 +33,11 @@ static struct batadv_neigh_node *
batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
const uint8_t *neigh_addr,
struct batadv_orig_node *orig_node,
- struct batadv_orig_node *orig_neigh, __be32 seqno)
+ struct batadv_orig_node *orig_neigh)
{
struct batadv_neigh_node *neigh_node;
- neigh_node = batadv_neigh_node_new(hard_iface, neigh_addr,
- ntohl(seqno));
+ neigh_node = batadv_neigh_node_new(hard_iface, neigh_addr);
if (!neigh_node)
goto out;
@@ -696,8 +695,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
ethhdr->h_source,
- orig_node, orig_tmp,
- batadv_ogm_packet->seqno);
+ orig_node, orig_tmp);
batadv_orig_node_free_ref(orig_tmp);
if (!neigh_node)
@@ -829,8 +827,7 @@ static int batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
neigh_node = batadv_iv_ogm_neigh_new(if_incoming,
orig_neigh_node->orig,
orig_neigh_node,
- orig_neigh_node,
- batadv_ogm_packet->seqno);
+ orig_neigh_node);
if (!neigh_node)
goto out;
diff --git a/originator.c b/originator.c
index 2f34525..ddd417c 100644
--- a/originator.c
+++ b/originator.c
@@ -92,7 +92,7 @@ batadv_orig_node_get_router(struct batadv_orig_node *orig_node)
struct batadv_neigh_node *
batadv_neigh_node_new(struct batadv_hard_iface *hard_iface,
- const uint8_t *neigh_addr, uint32_t seqno)
+ const uint8_t *neigh_addr)
{
struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
struct batadv_neigh_node *neigh_node;
@@ -110,8 +110,7 @@ batadv_neigh_node_new(struct batadv_hard_iface *hard_iface,
atomic_set(&neigh_node->refcount, 2);
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
- "Creating new neighbor %pM, initial seqno %d\n",
- neigh_addr, seqno);
+ "Creating new neighbor %pM\n", neigh_addr);
out:
return neigh_node;
diff --git a/originator.h b/originator.h
index 7df48fa..476c623 100644
--- a/originator.h
+++ b/originator.h
@@ -30,7 +30,7 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
const uint8_t *addr);
struct batadv_neigh_node *
batadv_neigh_node_new(struct batadv_hard_iface *hard_iface,
- const uint8_t *neigh_addr, uint32_t seqno);
+ const uint8_t *neigh_addr);
void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node);
struct batadv_neigh_node *
batadv_orig_node_get_router(struct batadv_orig_node *orig_node);
--
1.8.1.5
8 years
[B.A.T.M.A.N.] [RFCv2] batman-adv: Modified DAT structures and functions in order to support both IPv4 and IPv6
by Mihail Costea
Subject: [RFCv2] batman-adv: Modified DAT structures and functions in order
to support both IPv4 and IPv6
Signed-off-by: Mihail Costea <mihail.costea90(a)gmail.com>
---
Modified the debug message macro to a function and made it more generic
(in order to support seq_printf too).
Added IPv6 macros in order to NOT add IPv6 dependent code if support
is disabled. Also, removed as many switch-cases as possible to have less
"if defined(IPv6)" tests.
Added call_rcu for kfree dat_entry.
For compare function, test if both data fields have the same type.
distributed-arp-table.c | 338 +++++++++++++++++++++++++++++++++++++++--------
types.h | 23 +++-
2 files changed, 301 insertions(+), 60 deletions(-)
diff --git a/distributed-arp-table.c b/distributed-arp-table.c
index 3a3e1d8..30b683e 100644
--- a/distributed-arp-table.c
+++ b/distributed-arp-table.c
@@ -20,6 +20,7 @@
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <net/arp.h>
+#include <net/ipv6.h>
#include "main.h"
#include "hash.h"
@@ -31,6 +32,115 @@
#include "translation-table.h"
#include "unicast.h"
+/**
+ * batadv_dat_ip_format_string - construct a generic ip format string
+ * for printing
+ * @ip_type: IPv4 / IPv6 address
+ * @format_prefix: format before IP field
+ * @format_suffix: format after IP field
+ * @width: padding blank spaces for IP field or 0 if none
+ *
+ * format_string is allocated dynamically. It should be kfree when
+ * there is no more need for it.
+ *
+ * Returns the format string with an IP field inside, or NULL
+ * if allocation failed.
+ */
+static char *batadv_dat_ip_format_string(uint8_t ip_type,
+ char *format_prefix, char *format_suffix, int width)
+{
+ char *format_string, *tmp_string;
+ char ipv4[] = "pI4", ipv6[] = "pI6c";
+ int width_length = 0, tmp_witdh = width;
+ int ipv4_len = strlen(ipv4), ipv6_len = strlen(ipv6);
+ int ip_str_size = (ipv4_len > ipv6_len) ? ipv4_len : ipv6_len;
+
+ /* calculate number of chars need for width */
+ if (tmp_witdh < 0) {
+ width_length++;
+ tmp_witdh *= -1;
+ }
+ while (tmp_witdh > 0) {
+ width_length++;
+ tmp_witdh /= 10;
+ }
+
+ /* construct format string */
+ format_string = kmalloc(strlen(format_prefix) + width_length +
+ ip_str_size + strlen(format_suffix) +
+ 2, /* "%" and NULL chars */
+ GFP_ATOMIC);
+ if (!format_string)
+ goto out;
+
+ tmp_string = format_string;
+ sprintf(tmp_string, "%s%%", format_prefix);
+ tmp_string += strlen(tmp_string);
+ if (width != 0) {
+ sprintf(tmp_string, "%i", width);
+ tmp_string += strlen(tmp_string);
+ }
+
+ switch (ip_type) {
+ case BATADV_DAT_IPV4:
+ sprintf(tmp_string, "%s%s", ipv4, format_suffix);
+ break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ case BATADV_DAT_IPV6:
+ sprintf(tmp_string, "%s%s", ipv6, format_suffix);
+ break;
+#endif
+ default:
+ goto out;
+ }
+
+ return format_string;
+out:
+ kfree(format_string);
+ return NULL;
+}
+
+#ifdef CONFIG_BATMAN_ADV_DEBUG
+
+/* batadv_dat_dbg_ip - print similar debug message for IPv4 and IPv6.
+ * @bat_priv: the bat priv with all the soft interface information
+ * @ip_type: IPv4 / IPv6 address
+ * @format_prefix: format before IP field
+ * @format_suffix: format after IP field
+ *
+ * At list one variable parameter should be the IP itself, and it should
+ * be placed correctly based on format prefix and format suffix arguments.
+ */
+static void batadv_dat_dbg_ip(struct batadv_priv *bat_priv,
+ uint8_t ip_type, char *format_prefix,
+ char *format_suffix, ...)
+{
+ va_list arg_va_list;
+ char *format_string;
+
+ va_start(arg_va_list, format_suffix);
+
+ format_string = batadv_dat_ip_format_string(ip_type,
+ format_prefix, format_suffix, 0);
+ if (format_string) {
+ batadv_dbg(BATADV_DBG_DAT, bat_priv, format_string,
+ arg_va_list);
+ kfree(format_string);
+ }
+
+ va_end(arg_va_list);
+}
+
+#else
+
+static void batadv_dat_dbg_ip(struct batadv_priv *bat_priv,
+ uint8_t ip_type, char *format_prefix,
+ char *format_suffix, ...)
+{
+}
+
+#endif /* CONFIG_BATMAN_ADV_DEBUG */
+
static void batadv_dat_purge(struct work_struct *work);
/**
@@ -45,6 +155,19 @@ static void batadv_dat_start_timer(struct
batadv_priv *bat_priv)
}
/**
+ * batadv_dat_entry_free_ref_rcu - free a dat entry using its rcu
+ * @rcu: the dat entry rcu
+ */
+static void batadv_dat_entry_free_ref_rcu(struct rcu_head *rcu)
+{
+ struct batadv_dat_entry *dat_entry;
+
+ dat_entry = container_of(rcu, struct batadv_dat_entry, rcu);
+ kfree(dat_entry->ip);
+ kfree(dat_entry);
+}
+
+/**
* batadv_dat_entry_free_ref - decrement the dat_entry refcounter and possibly
* free it
* @dat_entry: the entry to free
@@ -52,7 +175,7 @@ static void batadv_dat_start_timer(struct
batadv_priv *bat_priv)
static void batadv_dat_entry_free_ref(struct batadv_dat_entry *dat_entry)
{
if (atomic_dec_and_test(&dat_entry->refcount))
- kfree_rcu(dat_entry, rcu);
+ call_rcu(&dat_entry->rcu, batadv_dat_entry_free_ref_rcu);
}
/**
@@ -130,19 +253,62 @@ static void batadv_dat_purge(struct work_struct *work)
}
/**
+ * batadv_sizeof_ip - get sizeof IP based on its type (IPv4 / IPv6)
+ * @ip_type: type of IP address
+ *
+ * Returns sizeof IP, or sizeof IPv4 if ip_type is invalid.
+ */
+static size_t batadv_sizeof_ip(uint8_t ip_type)
+{
+ switch (ip_type) {
+ case BATADV_DAT_IPV4:
+ return sizeof(__be32);
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ case BATADV_DAT_IPV6:
+ return sizeof(struct in6_addr);
+#endif
+ default:
+ return sizeof(__be32); /* fallback to IPv4 */
+ }
+}
+
+/**
* batadv_compare_dat - comparing function used in the local DAT hash table
* @node: node in the local table
* @data2: second object to compare the node to
+ * @ip_type: type of IP address
*
* Returns 1 if the two entries are the same, 0 otherwise.
*/
-static int batadv_compare_dat(const struct hlist_node *node, const void *data2)
+static int batadv_compare_dat(const struct hlist_node *node, const void *data2,
+ uint8_t ip_type)
{
- const void *data1 = container_of(node, struct batadv_dat_entry,
- hash_entry);
+ struct batadv_dat_entry *dat_entry1 = container_of(node,
+ struct batadv_dat_entry, hash_entry);
+ struct batadv_dat_entry *dat_entry2 = container_of(data2,
+ struct batadv_dat_entry, ip);
+ size_t ip_size;
- return (memcmp(data1, data2, sizeof(__be32)) == 0 ? 1 : 0);
+ if (dat_entry1->type != dat_entry2->type)
+ return 0;
+
+ ip_size = batadv_sizeof_ip(ip_type);
+ return (memcmp(dat_entry1->ip, dat_entry2->ip, ip_size) == 0 ? 1 : 0);
+}
+
+static int batadv_compare_dat_ipv4(const struct hlist_node *node,
+ const void *data2)
+{
+ return batadv_compare_dat(node, data2, BATADV_DAT_IPV4);
+}
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static int batadv_compare_dat_ipv6(const struct hlist_node *node,
+ const void *data2)
+{
+ return batadv_compare_dat(node, data2, BATADV_DAT_IPV6);
}
+#endif
/**
* batadv_arp_hw_src - extract the hw_src field from an ARP packet
@@ -201,16 +367,19 @@ static __be32 batadv_arp_ip_dst(struct sk_buff
*skb, int hdr_size)
* batadv_hash_dat - compute the hash value for an IP address
* @data: data to hash
* @size: size of the hash table
+ * @ip_type: type of IP address
*
* Returns the selected index in the hash table for the given data.
*/
-static uint32_t batadv_hash_dat(const void *data, uint32_t size)
+static uint32_t batadv_hash_dat(const void *data, uint32_t size,
+ uint8_t ip_type)
{
const unsigned char *key = data;
uint32_t hash = 0;
- size_t i;
+ size_t i, ip_size;
- for (i = 0; i < 4; i++) {
+ ip_size = batadv_sizeof_ip(ip_type);
+ for (i = 0; i < ip_size; i++) {
hash += key[i];
hash += (hash << 10);
hash ^= (hash >> 6);
@@ -223,31 +392,47 @@ static uint32_t batadv_hash_dat(const void
*data, uint32_t size)
return hash % size;
}
+static uint32_t batadv_hash_dat_ipv4(const void *data, uint32_t size)
+{
+ return batadv_hash_dat(data, size, BATADV_DAT_IPV4);
+}
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static uint32_t batadv_hash_dat_ipv6(const void *data, uint32_t size)
+{
+ return batadv_hash_dat(data, size, BATADV_DAT_IPV6);
+}
+#endif
+
/**
* batadv_dat_entry_hash_find - look for a given dat_entry in the local hash
* table
* @bat_priv: the bat priv with all the soft interface information
* @ip: search key
+ * @ip_type: type of IP address
*
* Returns the dat_entry if found, NULL otherwise.
*/
static struct batadv_dat_entry *
-batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, __be32 ip)
+batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, unsigned char *ip,
+ uint8_t ip_type)
{
struct hlist_head *head;
struct batadv_dat_entry *dat_entry, *dat_entry_tmp = NULL;
struct batadv_hashtable *hash = bat_priv->dat.hash;
uint32_t index;
+ size_t ip_size;
if (!hash)
return NULL;
- index = batadv_hash_dat(&ip, hash->size);
+ ip_size = batadv_sizeof_ip(ip_type);
+ index = batadv_hash_dat(ip, hash->size, ip_type);
head = &hash->table[index];
rcu_read_lock();
hlist_for_each_entry_rcu(dat_entry, head, hash_entry) {
- if (dat_entry->ip != ip)
+ if (memcmp(dat_entry->ip, ip, ip_size))
continue;
if (!atomic_inc_not_zero(&dat_entry->refcount))
@@ -264,24 +449,26 @@ batadv_dat_entry_hash_find(struct batadv_priv
*bat_priv, __be32 ip)
/**
* batadv_dat_entry_add - add a new dat entry or update it if already exists
* @bat_priv: the bat priv with all the soft interface information
- * @ip: ipv4 to add/edit
+ * @ip: IP to add/edit
+ * @ip_type: type of IP address
* @mac_addr: mac address to assign to the given ipv4
*/
-static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
- uint8_t *mac_addr)
+static void batadv_dat_entry_add(struct batadv_priv *bat_priv,
+ unsigned char *ip, uint8_t ip_type, uint8_t *mac_addr)
{
struct batadv_dat_entry *dat_entry;
int hash_added;
+ size_t ip_size;
- dat_entry = batadv_dat_entry_hash_find(bat_priv, ip);
+ dat_entry = batadv_dat_entry_hash_find(bat_priv, ip, ip_type);
/* if this entry is already known, just update it */
if (dat_entry) {
if (!batadv_compare_eth(dat_entry->mac_addr, mac_addr))
memcpy(dat_entry->mac_addr, mac_addr, ETH_ALEN);
dat_entry->last_update = jiffies;
- batadv_dbg(BATADV_DBG_DAT, bat_priv,
- "Entry updated: %pI4 %pM\n", &dat_entry->ip,
- dat_entry->mac_addr);
+
+ batadv_dat_dbg_ip(bat_priv, ip_type, "Entry updated: ",
+ " %pM\n", dat_entry->ip, dat_entry->mac_addr);
goto out;
}
@@ -289,14 +476,34 @@ static void batadv_dat_entry_add(struct
batadv_priv *bat_priv, __be32 ip,
if (!dat_entry)
goto out;
- dat_entry->ip = ip;
+ ip_size = batadv_sizeof_ip(ip_type);
+ dat_entry->ip = kmalloc(ip_size, GFP_ATOMIC);
+ if (!dat_entry->ip)
+ goto out;
+ memcpy(dat_entry->ip, ip, ip_size);
+ dat_entry->type = ip_type;
+
memcpy(dat_entry->mac_addr, mac_addr, ETH_ALEN);
dat_entry->last_update = jiffies;
atomic_set(&dat_entry->refcount, 2);
- hash_added = batadv_hash_add(bat_priv->dat.hash, batadv_compare_dat,
- batadv_hash_dat, &dat_entry->ip,
- &dat_entry->hash_entry);
+ switch (ip_type) {
+ case BATADV_DAT_IPV4:
+ hash_added = batadv_hash_add(bat_priv->dat.hash,
+ batadv_compare_dat_ipv4, batadv_hash_dat_ipv4,
+ dat_entry->ip, &dat_entry->hash_entry);
+ break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ case BATADV_DAT_IPV6:
+ hash_added = batadv_hash_add(bat_priv->dat.hash,
+ batadv_compare_dat_ipv6, batadv_hash_dat_ipv6,
+ dat_entry->ip, &dat_entry->hash_entry);
+ break;
+#endif
+ default:
+ hash_added = 1; /* in order to catch next if */
+ break;
+ }
if (unlikely(hash_added != 0)) {
/* remove the reference for the hash */
@@ -304,9 +511,8 @@ static void batadv_dat_entry_add(struct
batadv_priv *bat_priv, __be32 ip,
goto out;
}
- batadv_dbg(BATADV_DBG_DAT, bat_priv, "New entry added: %pI4 %pM\n",
- &dat_entry->ip, dat_entry->mac_addr);
-
+ batadv_dat_dbg_ip(bat_priv, ip_type, "New entry added: ", " %pM\n",
+ dat_entry->ip, dat_entry->mac_addr);
out:
if (dat_entry)
batadv_dat_entry_free_ref(dat_entry);
@@ -513,7 +719,8 @@ static void batadv_choose_next_candidate(struct
batadv_priv *bat_priv,
* batadv_dat_select_candidates - select the nodes which the DHT message has to
* be sent to
* @bat_priv: the bat priv with all the soft interface information
- * @ip_dst: ipv4 to look up in the DHT
+ * @ip_dst: IP to look up in the DHT
+ * @ip_type: type of IP address
*
* An originator O is selected if and only if its DHT_ID value is one of three
* closest values (from the LEFT, with wrap around if needed) then the hash
@@ -522,7 +729,8 @@ static void batadv_choose_next_candidate(struct
batadv_priv *bat_priv,
* Returns the candidate array of size BATADV_DAT_CANDIDATE_NUM.
*/
static struct batadv_dat_candidate *
-batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
+batadv_dat_select_candidates(struct batadv_priv *bat_priv,
+ unsigned char *ip_dst, uint8_t ip_type)
{
int select;
batadv_dat_addr_t last_max = BATADV_DAT_ADDR_MAX, ip_key;
@@ -535,12 +743,11 @@ batadv_dat_select_candidates(struct batadv_priv
*bat_priv, __be32 ip_dst)
if (!res)
return NULL;
- ip_key = (batadv_dat_addr_t)batadv_hash_dat(&ip_dst,
- BATADV_DAT_ADDR_MAX);
+ ip_key = (batadv_dat_addr_t)batadv_hash_dat(ip_dst,
+ BATADV_DAT_ADDR_MAX, ip_type);
- batadv_dbg(BATADV_DBG_DAT, bat_priv,
- "dat_select_candidates(): IP=%pI4 hash(IP)=%u\n", &ip_dst,
- ip_key);
+ batadv_dat_dbg_ip(bat_priv, ip_type, "dat_select_candidates(): IP=",
+ " hash(IP)=%u\n", ip_dst, ip_key);
for (select = 0; select < BATADV_DAT_CANDIDATES_NUM; select++)
batadv_choose_next_candidate(bat_priv, res, select, ip_key,
@@ -554,6 +761,7 @@ batadv_dat_select_candidates(struct batadv_priv
*bat_priv, __be32 ip_dst)
* @bat_priv: the bat priv with all the soft interface information
* @skb: payload to send
* @ip: the DHT key
+ * @ip_type: type of IP address
* @packet_subtype: unicast4addr packet subtype to use
*
* This function copies the skb with pskb_copy() and is sent as unicast packet
@@ -563,8 +771,8 @@ batadv_dat_select_candidates(struct batadv_priv
*bat_priv, __be32 ip_dst)
* otherwise.
*/
static bool batadv_dat_send_data(struct batadv_priv *bat_priv,
- struct sk_buff *skb, __be32 ip,
- int packet_subtype)
+ struct sk_buff *skb, unsigned char *ip,
+ uint8_t ip_type, int packet_subtype)
{
int i;
bool ret = false;
@@ -573,11 +781,11 @@ static bool batadv_dat_send_data(struct
batadv_priv *bat_priv,
struct sk_buff *tmp_skb;
struct batadv_dat_candidate *cand;
- cand = batadv_dat_select_candidates(bat_priv, ip);
+ cand = batadv_dat_select_candidates(bat_priv, ip, ip_type);
if (!cand)
goto out;
- batadv_dbg(BATADV_DBG_DAT, bat_priv, "DHT_SEND for %pI4\n", &ip);
+ batadv_dat_dbg_ip(bat_priv, ip_type, "DHT_SEND for ", "\n", ip);
for (i = 0; i < BATADV_DAT_CANDIDATES_NUM; i++) {
if (cand[i].type == BATADV_DAT_CANDIDATE_NOT_FOUND)
@@ -685,6 +893,7 @@ int batadv_dat_cache_seq_print_text(struct
seq_file *seq, void *offset)
struct batadv_hard_iface *primary_if;
struct hlist_head *head;
unsigned long last_seen_jiffies;
+ char *format_string;
int last_seen_msecs, last_seen_secs, last_seen_mins;
uint32_t i;
@@ -693,8 +902,8 @@ int batadv_dat_cache_seq_print_text(struct
seq_file *seq, void *offset)
goto out;
seq_printf(seq, "Distributed ARP Table (%s):\n", net_dev->name);
- seq_printf(seq, " %-7s %-13s %5s\n", "IPv4", "MAC",
- "last-seen");
+ seq_printf(seq, " %-26s %-15s %5s\n",
+ "IPv4/IPv6", "MAC", "last-seen");
for (i = 0; i < hash->size; i++) {
head = &hash->table[i];
@@ -707,9 +916,16 @@ int batadv_dat_cache_seq_print_text(struct
seq_file *seq, void *offset)
last_seen_msecs = last_seen_msecs % 60000;
last_seen_secs = last_seen_msecs / 1000;
- seq_printf(seq, " * %15pI4 %14pM %6i:%02i\n",
- &dat_entry->ip, dat_entry->mac_addr,
- last_seen_mins, last_seen_secs);
+ format_string =
+ batadv_dat_ip_format_string(dat_entry->type,
+ " * ", " %15pM %6i:%02i\n", -40);
+ if (format_string) {
+ seq_printf(seq, format_string, dat_entry->ip,
+ dat_entry->mac_addr,
+ last_seen_mins,
+ last_seen_secs);
+ kfree(format_string);
+ }
}
rcu_read_unlock();
}
@@ -830,9 +1046,11 @@ bool
batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
hw_src = batadv_arp_hw_src(skb, 0);
ip_dst = batadv_arp_ip_dst(skb, 0);
- batadv_dat_entry_add(bat_priv, ip_src, hw_src);
+ batadv_dat_entry_add(bat_priv, (unsigned char *)&ip_src,
+ BATADV_DAT_IPV4, hw_src);
- dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst);
+ dat_entry = batadv_dat_entry_hash_find(bat_priv,
+ (unsigned char *)&ip_dst, BATADV_DAT_IPV4);
if (dat_entry) {
skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src,
bat_priv->soft_iface, ip_dst, hw_src,
@@ -851,9 +1069,10 @@ bool
batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
batadv_dbg(BATADV_DBG_DAT, bat_priv, "ARP request replied locally\n");
ret = true;
} else {
- /* Send the request to the DHT */
- ret = batadv_dat_send_data(bat_priv, skb, ip_dst,
- BATADV_P_DAT_DHT_GET);
+ /* Send the request on the DHT */
+ ret = batadv_dat_send_data(bat_priv, skb,
+ (unsigned char *)&ip_dst, BATADV_DAT_IPV4,
+ BATADV_P_DAT_DHT_GET);
}
out:
if (dat_entry)
@@ -895,9 +1114,11 @@ bool
batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
batadv_dbg_arp(bat_priv, skb, type, hdr_size,
"Parsing incoming ARP REQUEST");
- batadv_dat_entry_add(bat_priv, ip_src, hw_src);
+ batadv_dat_entry_add(bat_priv, (unsigned char *)&ip_src,
+ BATADV_DAT_IPV4, hw_src);
- dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst);
+ dat_entry = batadv_dat_entry_hash_find(bat_priv,
+ (unsigned char *)&ip_dst, BATADV_DAT_IPV4);
if (!dat_entry)
goto out;
@@ -956,14 +1177,18 @@ void batadv_dat_snoop_outgoing_arp_reply(struct
batadv_priv *bat_priv,
hw_dst = batadv_arp_hw_dst(skb, 0);
ip_dst = batadv_arp_ip_dst(skb, 0);
- batadv_dat_entry_add(bat_priv, ip_src, hw_src);
- batadv_dat_entry_add(bat_priv, ip_dst, hw_dst);
+ batadv_dat_entry_add(bat_priv, (unsigned char *)&ip_src,
+ BATADV_DAT_IPV4, hw_src);
+ batadv_dat_entry_add(bat_priv, (unsigned char *)&ip_dst,
+ BATADV_DAT_IPV4, hw_dst);
/* Send the ARP reply to the candidates for both the IP addresses that
* the node obtained from the ARP reply
*/
- batadv_dat_send_data(bat_priv, skb, ip_src, BATADV_P_DAT_DHT_PUT);
- batadv_dat_send_data(bat_priv, skb, ip_dst, BATADV_P_DAT_DHT_PUT);
+ batadv_dat_send_data(bat_priv, skb, (unsigned char *)&ip_src,
+ BATADV_DAT_IPV4, BATADV_P_DAT_DHT_PUT);
+ batadv_dat_send_data(bat_priv, skb, (unsigned char *)&ip_dst,
+ BATADV_DAT_IPV4, BATADV_P_DAT_DHT_PUT);
}
/**
* batadv_dat_snoop_incoming_arp_reply - snoop the ARP reply and fill the local
@@ -998,8 +1223,10 @@ bool batadv_dat_snoop_incoming_arp_reply(struct
batadv_priv *bat_priv,
/* Update our internal cache with both the IP addresses the node got
* within the ARP reply
*/
- batadv_dat_entry_add(bat_priv, ip_src, hw_src);
- batadv_dat_entry_add(bat_priv, ip_dst, hw_dst);
+ batadv_dat_entry_add(bat_priv, (unsigned char *)&ip_src,
+ BATADV_DAT_IPV4, hw_src);
+ batadv_dat_entry_add(bat_priv, (unsigned char *)&ip_dst,
+ BATADV_DAT_IPV4, hw_dst);
/* if this REPLY is directed to a client of mine, let's deliver the
* packet to the interface
@@ -1043,7 +1270,8 @@ bool batadv_dat_drop_broadcast_packet(struct
batadv_priv *bat_priv,
goto out;
ip_dst = batadv_arp_ip_dst(forw_packet->skb, bcast_len);
- dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst);
+ dat_entry = batadv_dat_entry_hash_find(bat_priv,
+ (unsigned char *)&ip_dst, BATADV_DAT_IPV4);
/* check if the node already got this entry */
if (!dat_entry) {
batadv_dbg(BATADV_DBG_DAT, bat_priv,
diff --git a/types.h b/types.h
index 5f542bd..5f8b183 100644
--- a/types.h
+++ b/types.h
@@ -961,17 +961,18 @@ struct batadv_algo_ops {
};
/**
- * struct batadv_dat_entry - it is a single entry of batman-adv ARP backend. It
- * is used to stored ARP entries needed for the global DAT cache
- * @ip: the IPv4 corresponding to this DAT/ARP entry
- * @mac_addr: the MAC address associated to the stored IPv4
+ * struct batadv_dat_entry - it is a single entry of batman-adv
ARP/NDP backend. It
+ * is used to stored ARP/NDP entries needed for the global DAT cache
+ * @ip: the IPv4 / IPv6 corresponding to this DAT ARP/NDP entry
+ * @mac_addr: the MAC address associated to the stored @ip
* @last_update: time in jiffies when this entry was refreshed last time
* @hash_entry: hlist node for batadv_priv_dat::hash
* @refcount: number of contexts the object is used
* @rcu: struct used for freeing in an RCU-safe manner
*/
struct batadv_dat_entry {
- __be32 ip;
+ unsigned char *ip;
+ uint8_t type;
uint8_t mac_addr[ETH_ALEN];
unsigned long last_update;
struct hlist_node hash_entry;
@@ -980,6 +981,18 @@ struct batadv_dat_entry {
};
/**
+ * batadv_dat_types - types used in batadv_dat_entry for IP
+ * @BATADV_DAT_IPv4: IPv4 address type
+ * @BATADV_DAT_IPv6: IPv6 address type
+ */
+enum batadv_dat_types {
+ BATADV_DAT_IPV4,
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ BATADV_DAT_IPV6,
+#endif
+};
+
+/**
* struct batadv_dat_candidate - candidate destination for DAT operations
* @type: the type of the selected candidate. It can one of the following:
* - BATADV_DAT_CANDIDATE_NOT_FOUND
--
1.7.10.4
8 years
[B.A.T.M.A.N.] [PATCH 1/2] batctl: fix 4addr parsing in tcpdump
by Antonio Quartulli
In the UNICAST4ADDR parsing routing a wrong type is used to
parse the batman header, resulting in a wrong data
visualization. Fix this by using the correct data type.
Introduced by 70aefcf8abefd509e5721c6ae228d3854d5e8b16
("batctl: Add minimal unicast 4addr dissector support")
Signed-off-by: Antonio Quartulli <ordex(a)autistici.org>
---
tcpdump.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/tcpdump.c b/tcpdump.c
index f357c6d..39239dd 100644
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -545,14 +545,14 @@ static void dump_batman_frag(unsigned char *packet_buff, ssize_t buff_len, int r
static void dump_batman_4addr(unsigned char *packet_buff, ssize_t buff_len, int read_opt, int time_printed)
{
struct ether_header *ether_header;
- struct batadv_unicast_packet *unicast_4addr_packet;
+ struct batadv_unicast_4addr_packet *unicast_4addr_packet;
- LEN_CHECK((size_t)buff_len - sizeof(struct ether_header), sizeof(struct batadv_unicast_packet), "BAT 4ADDR");
- LEN_CHECK((size_t)buff_len - sizeof(struct ether_header) - sizeof(struct batadv_unicast_packet),
+ LEN_CHECK((size_t)buff_len - sizeof(struct ether_header), sizeof(struct batadv_unicast_4addr_packet), "BAT 4ADDR");
+ LEN_CHECK((size_t)buff_len - sizeof(struct ether_header) - sizeof(struct batadv_unicast_4addr_packet),
sizeof(struct ether_header), "BAT 4ADDR (unpacked)");
ether_header = (struct ether_header *)packet_buff;
- unicast_4addr_packet = (struct batadv_unicast_packet *)(packet_buff + sizeof(struct ether_header));
+ unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)(packet_buff + sizeof(struct ether_header));
if (!time_printed)
time_printed = print_time();
@@ -560,12 +560,12 @@ static void dump_batman_4addr(unsigned char *packet_buff, ssize_t buff_len, int
printf("BAT %s > ",
get_name_by_macaddr((struct ether_addr *)ether_header->ether_shost, read_opt));
- printf("%s: 4ADDR, ttvn %d, ttl %hhu, ",
- get_name_by_macaddr((struct ether_addr *)unicast_4addr_packet->dest, read_opt),
- unicast_4addr_packet->ttvn, unicast_4addr_packet->header.ttl);
+ printf("%s: 4ADDR, subtype %d, ttvn %d, ttl %hhu, ",
+ get_name_by_macaddr((struct ether_addr *)unicast_4addr_packet->u.dest, read_opt),
+ unicast_4addr_packet->u.ttvn, unicast_4addr_packet->u.header.ttl);
- parse_eth_hdr(packet_buff + ETH_HLEN + sizeof(struct batadv_unicast_packet),
- buff_len - ETH_HLEN - sizeof(struct batadv_unicast_packet),
+ parse_eth_hdr(packet_buff + ETH_HLEN + sizeof(struct batadv_unicast_4addr_packet),
+ buff_len - ETH_HLEN - sizeof(struct batadv_unicast_4addr_packet),
read_opt, time_printed);
}
--
1.8.1.5
8 years
Re: [B.A.T.M.A.N.] Bug#703540: Inconsistent use of _GNU_SOURCE
by Sven Eckelmann
tags 703540 + pending patch
thanks
On Wednesday 20 March 2013 17:51:54 you wrote:
> While building the package using our research compiler infrastructure we
> noticed conflicting types being used in the linked executable. This is due
> to _GNU_SOURCE being defined in linux/route.c and posix/unix_socket.c, but
> not in any other file. As a result, system headers expand to conflicting
> declarations. (This was at least noticed for the sendto function, but may
> extend to others.)
>
> Either all or no file should #define _GNU_SOURCE.
Please add information how to reproduce this the next time you are adding such
such a bug. Now I can just assume what you are writing is true (even when the
man page about sendto says otherwise). Not knowing how to reproduce it in the
best possible way just makes it harder for everyone to check the impact of the
problem.
I've forwarded it to the upstream maintainer and attached the change for
Debian.
Kind regards,
Sven
8 years