This patchset introduces the AP-isolation functionality. As for common access points, the AP-isolation is a mechanism that prevents clients to communicate to each other. In batman-adv the AP-isolation, if activated, will prevent "WIFI bridged-in clients" to communicate with any other "WIFI bridged-in client".
The first patch introduces a mechanism which permit to detect the interface type used by a client and to possibly mark its tt_local_entry in case of WIFI. This information is then spread over the network within the TT announcements.
The other two patches implement the AP-isolation mechanism which exploits the WIFI mark (on tt_entries) to prevent communications between WIFI clients.
The "AP-isolation check" is done either on the receiver and on the sender side.
Best regards, Antonio Quartulli
Clients connected through a 802.11 device are now marked with the TT_CLIENT_WIFI flag. This flag is also advertised with the tt announcement.
Signed-off-by: Antonio Quartulli ordex@autistici.org --- compat.h | 2 + main.c | 2 +- packet.h | 3 +- routing.c | 2 +- soft-interface.c | 4 +- translation-table.c | 59 ++++++++++++++++++++++++++++++++++++++++---------- translation-table.h | 17 +++++++++----- types.h | 2 +- 8 files changed, 67 insertions(+), 24 deletions(-)
diff --git a/compat.h b/compat.h index 66a8adc..f1965d0 100644 --- a/compat.h +++ b/compat.h @@ -263,6 +263,8 @@ int bat_seq_printf(struct seq_file *m, const char *f, ...);
#define __always_unused __attribute__((unused))
+#define skb_iif iif + #endif /* < KERNEL_VERSION(2, 6, 33) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34) diff --git a/main.c b/main.c index c2b06b7..9f3ff52 100644 --- a/main.c +++ b/main.c @@ -108,7 +108,7 @@ int mesh_init(struct net_device *soft_iface) if (tt_init(bat_priv) < 1) goto err;
- tt_local_add(soft_iface, soft_iface->dev_addr); + tt_local_add(soft_iface, soft_iface->dev_addr, 0);
if (vis_init(bat_priv) < 1) goto err; diff --git a/packet.h b/packet.h index 0c3e44d..d1bbdbc 100644 --- a/packet.h +++ b/packet.h @@ -75,7 +75,8 @@ enum tt_query_flags { /* TT_CHANGE flags */ enum tt_change_flags { TT_CHANGE_DEL = 0x01, - TT_CLIENT_ROAM = 0x02 + TT_CLIENT_ROAM = 0x02, + TT_CLIENT_WIFI = 0x04 };
struct batman_packet { diff --git a/routing.c b/routing.c index c620d4f..70c39dd 100644 --- a/routing.c +++ b/routing.c @@ -1290,7 +1290,7 @@ int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if) roam_adv_packet->client);
tt_global_add(bat_priv, orig_node, roam_adv_packet->client, - atomic_read(&orig_node->last_ttvn) + 1, true); + atomic_read(&orig_node->last_ttvn) + 1, true, false);
/* Roaming phase starts: I have new information but the ttvn has not * been incremented yet. This flag will make me check all the incoming diff --git a/soft-interface.c b/soft-interface.c index b268f85..60234af 100644 --- a/soft-interface.c +++ b/soft-interface.c @@ -535,7 +535,7 @@ static int interface_set_mac_addr(struct net_device *dev, void *p) if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) { tt_local_remove(bat_priv, dev->dev_addr, "mac address changed", false); - tt_local_add(dev, addr->sa_data); + tt_local_add(dev, addr->sa_data, 0); }
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); @@ -593,7 +593,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) goto dropped;
/* Register the client MAC in the transtable */ - tt_local_add(soft_iface, ethhdr->h_source); + tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif);
if (is_multicast_ether_addr(ethhdr->h_dest)) { ret = gw_is_target(bat_priv, skb); diff --git a/translation-table.c b/translation-table.c index d2a9f80..1d4c34c 100644 --- a/translation-table.c +++ b/translation-table.c @@ -144,7 +144,7 @@ static void tt_global_entry_free_ref(struct tt_global_entry *tt_global_entry) }
static void tt_local_event(struct bat_priv *bat_priv, uint8_t op, - const uint8_t *addr, bool roaming) + const uint8_t *addr, bool roaming, bool wifi) { struct tt_change_node *tt_change_node;
@@ -158,6 +158,9 @@ static void tt_local_event(struct bat_priv *bat_priv, uint8_t op, if (roaming) tt_change_node->change.flags |= TT_CLIENT_ROAM;
+ if (wifi) + tt_change_node->change.flags |= TT_CLIENT_WIFI; + memcpy(tt_change_node->change.addr, addr, ETH_ALEN);
spin_lock_bh(&bat_priv->tt_changes_list_lock); @@ -187,7 +190,31 @@ static int tt_local_init(struct bat_priv *bat_priv) return 1; }
-void tt_local_add(struct net_device *soft_iface, const uint8_t *addr) +/* This function check whether the interface represented by ifindex is a + * 802.11 wireless device or not. If so the tt_local_entry is marked with the + * TT_CLIENT_WIFI flag */ +static void tt_check_iface(struct tt_local_entry *tt_local_entry, int ifindex) +{ + struct net_device *net_device; + + net_device = dev_get_by_index(&init_net, ifindex); + if (!net_device) + return; + +#ifdef CONFIG_WIRELESS_EXT + /* pre-cfg80211 driver have to implement WEXT, so it is possible to + * check for wireless_handlers != NULL */ + if (net_device->wireless_handlers) + tt_local_entry->flags |= TT_CLIENT_WIFI; + else +#endif + /* cfg80211 drivers have to set ieee80211_ptr */ + if (net_device->ieee80211_ptr) + tt_local_entry->flags |= TT_CLIENT_WIFI; +} + +void tt_local_add(struct net_device *soft_iface, const uint8_t *addr, + int ifindex) { struct bat_priv *bat_priv = netdev_priv(soft_iface); struct tt_local_entry *tt_local_entry = NULL; @@ -204,21 +231,22 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr) if (!tt_local_entry) goto out;
- tt_local_event(bat_priv, NO_FLAGS, addr, false); - bat_dbg(DBG_TT, bat_priv, "Creating new local tt entry: %pM (ttvn: %d)\n", addr, (uint8_t)atomic_read(&bat_priv->ttvn));
memcpy(tt_local_entry->addr, addr, ETH_ALEN); tt_local_entry->last_seen = jiffies; + tt_local_entry->flags = 0; + tt_check_iface(tt_local_entry, ifindex); atomic_set(&tt_local_entry->refcount, 2);
/* the batman interface mac address should never be purged */ if (compare_eth(addr, soft_iface->dev_addr)) - tt_local_entry->never_purge = 1; - else - tt_local_entry->never_purge = 0; + tt_local_entry->flags |= TT_LOCAL_NOPURGE; + + tt_local_event(bat_priv, NO_FLAGS, addr, false, + tt_local_entry->flags & TT_CLIENT_WIFI);
hash_add(bat_priv->tt_local_hash, compare_ltt, choose_orig, tt_local_entry, &tt_local_entry->hash_entry); @@ -388,7 +416,8 @@ void tt_local_remove(struct bat_priv *bat_priv, const uint8_t *addr, if (!tt_local_entry) goto out;
- tt_local_event(bat_priv, TT_CHANGE_DEL, tt_local_entry->addr, roaming); + tt_local_event(bat_priv, TT_CHANGE_DEL, tt_local_entry->addr, roaming, + false); tt_local_del(bat_priv, tt_local_entry, message); out: if (tt_local_entry) @@ -411,7 +440,7 @@ static void tt_local_purge(struct bat_priv *bat_priv) spin_lock_bh(list_lock); hlist_for_each_entry_safe(tt_local_entry, node, node_tmp, head, hash_entry) { - if (tt_local_entry->never_purge) + if (tt_local_entry->flags & TT_LOCAL_NOPURGE) continue;
if (!is_out_of_time(tt_local_entry->last_seen, @@ -419,7 +448,7 @@ static void tt_local_purge(struct bat_priv *bat_priv) continue;
tt_local_event(bat_priv, TT_CHANGE_DEL, - tt_local_entry->addr, false); + tt_local_entry->addr, false, false); atomic_dec(&bat_priv->num_local_tt); bat_dbg(DBG_TT, bat_priv, "Deleting local " "tt entry (%pM): timed out\n", @@ -495,7 +524,8 @@ static void tt_changes_list_free(struct bat_priv *bat_priv)
/* caller must hold orig_node refcount */ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, - const unsigned char *tt_addr, uint8_t ttvn, bool roaming) + const unsigned char *tt_addr, uint8_t ttvn, bool roaming, + bool wifi) { struct tt_global_entry *tt_global_entry; struct orig_node *orig_node_tmp; @@ -537,6 +567,9 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, tt_global_entry->roam_at = 0; }
+ if (wifi) + tt_global_entry->flags |= TT_CLIENT_WIFI; + bat_dbg(DBG_TT, bat_priv, "Creating new global tt entry: %pM (via %pM)\n", tt_global_entry->addr, orig_node->orig); @@ -1342,7 +1375,9 @@ static void _tt_update_changes(struct bat_priv *bat_priv, (tt_change + i)->flags & TT_CLIENT_ROAM); else if (!tt_global_add(bat_priv, orig_node, - (tt_change + i)->addr, ttvn, false)) + (tt_change + i)->addr, ttvn, false, + (tt_change + i)->flags & + TT_CLIENT_WIFI)) /* In case of problem while storing a * global_entry, we stop the updating * procedure without committing the diff --git a/translation-table.h b/translation-table.h index 1cd2d39..b62ae00 100644 --- a/translation-table.h +++ b/translation-table.h @@ -22,20 +22,25 @@ #ifndef _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ #define _NET_BATMAN_ADV_TRANSLATION_TABLE_H_
+/* Transtable local entry flags */ +enum tt_local_flags { + TT_LOCAL_NOPURGE = 0x01 +}; + int tt_len(int changes_num); int tt_changes_fill_buffer(struct bat_priv *bat_priv, unsigned char *buff, int buff_len); int tt_init(struct bat_priv *bat_priv); -void tt_local_add(struct net_device *soft_iface, const uint8_t *addr); +void tt_local_add(struct net_device *soft_iface, const uint8_t *addr, + int ifindex); void tt_local_remove(struct bat_priv *bat_priv, const uint8_t *addr, const char *message, bool roaming); int tt_local_seq_print_text(struct seq_file *seq, void *offset); -void tt_global_add_orig(struct bat_priv *bat_priv, - struct orig_node *orig_node, +void tt_global_add_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, const unsigned char *tt_buff, int tt_buff_len); -int tt_global_add(struct bat_priv *bat_priv, - struct orig_node *orig_node, const unsigned char *addr, - uint8_t ttvn, bool roaming); +int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, + const unsigned char *addr, uint8_t ttvn, bool roaming, + bool wifi); int tt_global_seq_print_text(struct seq_file *seq, void *offset); void tt_global_del_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, const char *message); diff --git a/types.h b/types.h index 11e8569..0d85ba7 100644 --- a/types.h +++ b/types.h @@ -223,7 +223,7 @@ struct socket_packet { struct tt_local_entry { uint8_t addr[ETH_ALEN]; unsigned long last_seen; - char never_purge; + uint8_t flags; atomic_t refcount; struct rcu_head rcu; struct hlist_node hash_entry;
Hi Antonio
- tt_local_add(soft_iface, soft_iface->dev_addr);
- tt_local_add(soft_iface, soft_iface->dev_addr, 0);
Reading the code, it is not obvious what this 0 mean here. Did you see Sven's recent patches which introduced enums in various places? Maybe instead of a bool you could have an enum with two values: wired, wifi?
I've not looked at the other patches yet, but it might even make sense to have enums for wired, AP, client, adhoc?
+/* This function check whether the interface represented by ifindex is a
- 802.11 wireless device or not. If so the tt_local_entry is marked with the
- TT_CLIENT_WIFI flag */
+static void tt_check_iface(struct tt_local_entry *tt_local_entry, int ifindex)
It would be nice to have a more descriptive name, one which tells you what it is checking. Here it is clear, because of the comment, but where it is actually used, it is not possible to know what the function is checking.
Maybe what is actually needed is a function:
bool is_iface_wifi(int ifindex)
and maybe that should be in hard-interface.c? It could be that knowing if an interface is wired or wifi could be useful in other places. This was one of the discussions at WBMv4, giving preference to wired interfaces over wireless.
Andrew
Hi Andrew, Thank you for replying
On dom, giu 05, 2011 at 11:42:36 +0200, Andrew Lunn wrote:
Hi Antonio
- tt_local_add(soft_iface, soft_iface->dev_addr);
- tt_local_add(soft_iface, soft_iface->dev_addr, 0);
Reading the code, it is not obvious what this 0 mean here. Did you see Sven's recent patches which introduced enums in various places? Maybe instead of a bool you could have an enum with two values: wired, wifi?
I've not looked at the other patches yet, but it might even make sense to have enums for wired, AP, client, adhoc?
Actually I only know whether the device is 802.11 or not. It could also be something different from both wired and wireless. However you are right, I should avoid the hardcoded zero. Maybe I can use NO_FLAGS as we did for the other patches.
Later on someone else could add more enum values (interface types) and avoid using NO_FLAGS here (TT_CLIENT_WIFI is an enum already).
+/* This function check whether the interface represented by ifindex is a
- 802.11 wireless device or not. If so the tt_local_entry is marked with the
- TT_CLIENT_WIFI flag */
+static void tt_check_iface(struct tt_local_entry *tt_local_entry, int ifindex)
It would be nice to have a more descriptive name, one which tells you what it is checking. Here it is clear, because of the comment, but where it is actually used, it is not possible to know what the function is checking.
Maybe what is actually needed is a function:
bool is_iface_wifi(int ifindex)
sounds good. It is definitely simpler to read and to understand.
and maybe that should be in hard-interface.c? It could be that knowing if an interface is wired or wifi could be useful in other places. This was one of the discussions at WBMv4, giving preference to wired interfaces over wireless.
mh..Yes, once the function is named is_iface_wifi(), it makes definitely sense to move it in hard-interface.c and make it usable by other part of the code.
Regards,
Hi all,
On lun, giu 06, 2011 at 12:01:10 +0200, Antonio Quartulli wrote:
Hi Andrew, Thank you for replying
On dom, giu 05, 2011 at 11:42:36 +0200, Andrew Lunn wrote:
Hi Antonio
- tt_local_add(soft_iface, soft_iface->dev_addr);
- tt_local_add(soft_iface, soft_iface->dev_addr, 0);
Reading the code, it is not obvious what this 0 mean here. Did you see Sven's recent patches which introduced enums in various places? Maybe instead of a bool you could have an enum with two values: wired, wifi?
I've not looked at the other patches yet, but it might even make sense to have enums for wired, AP, client, adhoc?
Actually I only know whether the device is 802.11 or not. It could also be something different from both wired and wireless. However you are right, I should avoid the hardcoded zero. Maybe I can use NO_FLAGS as we did for the other patches.
Ok, this was not the case for NO_FLAGS (this is not a flag field). I introduced a new constant:
#define NULL_IFINDEX 0 /* dummy ifindex used to avoid iface checks */
I can't use an enum here because it is just a simple MACRO, not a set of values. However does it make sense to have several constats defined as 0? should we always use the same? But what about the name?
Later on someone else could add more enum values (interface types) and avoid using NO_FLAGS here (TT_CLIENT_WIFI is an enum already).
It is late. I mixed things up. These are two separated issues:
1) With NULL_IFINDEX I account the hardcoded 0.
2) Later on more enum values similar to TT_CLIENT_WIFI (e.g. TT_CLIENT_ETH, TT_CLIENT_ADHOC, etc..) can be added. But till now we only have is_wifi_iface().
Regards,
On Sunday, June 05, 2011 11:01:02 PM Antonio Quartulli wrote:
+/* This function returns true if the interface represented by ifindex is a
- 802.11 wireless device */
+bool is_wifi_iface(int ifindex) +{
struct net_device *net_device;
if (ifindex == NULL_IFINDEX)
return false;
net_device = dev_get_by_index(&init_net, ifindex);
if (!net_device)
return false;
+#ifdef CONFIG_WIRELESS_EXT
/* pre-cfg80211 drivers have to implement WEXT, so it is possible to
* check for wireless_handlers != NULL */
if (net_device->wireless_handlers)
return true;
else
+#endif
/* cfg80211 drivers have to set ieee80211_ptr */
if (net_device->ieee80211_ptr)
return true;
return false;
+}
If I am not mistaken dev_get_by_index() increases a counter on the returned interface. We have to decrease that counter as soon as we don't need the interface anymore otherwise the interface can never be freed.
@@ -108,7 +108,7 @@ int mesh_init(struct net_device *soft_iface) if (tt_init(bat_priv) < 1) goto err;
- tt_local_add(soft_iface, soft_iface->dev_addr);
- tt_local_add(soft_iface, soft_iface->dev_addr, NULL_IFINDEX);
Are you sure 0 is not a valid index for any interface ?
static void tt_local_event(struct bat_priv *bat_priv, uint8_t op,
const uint8_t *addr, bool roaming)
const uint8_t *addr, bool roaming, bool wifi)
How about adding a set of flags (TT_CLIENT_ROAM / TT_CLIENT_WIFI / etc) instead of adding more and more bool arguments ? In several places the code converts one to the other which does not seem necessary.
+void tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
int ifindex)
{ struct bat_priv *bat_priv = netdev_priv(soft_iface); struct tt_local_entry *tt_local_entry = NULL; @@ -204,21 +231,22 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr) if (!tt_local_entry) goto out;
tt_local_event(bat_priv, NO_FLAGS, addr, false);
bat_dbg(DBG_TT, bat_priv, "Creating new local tt entry: %pM (ttvn: %d)\n", addr, (uint8_t)atomic_read(&bat_priv->ttvn));
memcpy(tt_local_entry->addr, addr, ETH_ALEN); tt_local_entry->last_seen = jiffies;
- tt_local_entry->flags = 0;
Here you should make use of the NO_FLAGS define you introduced. :-)
/* the batman interface mac address should never be purged */ if (compare_eth(addr, soft_iface->dev_addr))
tt_local_entry->never_purge = 1;
- else
tt_local_entry->never_purge = 0;
tt_local_entry->flags |= TT_LOCAL_NOPURGE;
- tt_local_event(bat_priv, NO_FLAGS, addr, false,
tt_local_entry->flags & TT_CLIENT_WIFI);
Changing "never_purge" to a flag probably is a good idea but should go into a separate patch.
Regards, Marek
On mer, giu 15, 2011 at 11:28:28 +0200, Marek Lindner wrote:
On Sunday, June 05, 2011 11:01:02 PM Antonio Quartulli wrote:
+/* This function returns true if the interface represented by ifindex is a
- 802.11 wireless device */
+bool is_wifi_iface(int ifindex) +{
struct net_device *net_device;
if (ifindex == NULL_IFINDEX)
return false;
net_device = dev_get_by_index(&init_net, ifindex);
if (!net_device)
return false;
+#ifdef CONFIG_WIRELESS_EXT
/* pre-cfg80211 drivers have to implement WEXT, so it is possible to
* check for wireless_handlers != NULL */
if (net_device->wireless_handlers)
return true;
else
+#endif
/* cfg80211 drivers have to set ieee80211_ptr */
if (net_device->ieee80211_ptr)
return true;
return false;
+}
If I am not mistaken dev_get_by_index() increases a counter on the returned interface. We have to decrease that counter as soon as we don't need the interface anymore otherwise the interface can never be freed.
Definitely right!
@@ -108,7 +108,7 @@ int mesh_init(struct net_device *soft_iface) if (tt_init(bat_priv) < 1) goto err;
- tt_local_add(soft_iface, soft_iface->dev_addr);
- tt_local_add(soft_iface, soft_iface->dev_addr, NULL_IFINDEX);
Are you sure 0 is not a valid index for any interface ?
Yes. You can also check the function dev_new_index() at http://lxr.linux.no/linux+v2.6.39/net/core/dev.c#L5080 indexes start from 1 :)
static void tt_local_event(struct bat_priv *bat_priv, uint8_t op,
const uint8_t *addr, bool roaming)
const uint8_t *addr, bool roaming, bool wifi)
How about adding a set of flags (TT_CLIENT_ROAM / TT_CLIENT_WIFI / etc) instead of adding more and more bool arguments ? In several places the code converts one to the other which does not seem necessary.
You mean simply passing a int value which is combination of the used flags? mught be a good idea, even for further changes.
+void tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
int ifindex)
{ struct bat_priv *bat_priv = netdev_priv(soft_iface); struct tt_local_entry *tt_local_entry = NULL; @@ -204,21 +231,22 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr) if (!tt_local_entry) goto out;
tt_local_event(bat_priv, NO_FLAGS, addr, false);
bat_dbg(DBG_TT, bat_priv, "Creating new local tt entry: %pM (ttvn: %d)\n", addr, (uint8_t)atomic_read(&bat_priv->ttvn));
memcpy(tt_local_entry->addr, addr, ETH_ALEN); tt_local_entry->last_seen = jiffies;
- tt_local_entry->flags = 0;
Here you should make use of the NO_FLAGS define you introduced. :-)
Right :)
/* the batman interface mac address should never be purged */ if (compare_eth(addr, soft_iface->dev_addr))
tt_local_entry->never_purge = 1;
- else
tt_local_entry->never_purge = 0;
tt_local_entry->flags |= TT_LOCAL_NOPURGE;
- tt_local_event(bat_priv, NO_FLAGS, addr, false,
tt_local_entry->flags & TT_CLIENT_WIFI);
Changing "never_purge" to a flag probably is a good idea but should go into a separate patch.
Ok, I'll propose a separated patch.
Thank you for reviewing!
Regards,
On Thursday, June 16, 2011 12:43:55 AM Antonio Quartulli wrote:
- tt_local_add(soft_iface, soft_iface->dev_addr);
- tt_local_add(soft_iface, soft_iface->dev_addr, NULL_IFINDEX);
Are you sure 0 is not a valid index for any interface ?
Yes. You can also check the function dev_new_index() at http://lxr.linux.no/linux+v2.6.39/net/core/dev.c#L5080 indexes start from 1 :)
Ok.
How about adding a set of flags (TT_CLIENT_ROAM / TT_CLIENT_WIFI / etc) instead of adding more and more bool arguments ? In several places the code converts one to the other which does not seem necessary.
You mean simply passing a int value which is combination of the used flags? mught be a good idea, even for further changes.
Yes, that is what I had in mind.
Regards, Marek
If a node has to send a packet issued by a WIFI client to another WIFI client, the packet is dropped.
Signed-off-by: Antonio Quartulli ordex@autistici.org --- bat_sysfs.c | 2 ++ routing.c | 2 +- soft-interface.c | 1 + sysfs-class-net-mesh | 8 ++++++++ translation-table.c | 38 ++++++++++++++++++++++++++++++++------ translation-table.h | 2 +- types.h | 1 + unicast.c | 6 ++++-- 8 files changed, 50 insertions(+), 10 deletions(-)
diff --git a/bat_sysfs.c b/bat_sysfs.c index 63738ec..29cba25 100644 --- a/bat_sysfs.c +++ b/bat_sysfs.c @@ -366,6 +366,7 @@ static ssize_t store_gw_bwidth(struct kobject *kobj, struct attribute *attr, BAT_ATTR_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL); BAT_ATTR_BOOL(bonding, S_IRUGO | S_IWUSR, NULL); BAT_ATTR_BOOL(fragmentation, S_IRUGO | S_IWUSR, update_min_mtu); +BAT_ATTR_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL); static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode); static BAT_ATTR(gw_mode, S_IRUGO | S_IWUSR, show_gw_mode, store_gw_mode); BAT_ATTR_UINT(orig_interval, S_IRUGO | S_IWUSR, 2 * JITTER, INT_MAX, NULL); @@ -382,6 +383,7 @@ static struct bat_attribute *mesh_attrs[] = { &bat_attr_aggregated_ogms, &bat_attr_bonding, &bat_attr_fragmentation, + &bat_attr_ap_isolation, &bat_attr_vis_mode, &bat_attr_gw_mode, &bat_attr_orig_interval, diff --git a/routing.c b/routing.c index 70c39dd..d5fd35f 100644 --- a/routing.c +++ b/routing.c @@ -1527,7 +1527,7 @@ static int check_unicast_ttvn(struct bat_priv *bat_priv,
ethhdr = (struct ethhdr *)(skb->data + sizeof(struct unicast_packet)); - orig_node = transtable_search(bat_priv, ethhdr->h_dest); + orig_node = transtable_search(bat_priv, NULL, ethhdr->h_dest);
if (!orig_node) { if (!is_my_client(bat_priv, ethhdr->h_dest)) diff --git a/soft-interface.c b/soft-interface.c index 60234af..6489665 100644 --- a/soft-interface.c +++ b/soft-interface.c @@ -817,6 +817,7 @@ struct net_device *softif_create(const char *name)
atomic_set(&bat_priv->aggregated_ogms, 1); atomic_set(&bat_priv->bonding, 0); + atomic_set(&bat_priv->ap_isolation, 0); atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE); atomic_set(&bat_priv->gw_mode, GW_MODE_OFF); atomic_set(&bat_priv->gw_sel_class, 20); diff --git a/sysfs-class-net-mesh b/sysfs-class-net-mesh index 748fe17..b020014 100644 --- a/sysfs-class-net-mesh +++ b/sysfs-class-net-mesh @@ -22,6 +22,14 @@ Description: mesh will be fragmented or silently discarded if the packet size exceeds the outgoing interface MTU.
+What: /sys/class/net/<mesh_iface>/mesh/ap_isolation +Date: May 2011 +Contact: Antonio Quartulli ordex@autistici.org +Description: + Indicates whether the data traffic going from a + wireless client to another wireless client will be + silently dropped. + What: /sys/class/net/<mesh_iface>/mesh/gw_bandwidth Date: October 2010 Contact: Marek Lindner lindner_marek@yahoo.de diff --git a/translation-table.c b/translation-table.c index 1d4c34c..e0c5945 100644 --- a/translation-table.c +++ b/translation-table.c @@ -807,25 +807,51 @@ static void tt_global_table_free(struct bat_priv *bat_priv) bat_priv->tt_global_hash = NULL; }
+static bool _is_ap_isolated(struct tt_local_entry *tt_local_entry, + struct tt_global_entry *tt_global_entry) +{ + bool ret = false; + + if (tt_local_entry->flags & TT_CLIENT_WIFI && + tt_global_entry->flags & TT_CLIENT_WIFI) + ret = true; + + return ret; +} + struct orig_node *transtable_search(struct bat_priv *bat_priv, - const uint8_t *addr) + const uint8_t *src, const uint8_t *addr) { - struct tt_global_entry *tt_global_entry; + struct tt_local_entry *tt_local_entry = NULL; + struct tt_global_entry *tt_global_entry = NULL; struct orig_node *orig_node = NULL;
- tt_global_entry = tt_global_hash_find(bat_priv, addr); + if (src && atomic_read(&bat_priv->ap_isolation)) { + tt_local_entry = tt_local_hash_find(bat_priv, src); + if (!tt_local_entry) + goto out; + }
+ tt_global_entry = tt_global_hash_find(bat_priv, addr); if (!tt_global_entry) goto out;
+ /* check whether the clients should not communicate due to AP + * isolation */ + if (tt_local_entry && _is_ap_isolated(tt_local_entry, tt_global_entry)) + goto out; + if (!atomic_inc_not_zero(&tt_global_entry->orig_node->refcount)) - goto free_tt; + goto out;
orig_node = tt_global_entry->orig_node;
-free_tt: - tt_global_entry_free_ref(tt_global_entry); out: + if (tt_global_entry) + tt_global_entry_free_ref(tt_global_entry); + if (tt_local_entry) + tt_local_entry_free_ref(tt_local_entry); + return orig_node; }
diff --git a/translation-table.h b/translation-table.h index b62ae00..3055b8b 100644 --- a/translation-table.h +++ b/translation-table.h @@ -48,7 +48,7 @@ void tt_global_del(struct bat_priv *bat_priv, struct orig_node *orig_node, const unsigned char *addr, const char *message, bool roaming); struct orig_node *transtable_search(struct bat_priv *bat_priv, - const uint8_t *addr); + const uint8_t *src, const uint8_t *addr); void tt_save_orig_buffer(struct bat_priv *bat_priv, struct orig_node *orig_node, const unsigned char *tt_buff, uint8_t tt_num_changes); uint16_t tt_local_crc(struct bat_priv *bat_priv); diff --git a/types.h b/types.h index 0d85ba7..2ec748d 100644 --- a/types.h +++ b/types.h @@ -146,6 +146,7 @@ struct bat_priv { atomic_t aggregated_ogms; /* boolean */ atomic_t bonding; /* boolean */ atomic_t fragmentation; /* boolean */ + atomic_t ap_isolation; /* boolean */ atomic_t vis_mode; /* VIS_TYPE_* */ atomic_t gw_mode; /* GW_MODE_* */ atomic_t gw_sel_class; /* uint */ diff --git a/unicast.c b/unicast.c index 32b125f..07d1c1d 100644 --- a/unicast.c +++ b/unicast.c @@ -299,8 +299,10 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) goto find_router; }
- /* check for tt host - increases orig_node refcount */ - orig_node = transtable_search(bat_priv, ethhdr->h_dest); + /* check for tt host - increases orig_node refcount. + * returns NULL in case of AP isolation */ + orig_node = transtable_search(bat_priv, ethhdr->h_source, + ethhdr->h_dest);
find_router: /**
Hi Antonio
+static bool _is_ap_isolated(struct tt_local_entry *tt_local_entry,
struct tt_global_entry *tt_global_entry)
The general pattern i've seen in linux code is that a function _foobar is a helper for a function foobar. I don't see an is_ap_isolated() here. So i would just call it is_ap_isolated.
Andrew
On Sunday, June 05, 2011 11:50:52 PM Andrew Lunn wrote:
Hi Antonio
+static bool _is_ap_isolated(struct tt_local_entry *tt_local_entry,
struct tt_global_entry *tt_global_entry)
The general pattern i've seen in linux code is that a function _foobar is a helper for a function foobar. I don't see an is_ap_isolated() here. So i would just call it is_ap_isolated.
I agree - I also wondered about where to find is_ap_isolated() when I saw _is_ap_isolated().
Regards, Marek
When a node receives a unicast packet it checks if the source and the destination client can communicate or not due to the AP isolation
Signed-off-by: Antonio Quartulli ordex@autistici.org --- soft-interface.c | 3 +++ translation-table.c | 30 ++++++++++++++++++++++++++++++ translation-table.h | 1 + 3 files changed, 34 insertions(+), 0 deletions(-)
diff --git a/soft-interface.c b/soft-interface.c index 6489665..714a2af 100644 --- a/soft-interface.c +++ b/soft-interface.c @@ -733,6 +733,9 @@ void interface_rx(struct net_device *soft_iface,
soft_iface->last_rx = jiffies;
+ if (is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest)) + goto dropped; + netif_rx(skb); goto out;
diff --git a/translation-table.c b/translation-table.c index e0c5945..24e48e7 100644 --- a/translation-table.c +++ b/translation-table.c @@ -1683,3 +1683,33 @@ void tt_free(struct bat_priv *bat_priv)
kfree(bat_priv->tt_buff); } + +bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst) +{ + struct tt_local_entry *tt_local_entry = NULL; + struct tt_global_entry *tt_global_entry = NULL; + bool ret = true; + + if (!atomic_read(&bat_priv->ap_isolation)) + return false; + + tt_local_entry = tt_local_hash_find(bat_priv, dst); + if (!tt_local_entry) + goto out; + + tt_global_entry = tt_global_hash_find(bat_priv, src); + if (!tt_global_entry) + goto out; + + if (_is_ap_isolated(tt_local_entry, tt_global_entry)) + goto out; + + ret = false; + +out: + if (tt_global_entry) + tt_global_entry_free_ref(tt_global_entry); + if (tt_local_entry) + tt_local_entry_free_ref(tt_local_entry); + return ret; +} diff --git a/translation-table.h b/translation-table.h index 3055b8b..8080153 100644 --- a/translation-table.h +++ b/translation-table.h @@ -67,5 +67,6 @@ void handle_tt_response(struct bat_priv *bat_priv, struct tt_query_packet *tt_response); void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client, struct orig_node *orig_node); +bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst);
#endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */
diff --git a/translation-table.c b/translation-table.c index e0c5945..24e48e7 100644 --- a/translation-table.c +++ b/translation-table.c @@ -1683,3 +1683,33 @@ void tt_free(struct bat_priv *bat_priv)
kfree(bat_priv->tt_buff); }
+bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst)
Doh!
O.K. The ordering could of been better... but the code at the end is O.K, which is what matters.
Andrew
On dom, giu 05, 2011 at 11:55:52 +0200, Andrew Lunn wrote:
diff --git a/translation-table.c b/translation-table.c index e0c5945..24e48e7 100644 --- a/translation-table.c +++ b/translation-table.c @@ -1683,3 +1683,33 @@ void tt_free(struct bat_priv *bat_priv)
kfree(bat_priv->tt_buff); }
+bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst)
Doh!
O.K. The ordering could of been better... but the code at the end is O.K, which is what matters.
:-) I avoided to rename such function...so I directly called it _foobar from the beginning.
Regards,
On Sunday, June 05, 2011 11:55:52 PM Andrew Lunn wrote:
diff --git a/translation-table.c b/translation-table.c index e0c5945..24e48e7 100644 --- a/translation-table.c +++ b/translation-table.c @@ -1683,3 +1683,33 @@ void tt_free(struct bat_priv *bat_priv)
kfree(bat_priv->tt_buff);
}
+bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst)
Doh!
O.K. The ordering could of been better... but the code at the end is O.K, which is what matters.
Aarrgh, same here. Let's see how many others fall into this trap. How about reversing the order of these patches to avoid this "problem" ?
Regards, Marek
On mer, giu 15, 2011 at 11:42:38 +0200, Marek Lindner wrote:
On Sunday, June 05, 2011 11:55:52 PM Andrew Lunn wrote:
diff --git a/translation-table.c b/translation-table.c index e0c5945..24e48e7 100644 --- a/translation-table.c +++ b/translation-table.c @@ -1683,3 +1683,33 @@ void tt_free(struct bat_priv *bat_priv)
kfree(bat_priv->tt_buff);
}
+bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst)
Doh!
O.K. The ordering could of been better... but the code at the end is O.K, which is what matters.
Aarrgh, same here. Let's see how many others fall into this trap. How about reversing the order of these patches to avoid this "problem" ?
Mh...the patches should be independent from each other. ok I like your suggestion :)
Thank you!
Regards,
Clients connected through a 802.11 device are now marked with the TT_CLIENT_WIFI flag. This flag is also advertised with the tt announcement.
Signed-off-by: Antonio Quartulli ordex@autistici.org ---
This patchset is based on top of: "batman-adv: pass a unique flag arg instead of a sequence of bool ones" which is on the ML but has not been applied yet.
Several stuff have been fixed in this version following Andrew's and Marek's suggestion. ** Patch4 adds support for showing client flags in the transtables output. ** For more details look at the following mails:
- patch 1: http://www.mail-archive.com/b.a.t.m.a.n@lists.open-mesh.org/msg04814.html http://www.mail-archive.com/b.a.t.m.a.n@lists.open-mesh.org/msg04892.html
- patch 2: http://www.mail-archive.com/b.a.t.m.a.n@lists.open-mesh.org/msg04816.html
- patch 3: http://www.mail-archive.com/b.a.t.m.a.n@lists.open-mesh.org/msg04817.html http://www.mail-archive.com/b.a.t.m.a.n@lists.open-mesh.org/msg04894.html
compat.h | 2 ++ hard-interface.c | 30 ++++++++++++++++++++++++++++++ hard-interface.h | 1 + main.c | 2 +- main.h | 2 ++ packet.h | 3 ++- routing.c | 2 +- soft-interface.c | 4 ++-- translation-table.c | 15 ++++++++++++--- translation-table.h | 9 +++++---- 10 files changed, 58 insertions(+), 12 deletions(-)
diff --git a/compat.h b/compat.h index 66a8adc..f1965d0 100644 --- a/compat.h +++ b/compat.h @@ -263,6 +263,8 @@ int bat_seq_printf(struct seq_file *m, const char *f, ...);
#define __always_unused __attribute__((unused))
+#define skb_iif iif + #endif /* < KERNEL_VERSION(2, 6, 33) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34) diff --git a/hard-interface.c b/hard-interface.c index db7aacf..f2b6fd9 100644 --- a/hard-interface.c +++ b/hard-interface.c @@ -681,6 +681,36 @@ err_out: return NET_RX_DROP; }
+/* This function returns true if the interface represented by ifindex is a + * 802.11 wireless device */ +bool is_wifi_iface(int ifindex) +{ + struct net_device *net_device = NULL; + bool ret = false; + + if (ifindex == NULL_IFINDEX) + goto out; + + net_device = dev_get_by_index(&init_net, ifindex); + if (!net_device) + goto out; + +#ifdef CONFIG_WIRELESS_EXT + /* pre-cfg80211 drivers have to implement WEXT, so it is possible to + * check for wireless_handlers != NULL */ + if (net_device->wireless_handlers) + ret = true; + else +#endif + /* cfg80211 drivers have to set ieee80211_ptr */ + if (net_device->ieee80211_ptr) + ret = true; +out: + if (net_device) + dev_put(net_device); + return ret; +} + struct notifier_block hard_if_notifier = { .notifier_call = hard_if_event, }; diff --git a/hard-interface.h b/hard-interface.h index 442eacb..67f78d1 100644 --- a/hard-interface.h +++ b/hard-interface.h @@ -42,6 +42,7 @@ void hardif_remove_interfaces(void); int hardif_min_mtu(struct net_device *soft_iface); void update_min_mtu(struct net_device *soft_iface); void hardif_free_rcu(struct rcu_head *rcu); +bool is_wifi_iface(int ifindex);
static inline void hardif_free_ref(struct hard_iface *hard_iface) { diff --git a/main.c b/main.c index e367e69..5dc47a3 100644 --- a/main.c +++ b/main.c @@ -108,7 +108,7 @@ int mesh_init(struct net_device *soft_iface) if (tt_init(bat_priv) < 1) goto err;
- tt_local_add(soft_iface, soft_iface->dev_addr); + tt_local_add(soft_iface, soft_iface->dev_addr, NULL_IFINDEX);
if (vis_init(bat_priv) < 1) goto err; diff --git a/main.h b/main.h index f3fe9f4..4e2bbe3 100644 --- a/main.h +++ b/main.h @@ -61,6 +61,8 @@
#define NO_FLAGS 0
+#define NULL_IFINDEX 0 /* dummy ifindex used to avoid iface checks */ + #define NUM_WORDS (TQ_LOCAL_WINDOW_SIZE / WORD_BIT_SIZE)
#define LOG_BUF_LEN 8192 /* has to be a power of 2 */ diff --git a/packet.h b/packet.h index 8fd2fde..b17baa5 100644 --- a/packet.h +++ b/packet.h @@ -82,7 +82,8 @@ enum tt_query_flags { enum tt_client_flags { TT_CLIENT_DEL = 0x01, TT_CLIENT_ROAM = 0x02, - TT_CLIENT_NOPURGE = 0x04 + TT_CLIENT_NOPURGE = 0x04, + TT_CLIENT_WIFI = 0x08 };
struct batman_packet { diff --git a/routing.c b/routing.c index 2cb98be..d86fbd9 100644 --- a/routing.c +++ b/routing.c @@ -1288,7 +1288,7 @@ int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if) roam_adv_packet->client);
tt_global_add(bat_priv, orig_node, roam_adv_packet->client, - atomic_read(&orig_node->last_ttvn) + 1, true); + atomic_read(&orig_node->last_ttvn) + 1, true, false);
/* Roaming phase starts: I have new information but the ttvn has not * been incremented yet. This flag will make me check all the incoming diff --git a/soft-interface.c b/soft-interface.c index 3f20332..48146e5 100644 --- a/soft-interface.c +++ b/soft-interface.c @@ -536,7 +536,7 @@ static int interface_set_mac_addr(struct net_device *dev, void *p) if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) { tt_local_remove(bat_priv, dev->dev_addr, "mac address changed", false); - tt_local_add(dev, addr->sa_data); + tt_local_add(dev, addr->sa_data, NULL_IFINDEX); }
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); @@ -595,7 +595,7 @@ static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) goto dropped;
/* Register the client MAC in the transtable */ - tt_local_add(soft_iface, ethhdr->h_source); + tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif);
orig_node = transtable_search(bat_priv, ethhdr->h_dest); if (is_multicast_ether_addr(ethhdr->h_dest) || diff --git a/translation-table.c b/translation-table.c index 796303d..e1dede1 100644 --- a/translation-table.c +++ b/translation-table.c @@ -186,7 +186,8 @@ static int tt_local_init(struct bat_priv *bat_priv) return 1; }
-void tt_local_add(struct net_device *soft_iface, const uint8_t *addr) +void tt_local_add(struct net_device *soft_iface, const uint8_t *addr, + int ifindex) { struct bat_priv *bat_priv = netdev_priv(soft_iface); struct tt_local_entry *tt_local_entry = NULL; @@ -210,6 +211,8 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr) memcpy(tt_local_entry->addr, addr, ETH_ALEN); tt_local_entry->last_seen = jiffies; tt_local_entry->flags = NO_FLAGS; + if (is_wifi_iface(ifindex)) + tt_local_entry->flags |= TT_CLIENT_WIFI; atomic_set(&tt_local_entry->refcount, 2);
/* the batman interface mac address should never be purged */ @@ -494,7 +497,8 @@ static void tt_changes_list_free(struct bat_priv *bat_priv)
/* caller must hold orig_node refcount */ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, - const unsigned char *tt_addr, uint8_t ttvn, bool roaming) + const unsigned char *tt_addr, uint8_t ttvn, bool roaming, + bool wifi) { struct tt_global_entry *tt_global_entry; struct orig_node *orig_node_tmp; @@ -536,6 +540,9 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, tt_global_entry->roam_at = 0; }
+ if (wifi) + tt_global_entry->flags |= TT_CLIENT_WIFI; + bat_dbg(DBG_TT, bat_priv, "Creating new global tt entry: %pM (via %pM)\n", tt_global_entry->addr, orig_node->orig); @@ -1342,7 +1349,9 @@ static void _tt_update_changes(struct bat_priv *bat_priv, (tt_change + i)->flags & TT_CLIENT_ROAM); else if (!tt_global_add(bat_priv, orig_node, - (tt_change + i)->addr, ttvn, false)) + (tt_change + i)->addr, ttvn, false, + (tt_change + i)->flags & + TT_CLIENT_WIFI)) /* In case of problem while storing a * global_entry, we stop the updating * procedure without committing the diff --git a/translation-table.h b/translation-table.h index 460e583..e244858 100644 --- a/translation-table.h +++ b/translation-table.h @@ -26,15 +26,16 @@ int tt_len(int changes_num); int tt_changes_fill_buffer(struct bat_priv *bat_priv, unsigned char *buff, int buff_len); int tt_init(struct bat_priv *bat_priv); -void tt_local_add(struct net_device *soft_iface, const uint8_t *addr); +void tt_local_add(struct net_device *soft_iface, const uint8_t *addr, + int ifindex); void tt_local_remove(struct bat_priv *bat_priv, const uint8_t *addr, const char *message, bool roaming); int tt_local_seq_print_text(struct seq_file *seq, void *offset); void tt_global_add_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, const unsigned char *tt_buff, int tt_buff_len); -int tt_global_add(struct bat_priv *bat_priv, - struct orig_node *orig_node, const unsigned char *addr, - uint8_t ttvn, bool roaming); +int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, + const unsigned char *addr, uint8_t ttvn, bool roaming, + bool wifi); int tt_global_seq_print_text(struct seq_file *seq, void *offset); void tt_global_del_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, const char *message);
When a node receives a unicast packet it checks if the source and the destination client can communicate or not due to the AP isolation
Signed-off-by: Antonio Quartulli ordex@autistici.org --- bat_sysfs.c | 2 ++ soft-interface.c | 4 ++++ sysfs-class-net-mesh | 8 ++++++++ translation-table.c | 42 ++++++++++++++++++++++++++++++++++++++++++ translation-table.h | 1 + types.h | 1 + 6 files changed, 58 insertions(+), 0 deletions(-)
diff --git a/bat_sysfs.c b/bat_sysfs.c index cd15deb..b8a7414 100644 --- a/bat_sysfs.c +++ b/bat_sysfs.c @@ -380,6 +380,7 @@ static ssize_t store_gw_bwidth(struct kobject *kobj, struct attribute *attr, BAT_ATTR_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL); BAT_ATTR_BOOL(bonding, S_IRUGO | S_IWUSR, NULL); BAT_ATTR_BOOL(fragmentation, S_IRUGO | S_IWUSR, update_min_mtu); +BAT_ATTR_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL); static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode); static BAT_ATTR(gw_mode, S_IRUGO | S_IWUSR, show_gw_mode, store_gw_mode); BAT_ATTR_UINT(orig_interval, S_IRUGO | S_IWUSR, 2 * JITTER, INT_MAX, NULL); @@ -396,6 +397,7 @@ static struct bat_attribute *mesh_attrs[] = { &bat_attr_aggregated_ogms, &bat_attr_bonding, &bat_attr_fragmentation, + &bat_attr_ap_isolation, &bat_attr_vis_mode, &bat_attr_gw_mode, &bat_attr_orig_interval, diff --git a/soft-interface.c b/soft-interface.c index 48146e5..839ded9 100644 --- a/soft-interface.c +++ b/soft-interface.c @@ -739,6 +739,9 @@ void interface_rx(struct net_device *soft_iface,
soft_iface->last_rx = jiffies;
+ if (is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest)) + goto dropped; + netif_rx(skb); goto out;
@@ -823,6 +826,7 @@ struct net_device *softif_create(const char *name)
atomic_set(&bat_priv->aggregated_ogms, 1); atomic_set(&bat_priv->bonding, 0); + atomic_set(&bat_priv->ap_isolation, 0); atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE); atomic_set(&bat_priv->gw_mode, GW_MODE_OFF); atomic_set(&bat_priv->gw_sel_class, 20); diff --git a/sysfs-class-net-mesh b/sysfs-class-net-mesh index 748fe17..b020014 100644 --- a/sysfs-class-net-mesh +++ b/sysfs-class-net-mesh @@ -22,6 +22,14 @@ Description: mesh will be fragmented or silently discarded if the packet size exceeds the outgoing interface MTU.
+What: /sys/class/net/<mesh_iface>/mesh/ap_isolation +Date: May 2011 +Contact: Antonio Quartulli ordex@autistici.org +Description: + Indicates whether the data traffic going from a + wireless client to another wireless client will be + silently dropped. + What: /sys/class/net/<mesh_iface>/mesh/gw_bandwidth Date: October 2010 Contact: Marek Lindner lindner_marek@yahoo.de diff --git a/translation-table.c b/translation-table.c index e1dede1..3deccc0 100644 --- a/translation-table.c +++ b/translation-table.c @@ -780,6 +780,18 @@ static void tt_global_table_free(struct bat_priv *bat_priv) bat_priv->tt_global_hash = NULL; }
+static bool _is_ap_isolated(struct tt_local_entry *tt_local_entry, + struct tt_global_entry *tt_global_entry) +{ + bool ret = false; + + if (tt_local_entry->flags & TT_CLIENT_WIFI && + tt_global_entry->flags & TT_CLIENT_WIFI) + ret = true; + + return ret; +} + struct orig_node *transtable_search(struct bat_priv *bat_priv, const uint8_t *addr) { @@ -1631,3 +1643,33 @@ void tt_free(struct bat_priv *bat_priv)
kfree(bat_priv->tt_buff); } + +bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst) +{ + struct tt_local_entry *tt_local_entry = NULL; + struct tt_global_entry *tt_global_entry = NULL; + bool ret = true; + + if (!atomic_read(&bat_priv->ap_isolation)) + return false; + + tt_local_entry = tt_local_hash_find(bat_priv, dst); + if (!tt_local_entry) + goto out; + + tt_global_entry = tt_global_hash_find(bat_priv, src); + if (!tt_global_entry) + goto out; + + if (_is_ap_isolated(tt_local_entry, tt_global_entry)) + goto out; + + ret = false; + +out: + if (tt_global_entry) + tt_global_entry_free_ref(tt_global_entry); + if (tt_local_entry) + tt_local_entry_free_ref(tt_local_entry); + return ret; +} diff --git a/translation-table.h b/translation-table.h index e244858..9b93c16 100644 --- a/translation-table.h +++ b/translation-table.h @@ -62,5 +62,6 @@ void handle_tt_response(struct bat_priv *bat_priv, struct tt_query_packet *tt_response); void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client, struct orig_node *orig_node); +bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst);
#endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */ diff --git a/types.h b/types.h index 582283a..4df1f5f 100644 --- a/types.h +++ b/types.h @@ -146,6 +146,7 @@ struct bat_priv { atomic_t aggregated_ogms; /* boolean */ atomic_t bonding; /* boolean */ atomic_t fragmentation; /* boolean */ + atomic_t ap_isolation; /* boolean */ atomic_t vis_mode; /* VIS_TYPE_* */ atomic_t gw_mode; /* GW_MODE_* */ atomic_t gw_sel_class; /* uint */
If a node has to send a packet issued by a WIFI client to another WIFI client, the packet is dropped.
Signed-off-by: Antonio Quartulli ordex@autistici.org --- routing.c | 2 +- soft-interface.c | 3 ++- translation-table.c | 26 ++++++++++++++++++++------ translation-table.h | 2 +- unicast.c | 6 ++++-- 5 files changed, 28 insertions(+), 11 deletions(-)
diff --git a/routing.c b/routing.c index d86fbd9..dbef1e2 100644 --- a/routing.c +++ b/routing.c @@ -1524,7 +1524,7 @@ static int check_unicast_ttvn(struct bat_priv *bat_priv,
ethhdr = (struct ethhdr *)(skb->data + sizeof(struct unicast_packet)); - orig_node = transtable_search(bat_priv, ethhdr->h_dest); + orig_node = transtable_search(bat_priv, NULL, ethhdr->h_dest);
if (!orig_node) { if (!is_my_client(bat_priv, ethhdr->h_dest)) diff --git a/soft-interface.c b/soft-interface.c index 839ded9..ef2fad5 100644 --- a/soft-interface.c +++ b/soft-interface.c @@ -597,7 +597,8 @@ static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) /* Register the client MAC in the transtable */ tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif);
- orig_node = transtable_search(bat_priv, ethhdr->h_dest); + orig_node = transtable_search(bat_priv, ethhdr->h_source, + ethhdr->h_dest); if (is_multicast_ether_addr(ethhdr->h_dest) || (orig_node && orig_node->gw_flags)) { ret = gw_is_target(bat_priv, skb, orig_node); diff --git a/translation-table.c b/translation-table.c index 3deccc0..f5a772f 100644 --- a/translation-table.c +++ b/translation-table.c @@ -793,24 +793,38 @@ static bool _is_ap_isolated(struct tt_local_entry *tt_local_entry, }
struct orig_node *transtable_search(struct bat_priv *bat_priv, - const uint8_t *addr) + const uint8_t *src, const uint8_t *addr) { - struct tt_global_entry *tt_global_entry; + struct tt_local_entry *tt_local_entry = NULL; + struct tt_global_entry *tt_global_entry = NULL; struct orig_node *orig_node = NULL;
- tt_global_entry = tt_global_hash_find(bat_priv, addr); + if (src && atomic_read(&bat_priv->ap_isolation)) { + tt_local_entry = tt_local_hash_find(bat_priv, src); + if (!tt_local_entry) + goto out; + }
+ tt_global_entry = tt_global_hash_find(bat_priv, addr); if (!tt_global_entry) goto out;
+ /* check whether the clients should not communicate due to AP + * isolation */ + if (tt_local_entry && _is_ap_isolated(tt_local_entry, tt_global_entry)) + goto out; + if (!atomic_inc_not_zero(&tt_global_entry->orig_node->refcount)) - goto free_tt; + goto out;
orig_node = tt_global_entry->orig_node;
-free_tt: - tt_global_entry_free_ref(tt_global_entry); out: + if (tt_global_entry) + tt_global_entry_free_ref(tt_global_entry); + if (tt_local_entry) + tt_local_entry_free_ref(tt_local_entry); + return orig_node; }
diff --git a/translation-table.h b/translation-table.h index 9b93c16..9765034 100644 --- a/translation-table.h +++ b/translation-table.h @@ -43,7 +43,7 @@ void tt_global_del(struct bat_priv *bat_priv, struct orig_node *orig_node, const unsigned char *addr, const char *message, bool roaming); struct orig_node *transtable_search(struct bat_priv *bat_priv, - const uint8_t *addr); + const uint8_t *src, const uint8_t *addr); void tt_save_orig_buffer(struct bat_priv *bat_priv, struct orig_node *orig_node, const unsigned char *tt_buff, uint8_t tt_num_changes); uint16_t tt_local_crc(struct bat_priv *bat_priv); diff --git a/unicast.c b/unicast.c index 32b125f..07d1c1d 100644 --- a/unicast.c +++ b/unicast.c @@ -299,8 +299,10 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) goto find_router; }
- /* check for tt host - increases orig_node refcount */ - orig_node = transtable_search(bat_priv, ethhdr->h_dest); + /* check for tt host - increases orig_node refcount. + * returns NULL in case of AP isolation */ + orig_node = transtable_search(bat_priv, ethhdr->h_source, + ethhdr->h_dest);
find_router: /**
Since clients can have several flags on or off, this patches make them appear in the local/global transtable output so that they can be checked for debugging purposes.
Signed-off-by: Antonio Quartulli ordex@autistici.org --- translation-table.c | 28 +++++++++++++++++++--------- 1 files changed, 19 insertions(+), 9 deletions(-)
diff --git a/translation-table.c b/translation-table.c index f5a772f..b413eff 100644 --- a/translation-table.c +++ b/translation-table.c @@ -331,7 +331,7 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset)
rcu_read_lock(); __hlist_for_each_rcu(node, head) - buf_size += 21; + buf_size += 27; rcu_read_unlock(); }
@@ -350,8 +350,14 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset) rcu_read_lock(); hlist_for_each_entry_rcu(tt_local_entry, node, head, hash_entry) { - pos += snprintf(buff + pos, 22, " * %pM\n", - tt_local_entry->addr); + pos += snprintf(buff + pos, 28, " * %pM [%c%c%c]\n", + tt_local_entry->addr, + (tt_local_entry->flags & + TT_CLIENT_ROAM ? 'R' : '.'), + (tt_local_entry->flags & + TT_CLIENT_NOPURGE ? 'N' : '.'), + (tt_local_entry->flags & + TT_CLIENT_WIFI ? 'W' : '.')); } rcu_read_unlock(); } @@ -588,8 +594,8 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset) seq_printf(seq, "Globally announced TT entries received via the mesh %s\n", net_dev->name); - seq_printf(seq, " %-13s %s %-15s %s\n", - "Client", "(TTVN)", "Originator", "(Curr TTVN)"); + seq_printf(seq, " %-13s %s %-15s %s %s\n", + "Client", "(TTVN)", "Originator", "(Curr TTVN)", "Flags");
buf_size = 1; /* Estimate length for: " * xx:xx:xx:xx:xx:xx (ttvn) via @@ -599,7 +605,7 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset)
rcu_read_lock(); __hlist_for_each_rcu(node, head) - buf_size += 59; + buf_size += 66; rcu_read_unlock(); }
@@ -618,14 +624,18 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset) rcu_read_lock(); hlist_for_each_entry_rcu(tt_global_entry, node, head, hash_entry) { - pos += snprintf(buff + pos, 61, - " * %pM (%3u) via %pM (%3u)\n", + pos += snprintf(buff + pos, 68, + " * %pM (%3u) via %pM (%3u) [%c%c]\n", tt_global_entry->addr, tt_global_entry->ttvn, tt_global_entry->orig_node->orig, (uint8_t) atomic_read( &tt_global_entry->orig_node-> - last_ttvn)); + last_ttvn), + (tt_global_entry->flags & + TT_CLIENT_ROAM ? 'R' : '.'), + (tt_global_entry->flags & + TT_CLIENT_WIFI ? 'W' : '.')); } rcu_read_unlock(); }
b.a.t.m.a.n@lists.open-mesh.org