| Sven Eckelmann | 9cfc7bd | 2012-05-12 02:09:43 +0200 | [diff] [blame] | 1 | /* Copyright (C) 2007-2012 B.A.T.M.A.N. contributors: | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 2 |  * | 
 | 3 |  * Marek Lindner, Simon Wunderlich | 
 | 4 |  * | 
 | 5 |  * This program is free software; you can redistribute it and/or | 
 | 6 |  * modify it under the terms of version 2 of the GNU General Public | 
 | 7 |  * License as published by the Free Software Foundation. | 
 | 8 |  * | 
 | 9 |  * This program is distributed in the hope that it will be useful, but | 
 | 10 |  * WITHOUT ANY WARRANTY; without even the implied warranty of | 
 | 11 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 
 | 12 |  * General Public License for more details. | 
 | 13 |  * | 
 | 14 |  * You should have received a copy of the GNU General Public License | 
 | 15 |  * along with this program; if not, write to the Free Software | 
 | 16 |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | 
 | 17 |  * 02110-1301, USA | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 18 |  */ | 
 | 19 |  | 
 | 20 | #include "main.h" | 
 | 21 | #include "routing.h" | 
 | 22 | #include "send.h" | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 23 | #include "soft-interface.h" | 
 | 24 | #include "hard-interface.h" | 
 | 25 | #include "icmp_socket.h" | 
 | 26 | #include "translation-table.h" | 
 | 27 | #include "originator.h" | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 28 | #include "vis.h" | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 29 | #include "unicast.h" | 
| Simon Wunderlich | 2372138 | 2012-01-22 20:00:19 +0100 | [diff] [blame] | 30 | #include "bridge_loop_avoidance.h" | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 31 |  | 
| Sven Eckelmann | 63b0103 | 2012-05-16 20:23:13 +0200 | [diff] [blame] | 32 | static int batadv_route_unicast_packet(struct sk_buff *skb, | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 33 | 				       struct batadv_hard_iface *recv_if); | 
| Simon Wunderlich | a7f6ee9 | 2012-01-22 20:00:18 +0100 | [diff] [blame] | 34 |  | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 35 | void batadv_slide_own_bcast_window(struct batadv_hard_iface *hard_iface) | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 36 | { | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 37 | 	struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); | 
| Sven Eckelmann | 5bf74e9 | 2012-06-05 22:31:28 +0200 | [diff] [blame] | 38 | 	struct batadv_hashtable *hash = bat_priv->orig_hash; | 
| Marek Lindner | 7aadf88 | 2011-02-18 12:28:09 +0000 | [diff] [blame] | 39 | 	struct hlist_node *node; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 40 | 	struct hlist_head *head; | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 41 | 	struct batadv_orig_node *orig_node; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 42 | 	unsigned long *word; | 
| Antonio Quartulli | c90681b | 2011-10-05 17:05:25 +0200 | [diff] [blame] | 43 | 	uint32_t i; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 44 | 	size_t word_index; | 
| Sven Eckelmann | 42d0b04 | 2012-06-03 22:19:17 +0200 | [diff] [blame] | 45 | 	uint8_t *w; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 46 |  | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 47 | 	for (i = 0; i < hash->size; i++) { | 
 | 48 | 		head = &hash->table[i]; | 
 | 49 |  | 
| Marek Lindner | fb778ea | 2011-01-19 20:01:40 +0000 | [diff] [blame] | 50 | 		rcu_read_lock(); | 
| Marek Lindner | 7aadf88 | 2011-02-18 12:28:09 +0000 | [diff] [blame] | 51 | 		hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { | 
| Marek Lindner | 2ae2daf | 2011-01-19 20:01:42 +0000 | [diff] [blame] | 52 | 			spin_lock_bh(&orig_node->ogm_cnt_lock); | 
| Sven Eckelmann | 42d0b04 | 2012-06-03 22:19:17 +0200 | [diff] [blame] | 53 | 			word_index = hard_iface->if_num * BATADV_NUM_WORDS; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 54 | 			word = &(orig_node->bcast_own[word_index]); | 
 | 55 |  | 
| Sven Eckelmann | 0f5f932 | 2012-05-12 02:09:25 +0200 | [diff] [blame] | 56 | 			batadv_bit_get_packet(bat_priv, word, 1, 0); | 
| Sven Eckelmann | 42d0b04 | 2012-06-03 22:19:17 +0200 | [diff] [blame] | 57 | 			w = &orig_node->bcast_own_sum[hard_iface->if_num]; | 
 | 58 | 			*w = bitmap_weight(word, BATADV_TQ_LOCAL_WINDOW_SIZE); | 
| Marek Lindner | 2ae2daf | 2011-01-19 20:01:42 +0000 | [diff] [blame] | 59 | 			spin_unlock_bh(&orig_node->ogm_cnt_lock); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 60 | 		} | 
| Marek Lindner | fb778ea | 2011-01-19 20:01:40 +0000 | [diff] [blame] | 61 | 		rcu_read_unlock(); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 62 | 	} | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 63 | } | 
 | 64 |  | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 65 | static void _batadv_update_route(struct batadv_priv *bat_priv, | 
 | 66 | 				 struct batadv_orig_node *orig_node, | 
 | 67 | 				 struct batadv_neigh_node *neigh_node) | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 68 | { | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 69 | 	struct batadv_neigh_node *curr_router; | 
| Linus Lüssing | e1a5382 | 2011-03-14 22:43:37 +0000 | [diff] [blame] | 70 |  | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 71 | 	curr_router = batadv_orig_node_get_router(orig_node); | 
| Marek Lindner | a8e7f4b | 2010-12-12 21:57:10 +0000 | [diff] [blame] | 72 |  | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 73 | 	/* route deleted */ | 
| Linus Lüssing | e1a5382 | 2011-03-14 22:43:37 +0000 | [diff] [blame] | 74 | 	if ((curr_router) && (!neigh_node)) { | 
| Sven Eckelmann | 39c75a5 | 2012-06-03 22:19:22 +0200 | [diff] [blame] | 75 | 		batadv_dbg(BATADV_DBG_ROUTES, bat_priv, | 
 | 76 | 			   "Deleting route towards: %pM\n", orig_node->orig); | 
| Sven Eckelmann | 08c36d3 | 2012-05-12 02:09:39 +0200 | [diff] [blame] | 77 | 		batadv_tt_global_del_orig(bat_priv, orig_node, | 
 | 78 | 					  "Deleted route towards originator"); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 79 |  | 
| Linus Lüssing | e1a5382 | 2011-03-14 22:43:37 +0000 | [diff] [blame] | 80 | 	/* route added */ | 
 | 81 | 	} else if ((!curr_router) && (neigh_node)) { | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 82 |  | 
| Sven Eckelmann | 39c75a5 | 2012-06-03 22:19:22 +0200 | [diff] [blame] | 83 | 		batadv_dbg(BATADV_DBG_ROUTES, bat_priv, | 
| Sven Eckelmann | 1eda58b | 2012-05-12 13:48:58 +0200 | [diff] [blame] | 84 | 			   "Adding route towards: %pM (via %pM)\n", | 
 | 85 | 			   orig_node->orig, neigh_node->addr); | 
| Linus Lüssing | e1a5382 | 2011-03-14 22:43:37 +0000 | [diff] [blame] | 86 | 	/* route changed */ | 
| Sven Eckelmann | bb899b8 | 2011-05-10 11:22:37 +0200 | [diff] [blame] | 87 | 	} else if (neigh_node && curr_router) { | 
| Sven Eckelmann | 39c75a5 | 2012-06-03 22:19:22 +0200 | [diff] [blame] | 88 | 		batadv_dbg(BATADV_DBG_ROUTES, bat_priv, | 
| Sven Eckelmann | 1eda58b | 2012-05-12 13:48:58 +0200 | [diff] [blame] | 89 | 			   "Changing route towards: %pM (now via %pM - was via %pM)\n", | 
 | 90 | 			   orig_node->orig, neigh_node->addr, | 
 | 91 | 			   curr_router->addr); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 92 | 	} | 
 | 93 |  | 
| Linus Lüssing | e1a5382 | 2011-03-14 22:43:37 +0000 | [diff] [blame] | 94 | 	if (curr_router) | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 95 | 		batadv_neigh_node_free_ref(curr_router); | 
| Linus Lüssing | e1a5382 | 2011-03-14 22:43:37 +0000 | [diff] [blame] | 96 |  | 
 | 97 | 	/* increase refcount of new best neighbor */ | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 98 | 	if (neigh_node && !atomic_inc_not_zero(&neigh_node->refcount)) | 
 | 99 | 		neigh_node = NULL; | 
| Linus Lüssing | e1a5382 | 2011-03-14 22:43:37 +0000 | [diff] [blame] | 100 |  | 
 | 101 | 	spin_lock_bh(&orig_node->neigh_list_lock); | 
 | 102 | 	rcu_assign_pointer(orig_node->router, neigh_node); | 
 | 103 | 	spin_unlock_bh(&orig_node->neigh_list_lock); | 
 | 104 |  | 
 | 105 | 	/* decrease refcount of previous best neighbor */ | 
 | 106 | 	if (curr_router) | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 107 | 		batadv_neigh_node_free_ref(curr_router); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 108 | } | 
 | 109 |  | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 110 | void batadv_update_route(struct batadv_priv *bat_priv, | 
 | 111 | 			 struct batadv_orig_node *orig_node, | 
 | 112 | 			 struct batadv_neigh_node *neigh_node) | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 113 | { | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 114 | 	struct batadv_neigh_node *router = NULL; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 115 |  | 
 | 116 | 	if (!orig_node) | 
| Linus Lüssing | e1a5382 | 2011-03-14 22:43:37 +0000 | [diff] [blame] | 117 | 		goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 118 |  | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 119 | 	router = batadv_orig_node_get_router(orig_node); | 
| Linus Lüssing | e1a5382 | 2011-03-14 22:43:37 +0000 | [diff] [blame] | 120 |  | 
 | 121 | 	if (router != neigh_node) | 
| Sven Eckelmann | 63b0103 | 2012-05-16 20:23:13 +0200 | [diff] [blame] | 122 | 		_batadv_update_route(bat_priv, orig_node, neigh_node); | 
| Linus Lüssing | e1a5382 | 2011-03-14 22:43:37 +0000 | [diff] [blame] | 123 |  | 
 | 124 | out: | 
 | 125 | 	if (router) | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 126 | 		batadv_neigh_node_free_ref(router); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 127 | } | 
 | 128 |  | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 129 | /* caller must hold the neigh_list_lock */ | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 130 | void batadv_bonding_candidate_del(struct batadv_orig_node *orig_node, | 
 | 131 | 				  struct batadv_neigh_node *neigh_node) | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 132 | { | 
 | 133 | 	/* this neighbor is not part of our candidate list */ | 
 | 134 | 	if (list_empty(&neigh_node->bonding_list)) | 
 | 135 | 		goto out; | 
 | 136 |  | 
 | 137 | 	list_del_rcu(&neigh_node->bonding_list); | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 138 | 	INIT_LIST_HEAD(&neigh_node->bonding_list); | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 139 | 	batadv_neigh_node_free_ref(neigh_node); | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 140 | 	atomic_dec(&orig_node->bond_candidates); | 
 | 141 |  | 
 | 142 | out: | 
 | 143 | 	return; | 
 | 144 | } | 
 | 145 |  | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 146 | void batadv_bonding_candidate_add(struct batadv_orig_node *orig_node, | 
 | 147 | 				  struct batadv_neigh_node *neigh_node) | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 148 | { | 
 | 149 | 	struct hlist_node *node; | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 150 | 	struct batadv_neigh_node *tmp_neigh_node, *router = NULL; | 
| Linus Lüssing | e1a5382 | 2011-03-14 22:43:37 +0000 | [diff] [blame] | 151 | 	uint8_t interference_candidate = 0; | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 152 |  | 
 | 153 | 	spin_lock_bh(&orig_node->neigh_list_lock); | 
 | 154 |  | 
 | 155 | 	/* only consider if it has the same primary address ...  */ | 
| Sven Eckelmann | 1eda58b | 2012-05-12 13:48:58 +0200 | [diff] [blame] | 156 | 	if (!batadv_compare_eth(orig_node->orig, | 
 | 157 | 				neigh_node->orig_node->primary_addr)) | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 158 | 		goto candidate_del; | 
 | 159 |  | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 160 | 	router = batadv_orig_node_get_router(orig_node); | 
| Linus Lüssing | e1a5382 | 2011-03-14 22:43:37 +0000 | [diff] [blame] | 161 | 	if (!router) | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 162 | 		goto candidate_del; | 
 | 163 |  | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 164 | 	/* ... and is good enough to be considered */ | 
| Sven Eckelmann | 42d0b04 | 2012-06-03 22:19:17 +0200 | [diff] [blame] | 165 | 	if (neigh_node->tq_avg < router->tq_avg - BATADV_BONDING_TQ_THRESHOLD) | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 166 | 		goto candidate_del; | 
 | 167 |  | 
| Sven Eckelmann | 9cfc7bd | 2012-05-12 02:09:43 +0200 | [diff] [blame] | 168 | 	/* check if we have another candidate with the same mac address or | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 169 | 	 * interface. If we do, we won't select this candidate because of | 
 | 170 | 	 * possible interference. | 
 | 171 | 	 */ | 
 | 172 | 	hlist_for_each_entry_rcu(tmp_neigh_node, node, | 
 | 173 | 				 &orig_node->neigh_list, list) { | 
 | 174 |  | 
 | 175 | 		if (tmp_neigh_node == neigh_node) | 
 | 176 | 			continue; | 
 | 177 |  | 
 | 178 | 		/* we only care if the other candidate is even | 
| Sven Eckelmann | 9cfc7bd | 2012-05-12 02:09:43 +0200 | [diff] [blame] | 179 | 		 * considered as candidate. | 
 | 180 | 		 */ | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 181 | 		if (list_empty(&tmp_neigh_node->bonding_list)) | 
 | 182 | 			continue; | 
 | 183 |  | 
 | 184 | 		if ((neigh_node->if_incoming == tmp_neigh_node->if_incoming) || | 
| Sven Eckelmann | 1eda58b | 2012-05-12 13:48:58 +0200 | [diff] [blame] | 185 | 		    (batadv_compare_eth(neigh_node->addr, | 
 | 186 | 					tmp_neigh_node->addr))) { | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 187 | 			interference_candidate = 1; | 
 | 188 | 			break; | 
 | 189 | 		} | 
 | 190 | 	} | 
 | 191 |  | 
 | 192 | 	/* don't care further if it is an interference candidate */ | 
 | 193 | 	if (interference_candidate) | 
 | 194 | 		goto candidate_del; | 
 | 195 |  | 
 | 196 | 	/* this neighbor already is part of our candidate list */ | 
 | 197 | 	if (!list_empty(&neigh_node->bonding_list)) | 
 | 198 | 		goto out; | 
 | 199 |  | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 200 | 	if (!atomic_inc_not_zero(&neigh_node->refcount)) | 
 | 201 | 		goto out; | 
 | 202 |  | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 203 | 	list_add_rcu(&neigh_node->bonding_list, &orig_node->bond_list); | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 204 | 	atomic_inc(&orig_node->bond_candidates); | 
 | 205 | 	goto out; | 
 | 206 |  | 
 | 207 | candidate_del: | 
| Sven Eckelmann | 30d3c51 | 2012-05-12 02:09:36 +0200 | [diff] [blame] | 208 | 	batadv_bonding_candidate_del(orig_node, neigh_node); | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 209 |  | 
 | 210 | out: | 
 | 211 | 	spin_unlock_bh(&orig_node->neigh_list_lock); | 
| Linus Lüssing | e1a5382 | 2011-03-14 22:43:37 +0000 | [diff] [blame] | 212 |  | 
 | 213 | 	if (router) | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 214 | 		batadv_neigh_node_free_ref(router); | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 215 | } | 
 | 216 |  | 
 | 217 | /* copy primary address for bonding */ | 
