2017-01-01 02:00:00 +03:00
/* Copyright (C) 2007-2017 B.A.T.M.A.N. contributors:
2010-12-13 14:19:28 +03:00
*
* Marek Lindner , Simon Wunderlich
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2013-11-03 23:40:48 +04:00
* along with this program ; if not , see < http : //www.gnu.org/licenses/>.
2010-12-13 14:19:28 +03:00
*/
2015-04-17 20:40:28 +03:00
# include "main.h"
# include <linux/atomic.h>
# include <linux/bug.h>
# include <linux/byteorder/generic.h>
2012-10-17 23:10:39 +04:00
# include <linux/crc32c.h>
2015-04-17 20:40:28 +03:00
# include <linux/errno.h>
# include <linux/fs.h>
2016-10-29 14:56:23 +03:00
# include <linux/genetlink.h>
2015-04-17 20:40:28 +03:00
# include <linux/if_ether.h>
2013-07-29 19:56:44 +04:00
# include <linux/if_vlan.h>
2015-04-17 20:40:28 +03:00
# include <linux/init.h>
# include <linux/ip.h>
# include <linux/ipv6.h>
# include <linux/kernel.h>
2016-01-16 12:29:48 +03:00
# include <linux/kref.h>
2015-04-17 20:40:28 +03:00
# include <linux/list.h>
# include <linux/module.h>
# include <linux/netdevice.h>
2016-05-16 00:48:31 +03:00
# include <linux/printk.h>
2015-04-17 20:40:28 +03:00
# include <linux/rculist.h>
# include <linux/rcupdate.h>
# include <linux/seq_file.h>
# include <linux/skbuff.h>
# include <linux/spinlock.h>
# include <linux/stddef.h>
# include <linux/string.h>
# include <linux/workqueue.h>
2013-07-29 19:56:44 +04:00
# include <net/dsfield.h>
2015-04-17 20:40:28 +03:00
# include <net/rtnetlink.h>
2016-10-29 14:56:23 +03:00
# include <uapi/linux/batman_adv.h>
2015-04-17 20:40:28 +03:00
# include "bat_algo.h"
2016-05-15 12:07:46 +03:00
# include "bat_iv_ogm.h"
# include "bat_v.h"
2015-04-17 20:40:28 +03:00
# include "bridge_loop_avoidance.h"
2012-06-11 01:58:51 +04:00
# include "debugfs.h"
2015-04-17 20:40:28 +03:00
# include "distributed-arp-table.h"
# include "gateway_client.h"
# include "gateway_common.h"
# include "hard-interface.h"
# include "icmp_socket.h"
2016-05-16 00:48:31 +03:00
# include "log.h"
2015-04-17 20:40:28 +03:00
# include "multicast.h"
2016-05-09 19:41:08 +03:00
# include "netlink.h"
2015-04-17 20:40:28 +03:00
# include "network-coding.h"
# include "originator.h"
# include "packet.h"
2010-12-13 14:19:28 +03:00
# include "routing.h"
# include "send.h"
# include "soft-interface.h"
2016-05-05 14:09:43 +03:00
# include "tp_meter.h"
2010-12-13 14:19:28 +03:00
# include "translation-table.h"
2011-05-03 13:51:38 +04:00
/* List manipulations on hardif_list have to be rtnl_lock()'ed,
2012-05-12 04:09:43 +04:00
* list traversals just rcu - locked
*/
2012-05-12 04:09:42 +04:00
struct list_head batadv_hardif_list ;
2017-09-30 10:24:28 +03:00
static int ( * batadv_rx_handler [ 256 ] ) ( struct sk_buff * skb ,
struct batadv_hard_iface * recv_if ) ;
2010-12-13 14:19:28 +03:00
2012-05-12 04:09:42 +04:00
unsigned char batadv_broadcast_addr [ ] = { 0xff , 0xff , 0xff , 0xff , 0xff , 0xff } ;
2010-12-13 14:19:28 +03:00
2012-05-12 04:09:42 +04:00
struct workqueue_struct * batadv_event_workqueue ;
2010-12-13 14:19:28 +03:00
2012-05-16 22:23:19 +04:00
static void batadv_recv_handler_init ( void ) ;
2012-03-01 11:35:17 +04:00
2012-05-16 22:23:19 +04:00
static int __init batadv_init ( void )
2010-12-13 14:19:28 +03:00
{
2016-06-25 17:44:06 +03:00
int ret ;
ret = batadv_tt_cache_init ( ) ;
if ( ret < 0 )
return ret ;
2012-05-12 04:09:42 +04:00
INIT_LIST_HEAD ( & batadv_hardif_list ) ;
2016-05-15 12:07:44 +03:00
batadv_algo_init ( ) ;
2011-11-28 13:40:17 +04:00
2012-05-16 22:23:19 +04:00
batadv_recv_handler_init ( ) ;
2012-03-01 11:35:17 +04:00
2016-01-16 11:40:09 +03:00
batadv_v_init ( ) ;
2012-05-12 04:09:22 +04:00
batadv_iv_init ( ) ;
2013-09-27 20:03:39 +04:00
batadv_nc_init ( ) ;
2016-05-05 14:09:43 +03:00
batadv_tp_meter_init ( ) ;
2010-12-13 14:19:28 +03:00
2012-05-12 04:09:42 +04:00
batadv_event_workqueue = create_singlethread_workqueue ( " bat_events " ) ;
if ( ! batadv_event_workqueue )
2016-06-25 17:44:06 +03:00
goto err_create_wq ;
2010-12-13 14:19:28 +03:00
2012-05-12 04:09:33 +04:00
batadv_socket_init ( ) ;
2012-05-12 04:09:23 +04:00
batadv_debugfs_init ( ) ;
2010-12-13 14:19:28 +03:00
2012-05-12 04:09:31 +04:00
register_netdevice_notifier ( & batadv_hard_if_notifier ) ;
2013-02-11 13:10:26 +04:00
rtnl_link_register ( & batadv_link_ops ) ;
2016-05-09 19:41:08 +03:00
batadv_netlink_register ( ) ;
2010-12-13 14:19:28 +03:00
2012-03-07 12:07:45 +04:00
pr_info ( " B.A.T.M.A.N. advanced %s (compatibility version %i) loaded \n " ,
2012-06-04 00:19:17 +04:00
BATADV_SOURCE_VERSION , BATADV_COMPAT_VERSION ) ;
2010-12-13 14:19:28 +03:00
return 0 ;
2016-06-25 17:44:06 +03:00
err_create_wq :
batadv_tt_cache_destroy ( ) ;
return - ENOMEM ;
2010-12-13 14:19:28 +03:00
}
2012-05-16 22:23:19 +04:00
static void __exit batadv_exit ( void )
2010-12-13 14:19:28 +03:00
{
2012-05-12 04:09:23 +04:00
batadv_debugfs_destroy ( ) ;
2016-05-09 19:41:08 +03:00
batadv_netlink_unregister ( ) ;
2013-02-11 13:10:26 +04:00
rtnl_link_unregister ( & batadv_link_ops ) ;
2012-05-12 04:09:31 +04:00
unregister_netdevice_notifier ( & batadv_hard_if_notifier ) ;
batadv_hardif_remove_interfaces ( ) ;
2010-12-13 14:19:28 +03:00
2012-05-12 04:09:42 +04:00
flush_workqueue ( batadv_event_workqueue ) ;
destroy_workqueue ( batadv_event_workqueue ) ;
batadv_event_workqueue = NULL ;
2010-12-13 14:19:28 +03:00
rcu_barrier ( ) ;
2016-06-25 17:44:06 +03:00
batadv_tt_cache_destroy ( ) ;
2010-12-13 14:19:28 +03:00
}
2012-05-12 04:09:42 +04:00
int batadv_mesh_init ( struct net_device * soft_iface )
2010-12-13 14:19:28 +03:00
{
2012-06-06 00:31:31 +04:00
struct batadv_priv * bat_priv = netdev_priv ( soft_iface ) ;
2012-05-05 15:27:28 +04:00
int ret ;
2010-12-13 14:19:28 +03:00
spin_lock_init ( & bat_priv - > forw_bat_list_lock ) ;
spin_lock_init ( & bat_priv - > forw_bcast_list_lock ) ;
2012-07-16 00:26:51 +04:00
spin_lock_init ( & bat_priv - > tt . changes_list_lock ) ;
spin_lock_init ( & bat_priv - > tt . req_list_lock ) ;
spin_lock_init ( & bat_priv - > tt . roam_list_lock ) ;
spin_lock_init ( & bat_priv - > tt . last_changeset_lock ) ;
2013-07-31 00:16:24 +04:00
spin_lock_init ( & bat_priv - > tt . commit_lock ) ;
2012-07-16 00:26:51 +04:00
spin_lock_init ( & bat_priv - > gw . list_lock ) ;
2014-02-15 20:47:53 +04:00
# ifdef CONFIG_BATMAN_ADV_MCAST
spin_lock_init ( & bat_priv - > mcast . want_lists_lock ) ;
# endif
2013-04-23 17:39:57 +04:00
spin_lock_init ( & bat_priv - > tvlv . container_list_lock ) ;
spin_lock_init ( & bat_priv - > tvlv . handler_list_lock ) ;
2013-07-02 13:04:34 +04:00
spin_lock_init ( & bat_priv - > softif_vlan_list_lock ) ;
2016-05-05 14:09:43 +03:00
spin_lock_init ( & bat_priv - > tp_list_lock ) ;
2010-12-13 14:19:28 +03:00
INIT_HLIST_HEAD ( & bat_priv - > forw_bat_list ) ;
INIT_HLIST_HEAD ( & bat_priv - > forw_bcast_list ) ;
2016-07-27 13:31:08 +03:00
INIT_HLIST_HEAD ( & bat_priv - > gw . gateway_list ) ;
2014-02-15 20:47:53 +04:00
# ifdef CONFIG_BATMAN_ADV_MCAST
INIT_HLIST_HEAD ( & bat_priv - > mcast . want_all_unsnoopables_list ) ;
2014-02-15 20:47:54 +04:00
INIT_HLIST_HEAD ( & bat_priv - > mcast . want_all_ipv4_list ) ;
INIT_HLIST_HEAD ( & bat_priv - > mcast . want_all_ipv6_list ) ;
2014-02-15 20:47:53 +04:00
# endif
2012-07-16 00:26:51 +04:00
INIT_LIST_HEAD ( & bat_priv - > tt . changes_list ) ;
2015-06-28 17:16:06 +03:00
INIT_HLIST_HEAD ( & bat_priv - > tt . req_list ) ;
2012-07-16 00:26:51 +04:00
INIT_LIST_HEAD ( & bat_priv - > tt . roam_list ) ;
2014-02-15 20:47:49 +04:00
# ifdef CONFIG_BATMAN_ADV_MCAST
INIT_HLIST_HEAD ( & bat_priv - > mcast . mla_list ) ;
# endif
2013-04-23 17:39:57 +04:00
INIT_HLIST_HEAD ( & bat_priv - > tvlv . container_list ) ;
INIT_HLIST_HEAD ( & bat_priv - > tvlv . handler_list ) ;
2013-07-02 13:04:34 +04:00
INIT_HLIST_HEAD ( & bat_priv - > softif_vlan_list ) ;
2016-05-05 14:09:43 +03:00
INIT_HLIST_HEAD ( & bat_priv - > tp_list ) ;
2010-12-13 14:19:28 +03:00
2016-01-16 11:40:12 +03:00
ret = batadv_v_mesh_init ( bat_priv ) ;
if ( ret < 0 )
goto err ;
2012-05-12 04:09:34 +04:00
ret = batadv_originator_init ( bat_priv ) ;
2012-05-05 15:27:28 +04:00
if ( ret < 0 )
2010-12-13 14:19:28 +03:00
goto err ;
2012-05-12 04:09:39 +04:00
ret = batadv_tt_init ( bat_priv ) ;
2012-05-05 15:27:28 +04:00
if ( ret < 0 )
2010-12-13 14:19:28 +03:00
goto err ;
2012-05-12 15:38:47 +04:00
ret = batadv_bla_init ( bat_priv ) ;
2012-05-05 15:27:28 +04:00
if ( ret < 0 )
2012-01-22 23:00:19 +04:00
goto err ;
2012-06-30 22:01:19 +04:00
ret = batadv_dat_init ( bat_priv ) ;
if ( ret < 0 )
goto err ;
2013-09-27 20:03:39 +04:00
ret = batadv_nc_mesh_init ( bat_priv ) ;
2013-01-25 14:12:38 +04:00
if ( ret < 0 )
goto err ;
2013-04-23 17:39:58 +04:00
batadv_gw_init ( bat_priv ) ;
2014-02-15 20:47:51 +04:00
batadv_mcast_init ( bat_priv ) ;
2013-04-23 17:39:58 +04:00
2012-07-16 00:26:51 +04:00
atomic_set ( & bat_priv - > gw . reselect , 0 ) ;
2012-06-04 00:19:22 +04:00
atomic_set ( & bat_priv - > mesh_state , BATADV_MESH_ACTIVE ) ;
2012-05-05 15:27:28 +04:00
return 0 ;
2010-12-13 14:19:28 +03:00
err :
2012-05-12 04:09:42 +04:00
batadv_mesh_free ( soft_iface ) ;
2012-05-05 15:27:28 +04:00
return ret ;
2010-12-13 14:19:28 +03:00
}
2012-05-12 04:09:42 +04:00
void batadv_mesh_free ( struct net_device * soft_iface )
2010-12-13 14:19:28 +03:00
{
2012-06-06 00:31:31 +04:00
struct batadv_priv * bat_priv = netdev_priv ( soft_iface ) ;
2010-12-13 14:19:28 +03:00
2012-06-04 00:19:22 +04:00
atomic_set ( & bat_priv - > mesh_state , BATADV_MESH_DEACTIVATING ) ;
2010-12-13 14:19:28 +03:00
2012-05-12 04:09:37 +04:00
batadv_purge_outstanding_packets ( bat_priv , NULL ) ;
2010-12-13 14:19:28 +03:00
2015-08-03 20:13:58 +03:00
batadv_gw_node_free ( bat_priv ) ;
2016-01-16 11:40:12 +03:00
batadv_v_mesh_free ( bat_priv ) ;
2013-09-27 20:03:39 +04:00
batadv_nc_mesh_free ( bat_priv ) ;
2013-05-07 03:06:18 +04:00
batadv_dat_free ( bat_priv ) ;
batadv_bla_free ( bat_priv ) ;
2010-12-13 14:19:28 +03:00
2014-02-15 20:47:49 +04:00
batadv_mcast_free ( bat_priv ) ;
2013-05-07 03:06:18 +04:00
/* Free the TT and the originator tables only after having terminated
* all the other depending components which may use these structures for
* their purposes .
*/
2012-05-12 04:09:39 +04:00
batadv_tt_free ( bat_priv ) ;
2010-12-13 14:19:28 +03:00
2013-05-07 03:06:18 +04:00
/* Since the originator table clean up routine is accessing the TT
* tables as well , it has to be invoked after the TT tables have been
* freed and marked as empty . This ensures that no cleanup RCU callbacks
* accessing the TT data are scheduled for later execution .
*/
batadv_originator_free ( bat_priv ) ;
2012-06-30 22:01:19 +04:00
2013-04-23 17:39:58 +04:00
batadv_gw_free ( bat_priv ) ;
2012-04-20 19:02:45 +04:00
free_percpu ( bat_priv - > bat_counters ) ;
2013-04-17 23:13:16 +04:00
bat_priv - > bat_counters = NULL ;
2012-04-20 19:02:45 +04:00
2012-06-04 00:19:22 +04:00
atomic_set ( & bat_priv - > mesh_state , BATADV_MESH_INACTIVE ) ;
2010-12-13 14:19:28 +03:00
}
2013-04-23 04:32:51 +04:00
/**
* batadv_is_my_mac - check if the given mac address belongs to any of the real
* interfaces in the current mesh
* @ bat_priv : the bat priv with all the soft interface information
* @ addr : the address to check
2014-12-26 14:41:38 +03:00
*
2015-09-15 20:00:48 +03:00
* Return : ' true ' if the mac address was found , false otherwise .
2013-04-23 04:32:51 +04:00
*/
2015-05-26 19:34:26 +03:00
bool batadv_is_my_mac ( struct batadv_priv * bat_priv , const u8 * addr )
2010-12-13 14:19:28 +03:00
{
2012-06-06 00:31:31 +04:00
const struct batadv_hard_iface * hard_iface ;
2014-12-26 14:41:38 +03:00
bool is_my_mac = false ;
2010-12-13 14:19:28 +03:00
rcu_read_lock ( ) ;
2012-05-12 04:09:42 +04:00
list_for_each_entry_rcu ( hard_iface , & batadv_hardif_list , list ) {
2012-06-04 00:19:19 +04:00
if ( hard_iface - > if_status ! = BATADV_IF_ACTIVE )
2010-12-13 14:19:28 +03:00
continue ;
2013-04-03 21:10:26 +04:00
if ( hard_iface - > soft_iface ! = bat_priv - > soft_iface )
continue ;
2012-05-12 15:48:58 +04:00
if ( batadv_compare_eth ( hard_iface - > net_dev - > dev_addr , addr ) ) {
2014-12-26 14:41:38 +03:00
is_my_mac = true ;
break ;
2010-12-13 14:19:28 +03:00
}
}
rcu_read_unlock ( ) ;
2014-12-26 14:41:38 +03:00
return is_my_mac ;
2010-12-13 14:19:28 +03:00
}
2016-07-16 10:31:20 +03:00
# ifdef CONFIG_BATMAN_ADV_DEBUGFS
2012-08-03 19:15:46 +04:00
/**
* batadv_seq_print_text_primary_if_get - called from debugfs table printing
* function that requires the primary interface
* @ seq : debugfs table seq_file struct
*
2015-09-15 20:00:48 +03:00
* Return : primary interface if found or NULL otherwise .
2012-08-03 19:15:46 +04:00
*/
struct batadv_hard_iface *
batadv_seq_print_text_primary_if_get ( struct seq_file * seq )
{
struct net_device * net_dev = ( struct net_device * ) seq - > private ;
struct batadv_priv * bat_priv = netdev_priv ( net_dev ) ;
struct batadv_hard_iface * primary_if ;
primary_if = batadv_primary_if_get_selected ( bat_priv ) ;
if ( ! primary_if ) {
seq_printf ( seq ,
" BATMAN mesh %s disabled - please specify interfaces to enable it \n " ,
net_dev - > name ) ;
goto out ;
}
if ( primary_if - > if_status = = BATADV_IF_ACTIVE )
goto out ;
seq_printf ( seq ,
" BATMAN mesh %s disabled - primary interface not active \n " ,
net_dev - > name ) ;
2016-01-17 13:01:10 +03:00
batadv_hardif_put ( primary_if ) ;
2012-08-03 19:15:46 +04:00
primary_if = NULL ;
out :
return primary_if ;
}
2016-07-16 10:31:20 +03:00
# endif
2012-08-03 19:15:46 +04:00
2013-05-08 09:31:59 +04:00
/**
* batadv_max_header_len - calculate maximum encapsulation overhead for a
* payload packet
*
2015-09-15 20:00:48 +03:00
* Return : the maximum encapsulation overhead in bytes .
2013-05-08 09:31:59 +04:00
*/
int batadv_max_header_len ( void )
{
int header_len = 0 ;
header_len = max_t ( int , header_len ,
sizeof ( struct batadv_unicast_packet ) ) ;
header_len = max_t ( int , header_len ,
sizeof ( struct batadv_unicast_4addr_packet ) ) ;
header_len = max_t ( int , header_len ,
sizeof ( struct batadv_bcast_packet ) ) ;
# ifdef CONFIG_BATMAN_ADV_NC
header_len = max_t ( int , header_len ,
sizeof ( struct batadv_coded_packet ) ) ;
# endif
2014-01-15 16:31:18 +04:00
return header_len + ETH_HLEN ;
2013-05-08 09:31:59 +04:00
}
2013-07-29 19:56:44 +04:00
/**
* batadv_skb_set_priority - sets skb priority according to packet content
* @ skb : the packet to be sent
* @ offset : offset to the packet content
*
* This function sets a value between 256 and 263 ( 802.1 d priority ) , which
* can be interpreted by the cfg80211 or other drivers .
*/
void batadv_skb_set_priority ( struct sk_buff * skb , int offset )
{
struct iphdr ip_hdr_tmp , * ip_hdr ;
struct ipv6hdr ip6_hdr_tmp , * ip6_hdr ;
struct ethhdr ethhdr_tmp , * ethhdr ;
struct vlan_ethhdr * vhdr , vhdr_tmp ;
u32 prio ;
/* already set, do nothing */
if ( skb - > priority > = 256 & & skb - > priority < = 263 )
return ;
ethhdr = skb_header_pointer ( skb , offset , sizeof ( * ethhdr ) , & ethhdr_tmp ) ;
if ( ! ethhdr )
return ;
switch ( ethhdr - > h_proto ) {
case htons ( ETH_P_8021Q ) :
vhdr = skb_header_pointer ( skb , offset + sizeof ( * vhdr ) ,
sizeof ( * vhdr ) , & vhdr_tmp ) ;
if ( ! vhdr )
return ;
prio = ntohs ( vhdr - > h_vlan_TCI ) & VLAN_PRIO_MASK ;
prio = prio > > VLAN_PRIO_SHIFT ;
break ;
case htons ( ETH_P_IP ) :
ip_hdr = skb_header_pointer ( skb , offset + sizeof ( * ethhdr ) ,
sizeof ( * ip_hdr ) , & ip_hdr_tmp ) ;
if ( ! ip_hdr )
return ;
prio = ( ipv4_get_dsfield ( ip_hdr ) & 0xfc ) > > 5 ;
break ;
case htons ( ETH_P_IPV6 ) :
ip6_hdr = skb_header_pointer ( skb , offset + sizeof ( * ethhdr ) ,
sizeof ( * ip6_hdr ) , & ip6_hdr_tmp ) ;
if ( ! ip6_hdr )
return ;
prio = ( ipv6_get_dsfield ( ip6_hdr ) & 0xfc ) > > 5 ;
break ;
default :
return ;
}
skb - > priority = prio + 256 ;
}
2012-05-16 22:23:19 +04:00
static int batadv_recv_unhandled_packet ( struct sk_buff * skb ,
2012-06-06 00:31:31 +04:00
struct batadv_hard_iface * recv_if )
2012-03-01 11:35:17 +04:00
{
2016-07-17 22:04:04 +03:00
kfree_skb ( skb ) ;
2012-03-01 11:35:17 +04:00
return NET_RX_DROP ;
}
/* incoming packets with the batman ethertype received on any active hard
* interface
*/
2012-05-12 04:09:42 +04:00
int batadv_batman_skb_recv ( struct sk_buff * skb , struct net_device * dev ,
struct packet_type * ptype ,
struct net_device * orig_dev )
2012-03-01 11:35:17 +04:00
{
2012-06-06 00:31:31 +04:00
struct batadv_priv * bat_priv ;
2012-06-06 00:31:30 +04:00
struct batadv_ogm_packet * batadv_ogm_packet ;
2012-06-06 00:31:31 +04:00
struct batadv_hard_iface * hard_iface ;
2015-05-26 19:34:26 +03:00
u8 idx ;
2012-03-01 11:35:17 +04:00
2012-06-06 00:31:31 +04:00
hard_iface = container_of ( ptype , struct batadv_hard_iface ,
batman_adv_ptype ) ;
2016-03-05 18:09:17 +03:00
/* Prevent processing a packet received on an interface which is getting
* shut down otherwise the packet may trigger de - reference errors
* further down in the receive path .
*/
if ( ! kref_get_unless_zero ( & hard_iface - > refcount ) )
goto err_out ;
2012-03-01 11:35:17 +04:00
skb = skb_share_check ( skb , GFP_ATOMIC ) ;
/* skb was released by skb_share_check() */
if ( ! skb )
2016-03-05 18:09:17 +03:00
goto err_put ;
2012-03-01 11:35:17 +04:00
/* packet should hold at least type and version */
if ( unlikely ( ! pskb_may_pull ( skb , 2 ) ) )
goto err_free ;
/* expect a valid ethernet header here. */
if ( unlikely ( skb - > mac_len ! = ETH_HLEN | | ! skb_mac_header ( skb ) ) )
goto err_free ;
if ( ! hard_iface - > soft_iface )
goto err_free ;
bat_priv = netdev_priv ( hard_iface - > soft_iface ) ;
2012-06-04 00:19:22 +04:00
if ( atomic_read ( & bat_priv - > mesh_state ) ! = BATADV_MESH_ACTIVE )
2012-03-01 11:35:17 +04:00
goto err_free ;
/* discard frames on not active interfaces */
2012-06-04 00:19:19 +04:00
if ( hard_iface - > if_status ! = BATADV_IF_ACTIVE )
2012-03-01 11:35:17 +04:00
goto err_free ;
2012-06-06 00:31:30 +04:00
batadv_ogm_packet = ( struct batadv_ogm_packet * ) skb - > data ;
2012-03-01 11:35:17 +04:00
2013-12-02 23:38:31 +04:00
if ( batadv_ogm_packet - > version ! = BATADV_COMPAT_VERSION ) {
2012-06-04 00:19:22 +04:00
batadv_dbg ( BATADV_DBG_BATMAN , bat_priv ,
2012-05-12 15:48:58 +04:00
" Drop packet: incompatible batman version (%i) \n " ,
2013-12-02 23:38:31 +04:00
batadv_ogm_packet - > version ) ;
2012-03-01 11:35:17 +04:00
goto err_free ;
}
2014-09-17 10:56:19 +04:00
/* reset control block to avoid left overs from previous users */
memset ( skb - > cb , 0 , sizeof ( struct batadv_skb_cb ) ) ;
2013-12-02 23:38:31 +04:00
idx = batadv_ogm_packet - > packet_type ;
2016-07-17 22:04:04 +03:00
( * batadv_rx_handler [ idx ] ) ( skb , hard_iface ) ;
2012-03-01 11:35:17 +04:00
2016-03-05 18:09:17 +03:00
batadv_hardif_put ( hard_iface ) ;
2012-03-01 11:35:17 +04:00
/* return NET_RX_SUCCESS in any case as we
* most probably dropped the packet for
* routing - logical reasons .
*/
return NET_RX_SUCCESS ;
err_free :
kfree_skb ( skb ) ;
2016-03-05 18:09:17 +03:00
err_put :
batadv_hardif_put ( hard_iface ) ;
2012-03-01 11:35:17 +04:00
err_out :
return NET_RX_DROP ;
}
2012-05-16 22:23:19 +04:00
static void batadv_recv_handler_init ( void )
2012-03-01 11:35:17 +04:00
{
int i ;
2012-05-16 22:23:19 +04:00
for ( i = 0 ; i < ARRAY_SIZE ( batadv_rx_handler ) ; i + + )
batadv_rx_handler [ i ] = batadv_recv_unhandled_packet ;
2012-03-01 11:35:17 +04:00
2013-04-25 12:37:23 +04:00
for ( i = BATADV_UNICAST_MIN ; i < = BATADV_UNICAST_MAX ; i + + )
batadv_rx_handler [ i ] = batadv_recv_unhandled_unicast_packet ;
2013-12-17 22:12:12 +04:00
/* compile time checks for sizes */
BUILD_BUG_ON ( sizeof ( struct batadv_bla_claim_dst ) ! = 6 ) ;
BUILD_BUG_ON ( sizeof ( struct batadv_ogm_packet ) ! = 24 ) ;
BUILD_BUG_ON ( sizeof ( struct batadv_icmp_header ) ! = 20 ) ;
BUILD_BUG_ON ( sizeof ( struct batadv_icmp_packet ) ! = 20 ) ;
BUILD_BUG_ON ( sizeof ( struct batadv_icmp_packet_rr ) ! = 116 ) ;
BUILD_BUG_ON ( sizeof ( struct batadv_unicast_packet ) ! = 10 ) ;
BUILD_BUG_ON ( sizeof ( struct batadv_unicast_4addr_packet ) ! = 18 ) ;
BUILD_BUG_ON ( sizeof ( struct batadv_frag_packet ) ! = 20 ) ;
BUILD_BUG_ON ( sizeof ( struct batadv_bcast_packet ) ! = 14 ) ;
BUILD_BUG_ON ( sizeof ( struct batadv_coded_packet ) ! = 46 ) ;
BUILD_BUG_ON ( sizeof ( struct batadv_unicast_tvlv_packet ) ! = 20 ) ;
BUILD_BUG_ON ( sizeof ( struct batadv_tvlv_hdr ) ! = 4 ) ;
BUILD_BUG_ON ( sizeof ( struct batadv_tvlv_gateway_data ) ! = 8 ) ;
BUILD_BUG_ON ( sizeof ( struct batadv_tvlv_tt_vlan_data ) ! = 8 ) ;
BUILD_BUG_ON ( sizeof ( struct batadv_tvlv_tt_change ) ! = 12 ) ;
BUILD_BUG_ON ( sizeof ( struct batadv_tvlv_roam_adv ) ! = 8 ) ;
2013-04-25 12:37:22 +04:00
2017-02-17 13:17:07 +03:00
i = FIELD_SIZEOF ( struct sk_buff , cb ) ;
BUILD_BUG_ON ( sizeof ( struct batadv_skb_cb ) > i ) ;
2013-04-25 12:37:23 +04:00
/* broadcast packet */
batadv_rx_handler [ BATADV_BCAST ] = batadv_recv_bcast_packet ;
/* unicast packets ... */
2012-10-01 11:57:35 +04:00
/* unicast with 4 addresses packet */
batadv_rx_handler [ BATADV_UNICAST_4ADDR ] = batadv_recv_unicast_packet ;
2012-03-01 11:35:17 +04:00
/* unicast packet */
2012-06-04 00:19:21 +04:00
batadv_rx_handler [ BATADV_UNICAST ] = batadv_recv_unicast_packet ;
2013-04-23 17:39:57 +04:00
/* unicast tvlv packet */
batadv_rx_handler [ BATADV_UNICAST_TVLV ] = batadv_recv_unicast_tvlv ;
2013-04-25 12:37:23 +04:00
/* batman icmp packet */
batadv_rx_handler [ BATADV_ICMP ] = batadv_recv_icmp_packet ;
2013-05-23 18:53:02 +04:00
/* Fragmented packets */
batadv_rx_handler [ BATADV_UNICAST_FRAG ] = batadv_recv_frag_packet ;
2012-03-01 11:35:17 +04:00
}
2012-06-06 00:31:31 +04:00
int
2015-05-26 19:34:26 +03:00
batadv_recv_handler_register ( u8 packet_type ,
2012-06-06 00:31:31 +04:00
int ( * recv_handler ) ( struct sk_buff * ,
struct batadv_hard_iface * ) )
2012-03-01 11:35:17 +04:00
{
2017-09-30 10:24:28 +03:00
int ( * curr ) ( struct sk_buff * skb ,
struct batadv_hard_iface * recv_if ) ;
2013-04-25 12:37:23 +04:00
curr = batadv_rx_handler [ packet_type ] ;
2017-08-23 22:52:13 +03:00
if ( curr ! = batadv_recv_unhandled_packet & &
curr ! = batadv_recv_unhandled_unicast_packet )
2012-03-01 11:35:17 +04:00
return - EBUSY ;
2012-05-16 22:23:19 +04:00
batadv_rx_handler [ packet_type ] = recv_handler ;
2012-03-01 11:35:17 +04:00
return 0 ;
}
2015-05-26 19:34:26 +03:00
void batadv_recv_handler_unregister ( u8 packet_type )
2012-03-01 11:35:17 +04:00
{
2012-05-16 22:23:19 +04:00
batadv_rx_handler [ packet_type ] = batadv_recv_unhandled_packet ;
2012-03-01 11:35:17 +04:00
}
2012-10-17 23:10:39 +04:00
/**
* batadv_skb_crc32 - calculate CRC32 of the whole packet and skip bytes in
* the header
* @ skb : skb pointing to fragmented socket buffers
* @ payload_ptr : Pointer to position inside the head buffer of the skb
* marking the start of the data to be CRC ' ed
*
* payload_ptr must always point to an address in the skb head buffer and not to
* a fragment .
2015-10-31 14:29:29 +03:00
*
* Return : big endian crc32c of the checksummed data
2012-10-17 23:10:39 +04:00
*/
__be32 batadv_skb_crc32 ( struct sk_buff * skb , u8 * payload_ptr )
{
u32 crc = 0 ;
unsigned int from ;
unsigned int to = skb - > len ;
struct skb_seq_state st ;
const u8 * data ;
unsigned int len ;
unsigned int consumed = 0 ;
from = ( unsigned int ) ( payload_ptr - skb - > data ) ;
skb_prepare_seq_read ( skb , from , to , & st ) ;
while ( ( len = skb_seq_read ( consumed , & data , & st ) ) ! = 0 ) {
crc = crc32c ( crc , data , len ) ;
consumed + = len ;
}
return htonl ( crc ) ;
}
2013-06-04 14:11:39 +04:00
/**
* batadv_get_vid - extract the VLAN identifier from skb if any
* @ skb : the buffer containing the packet
* @ header_len : length of the batman header preceding the ethernet header
*
2015-09-15 20:00:48 +03:00
* Return : VID with the BATADV_VLAN_HAS_TAG flag when the packet embedded in the
* skb is vlan tagged . Otherwise BATADV_NO_FLAGS .
2013-06-04 14:11:39 +04:00
*/
unsigned short batadv_get_vid ( struct sk_buff * skb , size_t header_len )
{
struct ethhdr * ethhdr = ( struct ethhdr * ) ( skb - > data + header_len ) ;
struct vlan_ethhdr * vhdr ;
unsigned short vid ;
if ( ethhdr - > h_proto ! = htons ( ETH_P_8021Q ) )
return BATADV_NO_FLAGS ;
if ( ! pskb_may_pull ( skb , header_len + VLAN_ETH_HLEN ) )
return BATADV_NO_FLAGS ;
vhdr = ( struct vlan_ethhdr * ) ( skb - > data + header_len ) ;
vid = ntohs ( vhdr - > h_vlan_TCI ) & VLAN_VID_MASK ;
vid | = BATADV_VLAN_HAS_TAG ;
return vid ;
}
2013-11-16 15:03:51 +04:00
/**
* batadv_vlan_ap_isola_get - return the AP isolation status for the given vlan
* @ bat_priv : the bat priv with all the soft interface information
* @ vid : the VLAN identifier for which the AP isolation attributed as to be
* looked up
*
2015-09-15 20:00:48 +03:00
* Return : true if AP isolation is on for the VLAN idenfied by vid , false
2013-11-16 15:03:51 +04:00
* otherwise
*/
bool batadv_vlan_ap_isola_get ( struct batadv_priv * bat_priv , unsigned short vid )
{
bool ap_isolation_enabled = false ;
struct batadv_softif_vlan * vlan ;
/* if the AP isolation is requested on a VLAN, then check for its
* setting in the proper VLAN private data structure
*/
vlan = batadv_softif_vlan_get ( bat_priv , vid ) ;
if ( vlan ) {
ap_isolation_enabled = atomic_read ( & vlan - > ap_isolation ) ;
2016-01-17 13:01:21 +03:00
batadv_softif_vlan_put ( vlan ) ;
2013-11-16 15:03:51 +04:00
}
return ap_isolation_enabled ;
}
2012-05-16 22:23:19 +04:00
module_init ( batadv_init ) ;
module_exit ( batadv_exit ) ;
2010-12-13 14:19:28 +03:00
MODULE_LICENSE ( " GPL " ) ;
2012-06-04 00:19:17 +04:00
MODULE_AUTHOR ( BATADV_DRIVER_AUTHOR ) ;
MODULE_DESCRIPTION ( BATADV_DRIVER_DESC ) ;
MODULE_SUPPORTED_DEVICE ( BATADV_DRIVER_DEVICE ) ;
MODULE_VERSION ( BATADV_SOURCE_VERSION ) ;
2016-06-11 00:00:55 +03:00
MODULE_ALIAS_RTNL_LINK ( " batadv " ) ;
2016-10-29 14:56:23 +03:00
MODULE_ALIAS_GENL_FAMILY ( BATADV_NL_NAME ) ;