aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/soft-interface.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/batman-adv/soft-interface.c')
-rw-r--r--net/batman-adv/soft-interface.c111
1 files changed, 66 insertions, 45 deletions
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index a8f99d1486c0..f82c267e1886 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -1,4 +1,4 @@
1/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors: 1/* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors:
2 * 2 *
3 * Marek Lindner, Simon Wunderlich 3 * Marek Lindner, Simon Wunderlich
4 * 4 *
@@ -12,9 +12,7 @@
12 * General Public License for more details. 12 * General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 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 15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA
18 */ 16 */
19 17
20#include "main.h" 18#include "main.h"
@@ -121,7 +119,7 @@ static int batadv_interface_set_mac_addr(struct net_device *dev, void *p)
121 batadv_tt_local_remove(bat_priv, old_addr, BATADV_NO_FLAGS, 119 batadv_tt_local_remove(bat_priv, old_addr, BATADV_NO_FLAGS,
122 "mac address changed", false); 120 "mac address changed", false);
123 batadv_tt_local_add(dev, addr->sa_data, BATADV_NO_FLAGS, 121 batadv_tt_local_add(dev, addr->sa_data, BATADV_NO_FLAGS,
124 BATADV_NULL_IFINDEX); 122 BATADV_NULL_IFINDEX, BATADV_NO_MARK);
125 } 123 }
126 124
127 return 0; 125 return 0;
@@ -162,6 +160,8 @@ static int batadv_interface_tx(struct sk_buff *skb,
162 0x00, 0x00}; 160 0x00, 0x00};
163 static const uint8_t ectp_addr[ETH_ALEN] = {0xCF, 0x00, 0x00, 0x00, 161 static const uint8_t ectp_addr[ETH_ALEN] = {0xCF, 0x00, 0x00, 0x00,
164 0x00, 0x00}; 162 0x00, 0x00};
163 enum batadv_dhcp_recipient dhcp_rcp = BATADV_DHCP_NO;
164 uint8_t *dst_hint = NULL, chaddr[ETH_ALEN];
165 struct vlan_ethhdr *vhdr; 165 struct vlan_ethhdr *vhdr;
166 unsigned int header_len = 0; 166 unsigned int header_len = 0;
167 int data_len = skb->len, ret; 167 int data_len = skb->len, ret;
@@ -169,6 +169,7 @@ static int batadv_interface_tx(struct sk_buff *skb,
169 bool do_bcast = false, client_added; 169 bool do_bcast = false, client_added;
170 unsigned short vid; 170 unsigned short vid;
171 uint32_t seqno; 171 uint32_t seqno;
172 int gw_mode;
172 173
173 if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) 174 if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
174 goto dropped; 175 goto dropped;
@@ -198,7 +199,8 @@ static int batadv_interface_tx(struct sk_buff *skb,
198 /* Register the client MAC in the transtable */ 199 /* Register the client MAC in the transtable */
199 if (!is_multicast_ether_addr(ethhdr->h_source)) { 200 if (!is_multicast_ether_addr(ethhdr->h_source)) {
200 client_added = batadv_tt_local_add(soft_iface, ethhdr->h_source, 201 client_added = batadv_tt_local_add(soft_iface, ethhdr->h_source,
201 vid, skb->skb_iif); 202 vid, skb->skb_iif,
203 skb->mark);
202 if (!client_added) 204 if (!client_added)
203 goto dropped; 205 goto dropped;
204 } 206 }
@@ -215,36 +217,39 @@ static int batadv_interface_tx(struct sk_buff *skb,
215 if (batadv_compare_eth(ethhdr->h_dest, ectp_addr)) 217 if (batadv_compare_eth(ethhdr->h_dest, ectp_addr))
216 goto dropped; 218 goto dropped;
217 219
220 gw_mode = atomic_read(&bat_priv->gw_mode);
218 if (is_multicast_ether_addr(ethhdr->h_dest)) { 221 if (is_multicast_ether_addr(ethhdr->h_dest)) {
219 do_bcast = true; 222 /* if gw mode is off, broadcast every packet */
220 223 if (gw_mode == BATADV_GW_MODE_OFF) {
221 switch (atomic_read(&bat_priv->gw_mode)) { 224 do_bcast = true;
222 case BATADV_GW_MODE_SERVER: 225 goto send;
223 /* gateway servers should not send dhcp
224 * requests into the mesh
225 */
226 ret = batadv_gw_is_dhcp_target(skb, &header_len);
227 if (ret)
228 goto dropped;
229 break;
230 case BATADV_GW_MODE_CLIENT:
231 /* gateway clients should send dhcp requests
232 * via unicast to their gateway
233 */
234 ret = batadv_gw_is_dhcp_target(skb, &header_len);
235 if (ret)
236 do_bcast = false;
237 break;
238 case BATADV_GW_MODE_OFF:
239 default:
240 break;
241 } 226 }
242 227
243 /* reminder: ethhdr might have become unusable from here on 228 dhcp_rcp = batadv_gw_dhcp_recipient_get(skb, &header_len,
244 * (batadv_gw_is_dhcp_target() might have reallocated skb data) 229 chaddr);
230 /* skb->data may have been modified by
231 * batadv_gw_dhcp_recipient_get()
245 */ 232 */
233 ethhdr = (struct ethhdr *)skb->data;
234 /* if gw_mode is on, broadcast any non-DHCP message.
235 * All the DHCP packets are going to be sent as unicast
236 */
237 if (dhcp_rcp == BATADV_DHCP_NO) {
238 do_bcast = true;
239 goto send;
240 }
241
242 if (dhcp_rcp == BATADV_DHCP_TO_CLIENT)
243 dst_hint = chaddr;
244 else if ((gw_mode == BATADV_GW_MODE_SERVER) &&
245 (dhcp_rcp == BATADV_DHCP_TO_SERVER))
246 /* gateways should not forward any DHCP message if
247 * directed to a DHCP server
248 */
249 goto dropped;
246 } 250 }
247 251
252send:
248 batadv_skb_set_priority(skb, 0); 253 batadv_skb_set_priority(skb, 0);
249 254
250 /* ethernet packet should be broadcasted */ 255 /* ethernet packet should be broadcasted */
@@ -290,22 +295,22 @@ static int batadv_interface_tx(struct sk_buff *skb,
290 295
291 /* unicast packet */ 296 /* unicast packet */
292 } else { 297 } else {
293 if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_OFF) { 298 /* DHCP packets going to a server will use the GW feature */
299 if (dhcp_rcp == BATADV_DHCP_TO_SERVER) {
294 ret = batadv_gw_out_of_range(bat_priv, skb); 300 ret = batadv_gw_out_of_range(bat_priv, skb);
295 if (ret) 301 if (ret)
296 goto dropped; 302 goto dropped;
297 }
298
299 if (batadv_dat_snoop_outgoing_arp_request(bat_priv, skb))
300 goto dropped;
301
302 batadv_dat_snoop_outgoing_arp_reply(bat_priv, skb);
303
304 if (is_multicast_ether_addr(ethhdr->h_dest))
305 ret = batadv_send_skb_via_gw(bat_priv, skb, vid); 303 ret = batadv_send_skb_via_gw(bat_priv, skb, vid);
306 else 304 } else {
307 ret = batadv_send_skb_via_tt(bat_priv, skb, vid); 305 if (batadv_dat_snoop_outgoing_arp_request(bat_priv,
306 skb))
307 goto dropped;
308 308
309 batadv_dat_snoop_outgoing_arp_reply(bat_priv, skb);
310
311 ret = batadv_send_skb_via_tt(bat_priv, skb, dst_hint,
312 vid);
313 }
309 if (ret == NET_XMIT_DROP) 314 if (ret == NET_XMIT_DROP)
310 goto dropped_freed; 315 goto dropped_freed;
311 } 316 }
@@ -394,9 +399,23 @@ void batadv_interface_rx(struct net_device *soft_iface,
394 batadv_tt_add_temporary_global_entry(bat_priv, orig_node, 399 batadv_tt_add_temporary_global_entry(bat_priv, orig_node,
395 ethhdr->h_source, vid); 400 ethhdr->h_source, vid);
396 401
397 if (batadv_is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest, 402 if (is_multicast_ether_addr(ethhdr->h_dest)) {
398 vid)) 403 /* set the mark on broadcast packets if AP isolation is ON and
404 * the packet is coming from an "isolated" client
405 */
406 if (batadv_vlan_ap_isola_get(bat_priv, vid) &&
407 batadv_tt_global_is_isolated(bat_priv, ethhdr->h_source,
408 vid)) {
409 /* save bits in skb->mark not covered by the mask and
410 * apply the mark on the rest
411 */
412 skb->mark &= ~bat_priv->isolation_mark_mask;
413 skb->mark |= bat_priv->isolation_mark;
414 }
415 } else if (batadv_is_ap_isolated(bat_priv, ethhdr->h_source,
416 ethhdr->h_dest, vid)) {
399 goto dropped; 417 goto dropped;
418 }
400 419
401 netif_rx(skb); 420 netif_rx(skb);
402 goto out; 421 goto out;
@@ -485,7 +504,7 @@ int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid)
485 */ 504 */
486 batadv_tt_local_add(bat_priv->soft_iface, 505 batadv_tt_local_add(bat_priv->soft_iface,
487 bat_priv->soft_iface->dev_addr, vid, 506 bat_priv->soft_iface->dev_addr, vid,
488 BATADV_NULL_IFINDEX); 507 BATADV_NULL_IFINDEX, BATADV_NO_MARK);
489 508
490 spin_lock_bh(&bat_priv->softif_vlan_list_lock); 509 spin_lock_bh(&bat_priv->softif_vlan_list_lock);
491 hlist_add_head_rcu(&vlan->list, &bat_priv->softif_vlan_list); 510 hlist_add_head_rcu(&vlan->list, &bat_priv->softif_vlan_list);
@@ -678,7 +697,7 @@ static int batadv_softif_init_late(struct net_device *dev)
678 atomic_set(&bat_priv->gw.bandwidth_down, 100); 697 atomic_set(&bat_priv->gw.bandwidth_down, 100);
679 atomic_set(&bat_priv->gw.bandwidth_up, 20); 698 atomic_set(&bat_priv->gw.bandwidth_up, 20);
680 atomic_set(&bat_priv->orig_interval, 1000); 699 atomic_set(&bat_priv->orig_interval, 1000);
681 atomic_set(&bat_priv->hop_penalty, 30); 700 atomic_set(&bat_priv->hop_penalty, 15);
682#ifdef CONFIG_BATMAN_ADV_DEBUG 701#ifdef CONFIG_BATMAN_ADV_DEBUG
683 atomic_set(&bat_priv->log_level, 0); 702 atomic_set(&bat_priv->log_level, 0);
684#endif 703#endif
@@ -697,6 +716,8 @@ static int batadv_softif_init_late(struct net_device *dev)
697#endif 716#endif
698 bat_priv->tt.last_changeset = NULL; 717 bat_priv->tt.last_changeset = NULL;
699 bat_priv->tt.last_changeset_len = 0; 718 bat_priv->tt.last_changeset_len = 0;
719 bat_priv->isolation_mark = 0;
720 bat_priv->isolation_mark_mask = 0;
700 721
701 /* randomize initial seqno to avoid collision */ 722 /* randomize initial seqno to avoid collision */
702 get_random_bytes(&random_seqno, sizeof(random_seqno)); 723 get_random_bytes(&random_seqno, sizeof(random_seqno));