| Sven Eckelmann | 30d3c51 | 2012-05-12 02:09:36 +0200 | [diff] [blame] | 218 | void | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 219 | batadv_bonding_save_primary(const struct batadv_orig_node *orig_node, | 
 | 220 | 			    struct batadv_orig_node *orig_neigh_node, | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 221 | 			    const struct batadv_ogm_packet *batman_ogm_packet) | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 222 | { | 
| Sven Eckelmann | acd34af | 2012-06-03 22:19:21 +0200 | [diff] [blame] | 223 | 	if (!(batman_ogm_packet->flags & BATADV_PRIMARIES_FIRST_HOP)) | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 224 | 		return; | 
 | 225 |  | 
 | 226 | 	memcpy(orig_neigh_node->primary_addr, orig_node->orig, ETH_ALEN); | 
 | 227 | } | 
 | 228 |  | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 229 | /* checks whether the host restarted and is in the protection time. | 
 | 230 |  * returns: | 
 | 231 |  *  0 if the packet is to be accepted | 
 | 232 |  *  1 if the packet is to be ignored. | 
 | 233 |  */ | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 234 | int batadv_window_protected(struct batadv_priv *bat_priv, int32_t seq_num_diff, | 
| Sven Eckelmann | 30d3c51 | 2012-05-12 02:09:36 +0200 | [diff] [blame] | 235 | 			    unsigned long *last_reset) | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 236 | { | 
| Sven Eckelmann | 42d0b04 | 2012-06-03 22:19:17 +0200 | [diff] [blame] | 237 | 	if (seq_num_diff <= -BATADV_TQ_LOCAL_WINDOW_SIZE || | 
 | 238 | 	    seq_num_diff >= BATADV_EXPECTED_SEQNO_RANGE) { | 
 | 239 | 		if (!batadv_has_timed_out(*last_reset, | 
 | 240 | 					  BATADV_RESET_PROTECTION_MS)) | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 241 | 			return 1; | 
| Marek Lindner | 8c7bf24 | 2012-03-17 15:28:33 +0800 | [diff] [blame] | 242 |  | 
 | 243 | 		*last_reset = jiffies; | 
| Sven Eckelmann | 39c75a5 | 2012-06-03 22:19:22 +0200 | [diff] [blame] | 244 | 		batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 
| Sven Eckelmann | 1eda58b | 2012-05-12 13:48:58 +0200 | [diff] [blame] | 245 | 			   "old packet received, start protection\n"); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 246 | 	} | 
| Marek Lindner | 8c7bf24 | 2012-03-17 15:28:33 +0800 | [diff] [blame] | 247 |  | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 248 | 	return 0; | 
 | 249 | } | 
 | 250 |  | 
| Sven Eckelmann | 30d3c51 | 2012-05-12 02:09:36 +0200 | [diff] [blame] | 251 | bool batadv_check_management_packet(struct sk_buff *skb, | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 252 | 				    struct batadv_hard_iface *hard_iface, | 
| Sven Eckelmann | 30d3c51 | 2012-05-12 02:09:36 +0200 | [diff] [blame] | 253 | 				    int header_len) | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 254 | { | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 255 | 	struct ethhdr *ethhdr; | 
 | 256 |  | 
 | 257 | 	/* drop packet if it has not necessary minimum size */ | 
| Marek Lindner | c3e2931 | 2012-03-04 16:56:25 +0800 | [diff] [blame] | 258 | 	if (unlikely(!pskb_may_pull(skb, header_len))) | 
 | 259 | 		return false; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 260 |  | 
 | 261 | 	ethhdr = (struct ethhdr *)skb_mac_header(skb); | 
 | 262 |  | 
 | 263 | 	/* packet with broadcast indication but unicast recipient */ | 
 | 264 | 	if (!is_broadcast_ether_addr(ethhdr->h_dest)) | 
| Marek Lindner | c3e2931 | 2012-03-04 16:56:25 +0800 | [diff] [blame] | 265 | 		return false; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 266 |  | 
 | 267 | 	/* packet with broadcast sender address */ | 
 | 268 | 	if (is_broadcast_ether_addr(ethhdr->h_source)) | 
| Marek Lindner | c3e2931 | 2012-03-04 16:56:25 +0800 | [diff] [blame] | 269 | 		return false; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 270 |  | 
 | 271 | 	/* create a copy of the skb, if needed, to modify it. */ | 
 | 272 | 	if (skb_cow(skb, 0) < 0) | 
| Marek Lindner | c3e2931 | 2012-03-04 16:56:25 +0800 | [diff] [blame] | 273 | 		return false; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 274 |  | 
 | 275 | 	/* keep skb linear */ | 
 | 276 | 	if (skb_linearize(skb) < 0) | 
| Marek Lindner | c3e2931 | 2012-03-04 16:56:25 +0800 | [diff] [blame] | 277 | 		return false; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 278 |  | 
| Marek Lindner | c3e2931 | 2012-03-04 16:56:25 +0800 | [diff] [blame] | 279 | 	return true; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 280 | } | 
 | 281 |  | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 282 | static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv, | 
| Sven Eckelmann | 63b0103 | 2012-05-16 20:23:13 +0200 | [diff] [blame] | 283 | 				      struct sk_buff *skb, size_t icmp_len) | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 284 | { | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 285 | 	struct batadv_hard_iface *primary_if = NULL; | 
 | 286 | 	struct batadv_orig_node *orig_node = NULL; | 
 | 287 | 	struct batadv_neigh_node *router = NULL; | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 288 | 	struct batadv_icmp_packet_rr *icmp_packet; | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 289 | 	int ret = NET_RX_DROP; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 290 |  | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 291 | 	icmp_packet = (struct batadv_icmp_packet_rr *)skb->data; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 292 |  | 
 | 293 | 	/* add data to device queue */ | 
| Sven Eckelmann | acd34af | 2012-06-03 22:19:21 +0200 | [diff] [blame] | 294 | 	if (icmp_packet->msg_type != BATADV_ECHO_REQUEST) { | 
| Sven Eckelmann | 9039dc7 | 2012-05-12 02:09:33 +0200 | [diff] [blame] | 295 | 		batadv_socket_receive_packet(icmp_packet, icmp_len); | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 296 | 		goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 297 | 	} | 
 | 298 |  | 
| Sven Eckelmann | e5d8925 | 2012-05-12 13:48:54 +0200 | [diff] [blame] | 299 | 	primary_if = batadv_primary_if_get_selected(bat_priv); | 
| Marek Lindner | 32ae9b2 | 2011-04-20 15:40:58 +0200 | [diff] [blame] | 300 | 	if (!primary_if) | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 301 | 		goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 302 |  | 
 | 303 | 	/* answer echo request (ping) */ | 
 | 304 | 	/* get routing information */ | 
| Sven Eckelmann | da64119 | 2012-05-12 13:48:56 +0200 | [diff] [blame] | 305 | 	orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->orig); | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 306 | 	if (!orig_node) | 
| Linus Lüssing | e1a5382 | 2011-03-14 22:43:37 +0000 | [diff] [blame] | 307 | 		goto out; | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 308 |  | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 309 | 	router = batadv_orig_node_get_router(orig_node); | 
| Linus Lüssing | e1a5382 | 2011-03-14 22:43:37 +0000 | [diff] [blame] | 310 | 	if (!router) | 
 | 311 | 		goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 312 |  | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 313 | 	/* create a copy of the skb, if needed, to modify it. */ | 
| Antonio Quartulli | 0d12507 | 2012-02-18 11:27:34 +0100 | [diff] [blame] | 314 | 	if (skb_cow(skb, ETH_HLEN) < 0) | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 315 | 		goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 316 |  | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 317 | 	icmp_packet = (struct batadv_icmp_packet_rr *)skb->data; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 318 |  | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 319 | 	memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); | 
| Marek Lindner | 32ae9b2 | 2011-04-20 15:40:58 +0200 | [diff] [blame] | 320 | 	memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN); | 
| Sven Eckelmann | acd34af | 2012-06-03 22:19:21 +0200 | [diff] [blame] | 321 | 	icmp_packet->msg_type = BATADV_ECHO_REPLY; | 
| Sven Eckelmann | 42d0b04 | 2012-06-03 22:19:17 +0200 | [diff] [blame] | 322 | 	icmp_packet->header.ttl = BATADV_TTL; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 323 |  | 
| Sven Eckelmann | 9455e34 | 2012-05-12 02:09:37 +0200 | [diff] [blame] | 324 | 	batadv_send_skb_packet(skb, router->if_incoming, router->addr); | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 325 | 	ret = NET_RX_SUCCESS; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 326 |  | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 327 | out: | 
| Marek Lindner | 32ae9b2 | 2011-04-20 15:40:58 +0200 | [diff] [blame] | 328 | 	if (primary_if) | 
| Sven Eckelmann | e5d8925 | 2012-05-12 13:48:54 +0200 | [diff] [blame] | 329 | 		batadv_hardif_free_ref(primary_if); | 
| Linus Lüssing | e1a5382 | 2011-03-14 22:43:37 +0000 | [diff] [blame] | 330 | 	if (router) | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 331 | 		batadv_neigh_node_free_ref(router); | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 332 | 	if (orig_node) | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 333 | 		batadv_orig_node_free_ref(orig_node); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 334 | 	return ret; | 
 | 335 | } | 
 | 336 |  | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 337 | static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv, | 
| Sven Eckelmann | 63b0103 | 2012-05-16 20:23:13 +0200 | [diff] [blame] | 338 | 					 struct sk_buff *skb) | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 339 | { | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 340 | 	struct batadv_hard_iface *primary_if = NULL; | 
 | 341 | 	struct batadv_orig_node *orig_node = NULL; | 
 | 342 | 	struct batadv_neigh_node *router = NULL; | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 343 | 	struct batadv_icmp_packet *icmp_packet; | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 344 | 	int ret = NET_RX_DROP; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 345 |  | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 346 | 	icmp_packet = (struct batadv_icmp_packet *)skb->data; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 347 |  | 
 | 348 | 	/* send TTL exceeded if packet is an echo request (traceroute) */ | 
| Sven Eckelmann | acd34af | 2012-06-03 22:19:21 +0200 | [diff] [blame] | 349 | 	if (icmp_packet->msg_type != BATADV_ECHO_REQUEST) { | 
| Sven Eckelmann | 86ceb36 | 2012-03-07 09:07:45 +0100 | [diff] [blame] | 350 | 		pr_debug("Warning - can't forward icmp packet from %pM to %pM: ttl exceeded\n", | 
 | 351 | 			 icmp_packet->orig, icmp_packet->dst); | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 352 | 		goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 353 | 	} | 
 | 354 |  | 
| Sven Eckelmann | e5d8925 | 2012-05-12 13:48:54 +0200 | [diff] [blame] | 355 | 	primary_if = batadv_primary_if_get_selected(bat_priv); | 
| Marek Lindner | 32ae9b2 | 2011-04-20 15:40:58 +0200 | [diff] [blame] | 356 | 	if (!primary_if) | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 357 | 		goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 358 |  | 
 | 359 | 	/* get routing information */ | 
| Sven Eckelmann | da64119 | 2012-05-12 13:48:56 +0200 | [diff] [blame] | 360 | 	orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->orig); | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 361 | 	if (!orig_node) | 
| Linus Lüssing | e1a5382 | 2011-03-14 22:43:37 +0000 | [diff] [blame] | 362 | 		goto out; | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 363 |  | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 364 | 	router = batadv_orig_node_get_router(orig_node); | 
| Linus Lüssing | e1a5382 | 2011-03-14 22:43:37 +0000 | [diff] [blame] | 365 | 	if (!router) | 
 | 366 | 		goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 367 |  | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 368 | 	/* create a copy of the skb, if needed, to modify it. */ | 
| Antonio Quartulli | 0d12507 | 2012-02-18 11:27:34 +0100 | [diff] [blame] | 369 | 	if (skb_cow(skb, ETH_HLEN) < 0) | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 370 | 		goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 371 |  | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 372 | 	icmp_packet = (struct batadv_icmp_packet *)skb->data; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 373 |  | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 374 | 	memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); | 
| Marek Lindner | 32ae9b2 | 2011-04-20 15:40:58 +0200 | [diff] [blame] | 375 | 	memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN); | 
| Sven Eckelmann | acd34af | 2012-06-03 22:19:21 +0200 | [diff] [blame] | 376 | 	icmp_packet->msg_type = BATADV_TTL_EXCEEDED; | 
| Sven Eckelmann | 42d0b04 | 2012-06-03 22:19:17 +0200 | [diff] [blame] | 377 | 	icmp_packet->header.ttl = BATADV_TTL; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 378 |  | 
| Sven Eckelmann | 9455e34 | 2012-05-12 02:09:37 +0200 | [diff] [blame] | 379 | 	batadv_send_skb_packet(skb, router->if_incoming, router->addr); | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 380 | 	ret = NET_RX_SUCCESS; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 381 |  | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 382 | out: | 
| Marek Lindner | 32ae9b2 | 2011-04-20 15:40:58 +0200 | [diff] [blame] | 383 | 	if (primary_if) | 
| Sven Eckelmann | e5d8925 | 2012-05-12 13:48:54 +0200 | [diff] [blame] | 384 | 		batadv_hardif_free_ref(primary_if); | 
| Linus Lüssing | e1a5382 | 2011-03-14 22:43:37 +0000 | [diff] [blame] | 385 | 	if (router) | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 386 | 		batadv_neigh_node_free_ref(router); | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 387 | 	if (orig_node) | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 388 | 		batadv_orig_node_free_ref(orig_node); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 389 | 	return ret; | 
 | 390 | } | 
 | 391 |  | 
 | 392 |  | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 393 | int batadv_recv_icmp_packet(struct sk_buff *skb, | 
 | 394 | 			    struct batadv_hard_iface *recv_if) | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 395 | { | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 396 | 	struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 397 | 	struct batadv_icmp_packet_rr *icmp_packet; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 398 | 	struct ethhdr *ethhdr; | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 399 | 	struct batadv_orig_node *orig_node = NULL; | 
 | 400 | 	struct batadv_neigh_node *router = NULL; | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 401 | 	int hdr_size = sizeof(struct batadv_icmp_packet); | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 402 | 	int ret = NET_RX_DROP; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 403 |  | 
| Sven Eckelmann | 9cfc7bd | 2012-05-12 02:09:43 +0200 | [diff] [blame] | 404 | 	/* we truncate all incoming icmp packets if they don't match our size */ | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 405 | 	if (skb->len >= sizeof(struct batadv_icmp_packet_rr)) | 
 | 406 | 		hdr_size = sizeof(struct batadv_icmp_packet_rr); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 407 |  | 
 | 408 | 	/* drop packet if it has not necessary minimum size */ | 
 | 409 | 	if (unlikely(!pskb_may_pull(skb, hdr_size))) | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 410 | 		goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 411 |  | 
 | 412 | 	ethhdr = (struct ethhdr *)skb_mac_header(skb); | 
 | 413 |  | 
 | 414 | 	/* packet with unicast indication but broadcast recipient */ | 
 | 415 | 	if (is_broadcast_ether_addr(ethhdr->h_dest)) | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 416 | 		goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 417 |  | 
 | 418 | 	/* packet with broadcast sender address */ | 
 | 419 | 	if (is_broadcast_ether_addr(ethhdr->h_source)) | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 420 | 		goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 421 |  | 
 | 422 | 	/* not for me */ | 
| Sven Eckelmann | 3193e8f | 2012-05-12 02:09:42 +0200 | [diff] [blame] | 423 | 	if (!batadv_is_my_mac(ethhdr->h_dest)) | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 424 | 		goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 425 |  | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 426 | 	icmp_packet = (struct batadv_icmp_packet_rr *)skb->data; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 427 |  | 
 | 428 | 	/* add record route information if not full */ | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 429 | 	if ((hdr_size == sizeof(struct batadv_icmp_packet_rr)) && | 
| Sven Eckelmann | 7e071c7 | 2012-06-03 22:19:13 +0200 | [diff] [blame] | 430 | 	    (icmp_packet->rr_cur < BATADV_RR_LEN)) { | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 431 | 		memcpy(&(icmp_packet->rr[icmp_packet->rr_cur]), | 
| Sven Eckelmann | 7c64fd9 | 2012-02-28 10:55:36 +0100 | [diff] [blame] | 432 | 		       ethhdr->h_dest, ETH_ALEN); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 433 | 		icmp_packet->rr_cur++; | 
 | 434 | 	} | 
 | 435 |  | 
 | 436 | 	/* packet for me */ | 
| Sven Eckelmann | 3193e8f | 2012-05-12 02:09:42 +0200 | [diff] [blame] | 437 | 	if (batadv_is_my_mac(icmp_packet->dst)) | 
| Sven Eckelmann | 63b0103 | 2012-05-16 20:23:13 +0200 | [diff] [blame] | 438 | 		return batadv_recv_my_icmp_packet(bat_priv, skb, hdr_size); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 439 |  | 
 | 440 | 	/* TTL exceeded */ | 
| Sven Eckelmann | 76543d1 | 2011-11-20 15:47:38 +0100 | [diff] [blame] | 441 | 	if (icmp_packet->header.ttl < 2) | 
| Sven Eckelmann | 63b0103 | 2012-05-16 20:23:13 +0200 | [diff] [blame] | 442 | 		return batadv_recv_icmp_ttl_exceeded(bat_priv, skb); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 443 |  | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 444 | 	/* get routing information */ | 
| Sven Eckelmann | da64119 | 2012-05-12 13:48:56 +0200 | [diff] [blame] | 445 | 	orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->dst); | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 446 | 	if (!orig_node) | 
| Linus Lüssing | e1a5382 | 2011-03-14 22:43:37 +0000 | [diff] [blame] | 447 | 		goto out; | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 448 |  | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 449 | 	router = batadv_orig_node_get_router(orig_node); | 
| Linus Lüssing | e1a5382 | 2011-03-14 22:43:37 +0000 | [diff] [blame] | 450 | 	if (!router) | 
 | 451 | 		goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 452 |  | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 453 | 	/* create a copy of the skb, if needed, to modify it. */ | 
| Antonio Quartulli | 0d12507 | 2012-02-18 11:27:34 +0100 | [diff] [blame] | 454 | 	if (skb_cow(skb, ETH_HLEN) < 0) | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 455 | 		goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 456 |  | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 457 | 	icmp_packet = (struct batadv_icmp_packet_rr *)skb->data; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 458 |  | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 459 | 	/* decrement ttl */ | 
| Sven Eckelmann | 76543d1 | 2011-11-20 15:47:38 +0100 | [diff] [blame] | 460 | 	icmp_packet->header.ttl--; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 461 |  | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 462 | 	/* route it */ | 
| Sven Eckelmann | 9455e34 | 2012-05-12 02:09:37 +0200 | [diff] [blame] | 463 | 	batadv_send_skb_packet(skb, router->if_incoming, router->addr); | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 464 | 	ret = NET_RX_SUCCESS; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 465 |  | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 466 | out: | 
| Linus Lüssing | e1a5382 | 2011-03-14 22:43:37 +0000 | [diff] [blame] | 467 | 	if (router) | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 468 | 		batadv_neigh_node_free_ref(router); | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 469 | 	if (orig_node) | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 470 | 		batadv_orig_node_free_ref(orig_node); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 471 | 	return ret; | 
 | 472 | } | 
 | 473 |  | 
| Linus Lüssing | 5515862 | 2011-03-14 22:43:27 +0000 | [diff] [blame] | 474 | /* In the bonding case, send the packets in a round | 
 | 475 |  * robin fashion over the remaining interfaces. | 
 | 476 |  * | 
 | 477 |  * This method rotates the bonding list and increases the | 
| Sven Eckelmann | 9cfc7bd | 2012-05-12 02:09:43 +0200 | [diff] [blame] | 478 |  * returned router's refcount. | 
 | 479 |  */ | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 480 | static struct batadv_neigh_node * | 
 | 481 | batadv_find_bond_router(struct batadv_orig_node *primary_orig, | 
 | 482 | 			const struct batadv_hard_iface *recv_if) | 
| Linus Lüssing | 5515862 | 2011-03-14 22:43:27 +0000 | [diff] [blame] | 483 | { | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 484 | 	struct batadv_neigh_node *tmp_neigh_node; | 
 | 485 | 	struct batadv_neigh_node *router = NULL, *first_candidate = NULL; | 
| Linus Lüssing | 5515862 | 2011-03-14 22:43:27 +0000 | [diff] [blame] | 486 |  | 
 | 487 | 	rcu_read_lock(); | 
 | 488 | 	list_for_each_entry_rcu(tmp_neigh_node, &primary_orig->bond_list, | 
 | 489 | 				bonding_list) { | 
 | 490 | 		if (!first_candidate) | 
 | 491 | 			first_candidate = tmp_neigh_node; | 
 | 492 |  | 
 | 493 | 		/* recv_if == NULL on the first node. */ | 
 | 494 | 		if (tmp_neigh_node->if_incoming == recv_if) | 
 | 495 | 			continue; | 
 | 496 |  | 
 | 497 | 		if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) | 
 | 498 | 			continue; | 
 | 499 |  | 
 | 500 | 		router = tmp_neigh_node; | 
 | 501 | 		break; | 
 | 502 | 	} | 
 | 503 |  | 
 | 504 | 	/* use the first candidate if nothing was found. */ | 
 | 505 | 	if (!router && first_candidate && | 
 | 506 | 	    atomic_inc_not_zero(&first_candidate->refcount)) | 
 | 507 | 		router = first_candidate; | 
 | 508 |  | 
 | 509 | 	if (!router) | 
 | 510 | 		goto out; | 
 | 511 |  | 
 | 512 | 	/* selected should point to the next element | 
| Sven Eckelmann | 9cfc7bd | 2012-05-12 02:09:43 +0200 | [diff] [blame] | 513 | 	 * after the current router | 
 | 514 | 	 */ | 
| Linus Lüssing | 5515862 | 2011-03-14 22:43:27 +0000 | [diff] [blame] | 515 | 	spin_lock_bh(&primary_orig->neigh_list_lock); | 
 | 516 | 	/* this is a list_move(), which unfortunately | 
| Sven Eckelmann | 9cfc7bd | 2012-05-12 02:09:43 +0200 | [diff] [blame] | 517 | 	 * does not exist as rcu version | 
 | 518 | 	 */ | 
| Linus Lüssing | 5515862 | 2011-03-14 22:43:27 +0000 | [diff] [blame] | 519 | 	list_del_rcu(&primary_orig->bond_list); | 
 | 520 | 	list_add_rcu(&primary_orig->bond_list, | 
 | 521 | 		     &router->bonding_list); | 
 | 522 | 	spin_unlock_bh(&primary_orig->neigh_list_lock); | 
 | 523 |  | 
 | 524 | out: | 
 | 525 | 	rcu_read_unlock(); | 
 | 526 | 	return router; | 
 | 527 | } | 
 | 528 |  | 
 | 529 | /* Interface Alternating: Use the best of the | 
 | 530 |  * remaining candidates which are not using | 
 | 531 |  * this interface. | 
 | 532 |  * | 
| Sven Eckelmann | 9cfc7bd | 2012-05-12 02:09:43 +0200 | [diff] [blame] | 533 |  * Increases the returned router's refcount | 
 | 534 |  */ | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 535 | static struct batadv_neigh_node * | 
 | 536 | batadv_find_ifalter_router(struct batadv_orig_node *primary_orig, | 
 | 537 | 			   const struct batadv_hard_iface *recv_if) | 
| Linus Lüssing | 5515862 | 2011-03-14 22:43:27 +0000 | [diff] [blame] | 538 | { | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 539 | 	struct batadv_neigh_node *tmp_neigh_node; | 
 | 540 | 	struct batadv_neigh_node *router = NULL, *first_candidate = NULL; | 
| Linus Lüssing | 5515862 | 2011-03-14 22:43:27 +0000 | [diff] [blame] | 541 |  | 
 | 542 | 	rcu_read_lock(); | 
 | 543 | 	list_for_each_entry_rcu(tmp_neigh_node, &primary_orig->bond_list, | 
 | 544 | 				bonding_list) { | 
 | 545 | 		if (!first_candidate) | 
 | 546 | 			first_candidate = tmp_neigh_node; | 
 | 547 |  | 
 | 548 | 		/* recv_if == NULL on the first node. */ | 
 | 549 | 		if (tmp_neigh_node->if_incoming == recv_if) | 
 | 550 | 			continue; | 
 | 551 |  | 
 | 552 | 		if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) | 
 | 553 | 			continue; | 
 | 554 |  | 
 | 555 | 		/* if we don't have a router yet | 
| Sven Eckelmann | 9cfc7bd | 2012-05-12 02:09:43 +0200 | [diff] [blame] | 556 | 		 * or this one is better, choose it. | 
 | 557 | 		 */ | 
| Linus Lüssing | 5515862 | 2011-03-14 22:43:27 +0000 | [diff] [blame] | 558 | 		if ((!router) || | 
 | 559 | 		    (tmp_neigh_node->tq_avg > router->tq_avg)) { | 
 | 560 | 			/* decrement refcount of | 
| Sven Eckelmann | 9cfc7bd | 2012-05-12 02:09:43 +0200 | [diff] [blame] | 561 | 			 * previously selected router | 
 | 562 | 			 */ | 
| Linus Lüssing | 5515862 | 2011-03-14 22:43:27 +0000 | [diff] [blame] | 563 | 			if (router) | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 564 | 				batadv_neigh_node_free_ref(router); | 
| Linus Lüssing | 5515862 | 2011-03-14 22:43:27 +0000 | [diff] [blame] | 565 |  | 
 | 566 | 			router = tmp_neigh_node; | 
 | 567 | 			atomic_inc_not_zero(&router->refcount); | 
 | 568 | 		} | 
 | 569 |  | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 570 | 		batadv_neigh_node_free_ref(tmp_neigh_node); | 
| Linus Lüssing | 5515862 | 2011-03-14 22:43:27 +0000 | [diff] [blame] | 571 | 	} | 
 | 572 |  | 
 | 573 | 	/* use the first candidate if nothing was found. */ | 
 | 574 | 	if (!router && first_candidate && | 
 | 575 | 	    atomic_inc_not_zero(&first_candidate->refcount)) | 
 | 576 | 		router = first_candidate; | 
 | 577 |  | 
 | 578 | 	rcu_read_unlock(); | 
 | 579 | 	return router; | 
 | 580 | } | 
 | 581 |  | 
| Martin Hundebøll | ff51fd7 | 2012-07-05 11:34:27 +0200 | [diff] [blame] | 582 | static int batadv_check_unicast_packet(struct sk_buff *skb, int hdr_size) | 
 | 583 | { | 
 | 584 | 	struct ethhdr *ethhdr; | 
 | 585 |  | 
 | 586 | 	/* drop packet if it has not necessary minimum size */ | 
 | 587 | 	if (unlikely(!pskb_may_pull(skb, hdr_size))) | 
 | 588 | 		return -1; | 
 | 589 |  | 
 | 590 | 	ethhdr = (struct ethhdr *)skb_mac_header(skb); | 
 | 591 |  | 
 | 592 | 	/* packet with unicast indication but broadcast recipient */ | 
 | 593 | 	if (is_broadcast_ether_addr(ethhdr->h_dest)) | 
 | 594 | 		return -1; | 
 | 595 |  | 
 | 596 | 	/* packet with broadcast sender address */ | 
 | 597 | 	if (is_broadcast_ether_addr(ethhdr->h_source)) | 
 | 598 | 		return -1; | 
 | 599 |  | 
 | 600 | 	/* not for me */ | 
 | 601 | 	if (!batadv_is_my_mac(ethhdr->h_dest)) | 
 | 602 | 		return -1; | 
 | 603 |  | 
 | 604 | 	return 0; | 
 | 605 | } | 
 | 606 |  | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 607 | int batadv_recv_tt_query(struct sk_buff *skb, struct batadv_hard_iface *recv_if) | 
| Antonio Quartulli | a73105b | 2011-04-27 14:27:44 +0200 | [diff] [blame] | 608 | { | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 609 | 	struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 610 | 	struct batadv_tt_query_packet *tt_query; | 
| Al Viro | f25bd58 | 2012-04-22 07:44:27 +0100 | [diff] [blame] | 611 | 	uint16_t tt_size; | 
| Martin Hundebøll | 74ee363 | 2012-07-05 11:34:28 +0200 | [diff] [blame] | 612 | 	int hdr_size = sizeof(*tt_query); | 
| Sven Eckelmann | 1eda58b | 2012-05-12 13:48:58 +0200 | [diff] [blame] | 613 | 	char tt_flag; | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 614 | 	size_t packet_size; | 
| Antonio Quartulli | a73105b | 2011-04-27 14:27:44 +0200 | [diff] [blame] | 615 |  | 
| Martin Hundebøll | 74ee363 | 2012-07-05 11:34:28 +0200 | [diff] [blame] | 616 | 	if (batadv_check_unicast_packet(skb, hdr_size) < 0) | 
 | 617 | 		return NET_RX_DROP; | 
| Antonio Quartulli | a73105b | 2011-04-27 14:27:44 +0200 | [diff] [blame] | 618 |  | 
 | 619 | 	/* I could need to modify it */ | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 620 | 	if (skb_cow(skb, sizeof(struct batadv_tt_query_packet)) < 0) | 
| Antonio Quartulli | a73105b | 2011-04-27 14:27:44 +0200 | [diff] [blame] | 621 | 		goto out; | 
 | 622 |  | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 623 | 	tt_query = (struct batadv_tt_query_packet *)skb->data; | 
| Antonio Quartulli | a73105b | 2011-04-27 14:27:44 +0200 | [diff] [blame] | 624 |  | 
| Sven Eckelmann | 7e071c7 | 2012-06-03 22:19:13 +0200 | [diff] [blame] | 625 | 	switch (tt_query->flags & BATADV_TT_QUERY_TYPE_MASK) { | 
| Sven Eckelmann | acd34af | 2012-06-03 22:19:21 +0200 | [diff] [blame] | 626 | 	case BATADV_TT_REQUEST: | 
| Sven Eckelmann | d69909d | 2012-06-03 22:19:20 +0200 | [diff] [blame] | 627 | 		batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_RX); | 
| Martin Hundebøll | f821486 | 2012-04-20 17:02:45 +0200 | [diff] [blame] | 628 |  | 
| Antonio Quartulli | a73105b | 2011-04-27 14:27:44 +0200 | [diff] [blame] | 629 | 		/* If we cannot provide an answer the tt_request is | 
| Sven Eckelmann | 9cfc7bd | 2012-05-12 02:09:43 +0200 | [diff] [blame] | 630 | 		 * forwarded | 
 | 631 | 		 */ | 
| Sven Eckelmann | 08c36d3 | 2012-05-12 02:09:39 +0200 | [diff] [blame] | 632 | 		if (!batadv_send_tt_response(bat_priv, tt_query)) { | 
| Sven Eckelmann | acd34af | 2012-06-03 22:19:21 +0200 | [diff] [blame] | 633 | 			if (tt_query->flags & BATADV_TT_FULL_TABLE) | 
 | 634 | 				tt_flag = 'F'; | 
 | 635 | 			else | 
 | 636 | 				tt_flag = '.'; | 
 | 637 |  | 
| Sven Eckelmann | 39c75a5 | 2012-06-03 22:19:22 +0200 | [diff] [blame] | 638 | 			batadv_dbg(BATADV_DBG_TT, bat_priv, | 
| Sven Eckelmann | 1eda58b | 2012-05-12 13:48:58 +0200 | [diff] [blame] | 639 | 				   "Routing TT_REQUEST to %pM [%c]\n", | 
 | 640 | 				   tt_query->dst, | 
 | 641 | 				   tt_flag); | 
| Sven Eckelmann | 63b0103 | 2012-05-16 20:23:13 +0200 | [diff] [blame] | 642 | 			return batadv_route_unicast_packet(skb, recv_if); | 
| Antonio Quartulli | a73105b | 2011-04-27 14:27:44 +0200 | [diff] [blame] | 643 | 		} | 
 | 644 | 		break; | 
| Sven Eckelmann | acd34af | 2012-06-03 22:19:21 +0200 | [diff] [blame] | 645 | 	case BATADV_TT_RESPONSE: | 
| Sven Eckelmann | d69909d | 2012-06-03 22:19:20 +0200 | [diff] [blame] | 646 | 		batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_RX); | 
| Martin Hundebøll | f821486 | 2012-04-20 17:02:45 +0200 | [diff] [blame] | 647 |  | 
| Sven Eckelmann | 3193e8f | 2012-05-12 02:09:42 +0200 | [diff] [blame] | 648 | 		if (batadv_is_my_mac(tt_query->dst)) { | 
| Antonio Quartulli | dc58fe3 | 2011-10-16 20:32:02 +0200 | [diff] [blame] | 649 | 			/* packet needs to be linearized to access the TT | 
| Sven Eckelmann | 9cfc7bd | 2012-05-12 02:09:43 +0200 | [diff] [blame] | 650 | 			 * changes | 
 | 651 | 			 */ | 
| Antonio Quartulli | dc58fe3 | 2011-10-16 20:32:02 +0200 | [diff] [blame] | 652 | 			if (skb_linearize(skb) < 0) | 
 | 653 | 				goto out; | 
| Antonio Quartulli | d2b6cc8 | 2012-06-14 22:21:28 +0200 | [diff] [blame] | 654 | 			/* skb_linearize() possibly changed skb->data */ | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 655 | 			tt_query = (struct batadv_tt_query_packet *)skb->data; | 
| Antonio Quartulli | a73105b | 2011-04-27 14:27:44 +0200 | [diff] [blame] | 656 |  | 
| Sven Eckelmann | 08c36d3 | 2012-05-12 02:09:39 +0200 | [diff] [blame] | 657 | 			tt_size = batadv_tt_len(ntohs(tt_query->tt_data)); | 
| Antonio Quartulli | 8b7342d | 2011-10-16 20:32:03 +0200 | [diff] [blame] | 658 |  | 
 | 659 | 			/* Ensure we have all the claimed data */ | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 660 | 			packet_size = sizeof(struct batadv_tt_query_packet); | 
 | 661 | 			packet_size += tt_size; | 
 | 662 | 			if (unlikely(skb_headlen(skb) < packet_size)) | 
| Antonio Quartulli | 8b7342d | 2011-10-16 20:32:03 +0200 | [diff] [blame] | 663 | 				goto out; | 
 | 664 |  | 
| Sven Eckelmann | 08c36d3 | 2012-05-12 02:09:39 +0200 | [diff] [blame] | 665 | 			batadv_handle_tt_response(bat_priv, tt_query); | 
| Antonio Quartulli | dc58fe3 | 2011-10-16 20:32:02 +0200 | [diff] [blame] | 666 | 		} else { | 
| Sven Eckelmann | acd34af | 2012-06-03 22:19:21 +0200 | [diff] [blame] | 667 | 			if (tt_query->flags & BATADV_TT_FULL_TABLE) | 
 | 668 | 				tt_flag =  'F'; | 
 | 669 | 			else | 
 | 670 | 				tt_flag = '.'; | 
| Sven Eckelmann | 39c75a5 | 2012-06-03 22:19:22 +0200 | [diff] [blame] | 671 | 			batadv_dbg(BATADV_DBG_TT, bat_priv, | 
| Sven Eckelmann | 1eda58b | 2012-05-12 13:48:58 +0200 | [diff] [blame] | 672 | 				   "Routing TT_RESPONSE to %pM [%c]\n", | 
 | 673 | 				   tt_query->dst, | 
 | 674 | 				   tt_flag); | 
| Sven Eckelmann | 63b0103 | 2012-05-16 20:23:13 +0200 | [diff] [blame] | 675 | 			return batadv_route_unicast_packet(skb, recv_if); | 
| Antonio Quartulli | a73105b | 2011-04-27 14:27:44 +0200 | [diff] [blame] | 676 | 		} | 
 | 677 | 		break; | 
 | 678 | 	} | 
 | 679 |  | 
 | 680 | out: | 
 | 681 | 	/* returning NET_RX_DROP will make the caller function kfree the skb */ | 
 | 682 | 	return NET_RX_DROP; | 
 | 683 | } | 
 | 684 |  | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 685 | int batadv_recv_roam_adv(struct sk_buff *skb, struct batadv_hard_iface *recv_if) | 
