From: Sven Eckelmann sven.eckelmann@gmx.de
The code which uses the raw packet sockets was removed. The only related dependencies are the skb and netdev handling code. This is provided by NET in Kconfig.
Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de Signed-off-by: Andrew Lunn andrew@lunn.ch --- drivers/staging/batman-adv/Kconfig | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/staging/batman-adv/Kconfig b/drivers/staging/batman-adv/Kconfig index 69e8fb0..1e7e0a8 100644 --- a/drivers/staging/batman-adv/Kconfig +++ b/drivers/staging/batman-adv/Kconfig @@ -4,7 +4,7 @@
config BATMAN_ADV tristate "B.A.T.M.A.N. Advanced Meshing Protocol" - depends on PROC_FS && PACKET + depends on PROC_FS && NET default n ---help---
From: Simon Wunderlich siwu@hrz.tu-chemnitz.de
As in other parts of batman-adv, we should not lock while sending a packet but keep the lock held for as short as possible. Additionally, we should check whether the interface is active, otherwise batman_if->net_dev might not be available ...
Signed-off-by: Simon Wunderlich siwu@hrz.tu-chemnitz.de Acked-by: Marek Lindner lindner_marek@yahoo.de Signed-off-by: Andrew Lunn andrew@lunn.ch --- drivers/staging/batman-adv/device.c | 13 ++++++++++--- 1 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/staging/batman-adv/device.c b/drivers/staging/batman-adv/device.c index a3e7429..451898c 100644 --- a/drivers/staging/batman-adv/device.c +++ b/drivers/staging/batman-adv/device.c @@ -25,6 +25,7 @@ #include "send.h" #include "types.h" #include "hash.h" +#include "hard-interface.h"
static struct class *batman_class;
@@ -206,6 +207,7 @@ ssize_t bat_device_write(struct file *file, const char __user *buff, struct icmp_packet icmp_packet; struct orig_node *orig_node; struct batman_if *batman_if; + uint8_t dstaddr[ETH_ALEN]; unsigned long flags;
if (len < sizeof(struct icmp_packet)) { @@ -251,9 +253,15 @@ ssize_t bat_device_write(struct file *file, const char __user *buff, goto unlock;
batman_if = orig_node->batman_if; + memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); + + spin_unlock_irqrestore(&orig_hash_lock, flags);
if (!batman_if) - goto unlock; + goto dst_unreach; + + if (batman_if->if_active != IF_ACTIVE) + goto dst_unreach;
memcpy(icmp_packet.orig, batman_if->net_dev->dev_addr, @@ -261,9 +269,8 @@ ssize_t bat_device_write(struct file *file, const char __user *buff,
send_raw_packet((unsigned char *)&icmp_packet, sizeof(struct icmp_packet), - batman_if, orig_node->router->addr); + batman_if, dstaddr);
- spin_unlock_irqrestore(&orig_hash_lock, flags); goto out;
unlock:
From: Marek Lindner lindner_marek@yahoo.de
The routing code has 2 sections which warn about ttl exceeded. The corresponding warnings were identical which makes it hard to debug. In addition, batman-adv does not need to warn about ttl exceeded in case we encountered an echo request as this is commonly used to generate traceroute graphs.
Signed-off-by: Marek Lindner lindner_marek@yahoo.de Signed-off-by: Andrew Lunn andrew@lunn.ch --- drivers/staging/batman-adv/routing.c | 14 ++++++++------ 1 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index 09917e5..8abaa61 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c @@ -655,14 +655,15 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb) unsigned long flags; uint8_t dstaddr[ETH_ALEN];
- icmp_packet = (struct icmp_packet *) skb->data; - ethhdr = (struct ethhdr *) skb_mac_header(skb); - - printk(KERN_WARNING "batman-adv:Warning - can't send packet from %pM to %pM: ttl exceeded\n", icmp_packet->orig, icmp_packet->dst); + icmp_packet = (struct icmp_packet *)skb->data; + ethhdr = (struct ethhdr *)skb_mac_header(skb);
/* send TTL exceeded if packet is an echo request (traceroute) */ - if (icmp_packet->msg_type != ECHO_REQUEST) + if (icmp_packet->msg_type != ECHO_REQUEST) { + printk(KERN_WARNING "batman-adv:Warning - can't forward icmp packet from %pM to %pM: ttl exceeded\n", + icmp_packet->orig, icmp_packet->dst); return NET_RX_DROP; + }
/* get routing information */ spin_lock_irqsave(&orig_hash_lock, flags); @@ -825,7 +826,8 @@ int recv_unicast_packet(struct sk_buff *skb)
/* TTL exceeded */ if (unicast_packet->ttl < 2) { - printk(KERN_WARNING "batman-adv:Warning - can't send packet from %pM to %pM: ttl exceeded\n", ethhdr->h_source, unicast_packet->dest); + printk(KERN_WARNING "batman-adv:Warning - can't forward unicast packet from %pM to %pM: ttl exceeded\n", + ethhdr->h_source, unicast_packet->dest); return NET_RX_DROP; }
From: Marek Lindner lindner_marek@yahoo.de
This patch removes a variable that became obsolete since the skb handling replaced the packet handling thread.
Signed-off-by: Marek Lindner lindner_marek@yahoo.de Signed-off-by: Andrew Lunn andrew@lunn.ch --- drivers/staging/batman-adv/routing.c | 2 -- drivers/staging/batman-adv/routing.h | 1 - 2 files changed, 0 insertions(+), 3 deletions(-)
diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index 8abaa61..7dc9aef 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c @@ -35,8 +35,6 @@
DECLARE_WAIT_QUEUE_HEAD(thread_wait);
-atomic_t exit_cond; - void slide_own_bcast_window(struct batman_if *batman_if) { HASHIT(hashit); diff --git a/drivers/staging/batman-adv/routing.h b/drivers/staging/batman-adv/routing.h index c217241..939b8d4 100644 --- a/drivers/staging/batman-adv/routing.h +++ b/drivers/staging/batman-adv/routing.h @@ -22,7 +22,6 @@ #include "types.h"
extern wait_queue_head_t thread_wait; -extern atomic_t exit_cond;
void slide_own_bcast_window(struct batman_if *batman_if); void receive_bat_packet(struct ethhdr *ethhdr,
From: Linus Luessing linus.luessing@web.de
This fixes the bug discovered by Marek Lindner which did not allow turning on the vis-server before an interface has been added. With this patch we are using a global atomic variable for activating and deactiating the vis-server-mode, which can be used before inserting an interface.
Signed-off-by: Linus Luessing linus.luessing@web.de Signed-off-by: Andrew Lunn andrew@lunn.ch --- drivers/staging/batman-adv/main.c | 2 + drivers/staging/batman-adv/main.h | 1 + drivers/staging/batman-adv/proc.c | 15 +++++------ drivers/staging/batman-adv/send.c | 3 +- drivers/staging/batman-adv/vis.c | 46 +++++-------------------------------- drivers/staging/batman-adv/vis.h | 2 - 6 files changed, 18 insertions(+), 51 deletions(-)
diff --git a/drivers/staging/batman-adv/main.c b/drivers/staging/batman-adv/main.c index 3f78075..2e0b482 100644 --- a/drivers/staging/batman-adv/main.c +++ b/drivers/staging/batman-adv/main.c @@ -43,6 +43,7 @@ DEFINE_SPINLOCK(forw_bcast_list_lock);
atomic_t originator_interval; atomic_t vis_interval; +atomic_t vis_mode; atomic_t aggregation_enabled; int16_t num_hna; int16_t num_ifs; @@ -83,6 +84,7 @@ int init_module(void) atomic_set(&originator_interval, 1000); atomic_set(&vis_interval, 1000);/* TODO: raise this later, this is only * for debugging now. */ + atomic_set(&vis_mode, VIS_TYPE_CLIENT_UPDATE); atomic_set(&aggregation_enabled, 1);
/* the name should not be longer than 10 chars - see diff --git a/drivers/staging/batman-adv/main.h b/drivers/staging/batman-adv/main.h index eb6a702..deb41f5 100644 --- a/drivers/staging/batman-adv/main.h +++ b/drivers/staging/batman-adv/main.h @@ -130,6 +130,7 @@ extern spinlock_t forw_bcast_list_lock;
extern atomic_t originator_interval; extern atomic_t vis_interval; +extern atomic_t vis_mode; extern atomic_t aggregation_enabled; extern int16_t num_hna; extern int16_t num_ifs; diff --git a/drivers/staging/batman-adv/proc.c b/drivers/staging/batman-adv/proc.c index 68c36b0..0eadc6b 100644 --- a/drivers/staging/batman-adv/proc.c +++ b/drivers/staging/batman-adv/proc.c @@ -338,11 +338,11 @@ static ssize_t proc_vis_srv_write(struct file *file, const char __user * buffer, if ((strcmp(vis_mode_string, "client") == 0) || (strcmp(vis_mode_string, "disabled") == 0)) { printk(KERN_INFO "batman-adv:Setting VIS mode to client (disabling vis server)\n"); - vis_set_mode(VIS_TYPE_CLIENT_UPDATE); + atomic_set(&vis_mode, VIS_TYPE_CLIENT_UPDATE); } else if ((strcmp(vis_mode_string, "server") == 0) || (strcmp(vis_mode_string, "enabled") == 0)) { printk(KERN_INFO "batman-adv:Setting VIS mode to server (enabling vis server)\n"); - vis_set_mode(VIS_TYPE_SERVER_SYNC); + atomic_set(&vis_mode, VIS_TYPE_SERVER_SYNC); } else printk(KERN_ERR "batman-adv:Unknown VIS mode: %s\n", vis_mode_string); @@ -353,12 +353,12 @@ static ssize_t proc_vis_srv_write(struct file *file, const char __user * buffer,
static int proc_vis_srv_read(struct seq_file *seq, void *offset) { - int vis_server = is_vis_server(); + int vis_server = atomic_read(&vis_mode);
seq_printf(seq, "[%c] client mode (server disabled) \n", - (!vis_server) ? 'x' : ' '); + (vis_server == VIS_TYPE_CLIENT_UPDATE) ? 'x' : ' '); seq_printf(seq, "[%c] server mode (server enabled) \n", - (vis_server) ? 'x' : ' '); + (vis_server == VIS_TYPE_SERVER_SYNC) ? 'x' : ' ');
return 0; } @@ -377,9 +377,10 @@ static int proc_vis_data_read(struct seq_file *seq, void *offset) int i; char tmp_addr_str[ETH_STR_LEN]; unsigned long flags; + int vis_server = atomic_read(&vis_mode);
rcu_read_lock(); - if (list_empty(&if_list) || (!is_vis_server())) { + if (list_empty(&if_list) || (vis_server == VIS_TYPE_CLIENT_UPDATE)) { rcu_read_unlock(); goto end; } @@ -672,5 +673,3 @@ int setup_procfs(void)
return 0; } - - diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c index 944b2cd..2a9fac8 100644 --- a/drivers/staging/batman-adv/send.c +++ b/drivers/staging/batman-adv/send.c @@ -248,6 +248,7 @@ void schedule_own_packet(struct batman_if *batman_if) { unsigned long send_time; struct batman_packet *batman_packet; + int vis_server = atomic_read(&vis_mode);
/** * the interface gets activated here to avoid race conditions between @@ -272,7 +273,7 @@ void schedule_own_packet(struct batman_if *batman_if) /* change sequence number to network order */ batman_packet->seqno = htons((uint16_t)atomic_read(&batman_if->seqno));
- if (is_vis_server()) + if (vis_server == VIS_TYPE_SERVER_SYNC) batman_packet->flags = VIS_SERVER; else batman_packet->flags = 0; diff --git a/drivers/staging/batman-adv/vis.c b/drivers/staging/batman-adv/vis.c index ec8bb3f..fedec1b 100644 --- a/drivers/staging/batman-adv/vis.c +++ b/drivers/staging/batman-adv/vis.c @@ -48,41 +48,6 @@ static void free_info(void *data) kfree(info); }
-/* set the mode of the visualization to client or server */ -void vis_set_mode(int mode) -{ - unsigned long flags; - spin_lock_irqsave(&vis_hash_lock, flags); - - if (my_vis_info != NULL) - my_vis_info->packet.vis_type = mode; - - spin_unlock_irqrestore(&vis_hash_lock, flags); -} - -/* is_vis_server(), locked outside */ -static int is_vis_server_locked(void) -{ - if (my_vis_info != NULL) - if (my_vis_info->packet.vis_type == VIS_TYPE_SERVER_SYNC) - return 1; - - return 0; -} - -/* get the current set mode */ -int is_vis_server(void) -{ - int ret = 0; - unsigned long flags; - - spin_lock_irqsave(&vis_hash_lock, flags); - ret = is_vis_server_locked(); - spin_unlock_irqrestore(&vis_hash_lock, flags); - - return ret; -} - /* Compare two vis packets, used by the hashing algorithm */ static int vis_info_cmp(void *data1, void *data2) { @@ -271,6 +236,7 @@ void receive_server_sync_packet(struct vis_packet *vis_packet, int vis_info_len) struct vis_info *info; int is_new; unsigned long flags; + int vis_server = atomic_read(&vis_mode);
spin_lock_irqsave(&vis_hash_lock, flags); info = add_packet(vis_packet, vis_info_len, &is_new); @@ -279,7 +245,7 @@ void receive_server_sync_packet(struct vis_packet *vis_packet, int vis_info_len)
/* only if we are server ourselves and packet is newer than the one in * hash.*/ - if (is_vis_server_locked() && is_new) { + if (vis_server == VIS_TYPE_SERVER_SYNC && is_new) { memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN); if (list_empty(&info->send_list)) list_add_tail(&info->send_list, &send_list); @@ -295,6 +261,7 @@ void receive_client_update_packet(struct vis_packet *vis_packet, struct vis_info *info; int is_new; unsigned long flags; + int vis_server = atomic_read(&vis_mode);
/* clients shall not broadcast. */ if (is_bcast(vis_packet->target_orig)) @@ -308,7 +275,7 @@ void receive_client_update_packet(struct vis_packet *vis_packet,
/* send only if we're the target server or ... */ - if (is_vis_server_locked() && + if (vis_server == VIS_TYPE_SERVER_SYNC && is_my_mac(info->packet.target_orig) && is_new) { info->packet.vis_type = VIS_TYPE_SERVER_SYNC; /* upgrade! */ @@ -372,6 +339,7 @@ static int generate_vis_packet(void) unsigned long flags;
info->first_seen = jiffies; + info->packet.vis_type = atomic_read(&vis_mode);
spin_lock_irqsave(&orig_hash_lock, flags); memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN); @@ -379,7 +347,7 @@ static int generate_vis_packet(void) info->packet.seqno++; info->packet.entries = 0;
- if (!is_vis_server_locked()) { + if (info->packet.vis_type == VIS_TYPE_CLIENT_UPDATE) { best_tq = find_best_vis_server(info); if (best_tq < 0) { spin_unlock_irqrestore(&orig_hash_lock, flags); @@ -577,7 +545,6 @@ int vis_init(void) INIT_LIST_HEAD(&my_vis_info->send_list); my_vis_info->packet.version = COMPAT_VERSION; my_vis_info->packet.packet_type = BAT_VIS; - my_vis_info->packet.vis_type = VIS_TYPE_CLIENT_UPDATE; my_vis_info->packet.ttl = TTL; my_vis_info->packet.seqno = 0; my_vis_info->packet.entries = 0; @@ -628,4 +595,3 @@ static void start_vis_timer(void) queue_delayed_work(bat_event_workqueue, &vis_timer_wq, (atomic_read(&vis_interval) * HZ) / 1000); } - diff --git a/drivers/staging/batman-adv/vis.h b/drivers/staging/batman-adv/vis.h index 2e24258..0cdafde 100644 --- a/drivers/staging/batman-adv/vis.h +++ b/drivers/staging/batman-adv/vis.h @@ -48,8 +48,6 @@ struct recvlist_node { extern struct hashtable_t *vis_hash; extern spinlock_t vis_hash_lock;
-void vis_set_mode(int mode); -int is_vis_server(void); void proc_vis_read_entry(struct seq_file *seq, struct vis_info_entry *entry, struct hlist_head *if_list,
The vis code takes a copy of the data inside the skbuf if it is interesting for us, so we always need to release the skbuf.
Reported-by: Linus Luessing linus.luessing@web.de Signed-off-by: Andrew Lunn andrew@lunn.ch --- drivers/staging/batman-adv/routing.c | 9 ++++----- 1 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index 7dc9aef..d89048b 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c @@ -939,7 +939,6 @@ int recv_vis_packet(struct sk_buff *skb) struct vis_packet *vis_packet; struct ethhdr *ethhdr; int hdr_size = sizeof(struct vis_packet); - int ret;
if (skb_headlen(skb) < hdr_size) return NET_RX_DROP; @@ -962,18 +961,18 @@ int recv_vis_packet(struct sk_buff *skb) case VIS_TYPE_SERVER_SYNC: /* TODO: handle fragmented skbs properly */ receive_server_sync_packet(vis_packet, skb_headlen(skb)); - ret = NET_RX_SUCCESS; break;
case VIS_TYPE_CLIENT_UPDATE: /* TODO: handle fragmented skbs properly */ receive_client_update_packet(vis_packet, skb_headlen(skb)); - ret = NET_RX_SUCCESS; break;
default: /* ignore unknown packet */ - ret = NET_RX_DROP; break; } - return ret; + + /* We take a copy of the data in the packet, so we should + always free the skbuf. */ + return NET_RX_DROP; }
From: Marek Lindner lindner_marek@yahoo.de
skb_share_check() returns NULL if it can't allocate more memory but it still frees the skbuff.
Signed-off-by: Marek Lindner lindner_marek@yahoo.de Signed-off-by: Andrew Lunn andrew@lunn.ch --- drivers/staging/batman-adv/hard-interface.c | 16 +++++++++------- 1 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index f8b1ba3..0f94158 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -426,10 +426,11 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, struct net_device_stats *stats; int ret;
- skb = skb_share_check(skb, GFP_ATOMIC); + skb = skb_share_check(skb, GFP_ATOMIC);
- if (skb == NULL) - goto err_free; + /* skb was released by skb_share_check() */ + if (!skb) + goto err_out;
/* packet should hold at least type and version */ if (unlikely(skb_headlen(skb) < 2)) @@ -444,7 +445,7 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, if (!batman_if) goto err_free;
- stats = (struct net_device_stats *) dev_get_stats(skb->dev); + stats = (struct net_device_stats *)dev_get_stats(skb->dev); if (stats) { stats->rx_packets++; stats->rx_bytes += skb->len; @@ -490,6 +491,7 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, default: ret = NET_RX_DROP; } + if (ret == NET_RX_DROP) kfree_skb(skb);
@@ -500,9 +502,9 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, return NET_RX_SUCCESS;
err_free: - kfree_skb(skb); - return NET_RX_DROP; - + kfree_skb(skb); +err_out: + return NET_RX_DROP; }
From: Marek Lindner lindner_marek@yahoo.de
Make sure that batman-adv does not process packets before its initialization is complete. Some sanity checks added to the receiver function.
Signed-off-by: Marek Lindner lindner_marek@yahoo.de Signed-off-by: Simon Wunderlich siwu@hrz.tu-chemnitz.de Signed-off-by: Andrew Lunn andrew@lunn.ch --- drivers/staging/batman-adv/hard-interface.c | 7 +++++++ drivers/staging/batman-adv/proc.c | 17 ++++++----------- 2 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index 0f94158..befd488 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -432,6 +432,9 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, if (!skb) goto err_out;
+ if (atomic_read(&module_state) != MODULE_ACTIVE) + goto err_free; + /* packet should hold at least type and version */ if (unlikely(skb_headlen(skb) < 2)) goto err_free; @@ -445,6 +448,10 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, if (!batman_if) goto err_free;
+ /* discard frames on not active interfaces */ + if (batman_if->if_active != IF_ACTIVE) + goto err_free; + stats = (struct net_device_stats *)dev_get_stats(skb->dev); if (stats) { stats->rx_packets++; diff --git a/drivers/staging/batman-adv/proc.c b/drivers/staging/batman-adv/proc.c index 0eadc6b..7de60e8 100644 --- a/drivers/staging/batman-adv/proc.c +++ b/drivers/staging/batman-adv/proc.c @@ -63,7 +63,7 @@ static ssize_t proc_interfaces_write(struct file *instance, size_t count, loff_t *data) { char *if_string, *colon_ptr = NULL, *cr_ptr = NULL; - int not_copied = 0, if_num = 0; + int not_copied = 0, if_num = 0, add_success; struct batman_if *batman_if = NULL;
if_string = kmalloc(count, GFP_KERNEL); @@ -109,22 +109,17 @@ static ssize_t proc_interfaces_write(struct file *instance, } rcu_read_unlock();
- hardif_add_interface(if_string, if_num); + add_success = hardif_add_interface(if_string, if_num); + if (add_success < 0) + goto end; + + num_ifs = if_num + 1;
if ((atomic_read(&module_state) == MODULE_INACTIVE) && (hardif_get_active_if_num() > 0)) activate_module();
- rcu_read_lock(); - if (list_empty(&if_list)) { - rcu_read_unlock(); - goto end; - } - rcu_read_unlock(); - - num_ifs = if_num + 1; return count; - end: kfree(if_string); return count;
b.a.t.m.a.n@lists.open-mesh.org