diff options
Diffstat (limited to 'net/batman-adv/soft-interface.c')
-rw-r--r-- | net/batman-adv/soft-interface.c | 111 |
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 | ||
252 | send: | ||
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)); |