| Antonio Quartulli | cc47f66 | 2011-04-27 14:27:57 +0200 | [diff] [blame] | 686 | { | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 687 | 	struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 688 | 	struct batadv_roam_adv_packet *roam_adv_packet; | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 689 | 	struct batadv_orig_node *orig_node; | 
| Antonio Quartulli | cc47f66 | 2011-04-27 14:27:57 +0200 | [diff] [blame] | 690 | 	struct ethhdr *ethhdr; | 
 | 691 |  | 
 | 692 | 	/* drop packet if it has not necessary minimum size */ | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 693 | 	if (unlikely(!pskb_may_pull(skb, | 
 | 694 | 				    sizeof(struct batadv_roam_adv_packet)))) | 
| Antonio Quartulli | cc47f66 | 2011-04-27 14:27:57 +0200 | [diff] [blame] | 695 | 		goto out; | 
 | 696 |  | 
 | 697 | 	ethhdr = (struct ethhdr *)skb_mac_header(skb); | 
 | 698 |  | 
 | 699 | 	/* packet with unicast indication but broadcast recipient */ | 
 | 700 | 	if (is_broadcast_ether_addr(ethhdr->h_dest)) | 
 | 701 | 		goto out; | 
 | 702 |  | 
 | 703 | 	/* packet with broadcast sender address */ | 
 | 704 | 	if (is_broadcast_ether_addr(ethhdr->h_source)) | 
 | 705 | 		goto out; | 
 | 706 |  | 
| Sven Eckelmann | d69909d | 2012-06-03 22:19:20 +0200 | [diff] [blame] | 707 | 	batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_RX); | 
| Martin Hundebøll | f821486 | 2012-04-20 17:02:45 +0200 | [diff] [blame] | 708 |  | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 709 | 	roam_adv_packet = (struct batadv_roam_adv_packet *)skb->data; | 
| Antonio Quartulli | cc47f66 | 2011-04-27 14:27:57 +0200 | [diff] [blame] | 710 |  | 
| Sven Eckelmann | 3193e8f | 2012-05-12 02:09:42 +0200 | [diff] [blame] | 711 | 	if (!batadv_is_my_mac(roam_adv_packet->dst)) | 
| Sven Eckelmann | 63b0103 | 2012-05-16 20:23:13 +0200 | [diff] [blame] | 712 | 		return batadv_route_unicast_packet(skb, recv_if); | 
| Antonio Quartulli | cc47f66 | 2011-04-27 14:27:57 +0200 | [diff] [blame] | 713 |  | 
| Simon Wunderlich | 20ff9d5 | 2012-01-22 20:00:23 +0100 | [diff] [blame] | 714 | 	/* check if it is a backbone gateway. we don't accept | 
 | 715 | 	 * roaming advertisement from it, as it has the same | 
 | 716 | 	 * entries as we have. | 
 | 717 | 	 */ | 
| Sven Eckelmann | 08adf15 | 2012-05-12 13:38:47 +0200 | [diff] [blame] | 718 | 	if (batadv_bla_is_backbone_gw_orig(bat_priv, roam_adv_packet->src)) | 
| Simon Wunderlich | 20ff9d5 | 2012-01-22 20:00:23 +0100 | [diff] [blame] | 719 | 		goto out; | 
 | 720 |  | 
| Sven Eckelmann | da64119 | 2012-05-12 13:48:56 +0200 | [diff] [blame] | 721 | 	orig_node = batadv_orig_hash_find(bat_priv, roam_adv_packet->src); | 
| Antonio Quartulli | cc47f66 | 2011-04-27 14:27:57 +0200 | [diff] [blame] | 722 | 	if (!orig_node) | 
 | 723 | 		goto out; | 
 | 724 |  | 
| Sven Eckelmann | 39c75a5 | 2012-06-03 22:19:22 +0200 | [diff] [blame] | 725 | 	batadv_dbg(BATADV_DBG_TT, bat_priv, | 
| Sven Eckelmann | 1eda58b | 2012-05-12 13:48:58 +0200 | [diff] [blame] | 726 | 		   "Received ROAMING_ADV from %pM (client %pM)\n", | 
 | 727 | 		   roam_adv_packet->src, roam_adv_packet->client); | 
| Antonio Quartulli | cc47f66 | 2011-04-27 14:27:57 +0200 | [diff] [blame] | 728 |  | 
| Sven Eckelmann | 08c36d3 | 2012-05-12 02:09:39 +0200 | [diff] [blame] | 729 | 	batadv_tt_global_add(bat_priv, orig_node, roam_adv_packet->client, | 
| Sven Eckelmann | acd34af | 2012-06-03 22:19:21 +0200 | [diff] [blame] | 730 | 			     BATADV_TT_CLIENT_ROAM, | 
| Antonio Quartulli | d4f4469 | 2012-05-25 00:00:54 +0200 | [diff] [blame] | 731 | 			     atomic_read(&orig_node->last_ttvn) + 1); | 
| Antonio Quartulli | cc47f66 | 2011-04-27 14:27:57 +0200 | [diff] [blame] | 732 |  | 
 | 733 | 	/* Roaming phase starts: I have new information but the ttvn has not | 
 | 734 | 	 * been incremented yet. This flag will make me check all the incoming | 
| Sven Eckelmann | 9cfc7bd | 2012-05-12 02:09:43 +0200 | [diff] [blame] | 735 | 	 * packets for the correct destination. | 
 | 736 | 	 */ | 
