Commit d6f03f29 authored by David S. Miller's avatar David S. Miller

Merge branch 'for_david' of git://git.open-mesh.org/linux-merge

parents 6f39da2c 76e8d7b0
...@@ -174,7 +174,7 @@ static int store_uint_attr(const char *buff, size_t count, ...@@ -174,7 +174,7 @@ static int store_uint_attr(const char *buff, size_t count,
unsigned long uint_val; unsigned long uint_val;
int ret; int ret;
ret = strict_strtoul(buff, 10, &uint_val); ret = kstrtoul(buff, 10, &uint_val);
if (ret) { if (ret) {
bat_info(net_dev, bat_info(net_dev,
"%s: Invalid parameter received: %s\n", "%s: Invalid parameter received: %s\n",
...@@ -239,7 +239,7 @@ static ssize_t store_vis_mode(struct kobject *kobj, struct attribute *attr, ...@@ -239,7 +239,7 @@ static ssize_t store_vis_mode(struct kobject *kobj, struct attribute *attr,
unsigned long val; unsigned long val;
int ret, vis_mode_tmp = -1; int ret, vis_mode_tmp = -1;
ret = strict_strtoul(buff, 10, &val); ret = kstrtoul(buff, 10, &val);
if (((count == 2) && (!ret) && (val == VIS_TYPE_CLIENT_UPDATE)) || if (((count == 2) && (!ret) && (val == VIS_TYPE_CLIENT_UPDATE)) ||
(strncmp(buff, "client", 6) == 0) || (strncmp(buff, "client", 6) == 0) ||
......
...@@ -155,7 +155,7 @@ int bit_get_packet(void *priv, unsigned long *seq_bits, ...@@ -155,7 +155,7 @@ int bit_get_packet(void *priv, unsigned long *seq_bits,
/* sequence number is much newer, probably missed a lot of packets */ /* sequence number is much newer, probably missed a lot of packets */
if ((seq_num_diff >= TQ_LOCAL_WINDOW_SIZE) if ((seq_num_diff >= TQ_LOCAL_WINDOW_SIZE)
|| (seq_num_diff < EXPECTED_SEQNO_RANGE)) { && (seq_num_diff < EXPECTED_SEQNO_RANGE)) {
bat_dbg(DBG_BATMAN, bat_priv, bat_dbg(DBG_BATMAN, bat_priv,
"We missed a lot of packets (%i) !\n", "We missed a lot of packets (%i) !\n",
seq_num_diff - 1); seq_num_diff - 1);
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "gateway_common.h" #include "gateway_common.h"
#include "hard-interface.h" #include "hard-interface.h"
#include "originator.h" #include "originator.h"
#include "translation-table.h"
#include "routing.h" #include "routing.h"
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/ipv6.h> #include <linux/ipv6.h>
...@@ -572,108 +573,142 @@ static bool is_type_dhcprequest(struct sk_buff *skb, int header_len) ...@@ -572,108 +573,142 @@ static bool is_type_dhcprequest(struct sk_buff *skb, int header_len)
return ret; return ret;
} }
int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb, bool gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len)
struct orig_node *old_gw)
{ {
struct ethhdr *ethhdr; struct ethhdr *ethhdr;
struct iphdr *iphdr; struct iphdr *iphdr;
struct ipv6hdr *ipv6hdr; struct ipv6hdr *ipv6hdr;
struct udphdr *udphdr; struct udphdr *udphdr;
struct gw_node *curr_gw;
struct neigh_node *neigh_curr = NULL, *neigh_old = NULL;
unsigned int header_len = 0;
int ret = 1;
if (atomic_read(&bat_priv->gw_mode) == GW_MODE_OFF)
return 0;
/* check for ethernet header */ /* check for ethernet header */
if (!pskb_may_pull(skb, header_len + ETH_HLEN)) if (!pskb_may_pull(skb, *header_len + ETH_HLEN))
return 0; return false;
ethhdr = (struct ethhdr *)skb->data; ethhdr = (struct ethhdr *)skb->data;
header_len += ETH_HLEN; *header_len += ETH_HLEN;
/* check for initial vlan header */ /* check for initial vlan header */
if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) { if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) {
if (!pskb_may_pull(skb, header_len + VLAN_HLEN)) if (!pskb_may_pull(skb, *header_len + VLAN_HLEN))
return 0; return false;
ethhdr = (struct ethhdr *)(skb->data + VLAN_HLEN); ethhdr = (struct ethhdr *)(skb->data + VLAN_HLEN);
header_len += VLAN_HLEN; *header_len += VLAN_HLEN;
} }
/* check for ip header */ /* check for ip header */
switch (ntohs(ethhdr->h_proto)) { switch (ntohs(ethhdr->h_proto)) {
case ETH_P_IP: case ETH_P_IP:
if (!pskb_may_pull(skb, header_len + sizeof(*iphdr))) if (!pskb_may_pull(skb, *header_len + sizeof(*iphdr)))
return 0; return false;
iphdr = (struct iphdr *)(skb->data + header_len); iphdr = (struct iphdr *)(skb->data + *header_len);
header_len += iphdr->ihl * 4; *header_len += iphdr->ihl * 4;
/* check for udp header */ /* check for udp header */
if (iphdr->protocol != IPPROTO_UDP) if (iphdr->protocol != IPPROTO_UDP)
return 0; return false;
break; break;
case ETH_P_IPV6: case ETH_P_IPV6:
if (!pskb_may_pull(skb, header_len + sizeof(*ipv6hdr))) if (!pskb_may_pull(skb, *header_len + sizeof(*ipv6hdr)))
return 0; return false;
ipv6hdr = (struct ipv6hdr *)(skb->data + header_len); ipv6hdr = (struct ipv6hdr *)(skb->data + *header_len);
header_len += sizeof(*ipv6hdr); *header_len += sizeof(*ipv6hdr);
/* check for udp header */ /* check for udp header */
if (ipv6hdr->nexthdr != IPPROTO_UDP) if (ipv6hdr->nexthdr != IPPROTO_UDP)
return 0; return false;
break; break;
default: default:
return 0; return false;
} }
if (!pskb_may_pull(skb, header_len + sizeof(*udphdr))) if (!pskb_may_pull(skb, *header_len + sizeof(*udphdr)))
return 0; return false;
udphdr = (struct udphdr *)(skb->data + header_len); udphdr = (struct udphdr *)(skb->data + *header_len);
header_len += sizeof(*udphdr); *header_len += sizeof(*udphdr);
/* check for bootp port */ /* check for bootp port */
if ((ntohs(ethhdr->h_proto) == ETH_P_IP) && if ((ntohs(ethhdr->h_proto) == ETH_P_IP) &&
(ntohs(udphdr->dest) != 67)) (ntohs(udphdr->dest) != 67))
return 0; return false;
if ((ntohs(ethhdr->h_proto) == ETH_P_IPV6) && if ((ntohs(ethhdr->h_proto) == ETH_P_IPV6) &&
(ntohs(udphdr->dest) != 547)) (ntohs(udphdr->dest) != 547))
return 0; return false;
if (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER) return true;
return -1; }
curr_gw = gw_get_selected_gw_node(bat_priv); bool gw_out_of_range(struct bat_priv *bat_priv,
if (!curr_gw) struct sk_buff *skb, struct ethhdr *ethhdr)
return 0; {
struct neigh_node *neigh_curr = NULL, *neigh_old = NULL;
/* If old_gw != NULL then this packet is unicast. struct orig_node *orig_dst_node = NULL;
* So, at this point we have to check the message type: if it is a struct gw_node *curr_gw = NULL;
* DHCPREQUEST we have to decide whether to drop it or not */ bool ret, out_of_range = false;
if (old_gw && curr_gw->orig_node != old_gw) { unsigned int header_len = 0;
if (is_type_dhcprequest(skb, header_len)) { uint8_t curr_tq_avg;
/* If the dhcp packet has been sent to a different gw,
* we have to evaluate whether the old gw is still ret = gw_is_dhcp_target(skb, &header_len);
* reliable enough */ if (!ret)
neigh_curr = find_router(bat_priv, curr_gw->orig_node, goto out;
NULL);
neigh_old = find_router(bat_priv, old_gw, NULL); orig_dst_node = transtable_search(bat_priv, ethhdr->h_source,
if (!neigh_curr || !neigh_old) ethhdr->h_dest);
goto free_neigh; if (!orig_dst_node)
if (neigh_curr->tq_avg - neigh_old->tq_avg < goto out;
GW_THRESHOLD)
ret = -1; if (!orig_dst_node->gw_flags)
} goto out;
ret = is_type_dhcprequest(skb, header_len);
if (!ret)
goto out;
switch (atomic_read(&bat_priv->gw_mode)) {
case GW_MODE_SERVER:
/* If we are a GW then we are our best GW. We can artificially
* set the tq towards ourself as the maximum value */
curr_tq_avg = TQ_MAX_VALUE;
break;
case GW_MODE_CLIENT:
curr_gw = gw_get_selected_gw_node(bat_priv);
if (!curr_gw)
goto out;
/* packet is going to our gateway */
if (curr_gw->orig_node == orig_dst_node)
goto out;
/* If the dhcp packet has been sent to a different gw,
* we have to evaluate whether the old gw is still
* reliable enough */
neigh_curr = find_router(bat_priv, curr_gw->orig_node, NULL);
if (!neigh_curr)
goto out;
curr_tq_avg = neigh_curr->tq_avg;
break;
case GW_MODE_OFF:
default:
goto out;
} }
free_neigh:
neigh_old = find_router(bat_priv, orig_dst_node, NULL);
if (!!neigh_old)
goto out;
if (curr_tq_avg - neigh_old->tq_avg > GW_THRESHOLD)
out_of_range = true;
out:
if (orig_dst_node)
orig_node_free_ref(orig_dst_node);
if (curr_gw)
gw_node_free_ref(curr_gw);
if (neigh_old) if (neigh_old)
neigh_node_free_ref(neigh_old); neigh_node_free_ref(neigh_old);
if (neigh_curr) if (neigh_curr)
neigh_node_free_ref(neigh_curr); neigh_node_free_ref(neigh_curr);
if (curr_gw) return out_of_range;
gw_node_free_ref(curr_gw);
return ret;
} }
...@@ -31,7 +31,8 @@ void gw_node_update(struct bat_priv *bat_priv, ...@@ -31,7 +31,8 @@ void gw_node_update(struct bat_priv *bat_priv,
void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node); void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node);
void gw_node_purge(struct bat_priv *bat_priv); void gw_node_purge(struct bat_priv *bat_priv);
int gw_client_seq_print_text(struct seq_file *seq, void *offset); int gw_client_seq_print_text(struct seq_file *seq, void *offset);
int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb, bool gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len);
struct orig_node *old_gw); bool gw_out_of_range(struct bat_priv *bat_priv,
struct sk_buff *skb, struct ethhdr *ethhdr);
#endif /* _NET_BATMAN_ADV_GATEWAY_CLIENT_H_ */ #endif /* _NET_BATMAN_ADV_GATEWAY_CLIENT_H_ */
...@@ -97,7 +97,7 @@ static bool parse_gw_bandwidth(struct net_device *net_dev, char *buff, ...@@ -97,7 +97,7 @@ static bool parse_gw_bandwidth(struct net_device *net_dev, char *buff,
*tmp_ptr = '\0'; *tmp_ptr = '\0';
} }
ret = strict_strtol(buff, 10, &ldown); ret = kstrtol(buff, 10, &ldown);
if (ret) { if (ret) {
bat_err(net_dev, bat_err(net_dev,
"Download speed of gateway mode invalid: %s\n", "Download speed of gateway mode invalid: %s\n",
...@@ -122,7 +122,7 @@ static bool parse_gw_bandwidth(struct net_device *net_dev, char *buff, ...@@ -122,7 +122,7 @@ static bool parse_gw_bandwidth(struct net_device *net_dev, char *buff,
*tmp_ptr = '\0'; *tmp_ptr = '\0';
} }
ret = strict_strtol(slash_ptr + 1, 10, &lup); ret = kstrtol(slash_ptr + 1, 10, &lup);
if (ret) { if (ret) {
bat_err(net_dev, bat_err(net_dev,
"Upload speed of gateway mode invalid: " "Upload speed of gateway mode invalid: "
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
/* clears the hash */ /* clears the hash */
static void hash_init(struct hashtable_t *hash) static void hash_init(struct hashtable_t *hash)
{ {
int i; uint32_t i;
for (i = 0 ; i < hash->size; i++) { for (i = 0 ; i < hash->size; i++) {
INIT_HLIST_HEAD(&hash->table[i]); INIT_HLIST_HEAD(&hash->table[i]);
...@@ -42,7 +42,7 @@ void hash_destroy(struct hashtable_t *hash) ...@@ -42,7 +42,7 @@ void hash_destroy(struct hashtable_t *hash)
} }
/* allocates and clears the hash */ /* allocates and clears the hash */
struct hashtable_t *hash_new(int size) struct hashtable_t *hash_new(uint32_t size)
{ {
struct hashtable_t *hash; struct hashtable_t *hash;
......
...@@ -33,17 +33,17 @@ typedef int (*hashdata_compare_cb)(const struct hlist_node *, const void *); ...@@ -33,17 +33,17 @@ typedef int (*hashdata_compare_cb)(const struct hlist_node *, const void *);
/* the hashfunction, should return an index /* the hashfunction, should return an index
* based on the key in the data of the first * based on the key in the data of the first
* argument and the size the second */ * argument and the size the second */
typedef int (*hashdata_choose_cb)(const void *, int); typedef uint32_t (*hashdata_choose_cb)(const void *, uint32_t);
typedef void (*hashdata_free_cb)(struct hlist_node *, void *); typedef void (*hashdata_free_cb)(struct hlist_node *, void *);
struct hashtable_t { struct hashtable_t {
struct hlist_head *table; /* the hashtable itself with the buckets */ struct hlist_head *table; /* the hashtable itself with the buckets */
spinlock_t *list_locks; /* spinlock for each hash list entry */ spinlock_t *list_locks; /* spinlock for each hash list entry */
int size; /* size of hashtable */ uint32_t size; /* size of hashtable */
}; };
/* allocates and clears the hash */ /* allocates and clears the hash */
struct hashtable_t *hash_new(int size); struct hashtable_t *hash_new(uint32_t size);
/* free only the hashtable and the hash itself. */ /* free only the hashtable and the hash itself. */
void hash_destroy(struct hashtable_t *hash); void hash_destroy(struct hashtable_t *hash);
...@@ -57,7 +57,7 @@ static inline void hash_delete(struct hashtable_t *hash, ...@@ -57,7 +57,7 @@ static inline void hash_delete(struct hashtable_t *hash,
struct hlist_head *head; struct hlist_head *head;
struct hlist_node *node, *node_tmp; struct hlist_node *node, *node_tmp;
spinlock_t *list_lock; /* spinlock to protect write access */ spinlock_t *list_lock; /* spinlock to protect write access */
int i; uint32_t i;
for (i = 0; i < hash->size; i++) { for (i = 0; i < hash->size; i++) {
head = &hash->table[i]; head = &hash->table[i];
...@@ -93,7 +93,8 @@ static inline int hash_add(struct hashtable_t *hash, ...@@ -93,7 +93,8 @@ static inline int hash_add(struct hashtable_t *hash,
hashdata_choose_cb choose, hashdata_choose_cb choose,
const void *data, struct hlist_node *data_node) const void *data, struct hlist_node *data_node)
{ {
int index, ret = -1; uint32_t index;
int ret = -1;
struct hlist_head *head; struct hlist_head *head;
struct hlist_node *node; struct hlist_node *node;
spinlock_t *list_lock; /* spinlock to protect write access */ spinlock_t *list_lock; /* spinlock to protect write access */
...@@ -137,7 +138,7 @@ static inline void *hash_remove(struct hashtable_t *hash, ...@@ -137,7 +138,7 @@ static inline void *hash_remove(struct hashtable_t *hash,
hashdata_compare_cb compare, hashdata_compare_cb compare,
hashdata_choose_cb choose, void *data) hashdata_choose_cb choose, void *data)
{ {
size_t index; uint32_t index;
struct hlist_node *node; struct hlist_node *node;
struct hlist_head *head; struct hlist_head *head;
void *data_save = NULL; void *data_save = NULL;
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#define DRIVER_DEVICE "batman-adv" #define DRIVER_DEVICE "batman-adv"
#ifndef SOURCE_VERSION #ifndef SOURCE_VERSION
#define SOURCE_VERSION "2011.4.0" #define SOURCE_VERSION "2012.0.0"
#endif #endif
/* B.A.T.M.A.N. parameters */ /* B.A.T.M.A.N. parameters */
......
...@@ -164,7 +164,7 @@ void originator_free(struct bat_priv *bat_priv) ...@@ -164,7 +164,7 @@ void originator_free(struct bat_priv *bat_priv)
struct hlist_head *head; struct hlist_head *head;
spinlock_t *list_lock; /* spinlock to protect write access */ spinlock_t *list_lock; /* spinlock to protect write access */
struct orig_node *orig_node; struct orig_node *orig_node;
int i; uint32_t i;
if (!hash) if (!hash)
return; return;
...@@ -350,7 +350,7 @@ static void _purge_orig(struct bat_priv *bat_priv) ...@@ -350,7 +350,7 @@ static void _purge_orig(struct bat_priv *bat_priv)
struct hlist_head *head; struct hlist_head *head;
spinlock_t *list_lock; /* spinlock to protect write access */ spinlock_t *list_lock; /* spinlock to protect write access */
struct orig_node *orig_node; struct orig_node *orig_node;
int i; uint32_t i;
if (!hash) if (!hash)
return; return;
...@@ -413,7 +413,8 @@ int orig_seq_print_text(struct seq_file *seq, void *offset) ...@@ -413,7 +413,8 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
int batman_count = 0; int batman_count = 0;
int last_seen_secs; int last_seen_secs;
int last_seen_msecs; int last_seen_msecs;
int i, ret = 0; uint32_t i;
int ret = 0;
primary_if = primary_if_get_selected(bat_priv); primary_if = primary_if_get_selected(bat_priv);
...@@ -519,7 +520,8 @@ int orig_hash_add_if(struct hard_iface *hard_iface, int max_if_num) ...@@ -519,7 +520,8 @@ int orig_hash_add_if(struct hard_iface *hard_iface, int max_if_num)
struct hlist_node *node; struct hlist_node *node;
struct hlist_head *head; struct hlist_head *head;
struct orig_node *orig_node; struct orig_node *orig_node;
int i, ret; uint32_t i;
int ret;
/* resize all orig nodes because orig_node->bcast_own(_sum) depend on /* resize all orig nodes because orig_node->bcast_own(_sum) depend on
* if_num */ * if_num */
...@@ -601,7 +603,8 @@ int orig_hash_del_if(struct hard_iface *hard_iface, int max_if_num) ...@@ -601,7 +603,8 @@ int orig_hash_del_if(struct hard_iface *hard_iface, int max_if_num)
struct hlist_head *head; struct hlist_head *head;
struct hard_iface *hard_iface_tmp; struct hard_iface *hard_iface_tmp;
struct orig_node *orig_node; struct orig_node *orig_node;
int i, ret; uint32_t i;
int ret;
/* resize all orig nodes because orig_node->bcast_own(_sum) depend on /* resize all orig nodes because orig_node->bcast_own(_sum) depend on
* if_num */ * if_num */
......
...@@ -42,7 +42,7 @@ int orig_hash_del_if(struct hard_iface *hard_iface, int max_if_num); ...@@ -42,7 +42,7 @@ int orig_hash_del_if(struct hard_iface *hard_iface, int max_if_num);
/* hashfunction to choose an entry in a hash table of given size */ /* hashfunction to choose an entry in a hash table of given size */
/* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */ /* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */
static inline int choose_orig(const void *data, int32_t size) static inline uint32_t choose_orig(const void *data, uint32_t size)
{ {
const unsigned char *key = data; const unsigned char *key = data;
uint32_t hash = 0; uint32_t hash = 0;
......
...@@ -39,7 +39,7 @@ void slide_own_bcast_window(struct hard_iface *hard_iface) ...@@ -39,7 +39,7 @@ void slide_own_bcast_window(struct hard_iface *hard_iface)
struct hlist_head *head; struct hlist_head *head;
struct orig_node *orig_node; struct orig_node *orig_node;
unsigned long *word; unsigned long *word;
int i; uint32_t i;
size_t word_index; size_t word_index;
for (i = 0; i < hash->size; i++) { for (i = 0; i < hash->size; i++) {
...@@ -578,6 +578,7 @@ int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if) ...@@ -578,6 +578,7 @@ int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if)
{ {
struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
struct tt_query_packet *tt_query; struct tt_query_packet *tt_query;
uint16_t tt_len;
struct ethhdr *ethhdr; struct ethhdr *ethhdr;
/* drop packet if it has not necessary minimum size */ /* drop packet if it has not necessary minimum size */
...@@ -616,13 +617,22 @@ int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if) ...@@ -616,13 +617,22 @@ int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if)
} }
break; break;
case TT_RESPONSE: case TT_RESPONSE:
/* packet needs to be linearized to access the TT changes */ if (is_my_mac(tt_query->dst)) {
if (skb_linearize(skb) < 0) /* packet needs to be linearized to access the TT
goto out; * changes */
if (skb_linearize(skb) < 0)
goto out;
tt_len = tt_query->tt_data * sizeof(struct tt_change);
/* Ensure we have all the claimed data */
if (unlikely(skb_headlen(skb) <
sizeof(struct tt_query_packet) +
tt_len))
goto out;
if (is_my_mac(tt_query->dst))
handle_tt_response(bat_priv, tt_query); handle_tt_response(bat_priv, tt_query);
else { } else {
bat_dbg(DBG_TT, bat_priv, bat_dbg(DBG_TT, bat_priv,
"Routing TT_RESPONSE to %pM [%c]\n", "Routing TT_RESPONSE to %pM [%c]\n",
tt_query->dst, tt_query->dst,
......
...@@ -563,10 +563,10 @@ static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) ...@@ -563,10 +563,10 @@ static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
struct bcast_packet *bcast_packet; struct bcast_packet *bcast_packet;
struct vlan_ethhdr *vhdr; struct vlan_ethhdr *vhdr;
struct softif_neigh *curr_softif_neigh = NULL; struct softif_neigh *curr_softif_neigh = NULL;
struct orig_node *orig_node = NULL; unsigned int header_len = 0;
int data_len = skb->len, ret; int data_len = skb->len, ret;
short vid = -1; short vid = -1;
bool do_bcast; bool do_bcast = false;
if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE) if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE)
goto dropped; goto dropped;
...@@ -598,17 +598,28 @@ static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) ...@@ -598,17 +598,28 @@ static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
/* Register the client MAC in the transtable */ /* Register the client MAC in the transtable */
tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif); tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif);
orig_node = transtable_search(bat_priv, ethhdr->h_source, if (is_multicast_ether_addr(ethhdr->h_dest)) {
ethhdr->h_dest); do_bcast = true;
do_bcast = is_multicast_ether_addr(ethhdr->h_dest);
if (do_bcast || (orig_node && orig_node->gw_flags)) {
ret = gw_is_target(bat_priv, skb, orig_node);
if (ret < 0) switch (atomic_read(&bat_priv->gw_mode)) {
goto dropped; case GW_MODE_SERVER:
/* gateway servers should not send dhcp
if (ret) * requests into the mesh */
do_bcast = false; ret = gw_is_dhcp_target(skb, &header_len);
if (ret)
goto dropped;
break;
case GW_MODE_CLIENT:
/* gateway clients should send dhcp requests
* via unicast to their gateway */
ret = gw_is_dhcp_target(skb, &header_len);
if (ret)
do_bcast = false;
break;
case GW_MODE_OFF:
default:
break;
}
} }
/* ethernet packet should be broadcasted */ /* ethernet packet should be broadcasted */
...@@ -644,6 +655,12 @@ static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) ...@@ -644,6 +655,12 @@ static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
/* unicast packet */ /* unicast packet */
} else { } else {
if (atomic_read(&bat_priv->gw_mode) != GW_MODE_OFF) {
ret = gw_out_of_range(bat_priv, skb, ethhdr);
if (ret)
goto dropped;
}
ret = unicast_send_skb(skb, bat_priv); ret = unicast_send_skb(skb, bat_priv);
if (ret != 0) if (ret != 0)
goto dropped_freed; goto dropped_freed;
...@@ -662,8 +679,6 @@ static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) ...@@ -662,8 +679,6 @@ static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
softif_neigh_free_ref(curr_softif_neigh); softif_neigh_free_ref(curr_softif_neigh);
if (primary_if) if (primary_if)
hardif_free_ref(primary_if); hardif_free_ref(primary_if);
if (orig_node)
orig_node_free_ref(orig_node);
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
......
...@@ -67,7 +67,7 @@ static struct tt_local_entry *tt_local_hash_find(struct bat_priv *bat_priv, ...@@ -67,7 +67,7 @@ static struct tt_local_entry *tt_local_hash_find(struct bat_priv *bat_priv,
struct hlist_head *head; struct hlist_head *head;
struct hlist_node *node; struct hlist_node *node;
struct tt_local_entry *tt_local_entry, *tt_local_entry_tmp = NULL; struct tt_local_entry *tt_local_entry, *tt_local_entry_tmp = NULL;
int index; uint32_t index;
if (!hash) if (!hash)
return NULL; return NULL;
...@@ -99,7 +99,7 @@ static struct tt_global_entry *tt_global_hash_find(struct bat_priv *bat_priv, ...@@ -99,7 +99,7 @@ static struct tt_global_entry *tt_global_hash_find(struct bat_priv *bat_priv,
struct hlist_node *node; struct hlist_node *node;
struct tt_global_entry *tt_global_entry; struct tt_global_entry *tt_global_entry;
struct tt_global_entry *tt_global_entry_tmp = NULL; struct tt_global_entry *tt_global_entry_tmp = NULL;
int index; uint32_t index;
if (!hash) if (!hash)
return NULL; return NULL;
...@@ -314,9 +314,8 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset) ...@@ -314,9 +314,8 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset)
struct hard_iface *primary_if; struct hard_iface *primary_if;
struct hlist_node *node; struct hlist_node *node;
struct hlist_head *head; struct hlist_head *head;
size_t buf_size, pos; uint32_t i;
char *buff; int ret = 0;
int i, ret = 0;
primary_if = primary_if_get_selected(bat_priv); primary_if = primary_if_get_selected(bat_priv);
if (!primary_if) { if (!primary_if) {
...@@ -337,34 +336,13 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset) ...@@ -337,34 +336,13 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset)
"announced via TT (TTVN: %u):\n", "announced via TT (TTVN: %u):\n",
net_dev->name, (uint8_t)atomic_read(&bat_priv->ttvn)); net_dev->name, (uint8_t)atomic_read(&bat_priv->ttvn));
buf_size = 1;
/* Estimate length for: " * xx:xx:xx:xx:xx:xx\n" */
for (i = 0; i < hash->size; i++) {
head = &hash->table[i];
rcu_read_lock();
__hlist_for_each_rcu(node, head)
buf_size += 29;
rcu_read_unlock();
}
buff = kmalloc(buf_size, GFP_ATOMIC);
if (!buff) {
ret = -ENOMEM;
goto out;
}
buff[0] = '\0';
pos = 0;
for (i = 0; i < hash->size; i++) { for (i = 0; i < hash->size; i++) {
head = &hash->table[i]; head = &hash->table[i];
rcu_read_lock(); rcu_read_lock();
hlist_for_each_entry_rcu(tt_local_entry, node, hlist_for_each_entry_rcu(tt_local_entry, node,
head, hash_entry) { head, hash_entry) {
pos += snprintf(buff + pos, 30, " * %pM " seq_printf(seq, " * %pM [%c%c%c%c%c]\n",
"[%c%c%c%c%c]\n",
tt_local_entry->addr, tt_local_entry->addr,
(tt_local_entry->flags & (tt_local_entry->flags &
TT_CLIENT_ROAM ? 'R' : '.'), TT_CLIENT_ROAM ? 'R' : '.'),
...@@ -379,9 +357,6 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset) ...@@ -379,9 +357,6 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset)
} }
rcu_read_unlock(); rcu_read_unlock();
} }
seq_printf(seq, "%s", buff);
kfree(buff);
out: out:
if (primary_if) if (primary_if)
hardif_free_ref(primary_if); hardif_free_ref(primary_if);
...@@ -427,7 +402,7 @@ static void tt_local_purge(struct bat_priv *bat_priv) ...@@ -427,7 +402,7 @@ static void tt_local_purge(struct bat_priv *bat_priv)
struct hlist_node *node, *node_tmp; struct hlist_node *node, *node_tmp;
struct hlist_head *head; struct hlist_head *head;
spinlock_t *list_lock; /* protects write access to the hash lists */ spinlock_t *list_lock; /* protects write access to the hash lists */
int i; uint32_t i;
for (i = 0; i < hash->size; i++) { for (i = 0; i < hash->size; i++) {
head = &hash->table[i]; head = &hash->table[i];
...@@ -465,7 +440,7 @@ static void tt_local_table_free(struct bat_priv *bat_priv) ...@@ -465,7 +440,7 @@ static void tt_local_table_free(struct bat_priv *bat_priv)
struct tt_local_entry *tt_local_entry; struct tt_local_entry *tt_local_entry;
struct hlist_node *node, *node_tmp; struct hlist_node *node, *node_tmp;
struct hlist_head *head; struct hlist_head *head;
int i; uint32_t i;
if (!bat_priv->tt_local_hash) if (!bat_priv->tt_local_hash)
return; return;
...@@ -590,9 +565,8 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset) ...@@ -590,9 +565,8 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset)
struct hard_iface *primary_if; struct hard_iface *primary_if;
struct hlist_node *node; struct hlist_node *node;
struct hlist_head *head; struct hlist_head *head;
size_t buf_size, pos; uint32_t i;
char *buff; int ret = 0;
int i, ret = 0;
primary_if = primary_if_get_selected(bat_priv); primary_if = primary_if_get_selected(bat_priv);
if (!primary_if) { if (!primary_if) {
...@@ -615,35 +589,13 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset) ...@@ -615,35 +589,13 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset)
seq_printf(seq, " %-13s %s %-15s %s %s\n", seq_printf(seq, " %-13s %s %-15s %s %s\n",
"Client", "(TTVN)", "Originator", "(Curr TTVN)", "Flags"); "Client", "(TTVN)", "Originator", "(Curr TTVN)", "Flags");
buf_size = 1;
/* Estimate length for: " * xx:xx:xx:xx:xx:xx (ttvn) via
* xx:xx:xx:xx:xx:xx (cur_ttvn)\n"*/
for (i = 0; i < hash->size; i++) {
head = &hash->table[i];
rcu_read_lock();
__hlist_for_each_rcu(node, head)
buf_size += 67;
rcu_read_unlock();
}
buff = kmalloc(buf_size, GFP_ATOMIC);
if (!buff) {
ret = -ENOMEM;
goto out;
}
buff[0] = '\0';
pos = 0;
for (i = 0; i < hash->size; i++) { for (i = 0; i < hash->size; i++) {
head = &hash->table[i]; head = &hash->table[i];
rcu_read_lock(); rcu_read_lock();
hlist_for_each_entry_rcu(tt_global_entry, node, hlist_for_each_entry_rcu(tt_global_entry, node,
head, hash_entry) { head, hash_entry) {
pos += snprintf(buff + pos, 69, seq_printf(seq, " * %pM (%3u) via %pM (%3u) "
" * %pM (%3u) via %pM (%3u) "
"[%c%c%c]\n", tt_global_entry->addr, "[%c%c%c]\n", tt_global_entry->addr,
tt_global_entry->ttvn, tt_global_entry->ttvn,
tt_global_entry->orig_node->orig, tt_global_entry->orig_node->orig,
...@@ -659,9 +611,6 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset) ...@@ -659,9 +611,6 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset)
} }
rcu_read_unlock(); rcu_read_unlock();
} }
seq_printf(seq, "%s", buff);
kfree(buff);
out: out:
if (primary_if) if (primary_if)
hardif_free_ref(primary_if); hardif_free_ref(primary_if);
...@@ -716,7 +665,7 @@ void tt_global_del_orig(struct bat_priv *bat_priv, ...@@ -716,7 +665,7 @@ void tt_global_del_orig(struct bat_priv *bat_priv,
struct orig_node *orig_node, const char *message) struct orig_node *orig_node, const char *message)
{ {
struct tt_global_entry *tt_global_entry; struct tt_global_entry *tt_global_entry;
int i; uint32_t i;
struct hashtable_t *hash = bat_priv->tt_global_hash; struct hashtable_t *hash = bat_priv->tt_global_hash;
struct hlist_node *node, *safe; struct hlist_node *node, *safe;
struct hlist_head *head; struct hlist_head *head;
...@@ -735,9 +684,10 @@ void tt_global_del_orig(struct bat_priv *bat_priv, ...@@ -735,9 +684,10 @@ void tt_global_del_orig(struct bat_priv *bat_priv,
if (tt_global_entry->orig_node == orig_node) { if (tt_global_entry->orig_node == orig_node) {
bat_dbg(DBG_TT, bat_priv, bat_dbg(DBG_TT, bat_priv,
"Deleting global tt entry %pM " "Deleting global tt entry %pM "
"(via %pM): originator time out\n", "(via %pM): %s\n",
tt_global_entry->addr, tt_global_entry->addr,
tt_global_entry->orig_node->orig); tt_global_entry->orig_node->orig,
message);
hlist_del_rcu(node); hlist_del_rcu(node);
tt_global_entry_free_ref(tt_global_entry); tt_global_entry_free_ref(tt_global_entry);
} }
...@@ -754,7 +704,7 @@ static void tt_global_roam_purge(struct bat_priv *bat_priv) ...@@ -754,7 +704,7 @@ static void tt_global_roam_purge(struct bat_priv *bat_priv)
struct hlist_node *node, *node_tmp; struct hlist_node *node, *node_tmp;
struct hlist_head *head; struct hlist_head *head;
spinlock_t *list_lock; /* protects write access to the hash lists */ spinlock_t *list_lock; /* protects write access to the hash lists */
int i; uint32_t i;
for (i = 0; i < hash->size; i++) { for (i = 0; i < hash->size; i++) {
head = &hash->table[i]; head = &hash->table[i];
...@@ -788,7 +738,7 @@ static void tt_global_table_free(struct bat_priv *bat_priv) ...@@ -788,7 +738,7 @@ static void tt_global_table_free(struct bat_priv *bat_priv)
struct tt_global_entry *tt_global_entry; struct tt_global_entry *tt_global_entry;
struct hlist_node *node, *node_tmp; struct hlist_node *node, *node_tmp;
struct hlist_head *head; struct hlist_head *head;
int i; uint32_t i;
if (!bat_priv->tt_global_hash) if (!bat_priv->tt_global_hash)
return; return;
...@@ -874,7 +824,8 @@ uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node) ...@@ -874,7 +824,8 @@ uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node)
struct tt_global_entry *tt_global_entry; struct tt_global_entry *tt_global_entry;
struct hlist_node *node; struct hlist_node *node;
struct hlist_head *head; struct hlist_head *head;
int i, j; uint32_t i;
int j;
for (i = 0; i < hash->size; i++) { for (i = 0; i < hash->size; i++) {
head = &hash->table[i]; head = &hash->table[i];
...@@ -911,7 +862,8 @@ uint16_t tt_local_crc(struct bat_priv *bat_priv) ...@@ -911,7 +862,8 @@ uint16_t tt_local_crc(struct bat_priv *bat_priv)
struct tt_local_entry *tt_local_entry; struct tt_local_entry *tt_local_entry;
struct hlist_node *node; struct hlist_node *node;
struct hlist_head *head; struct hlist_head *head;
int i, j; uint32_t i;
int j;
for (i = 0; i < hash->size; i++) { for (i = 0; i < hash->size; i++) {
head = &hash->table[i]; head = &hash->table[i];
...@@ -1048,7 +1000,7 @@ static struct sk_buff *tt_response_fill_table(uint16_t tt_len, uint8_t ttvn, ...@@ -1048,7 +1000,7 @@ static struct sk_buff *tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
struct sk_buff *skb = NULL; struct sk_buff *skb = NULL;
uint16_t tt_tot, tt_count; uint16_t tt_tot, tt_count;
ssize_t tt_query_size = sizeof(struct tt_query_packet); ssize_t tt_query_size = sizeof(struct tt_query_packet);
int i; uint32_t i;
if (tt_query_size + tt_len > primary_if->soft_iface->mtu) { if (tt_query_size + tt_len > primary_if->soft_iface->mtu) {
tt_len = primary_if->soft_iface->mtu - tt_query_size; tt_len = primary_if->soft_iface->mtu - tt_query_size;
...@@ -1187,11 +1139,11 @@ static bool send_other_tt_response(struct bat_priv *bat_priv, ...@@ -1187,11 +1139,11 @@ static bool send_other_tt_response(struct bat_priv *bat_priv,
(tt_request->flags & TT_FULL_TABLE ? 'F' : '.')); (tt_request->flags & TT_FULL_TABLE ? 'F' : '.'));
/* Let's get the orig node of the REAL destination */ /* Let's get the orig node of the REAL destination */
req_dst_orig_node = get_orig_node(bat_priv, tt_request->dst); req_dst_orig_node = orig_hash_find(bat_priv, tt_request->dst);
if (!req_dst_orig_node) if (!req_dst_orig_node)
goto out; goto out;
res_dst_orig_node = get_orig_node(bat_priv, tt_request->src); res_dst_orig_node = orig_hash_find(bat_priv, tt_request->src);
if (!res_dst_orig_node) if (!res_dst_orig_node)
goto out; goto out;
...@@ -1317,7 +1269,7 @@ static bool send_my_tt_response(struct bat_priv *bat_priv, ...@@ -1317,7 +1269,7 @@ static bool send_my_tt_response(struct bat_priv *bat_priv,
my_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn); my_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn);
req_ttvn = tt_request->ttvn; req_ttvn = tt_request->ttvn;
orig_node = get_orig_node(bat_priv, tt_request->src); orig_node = orig_hash_find(bat_priv, tt_request->src);
if (!orig_node) if (!orig_node)
goto out; goto out;
...@@ -1725,7 +1677,7 @@ void tt_free(struct bat_priv *bat_priv) ...@@ -1725,7 +1677,7 @@ void tt_free(struct bat_priv *bat_priv)
* entry */ * entry */
static void tt_local_reset_flags(struct bat_priv *bat_priv, uint16_t flags) static void tt_local_reset_flags(struct bat_priv *bat_priv, uint16_t flags)
{ {
int i; uint32_t i;
struct hashtable_t *hash = bat_priv->tt_local_hash; struct hashtable_t *hash = bat_priv->tt_local_hash;
struct hlist_head *head; struct hlist_head *head;
struct hlist_node *node; struct hlist_node *node;
...@@ -1758,7 +1710,7 @@ static void tt_local_purge_pending_clients(struct bat_priv *bat_priv) ...@@ -1758,7 +1710,7 @@ static void tt_local_purge_pending_clients(struct bat_priv *bat_priv)
struct hlist_node *node, *node_tmp; struct hlist_node *node, *node_tmp;
struct hlist_head *head; struct hlist_head *head;
spinlock_t *list_lock; /* protects write access to the hash lists */ spinlock_t *list_lock; /* protects write access to the hash lists */
int i; uint32_t i;
if (!hash) if (!hash)
return; return;
......
...@@ -66,7 +66,7 @@ static int vis_info_cmp(const struct hlist_node *node, const void *data2) ...@@ -66,7 +66,7 @@ static int vis_info_cmp(const struct hlist_node *node, const void *data2)
/* hash function to choose an entry in a hash table of given size */ /* hash function to choose an entry in a hash table of given size */
/* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */ /* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */
static int vis_info_choose(const void *data, int size) static uint32_t vis_info_choose(const void *data, uint32_t size)
{ {
const struct vis_info *vis_info = data; const struct vis_info *vis_info = data;
const struct vis_packet *packet; const struct vis_packet *packet;
...@@ -96,7 +96,7 @@ static struct vis_info *vis_hash_find(struct bat_priv *bat_priv, ...@@ -96,7 +96,7 @@ static struct vis_info *vis_hash_find(struct bat_priv *bat_priv,
struct hlist_head *head; struct hlist_head *head;
struct hlist_node *node; struct hlist_node *node;
struct vis_info *vis_info, *vis_info_tmp = NULL; struct vis_info *vis_info, *vis_info_tmp = NULL;
int index; uint32_t index;
if (!hash) if (!hash)
return NULL; return NULL;
...@@ -202,7 +202,8 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) ...@@ -202,7 +202,8 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
HLIST_HEAD(vis_if_list); HLIST_HEAD(vis_if_list);
struct if_list_entry *entry; struct if_list_entry *entry;
struct hlist_node *pos, *n; struct hlist_node *pos, *n;
int i, j, ret = 0; uint32_t i;
int j, ret = 0;
int vis_server = atomic_read(&bat_priv->vis_mode); int vis_server = atomic_read(&bat_priv->vis_mode);
size_t buff_pos, buf_size; size_t buff_pos, buf_size;
char *buff; char *buff;
...@@ -556,7 +557,8 @@ static int find_best_vis_server(struct bat_priv *bat_priv, ...@@ -556,7 +557,8 @@ static int find_best_vis_server(struct bat_priv *bat_priv,
struct hlist_head *head; struct hlist_head *head;
struct orig_node *orig_node; struct orig_node *orig_node;
struct vis_packet *packet; struct vis_packet *packet;
int best_tq = -1, i; int best_tq = -1;
uint32_t i;
packet = (struct vis_packet *)info->skb_packet->data; packet = (struct vis_packet *)info->skb_packet->data;
...@@ -608,7 +610,8 @@ static int generate_vis_packet(struct bat_priv *bat_priv) ...@@ -608,7 +610,8 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data; struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data;
struct vis_info_entry *entry; struct vis_info_entry *entry;
struct tt_local_entry *tt_local_entry; struct tt_local_entry *tt_local_entry;
int best_tq = -1, i; int best_tq = -1;
uint32_t i;
info->first_seen = jiffies; info->first_seen = jiffies;
packet->vis_type = atomic_read(&bat_priv->vis_mode); packet->vis_type = atomic_read(&bat_priv->vis_mode);
...@@ -696,7 +699,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv) ...@@ -696,7 +699,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
* held */ * held */
static void purge_vis_packets(struct bat_priv *bat_priv) static void purge_vis_packets(struct bat_priv *bat_priv)
{ {
int i; uint32_t i;
struct hashtable_t *hash = bat_priv->vis_hash; struct hashtable_t *hash = bat_priv->vis_hash;
struct hlist_node *node, *node_tmp; struct hlist_node *node, *node_tmp;
struct hlist_head *head; struct hlist_head *head;
...@@ -733,7 +736,7 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv, ...@@ -733,7 +736,7 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv,
struct sk_buff *skb; struct sk_buff *skb;
struct hard_iface *hard_iface; struct hard_iface *hard_iface;
uint8_t dstaddr[ETH_ALEN]; uint8_t dstaddr[ETH_ALEN];
int i; uint32_t i;
packet = (struct vis_packet *)info->skb_packet->data; packet = (struct vis_packet *)info->skb_packet->data;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment