]> Pileus Git - ~andy/linux/commitdiff
batman-adv: don't rely on positions in struct for hashing
authorSimon Wunderlich <simon.wunderlich@s2003.tu-chemnitz.de>
Thu, 30 Aug 2012 16:22:27 +0000 (18:22 +0200)
committerAntonio Quartulli <ordex@autistici.org>
Wed, 14 Nov 2012 20:00:32 +0000 (21:00 +0100)
The hash functions in the bridge loop avoidance code expects the
VLAN vid to be right after the mac address, but this is not guaranteed.

Fix this by explicitly hashing over the right fields of the struct.

Reported-by: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
net/batman-adv/bridge_loop_avoidance.c
net/batman-adv/hash.h

index 29a5542aac75f38b706f8120e0dab2bad14f09d0..49c35a60195a8f50324ca06e920df0e5345495b9 100644 (file)
@@ -40,15 +40,11 @@ static void batadv_bla_send_announce(struct batadv_priv *bat_priv,
 /* return the index of the claim */
 static inline uint32_t batadv_choose_claim(const void *data, uint32_t size)
 {
-       const unsigned char *key = data;
+       struct batadv_claim *claim = (struct batadv_claim *)data;
        uint32_t hash = 0;
-       size_t i;
 
-       for (i = 0; i < ETH_ALEN + sizeof(short); i++) {
-               hash += key[i];
-               hash += (hash << 10);
-               hash ^= (hash >> 6);
-       }
+       hash = batadv_hash_bytes(hash, &claim->addr, sizeof(claim->addr));
+       hash = batadv_hash_bytes(hash, &claim->vid, sizeof(claim->vid));
 
        hash += (hash << 3);
        hash ^= (hash >> 11);
@@ -61,15 +57,11 @@ static inline uint32_t batadv_choose_claim(const void *data, uint32_t size)
 static inline uint32_t batadv_choose_backbone_gw(const void *data,
                                                 uint32_t size)
 {
-       const unsigned char *key = data;
+       struct batadv_claim *claim = (struct batadv_claim *)data;
        uint32_t hash = 0;
-       size_t i;
 
-       for (i = 0; i < ETH_ALEN + sizeof(short); i++) {
-               hash += key[i];
-               hash += (hash << 10);
-               hash ^= (hash >> 6);
-       }
+       hash = batadv_hash_bytes(hash, &claim->addr, sizeof(claim->addr));
+       hash = batadv_hash_bytes(hash, &claim->vid, sizeof(claim->vid));
 
        hash += (hash << 3);
        hash ^= (hash >> 11);
index 977de9c75fc27010c1fd98dd3e11e3aa459ebe41..e05333905afd566117bf1267d6e3ac05596c89c1 100644 (file)
@@ -81,6 +81,28 @@ static inline void batadv_hash_delete(struct batadv_hashtable *hash,
        batadv_hash_destroy(hash);
 }
 
+/**
+ *     batadv_hash_bytes - hash some bytes and add them to the previous hash
+ *     @hash: previous hash value
+ *     @data: data to be hashed
+ *     @size: number of bytes to be hashed
+ *
+ *     Returns the new hash value.
+ */
+static inline uint32_t batadv_hash_bytes(uint32_t hash, void *data,
+                                        uint32_t size)
+{
+       const unsigned char *key = data;
+       int i;
+
+       for (i = 0; i < size; i++) {
+               hash += key[i];
+               hash += (hash << 10);
+               hash ^= (hash >> 6);
+       }
+       return hash;
+}
+
 /**
  *     batadv_hash_add - adds data to the hashtable
  *     @hash: storage hash table