| Sven Eckelmann | 807736f | 2012-07-15 22:26:51 +0200 | [diff] [blame] | 737 | 	bat_priv->tt.poss_change = true; | 
| Antonio Quartulli | cc47f66 | 2011-04-27 14:27:57 +0200 | [diff] [blame] | 738 |  | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 739 | 	batadv_orig_node_free_ref(orig_node); | 
| Antonio Quartulli | cc47f66 | 2011-04-27 14:27:57 +0200 | [diff] [blame] | 740 | out: | 
 | 741 | 	/* returning NET_RX_DROP will make the caller function kfree the skb */ | 
 | 742 | 	return NET_RX_DROP; | 
 | 743 | } | 
 | 744 |  | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 745 | /* find a suitable router for this originator, and use | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 746 |  * bonding if possible. increases the found neighbors | 
| Sven Eckelmann | 9cfc7bd | 2012-05-12 02:09:43 +0200 | [diff] [blame] | 747 |  * refcount. | 
 | 748 |  */ | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 749 | struct batadv_neigh_node * | 
 | 750 | batadv_find_router(struct batadv_priv *bat_priv, | 
 | 751 | 		   struct batadv_orig_node *orig_node, | 
 | 752 | 		   const struct batadv_hard_iface *recv_if) | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 753 | { | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 754 | 	struct batadv_orig_node *primary_orig_node; | 
 | 755 | 	struct batadv_orig_node *router_orig; | 
 | 756 | 	struct batadv_neigh_node *router; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 757 | 	static uint8_t zero_mac[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; | 
 | 758 | 	int bonding_enabled; | 
| Sven Eckelmann | da64119 | 2012-05-12 13:48:56 +0200 | [diff] [blame] | 759 | 	uint8_t *primary_addr; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 760 |  | 
 | 761 | 	if (!orig_node) | 
 | 762 | 		return NULL; | 
 | 763 |  | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 764 | 	router = batadv_orig_node_get_router(orig_node); | 
| Linus Lüssing | e1a5382 | 2011-03-14 22:43:37 +0000 | [diff] [blame] | 765 | 	if (!router) | 
| Marek Lindner | 01df2b6 | 2011-05-05 14:14:46 +0200 | [diff] [blame] | 766 | 		goto err; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 767 |  | 
 | 768 | 	/* without bonding, the first node should | 
| Sven Eckelmann | 9cfc7bd | 2012-05-12 02:09:43 +0200 | [diff] [blame] | 769 | 	 * always choose the default router. | 
 | 770 | 	 */ | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 771 | 	bonding_enabled = atomic_read(&bat_priv->bonding); | 
 | 772 |  | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 773 | 	rcu_read_lock(); | 
 | 774 | 	/* select default router to output */ | 
| Linus Lüssing | e1a5382 | 2011-03-14 22:43:37 +0000 | [diff] [blame] | 775 | 	router_orig = router->orig_node; | 
| Marek Lindner | 01df2b6 | 2011-05-05 14:14:46 +0200 | [diff] [blame] | 776 | 	if (!router_orig) | 
 | 777 | 		goto err_unlock; | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 778 |  | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 779 | 	if ((!recv_if) && (!bonding_enabled)) | 
 | 780 | 		goto return_router; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 781 |  | 
| Sven Eckelmann | da64119 | 2012-05-12 13:48:56 +0200 | [diff] [blame] | 782 | 	primary_addr = router_orig->primary_addr; | 
 | 783 |  | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 784 | 	/* if we have something in the primary_addr, we can search | 
| Sven Eckelmann | 9cfc7bd | 2012-05-12 02:09:43 +0200 | [diff] [blame] | 785 | 	 * for a potential bonding candidate. | 
 | 786 | 	 */ | 
| Sven Eckelmann | 1eda58b | 2012-05-12 13:48:58 +0200 | [diff] [blame] | 787 | 	if (batadv_compare_eth(primary_addr, zero_mac)) | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 788 | 		goto return_router; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 789 |  | 
 | 790 | 	/* find the orig_node which has the primary interface. might | 
| Sven Eckelmann | 9cfc7bd | 2012-05-12 02:09:43 +0200 | [diff] [blame] | 791 | 	 * even be the same as our router_orig in many cases | 
 | 792 | 	 */ | 
| Sven Eckelmann | 1eda58b | 2012-05-12 13:48:58 +0200 | [diff] [blame] | 793 | 	if (batadv_compare_eth(primary_addr, router_orig->orig)) { | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 794 | 		primary_orig_node = router_orig; | 
 | 795 | 	} else { | 
| Sven Eckelmann | da64119 | 2012-05-12 13:48:56 +0200 | [diff] [blame] | 796 | 		primary_orig_node = batadv_orig_hash_find(bat_priv, | 
 | 797 | 							  primary_addr); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 798 | 		if (!primary_orig_node) | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 799 | 			goto return_router; | 
| Marek Lindner | 7aadf88 | 2011-02-18 12:28:09 +0000 | [diff] [blame] | 800 |  | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 801 | 		batadv_orig_node_free_ref(primary_orig_node); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 802 | 	} | 
 | 803 |  | 
 | 804 | 	/* with less than 2 candidates, we can't do any | 
| Sven Eckelmann | 9cfc7bd | 2012-05-12 02:09:43 +0200 | [diff] [blame] | 805 | 	 * bonding and prefer the original router. | 
 | 806 | 	 */ | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 807 | 	if (atomic_read(&primary_orig_node->bond_candidates) < 2) | 
 | 808 | 		goto return_router; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 809 |  | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 810 | 	/* all nodes between should choose a candidate which | 
 | 811 | 	 * is is not on the interface where the packet came | 
| Sven Eckelmann | 9cfc7bd | 2012-05-12 02:09:43 +0200 | [diff] [blame] | 812 | 	 * in. | 
 | 813 | 	 */ | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 814 | 	batadv_neigh_node_free_ref(router); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 815 |  | 
| Linus Lüssing | 5515862 | 2011-03-14 22:43:27 +0000 | [diff] [blame] | 816 | 	if (bonding_enabled) | 
| Sven Eckelmann | 63b0103 | 2012-05-16 20:23:13 +0200 | [diff] [blame] | 817 | 		router = batadv_find_bond_router(primary_orig_node, recv_if); | 
| Linus Lüssing | 5515862 | 2011-03-14 22:43:27 +0000 | [diff] [blame] | 818 | 	else | 
| Sven Eckelmann | 63b0103 | 2012-05-16 20:23:13 +0200 | [diff] [blame] | 819 | 		router = batadv_find_ifalter_router(primary_orig_node, recv_if); | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 820 |  | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 821 | return_router: | 
| Sven Eckelmann | e9a4f29 | 2012-06-03 22:19:19 +0200 | [diff] [blame] | 822 | 	if (router && router->if_incoming->if_status != BATADV_IF_ACTIVE) | 
| Antonio Quartulli | e2cbc11 | 2011-05-08 20:52:57 +0200 | [diff] [blame] | 823 | 		goto err_unlock; | 
 | 824 |  | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 825 | 	rcu_read_unlock(); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 826 | 	return router; | 
| Marek Lindner | 01df2b6 | 2011-05-05 14:14:46 +0200 | [diff] [blame] | 827 | err_unlock: | 
 | 828 | 	rcu_read_unlock(); | 
 | 829 | err: | 
 | 830 | 	if (router) | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 831 | 		batadv_neigh_node_free_ref(router); | 
| Marek Lindner | 01df2b6 | 2011-05-05 14:14:46 +0200 | [diff] [blame] | 832 | 	return NULL; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 833 | } | 
 | 834 |  | 
| Sven Eckelmann | 63b0103 | 2012-05-16 20:23:13 +0200 | [diff] [blame] | 835 | static int batadv_route_unicast_packet(struct sk_buff *skb, | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 836 | 				       struct batadv_hard_iface *recv_if) | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 837 | { | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 838 | 	struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); | 
 | 839 | 	struct batadv_orig_node *orig_node = NULL; | 
 | 840 | 	struct batadv_neigh_node *neigh_node = NULL; | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 841 | 	struct batadv_unicast_packet *unicast_packet; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 842 | 	struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb); | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 843 | 	int ret = NET_RX_DROP; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 844 | 	struct sk_buff *new_skb; | 
 | 845 |  | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 846 | 	unicast_packet = (struct batadv_unicast_packet *)skb->data; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 847 |  | 
 | 848 | 	/* TTL exceeded */ | 
| Sven Eckelmann | 76543d1 | 2011-11-20 15:47:38 +0100 | [diff] [blame] | 849 | 	if (unicast_packet->header.ttl < 2) { | 
| Sven Eckelmann | 86ceb36 | 2012-03-07 09:07:45 +0100 | [diff] [blame] | 850 | 		pr_debug("Warning - can't forward unicast packet from %pM to %pM: ttl exceeded\n", | 
 | 851 | 			 ethhdr->h_source, unicast_packet->dest); | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 852 | 		goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 853 | 	} | 
 | 854 |  | 
 | 855 | 	/* get routing information */ | 
| Sven Eckelmann | da64119 | 2012-05-12 13:48:56 +0200 | [diff] [blame] | 856 | 	orig_node = batadv_orig_hash_find(bat_priv, unicast_packet->dest); | 
| Marek Lindner | 7aadf88 | 2011-02-18 12:28:09 +0000 | [diff] [blame] | 857 |  | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 858 | 	if (!orig_node) | 
| Antonio Quartulli | b5a6f69 | 2011-04-16 11:30:57 +0200 | [diff] [blame] | 859 | 		goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 860 |  | 
| Simon Wunderlich | a4c135c | 2011-01-19 20:01:43 +0000 | [diff] [blame] | 861 | 	/* find_router() increases neigh_nodes refcount if found. */ | 
| Sven Eckelmann | 30d3c51 | 2012-05-12 02:09:36 +0200 | [diff] [blame] | 862 | 	neigh_node = batadv_find_router(bat_priv, orig_node, recv_if); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 863 |  | 
| Marek Lindner | d007260 | 2011-01-19 20:01:44 +0000 | [diff] [blame] | 864 | 	if (!neigh_node) | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 865 | 		goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 866 |  | 
 | 867 | 	/* create a copy of the skb, if needed, to modify it. */ | 
| Antonio Quartulli | 0d12507 | 2012-02-18 11:27:34 +0100 | [diff] [blame] | 868 | 	if (skb_cow(skb, ETH_HLEN) < 0) | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 869 | 		goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 870 |  | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 871 | 	unicast_packet = (struct batadv_unicast_packet *)skb->data; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 872 |  | 
| Sven Eckelmann | acd34af | 2012-06-03 22:19:21 +0200 | [diff] [blame] | 873 | 	if (unicast_packet->header.packet_type == BATADV_UNICAST && | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 874 | 	    atomic_read(&bat_priv->fragmentation) && | 
| Marek Lindner | d007260 | 2011-01-19 20:01:44 +0000 | [diff] [blame] | 875 | 	    skb->len > neigh_node->if_incoming->net_dev->mtu) { | 
| Sven Eckelmann | 88ed1e77 | 2012-05-12 02:09:40 +0200 | [diff] [blame] | 876 | 		ret = batadv_frag_send_skb(skb, bat_priv, | 
 | 877 | 					   neigh_node->if_incoming, | 
 | 878 | 					   neigh_node->addr); | 
| Marek Lindner | d007260 | 2011-01-19 20:01:44 +0000 | [diff] [blame] | 879 | 		goto out; | 
 | 880 | 	} | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 881 |  | 
| Sven Eckelmann | acd34af | 2012-06-03 22:19:21 +0200 | [diff] [blame] | 882 | 	if (unicast_packet->header.packet_type == BATADV_UNICAST_FRAG && | 
| Sven Eckelmann | f0530ee | 2012-05-12 13:48:57 +0200 | [diff] [blame] | 883 | 	    batadv_frag_can_reassemble(skb, | 
 | 884 | 				       neigh_node->if_incoming->net_dev->mtu)) { | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 885 |  | 
| Sven Eckelmann | 88ed1e77 | 2012-05-12 02:09:40 +0200 | [diff] [blame] | 886 | 		ret = batadv_frag_reassemble_skb(skb, bat_priv, &new_skb); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 887 |  | 
 | 888 | 		if (ret == NET_RX_DROP) | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 889 | 			goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 890 |  | 
 | 891 | 		/* packet was buffered for late merge */ | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 892 | 		if (!new_skb) { | 
 | 893 | 			ret = NET_RX_SUCCESS; | 
 | 894 | 			goto out; | 
 | 895 | 		} | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 896 |  | 
 | 897 | 		skb = new_skb; | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 898 | 		unicast_packet = (struct batadv_unicast_packet *)skb->data; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 899 | 	} | 
 | 900 |  | 
 | 901 | 	/* decrement ttl */ | 
| Sven Eckelmann | 76543d1 | 2011-11-20 15:47:38 +0100 | [diff] [blame] | 902 | 	unicast_packet->header.ttl--; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 903 |  | 
| Martin Hundebøll | f821486 | 2012-04-20 17:02:45 +0200 | [diff] [blame] | 904 | 	/* Update stats counter */ | 
| Sven Eckelmann | d69909d | 2012-06-03 22:19:20 +0200 | [diff] [blame] | 905 | 	batadv_inc_counter(bat_priv, BATADV_CNT_FORWARD); | 
 | 906 | 	batadv_add_counter(bat_priv, BATADV_CNT_FORWARD_BYTES, | 
| Martin Hundebøll | f821486 | 2012-04-20 17:02:45 +0200 | [diff] [blame] | 907 | 			   skb->len + ETH_HLEN); | 
 | 908 |  | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 909 | 	/* route it */ | 
| Sven Eckelmann | 9455e34 | 2012-05-12 02:09:37 +0200 | [diff] [blame] | 910 | 	batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 911 | 	ret = NET_RX_SUCCESS; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 912 |  | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 913 | out: | 
 | 914 | 	if (neigh_node) | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 915 | 		batadv_neigh_node_free_ref(neigh_node); | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 916 | 	if (orig_node) | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 917 | 		batadv_orig_node_free_ref(orig_node); | 
| Marek Lindner | 44524fc | 2011-02-10 14:33:53 +0000 | [diff] [blame] | 918 | 	return ret; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 919 | } | 
 | 920 |  | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 921 | static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, | 
| Sven Eckelmann | 63b0103 | 2012-05-16 20:23:13 +0200 | [diff] [blame] | 922 | 				     struct sk_buff *skb) { | 
| Antonio Quartulli | a73105b | 2011-04-27 14:27:44 +0200 | [diff] [blame] | 923 | 	uint8_t curr_ttvn; | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 924 | 	struct batadv_orig_node *orig_node; | 
| Antonio Quartulli | a73105b | 2011-04-27 14:27:44 +0200 | [diff] [blame] | 925 | 	struct ethhdr *ethhdr; | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 926 | 	struct batadv_hard_iface *primary_if; | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 927 | 	struct batadv_unicast_packet *unicast_packet; | 
| Antonio Quartulli | cc47f66 | 2011-04-27 14:27:57 +0200 | [diff] [blame] | 928 | 	bool tt_poss_change; | 
| Sven Eckelmann | 3e34819 | 2012-05-16 20:23:22 +0200 | [diff] [blame] | 929 | 	int is_old_ttvn; | 
| Antonio Quartulli | a73105b | 2011-04-27 14:27:44 +0200 | [diff] [blame] | 930 |  | 
 | 931 | 	/* I could need to modify it */ | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 932 | 	if (skb_cow(skb, sizeof(struct batadv_unicast_packet)) < 0) | 
| Antonio Quartulli | a73105b | 2011-04-27 14:27:44 +0200 | [diff] [blame] | 933 | 		return 0; | 
 | 934 |  | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 935 | 	unicast_packet = (struct batadv_unicast_packet *)skb->data; | 
| Antonio Quartulli | a73105b | 2011-04-27 14:27:44 +0200 | [diff] [blame] | 936 |  | 
| Sven Eckelmann | 3193e8f | 2012-05-12 02:09:42 +0200 | [diff] [blame] | 937 | 	if (batadv_is_my_mac(unicast_packet->dest)) { | 
| Sven Eckelmann | 807736f | 2012-07-15 22:26:51 +0200 | [diff] [blame] | 938 | 		tt_poss_change = bat_priv->tt.poss_change; | 
 | 939 | 		curr_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); | 
| Antonio Quartulli | cc47f66 | 2011-04-27 14:27:57 +0200 | [diff] [blame] | 940 | 	} else { | 
| Sven Eckelmann | da64119 | 2012-05-12 13:48:56 +0200 | [diff] [blame] | 941 | 		orig_node = batadv_orig_hash_find(bat_priv, | 
 | 942 | 						  unicast_packet->dest); | 
| Antonio Quartulli | a73105b | 2011-04-27 14:27:44 +0200 | [diff] [blame] | 943 |  | 
 | 944 | 		if (!orig_node) | 
 | 945 | 			return 0; | 
 | 946 |  | 
 | 947 | 		curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); | 
| Antonio Quartulli | cc47f66 | 2011-04-27 14:27:57 +0200 | [diff] [blame] | 948 | 		tt_poss_change = orig_node->tt_poss_change; | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 949 | 		batadv_orig_node_free_ref(orig_node); | 
| Antonio Quartulli | a73105b | 2011-04-27 14:27:44 +0200 | [diff] [blame] | 950 | 	} | 
 | 951 |  | 
 | 952 | 	/* Check whether I have to reroute the packet */ | 
| Sven Eckelmann | 3e34819 | 2012-05-16 20:23:22 +0200 | [diff] [blame] | 953 | 	is_old_ttvn = batadv_seq_before(unicast_packet->ttvn, curr_ttvn); | 
 | 954 | 	if (is_old_ttvn || tt_poss_change) { | 
| Antonio Quartulli | 8710e26 | 2012-03-16 11:52:31 +0100 | [diff] [blame] | 955 | 		/* check if there is enough data before accessing it */ | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 956 | 		if (pskb_may_pull(skb, sizeof(struct batadv_unicast_packet) + | 
| Antonio Quartulli | 8710e26 | 2012-03-16 11:52:31 +0100 | [diff] [blame] | 957 | 				  ETH_HLEN) < 0) | 
| Antonio Quartulli | a73105b | 2011-04-27 14:27:44 +0200 | [diff] [blame] | 958 | 			return 0; | 
 | 959 |  | 
| Sven Eckelmann | 0aca236 | 2012-06-19 20:26:30 +0200 | [diff] [blame] | 960 | 		ethhdr = (struct ethhdr *)(skb->data + sizeof(*unicast_packet)); | 
| Antonio Quartulli | 3275e7c | 2012-03-16 18:03:28 +0100 | [diff] [blame] | 961 |  | 
 | 962 | 		/* we don't have an updated route for this client, so we should | 
 | 963 | 		 * not try to reroute the packet!! | 
 | 964 | 		 */ | 
| Sven Eckelmann | 08c36d3 | 2012-05-12 02:09:39 +0200 | [diff] [blame] | 965 | 		if (batadv_tt_global_client_is_roaming(bat_priv, | 
 | 966 | 						       ethhdr->h_dest)) | 
| Antonio Quartulli | 3275e7c | 2012-03-16 18:03:28 +0100 | [diff] [blame] | 967 | 			return 1; | 
 | 968 |  | 
| Sven Eckelmann | 08c36d3 | 2012-05-12 02:09:39 +0200 | [diff] [blame] | 969 | 		orig_node = batadv_transtable_search(bat_priv, NULL, | 
 | 970 | 						     ethhdr->h_dest); | 
| Antonio Quartulli | a73105b | 2011-04-27 14:27:44 +0200 | [diff] [blame] | 971 |  | 
 | 972 | 		if (!orig_node) { | 
| Sven Eckelmann | 08c36d3 | 2012-05-12 02:09:39 +0200 | [diff] [blame] | 973 | 			if (!batadv_is_my_client(bat_priv, ethhdr->h_dest)) | 
| Antonio Quartulli | a73105b | 2011-04-27 14:27:44 +0200 | [diff] [blame] | 974 | 				return 0; | 
| Sven Eckelmann | e5d8925 | 2012-05-12 13:48:54 +0200 | [diff] [blame] | 975 | 			primary_if = batadv_primary_if_get_selected(bat_priv); | 
| Antonio Quartulli | a73105b | 2011-04-27 14:27:44 +0200 | [diff] [blame] | 976 | 			if (!primary_if) | 
 | 977 | 				return 0; | 
 | 978 | 			memcpy(unicast_packet->dest, | 
 | 979 | 			       primary_if->net_dev->dev_addr, ETH_ALEN); | 
| Sven Eckelmann | e5d8925 | 2012-05-12 13:48:54 +0200 | [diff] [blame] | 980 | 			batadv_hardif_free_ref(primary_if); | 
| Antonio Quartulli | a73105b | 2011-04-27 14:27:44 +0200 | [diff] [blame] | 981 | 		} else { | 
 | 982 | 			memcpy(unicast_packet->dest, orig_node->orig, | 
 | 983 | 			       ETH_ALEN); | 
| Sven Eckelmann | c67893d | 2012-07-08 18:33:51 +0200 | [diff] [blame] | 984 | 			curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 985 | 			batadv_orig_node_free_ref(orig_node); | 
| Antonio Quartulli | a73105b | 2011-04-27 14:27:44 +0200 | [diff] [blame] | 986 | 		} | 
 | 987 |  | 
| Sven Eckelmann | 39c75a5 | 2012-06-03 22:19:22 +0200 | [diff] [blame] | 988 | 		batadv_dbg(BATADV_DBG_ROUTES, bat_priv, | 
| Sven Eckelmann | 1eda58b | 2012-05-12 13:48:58 +0200 | [diff] [blame] | 989 | 			   "TTVN mismatch (old_ttvn %u new_ttvn %u)! Rerouting unicast packet (for %pM) to %pM\n", | 
 | 990 | 			   unicast_packet->ttvn, curr_ttvn, ethhdr->h_dest, | 
 | 991 | 			   unicast_packet->dest); | 
| Antonio Quartulli | a73105b | 2011-04-27 14:27:44 +0200 | [diff] [blame] | 992 |  | 
 | 993 | 		unicast_packet->ttvn = curr_ttvn; | 
 | 994 | 	} | 
 | 995 | 	return 1; | 
 | 996 | } | 
 | 997 |  | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 998 | int batadv_recv_unicast_packet(struct sk_buff *skb, | 
 | 999 | 			       struct batadv_hard_iface *recv_if) | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1000 | { | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 1001 | 	struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 1002 | 	struct batadv_unicast_packet *unicast_packet; | 
| Sven Eckelmann | 704509b | 2011-05-14 23:14:54 +0200 | [diff] [blame] | 1003 | 	int hdr_size = sizeof(*unicast_packet); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1004 |  | 
| Sven Eckelmann | 63b0103 | 2012-05-16 20:23:13 +0200 | [diff] [blame] | 1005 | 	if (batadv_check_unicast_packet(skb, hdr_size) < 0) | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1006 | 		return NET_RX_DROP; | 
 | 1007 |  | 
| Sven Eckelmann | 63b0103 | 2012-05-16 20:23:13 +0200 | [diff] [blame] | 1008 | 	if (!batadv_check_unicast_ttvn(bat_priv, skb)) | 
| Antonio Quartulli | a73105b | 2011-04-27 14:27:44 +0200 | [diff] [blame] | 1009 | 		return NET_RX_DROP; | 
 | 1010 |  | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 1011 | 	unicast_packet = (struct batadv_unicast_packet *)skb->data; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1012 |  | 
 | 1013 | 	/* packet for me */ | 
| Sven Eckelmann | 3193e8f | 2012-05-12 02:09:42 +0200 | [diff] [blame] | 1014 | 	if (batadv_is_my_mac(unicast_packet->dest)) { | 
| Antonio Quartulli | 3713517 | 2012-07-05 23:38:30 +0200 | [diff] [blame] | 1015 | 		batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size, | 
 | 1016 | 				    NULL); | 
 | 1017 |  | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1018 | 		return NET_RX_SUCCESS; | 
 | 1019 | 	} | 
 | 1020 |  | 
| Sven Eckelmann | 63b0103 | 2012-05-16 20:23:13 +0200 | [diff] [blame] | 1021 | 	return batadv_route_unicast_packet(skb, recv_if); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1022 | } | 
 | 1023 |  | 
| Sven Eckelmann | 30d3c51 | 2012-05-12 02:09:36 +0200 | [diff] [blame] | 1024 | int batadv_recv_ucast_frag_packet(struct sk_buff *skb, | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 1025 | 				  struct batadv_hard_iface *recv_if) | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1026 | { | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 1027 | 	struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 1028 | 	struct batadv_unicast_frag_packet *unicast_packet; | 
| Sven Eckelmann | 704509b | 2011-05-14 23:14:54 +0200 | [diff] [blame] | 1029 | 	int hdr_size = sizeof(*unicast_packet); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1030 | 	struct sk_buff *new_skb = NULL; | 
 | 1031 | 	int ret; | 
 | 1032 |  | 
| Sven Eckelmann | 63b0103 | 2012-05-16 20:23:13 +0200 | [diff] [blame] | 1033 | 	if (batadv_check_unicast_packet(skb, hdr_size) < 0) | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1034 | 		return NET_RX_DROP; | 
 | 1035 |  | 
| Sven Eckelmann | 63b0103 | 2012-05-16 20:23:13 +0200 | [diff] [blame] | 1036 | 	if (!batadv_check_unicast_ttvn(bat_priv, skb)) | 
| Antonio Quartulli | a73105b | 2011-04-27 14:27:44 +0200 | [diff] [blame] | 1037 | 		return NET_RX_DROP; | 
 | 1038 |  | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 1039 | 	unicast_packet = (struct batadv_unicast_frag_packet *)skb->data; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1040 |  | 
 | 1041 | 	/* packet for me */ | 
| Sven Eckelmann | 3193e8f | 2012-05-12 02:09:42 +0200 | [diff] [blame] | 1042 | 	if (batadv_is_my_mac(unicast_packet->dest)) { | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1043 |  | 
| Sven Eckelmann | 88ed1e77 | 2012-05-12 02:09:40 +0200 | [diff] [blame] | 1044 | 		ret = batadv_frag_reassemble_skb(skb, bat_priv, &new_skb); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1045 |  | 
 | 1046 | 		if (ret == NET_RX_DROP) | 
 | 1047 | 			return NET_RX_DROP; | 
 | 1048 |  | 
 | 1049 | 		/* packet was buffered for late merge */ | 
 | 1050 | 		if (!new_skb) | 
 | 1051 | 			return NET_RX_SUCCESS; | 
 | 1052 |  | 
| Sven Eckelmann | 04b482a | 2012-05-12 02:09:38 +0200 | [diff] [blame] | 1053 | 		batadv_interface_rx(recv_if->soft_iface, new_skb, recv_if, | 
| Antonio Quartulli | 3713517 | 2012-07-05 23:38:30 +0200 | [diff] [blame] | 1054 | 				    sizeof(struct batadv_unicast_packet), NULL); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1055 | 		return NET_RX_SUCCESS; | 
 | 1056 | 	} | 
 | 1057 |  | 
| Sven Eckelmann | 63b0103 | 2012-05-16 20:23:13 +0200 | [diff] [blame] | 1058 | 	return batadv_route_unicast_packet(skb, recv_if); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1059 | } | 
 | 1060 |  | 
 | 1061 |  | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 1062 | int batadv_recv_bcast_packet(struct sk_buff *skb, | 
 | 1063 | 			     struct batadv_hard_iface *recv_if) | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1064 | { | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 1065 | 	struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); | 
 | 1066 | 	struct batadv_orig_node *orig_node = NULL; | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 1067 | 	struct batadv_bcast_packet *bcast_packet; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1068 | 	struct ethhdr *ethhdr; | 
| Sven Eckelmann | 704509b | 2011-05-14 23:14:54 +0200 | [diff] [blame] | 1069 | 	int hdr_size = sizeof(*bcast_packet); | 
| Marek Lindner | f3e0008 | 2011-01-25 21:52:11 +0000 | [diff] [blame] | 1070 | 	int ret = NET_RX_DROP; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1071 | 	int32_t seq_diff; | 
 | 1072 |  | 
 | 1073 | 	/* drop packet if it has not necessary minimum size */ | 
 | 1074 | 	if (unlikely(!pskb_may_pull(skb, hdr_size))) | 
| Marek Lindner | f3e0008 | 2011-01-25 21:52:11 +0000 | [diff] [blame] | 1075 | 		goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1076 |  | 
 | 1077 | 	ethhdr = (struct ethhdr *)skb_mac_header(skb); | 
 | 1078 |  | 
 | 1079 | 	/* packet with broadcast indication but unicast recipient */ | 
 | 1080 | 	if (!is_broadcast_ether_addr(ethhdr->h_dest)) | 
| Marek Lindner | f3e0008 | 2011-01-25 21:52:11 +0000 | [diff] [blame] | 1081 | 		goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1082 |  | 
 | 1083 | 	/* packet with broadcast sender address */ | 
 | 1084 | 	if (is_broadcast_ether_addr(ethhdr->h_source)) | 
| Marek Lindner | f3e0008 | 2011-01-25 21:52:11 +0000 | [diff] [blame] | 1085 | 		goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1086 |  | 
 | 1087 | 	/* ignore broadcasts sent by myself */ | 
| Sven Eckelmann | 3193e8f | 2012-05-12 02:09:42 +0200 | [diff] [blame] | 1088 | 	if (batadv_is_my_mac(ethhdr->h_source)) | 
| Marek Lindner | f3e0008 | 2011-01-25 21:52:11 +0000 | [diff] [blame] | 1089 | 		goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1090 |  | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 1091 | 	bcast_packet = (struct batadv_bcast_packet *)skb->data; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1092 |  | 
 | 1093 | 	/* ignore broadcasts originated by myself */ | 
| Sven Eckelmann | 3193e8f | 2012-05-12 02:09:42 +0200 | [diff] [blame] | 1094 | 	if (batadv_is_my_mac(bcast_packet->orig)) | 
| Marek Lindner | f3e0008 | 2011-01-25 21:52:11 +0000 | [diff] [blame] | 1095 | 		goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1096 |  | 
| Sven Eckelmann | 76543d1 | 2011-11-20 15:47:38 +0100 | [diff] [blame] | 1097 | 	if (bcast_packet->header.ttl < 2) | 
| Marek Lindner | f3e0008 | 2011-01-25 21:52:11 +0000 | [diff] [blame] | 1098 | 		goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1099 |  | 
| Sven Eckelmann | da64119 | 2012-05-12 13:48:56 +0200 | [diff] [blame] | 1100 | 	orig_node = batadv_orig_hash_find(bat_priv, bcast_packet->orig); | 
| Marek Lindner | f3e0008 | 2011-01-25 21:52:11 +0000 | [diff] [blame] | 1101 |  | 
 | 1102 | 	if (!orig_node) | 
| Antonio Quartulli | b5a6f69 | 2011-04-16 11:30:57 +0200 | [diff] [blame] | 1103 | 		goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1104 |  | 
| Marek Lindner | f3e0008 | 2011-01-25 21:52:11 +0000 | [diff] [blame] | 1105 | 	spin_lock_bh(&orig_node->bcast_seqno_lock); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1106 |  | 
 | 1107 | 	/* check whether the packet is a duplicate */ | 
| Sven Eckelmann | 9b4a115 | 2012-05-12 13:48:53 +0200 | [diff] [blame] | 1108 | 	if (batadv_test_bit(orig_node->bcast_bits, orig_node->last_bcast_seqno, | 
 | 1109 | 			    ntohl(bcast_packet->seqno))) | 
| Marek Lindner | f3e0008 | 2011-01-25 21:52:11 +0000 | [diff] [blame] | 1110 | 		goto spin_unlock; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1111 |  | 
 | 1112 | 	seq_diff = ntohl(bcast_packet->seqno) - orig_node->last_bcast_seqno; | 
 | 1113 |  | 
 | 1114 | 	/* check whether the packet is old and the host just restarted. */ | 
| Sven Eckelmann | 30d3c51 | 2012-05-12 02:09:36 +0200 | [diff] [blame] | 1115 | 	if (batadv_window_protected(bat_priv, seq_diff, | 
 | 1116 | 				    &orig_node->bcast_seqno_reset)) | 
| Marek Lindner | f3e0008 | 2011-01-25 21:52:11 +0000 | [diff] [blame] | 1117 | 		goto spin_unlock; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1118 |  | 
 | 1119 | 	/* mark broadcast in flood history, update window position | 
| Sven Eckelmann | 9cfc7bd | 2012-05-12 02:09:43 +0200 | [diff] [blame] | 1120 | 	 * if required. | 
 | 1121 | 	 */ | 
| Sven Eckelmann | 0f5f932 | 2012-05-12 02:09:25 +0200 | [diff] [blame] | 1122 | 	if (batadv_bit_get_packet(bat_priv, orig_node->bcast_bits, seq_diff, 1)) | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1123 | 		orig_node->last_bcast_seqno = ntohl(bcast_packet->seqno); | 
 | 1124 |  | 
| Marek Lindner | f3e0008 | 2011-01-25 21:52:11 +0000 | [diff] [blame] | 1125 | 	spin_unlock_bh(&orig_node->bcast_seqno_lock); | 
| Marek Lindner | f3e0008 | 2011-01-25 21:52:11 +0000 | [diff] [blame] | 1126 |  | 
| Simon Wunderlich | fe2da6f | 2012-01-22 20:00:24 +0100 | [diff] [blame] | 1127 | 	/* check whether this has been sent by another originator before */ | 
| Sven Eckelmann | 08adf15 | 2012-05-12 13:38:47 +0200 | [diff] [blame] | 1128 | 	if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, hdr_size)) | 
| Simon Wunderlich | fe2da6f | 2012-01-22 20:00:24 +0100 | [diff] [blame] | 1129 | 		goto out; | 
 | 1130 |  | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1131 | 	/* rebroadcast packet */ | 
| Sven Eckelmann | 9455e34 | 2012-05-12 02:09:37 +0200 | [diff] [blame] | 1132 | 	batadv_add_bcast_packet_to_list(bat_priv, skb, 1); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1133 |  | 
| Simon Wunderlich | 2372138 | 2012-01-22 20:00:19 +0100 | [diff] [blame] | 1134 | 	/* don't hand the broadcast up if it is from an originator | 
 | 1135 | 	 * from the same backbone. | 
 | 1136 | 	 */ | 
| Sven Eckelmann | 08adf15 | 2012-05-12 13:38:47 +0200 | [diff] [blame] | 1137 | 	if (batadv_bla_is_backbone_gw(skb, orig_node, hdr_size)) | 
| Simon Wunderlich | 2372138 | 2012-01-22 20:00:19 +0100 | [diff] [blame] | 1138 | 		goto out; | 
 | 1139 |  | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1140 | 	/* broadcast for me */ | 
| Antonio Quartulli | 3713517 | 2012-07-05 23:38:30 +0200 | [diff] [blame] | 1141 | 	batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size, | 
 | 1142 | 			    orig_node); | 
| Marek Lindner | f3e0008 | 2011-01-25 21:52:11 +0000 | [diff] [blame] | 1143 | 	ret = NET_RX_SUCCESS; | 
 | 1144 | 	goto out; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1145 |  | 
| Marek Lindner | f3e0008 | 2011-01-25 21:52:11 +0000 | [diff] [blame] | 1146 | spin_unlock: | 
 | 1147 | 	spin_unlock_bh(&orig_node->bcast_seqno_lock); | 
| Marek Lindner | f3e0008 | 2011-01-25 21:52:11 +0000 | [diff] [blame] | 1148 | out: | 
 | 1149 | 	if (orig_node) | 
| Sven Eckelmann | 7d211ef | 2012-05-12 02:09:34 +0200 | [diff] [blame] | 1150 | 		batadv_orig_node_free_ref(orig_node); | 
| Marek Lindner | f3e0008 | 2011-01-25 21:52:11 +0000 | [diff] [blame] | 1151 | 	return ret; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1152 | } | 
 | 1153 |  | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 1154 | int batadv_recv_vis_packet(struct sk_buff *skb, | 
 | 1155 | 			   struct batadv_hard_iface *recv_if) | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1156 | { | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 1157 | 	struct batadv_vis_packet *vis_packet; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1158 | 	struct ethhdr *ethhdr; | 
| Sven Eckelmann | 56303d3 | 2012-06-05 22:31:31 +0200 | [diff] [blame] | 1159 | 	struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); | 
| Sven Eckelmann | 704509b | 2011-05-14 23:14:54 +0200 | [diff] [blame] | 1160 | 	int hdr_size = sizeof(*vis_packet); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1161 |  | 
 | 1162 | 	/* keep skb linear */ | 
 | 1163 | 	if (skb_linearize(skb) < 0) | 
 | 1164 | 		return NET_RX_DROP; | 
 | 1165 |  | 
 | 1166 | 	if (unlikely(!pskb_may_pull(skb, hdr_size))) | 
 | 1167 | 		return NET_RX_DROP; | 
 | 1168 |  | 
| Sven Eckelmann | 9641269 | 2012-06-05 22:31:30 +0200 | [diff] [blame] | 1169 | 	vis_packet = (struct batadv_vis_packet *)skb->data; | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1170 | 	ethhdr = (struct ethhdr *)skb_mac_header(skb); | 
 | 1171 |  | 
 | 1172 | 	/* not for me */ | 
| Sven Eckelmann | 3193e8f | 2012-05-12 02:09:42 +0200 | [diff] [blame] | 1173 | 	if (!batadv_is_my_mac(ethhdr->h_dest)) | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1174 | 		return NET_RX_DROP; | 
 | 1175 |  | 
 | 1176 | 	/* ignore own packets */ | 
| Sven Eckelmann | 3193e8f | 2012-05-12 02:09:42 +0200 | [diff] [blame] | 1177 | 	if (batadv_is_my_mac(vis_packet->vis_orig)) | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1178 | 		return NET_RX_DROP; | 
 | 1179 |  | 
| Sven Eckelmann | 3193e8f | 2012-05-12 02:09:42 +0200 | [diff] [blame] | 1180 | 	if (batadv_is_my_mac(vis_packet->sender_orig)) | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1181 | 		return NET_RX_DROP; | 
 | 1182 |  | 
 | 1183 | 	switch (vis_packet->vis_type) { | 
| Sven Eckelmann | acd34af | 2012-06-03 22:19:21 +0200 | [diff] [blame] | 1184 | 	case BATADV_VIS_TYPE_SERVER_SYNC: | 
| Sven Eckelmann | d0f714f | 2012-05-12 02:09:41 +0200 | [diff] [blame] | 1185 | 		batadv_receive_server_sync_packet(bat_priv, vis_packet, | 
 | 1186 | 						  skb_headlen(skb)); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1187 | 		break; | 
 | 1188 |  | 
| Sven Eckelmann | acd34af | 2012-06-03 22:19:21 +0200 | [diff] [blame] | 1189 | 	case BATADV_VIS_TYPE_CLIENT_UPDATE: | 
| Sven Eckelmann | d0f714f | 2012-05-12 02:09:41 +0200 | [diff] [blame] | 1190 | 		batadv_receive_client_update_packet(bat_priv, vis_packet, | 
 | 1191 | 						    skb_headlen(skb)); | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1192 | 		break; | 
 | 1193 |  | 
 | 1194 | 	default:	/* ignore unknown packet */ | 
 | 1195 | 		break; | 
 | 1196 | 	} | 
 | 1197 |  | 
 | 1198 | 	/* We take a copy of the data in the packet, so we should | 
| Sven Eckelmann | 9cfc7bd | 2012-05-12 02:09:43 +0200 | [diff] [blame] | 1199 | 	 * always free the skbuf. | 
 | 1200 | 	 */ | 
| Sven Eckelmann | c6c8fea | 2010-12-13 11:19:28 +0000 | [diff] [blame] | 1201 | 	return NET_RX_DROP; | 
 | 1202 | } |