2013-01-04 06:05:31 +04:00
/* Copyright (C) 2010-2013 B.A.T.M.A.N. contributors:
2010-12-13 14:19:28 +03:00
*
* Marek Lindner
*
* 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
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA
* 02110 - 1301 , USA
*/
# include "main.h"
2012-06-11 01:58:51 +04:00
# include "sysfs.h"
2010-12-13 14:19:28 +03:00
# include "translation-table.h"
2012-08-08 20:50:57 +04:00
# include "distributed-arp-table.h"
2010-12-13 14:19:28 +03:00
# include "originator.h"
# include "hard-interface.h"
# include "gateway_common.h"
# include "gateway_client.h"
# include "vis.h"
2012-05-12 20:33:52 +04:00
static struct net_device * batadv_kobj_to_netdev ( struct kobject * obj )
2011-06-05 12:20:19 +04:00
{
struct device * dev = container_of ( obj - > parent , struct device , kobj ) ;
return to_net_dev ( dev ) ;
}
2012-06-06 00:31:31 +04:00
static struct batadv_priv * batadv_kobj_to_batpriv ( struct kobject * obj )
2011-06-05 12:20:19 +04:00
{
2012-05-12 20:33:52 +04:00
struct net_device * net_dev = batadv_kobj_to_netdev ( obj ) ;
2011-06-05 12:20:19 +04:00
return netdev_priv ( net_dev ) ;
}
2010-12-13 14:19:28 +03:00
2012-06-04 00:19:07 +04:00
# define BATADV_UEV_TYPE_VAR "BATTYPE="
# define BATADV_UEV_ACTION_VAR "BATACTION="
# define BATADV_UEV_DATA_VAR "BATDATA="
2011-04-26 20:26:01 +04:00
2012-05-12 20:33:52 +04:00
static char * batadv_uev_action_str [ ] = {
2011-04-26 20:26:01 +04:00
" add " ,
" del " ,
" change "
} ;
2012-05-12 20:33:52 +04:00
static char * batadv_uev_type_str [ ] = {
2011-04-26 20:26:01 +04:00
" gw "
} ;
2010-12-13 14:19:28 +03:00
/* Use this, if you have customized show and store functions */
2012-06-04 00:19:07 +04:00
# define BATADV_ATTR(_name, _mode, _show, _store) \
2012-06-06 00:31:29 +04:00
struct batadv_attribute batadv_attr_ # # _name = { \
2012-06-04 00:19:07 +04:00
. attr = { . name = __stringify ( _name ) , \
. mode = _mode } , \
. show = _show , \
. store = _store , \
2010-12-13 14:19:28 +03:00
} ;
2012-06-04 00:19:07 +04:00
# define BATADV_ATTR_SIF_STORE_BOOL(_name, _post_func) \
2012-05-12 20:33:52 +04:00
ssize_t batadv_store_ # # _name ( struct kobject * kobj , \
struct attribute * attr , char * buff , \
size_t count ) \
2010-12-13 14:19:28 +03:00
{ \
2012-05-12 20:33:52 +04:00
struct net_device * net_dev = batadv_kobj_to_netdev ( kobj ) ; \
2012-06-06 00:31:31 +04:00
struct batadv_priv * bat_priv = netdev_priv ( net_dev ) ; \
2012-05-12 20:33:52 +04:00
return __batadv_store_bool_attr ( buff , count , _post_func , attr , \
& bat_priv - > _name , net_dev ) ; \
2010-12-13 14:19:28 +03:00
}
2012-06-04 00:19:07 +04:00
# define BATADV_ATTR_SIF_SHOW_BOOL(_name) \
2012-05-12 20:33:52 +04:00
ssize_t batadv_show_ # # _name ( struct kobject * kobj , \
struct attribute * attr , char * buff ) \
2010-12-13 14:19:28 +03:00
{ \
2012-06-06 00:31:31 +04:00
struct batadv_priv * bat_priv = batadv_kobj_to_batpriv ( kobj ) ; \
2010-12-13 14:19:28 +03:00
return sprintf ( buff , " %s \n " , \
atomic_read ( & bat_priv - > _name ) = = 0 ? \
" disabled " : " enabled " ) ; \
} \
2012-03-11 02:17:51 +04:00
/* Use this, if you are going to turn a [name] in the soft-interface
2012-05-12 04:09:43 +04:00
* ( bat_priv ) on or off
*/
2012-06-04 00:19:07 +04:00
# define BATADV_ATTR_SIF_BOOL(_name, _mode, _post_func) \
static BATADV_ATTR_SIF_STORE_BOOL ( _name , _post_func ) \
static BATADV_ATTR_SIF_SHOW_BOOL ( _name ) \
static BATADV_ATTR ( _name , _mode , batadv_show_ # # _name , \
batadv_store_ # # _name )
2010-12-13 14:19:28 +03:00
2012-06-04 00:19:07 +04:00
# define BATADV_ATTR_SIF_STORE_UINT(_name, _min, _max, _post_func) \
2012-05-12 20:33:52 +04:00
ssize_t batadv_store_ # # _name ( struct kobject * kobj , \
struct attribute * attr , char * buff , \
size_t count ) \
2010-12-13 14:19:28 +03:00
{ \
2012-05-12 20:33:52 +04:00
struct net_device * net_dev = batadv_kobj_to_netdev ( kobj ) ; \
2012-06-06 00:31:31 +04:00
struct batadv_priv * bat_priv = netdev_priv ( net_dev ) ; \
2012-05-12 20:33:52 +04:00
return __batadv_store_uint_attr ( buff , count , _min , _max , \
_post_func , attr , \
& bat_priv - > _name , net_dev ) ; \
2010-12-13 14:19:28 +03:00
}
2012-06-04 00:19:07 +04:00
# define BATADV_ATTR_SIF_SHOW_UINT(_name) \
2012-05-12 20:33:52 +04:00
ssize_t batadv_show_ # # _name ( struct kobject * kobj , \
struct attribute * attr , char * buff ) \
2010-12-13 14:19:28 +03:00
{ \
2012-06-06 00:31:31 +04:00
struct batadv_priv * bat_priv = batadv_kobj_to_batpriv ( kobj ) ; \
2010-12-13 14:19:28 +03:00
return sprintf ( buff , " %i \n " , atomic_read ( & bat_priv - > _name ) ) ; \
} \
2012-03-11 02:17:51 +04:00
/* Use this, if you are going to set [name] in the soft-interface
2012-05-12 04:09:43 +04:00
* ( bat_priv ) to an unsigned integer value
*/
2012-06-04 00:19:07 +04:00
# define BATADV_ATTR_SIF_UINT(_name, _mode, _min, _max, _post_func) \
static BATADV_ATTR_SIF_STORE_UINT ( _name , _min , _max , _post_func ) \
static BATADV_ATTR_SIF_SHOW_UINT ( _name ) \
static BATADV_ATTR ( _name , _mode , batadv_show_ # # _name , \
batadv_store_ # # _name )
2010-12-13 14:19:28 +03:00
2012-05-12 20:33:52 +04:00
static int batadv_store_bool_attr ( char * buff , size_t count ,
struct net_device * net_dev ,
const char * attr_name , atomic_t * attr )
2010-12-13 14:19:28 +03:00
{
int enabled = - 1 ;
if ( buff [ count - 1 ] = = ' \n ' )
buff [ count - 1 ] = ' \0 ' ;
if ( ( strncmp ( buff , " 1 " , 2 ) = = 0 ) | |
( strncmp ( buff , " enable " , 7 ) = = 0 ) | |
( strncmp ( buff , " enabled " , 8 ) = = 0 ) )
enabled = 1 ;
if ( ( strncmp ( buff , " 0 " , 2 ) = = 0 ) | |
( strncmp ( buff , " disable " , 8 ) = = 0 ) | |
( strncmp ( buff , " disabled " , 9 ) = = 0 ) )
enabled = 0 ;
if ( enabled < 0 ) {
2012-05-16 22:23:22 +04:00
batadv_info ( net_dev , " %s: Invalid parameter received: %s \n " ,
attr_name , buff ) ;
2010-12-13 14:19:28 +03:00
return - EINVAL ;
}
if ( atomic_read ( attr ) = = enabled )
return count ;
2012-05-16 22:23:22 +04:00
batadv_info ( net_dev , " %s: Changing from: %s to: %s \n " , attr_name ,
atomic_read ( attr ) = = 1 ? " enabled " : " disabled " ,
enabled = = 1 ? " enabled " : " disabled " ) ;
2010-12-13 14:19:28 +03:00
2012-04-15 09:58:06 +04:00
atomic_set ( attr , ( unsigned int ) enabled ) ;
2010-12-13 14:19:28 +03:00
return count ;
}
2012-05-12 20:33:52 +04:00
static inline ssize_t
__batadv_store_bool_attr ( char * buff , size_t count ,
void ( * post_func ) ( struct net_device * ) ,
struct attribute * attr ,
atomic_t * attr_store , struct net_device * net_dev )
2010-12-13 14:19:28 +03:00
{
int ret ;
2012-05-12 20:33:52 +04:00
ret = batadv_store_bool_attr ( buff , count , net_dev , attr - > name ,
attr_store ) ;
2010-12-13 14:19:28 +03:00
if ( post_func & & ret )
post_func ( net_dev ) ;
return ret ;
}
2012-05-12 20:33:52 +04:00
static int batadv_store_uint_attr ( const char * buff , size_t count ,
struct net_device * net_dev ,
const char * attr_name ,
unsigned int min , unsigned int max ,
atomic_t * attr )
2010-12-13 14:19:28 +03:00
{
unsigned long uint_val ;
int ret ;
2011-09-30 15:32:01 +04:00
ret = kstrtoul ( buff , 10 , & uint_val ) ;
2010-12-13 14:19:28 +03:00
if ( ret ) {
2012-05-16 22:23:22 +04:00
batadv_info ( net_dev , " %s: Invalid parameter received: %s \n " ,
attr_name , buff ) ;
2010-12-13 14:19:28 +03:00
return - EINVAL ;
}
if ( uint_val < min ) {
2012-05-16 22:23:22 +04:00
batadv_info ( net_dev , " %s: Value is too small: %lu min: %u \n " ,
attr_name , uint_val , min ) ;
2010-12-13 14:19:28 +03:00
return - EINVAL ;
}
if ( uint_val > max ) {
2012-05-16 22:23:22 +04:00
batadv_info ( net_dev , " %s: Value is too big: %lu max: %u \n " ,
attr_name , uint_val , max ) ;
2010-12-13 14:19:28 +03:00
return - EINVAL ;
}
if ( atomic_read ( attr ) = = uint_val )
return count ;
2012-05-16 22:23:22 +04:00
batadv_info ( net_dev , " %s: Changing from: %i to: %lu \n " ,
attr_name , atomic_read ( attr ) , uint_val ) ;
2010-12-13 14:19:28 +03:00
atomic_set ( attr , uint_val ) ;
return count ;
}
2012-05-12 20:33:52 +04:00
static inline ssize_t
__batadv_store_uint_attr ( const char * buff , size_t count ,
int min , int max ,
void ( * post_func ) ( struct net_device * ) ,
const struct attribute * attr ,
atomic_t * attr_store , struct net_device * net_dev )
2010-12-13 14:19:28 +03:00
{
int ret ;
2012-05-12 20:33:52 +04:00
ret = batadv_store_uint_attr ( buff , count , net_dev , attr - > name , min , max ,
attr_store ) ;
2010-12-13 14:19:28 +03:00
if ( post_func & & ret )
post_func ( net_dev ) ;
return ret ;
}
2012-05-12 20:33:52 +04:00
static ssize_t batadv_show_vis_mode ( struct kobject * kobj ,
struct attribute * attr , char * buff )
2010-12-13 14:19:28 +03:00
{
2012-06-06 00:31:31 +04:00
struct batadv_priv * bat_priv = batadv_kobj_to_batpriv ( kobj ) ;
2010-12-13 14:19:28 +03:00
int vis_mode = atomic_read ( & bat_priv - > vis_mode ) ;
2012-06-04 00:19:21 +04:00
const char * mode ;
2010-12-13 14:19:28 +03:00
2012-06-04 00:19:21 +04:00
if ( vis_mode = = BATADV_VIS_TYPE_CLIENT_UPDATE )
mode = " client " ;
else
mode = " server " ;
return sprintf ( buff , " %s \n " , mode ) ;
2010-12-13 14:19:28 +03:00
}
2012-05-12 20:33:52 +04:00
static ssize_t batadv_store_vis_mode ( struct kobject * kobj ,
struct attribute * attr , char * buff ,
size_t count )
2010-12-13 14:19:28 +03:00
{
2012-05-12 20:33:52 +04:00
struct net_device * net_dev = batadv_kobj_to_netdev ( kobj ) ;
2012-06-06 00:31:31 +04:00
struct batadv_priv * bat_priv = netdev_priv ( net_dev ) ;
2010-12-13 14:19:28 +03:00
unsigned long val ;
int ret , vis_mode_tmp = - 1 ;
2012-05-16 22:23:22 +04:00
const char * old_mode , * new_mode ;
2010-12-13 14:19:28 +03:00
2011-09-30 15:32:01 +04:00
ret = kstrtoul ( buff , 10 , & val ) ;
2010-12-13 14:19:28 +03:00
2012-06-04 00:19:21 +04:00
if ( ( ( count = = 2 ) & & ( ! ret ) & &
( val = = BATADV_VIS_TYPE_CLIENT_UPDATE ) ) | |
2010-12-13 14:19:28 +03:00
( strncmp ( buff , " client " , 6 ) = = 0 ) | |
( strncmp ( buff , " off " , 3 ) = = 0 ) )
2012-06-04 00:19:21 +04:00
vis_mode_tmp = BATADV_VIS_TYPE_CLIENT_UPDATE ;
2010-12-13 14:19:28 +03:00
2012-06-04 00:19:21 +04:00
if ( ( ( count = = 2 ) & & ( ! ret ) & &
( val = = BATADV_VIS_TYPE_SERVER_SYNC ) ) | |
2010-12-13 14:19:28 +03:00
( strncmp ( buff , " server " , 6 ) = = 0 ) )
2012-06-04 00:19:21 +04:00
vis_mode_tmp = BATADV_VIS_TYPE_SERVER_SYNC ;
2010-12-13 14:19:28 +03:00
if ( vis_mode_tmp < 0 ) {
if ( buff [ count - 1 ] = = ' \n ' )
buff [ count - 1 ] = ' \0 ' ;
2012-05-16 22:23:22 +04:00
batadv_info ( net_dev ,
" Invalid parameter for 'vis mode' setting received: %s \n " ,
buff ) ;
2010-12-13 14:19:28 +03:00
return - EINVAL ;
}
if ( atomic_read ( & bat_priv - > vis_mode ) = = vis_mode_tmp )
return count ;
2012-06-04 00:19:21 +04:00
if ( atomic_read ( & bat_priv - > vis_mode ) = = BATADV_VIS_TYPE_CLIENT_UPDATE )
2012-05-16 22:23:22 +04:00
old_mode = " client " ;
else
old_mode = " server " ;
2012-06-04 00:19:21 +04:00
if ( vis_mode_tmp = = BATADV_VIS_TYPE_CLIENT_UPDATE )
2012-05-16 22:23:22 +04:00
new_mode = " client " ;
else
new_mode = " server " ;
batadv_info ( net_dev , " Changing vis mode from: %s to: %s \n " , old_mode ,
new_mode ) ;
2010-12-13 14:19:28 +03:00
2012-04-15 09:58:06 +04:00
atomic_set ( & bat_priv - > vis_mode , ( unsigned int ) vis_mode_tmp ) ;
2010-12-13 14:19:28 +03:00
return count ;
}
2012-05-12 20:33:52 +04:00
static ssize_t batadv_show_bat_algo ( struct kobject * kobj ,
struct attribute * attr , char * buff )
2011-11-28 20:15:37 +04:00
{
2012-06-06 00:31:31 +04:00
struct batadv_priv * bat_priv = batadv_kobj_to_batpriv ( kobj ) ;
2011-11-28 20:15:37 +04:00
return sprintf ( buff , " %s \n " , bat_priv - > bat_algo_ops - > name ) ;
}
2012-05-12 20:33:52 +04:00
static void batadv_post_gw_deselect ( struct net_device * net_dev )
2010-12-13 14:19:28 +03:00
{
2012-06-06 00:31:31 +04:00
struct batadv_priv * bat_priv = netdev_priv ( net_dev ) ;
2012-05-12 04:09:29 +04:00
batadv_gw_deselect ( bat_priv ) ;
2010-12-13 14:19:28 +03:00
}
2012-05-12 20:33:52 +04:00
static ssize_t batadv_show_gw_mode ( struct kobject * kobj , struct attribute * attr ,
char * buff )
2010-12-13 14:19:28 +03:00
{
2012-06-06 00:31:31 +04:00
struct batadv_priv * bat_priv = batadv_kobj_to_batpriv ( kobj ) ;
2010-12-13 14:19:28 +03:00
int bytes_written ;
switch ( atomic_read ( & bat_priv - > gw_mode ) ) {
2012-06-04 00:19:18 +04:00
case BATADV_GW_MODE_CLIENT :
2012-06-04 00:19:11 +04:00
bytes_written = sprintf ( buff , " %s \n " ,
BATADV_GW_MODE_CLIENT_NAME ) ;
2010-12-13 14:19:28 +03:00
break ;
2012-06-04 00:19:18 +04:00
case BATADV_GW_MODE_SERVER :
2012-06-04 00:19:11 +04:00
bytes_written = sprintf ( buff , " %s \n " ,
BATADV_GW_MODE_SERVER_NAME ) ;
2010-12-13 14:19:28 +03:00
break ;
default :
2012-06-04 00:19:11 +04:00
bytes_written = sprintf ( buff , " %s \n " ,
BATADV_GW_MODE_OFF_NAME ) ;
2010-12-13 14:19:28 +03:00
break ;
}
return bytes_written ;
}
2012-05-12 20:33:52 +04:00
static ssize_t batadv_store_gw_mode ( struct kobject * kobj ,
struct attribute * attr , char * buff ,
size_t count )
2010-12-13 14:19:28 +03:00
{
2012-05-12 20:33:52 +04:00
struct net_device * net_dev = batadv_kobj_to_netdev ( kobj ) ;
2012-06-06 00:31:31 +04:00
struct batadv_priv * bat_priv = netdev_priv ( net_dev ) ;
2010-12-13 14:19:28 +03:00
char * curr_gw_mode_str ;
int gw_mode_tmp = - 1 ;
if ( buff [ count - 1 ] = = ' \n ' )
buff [ count - 1 ] = ' \0 ' ;
2012-06-04 00:19:11 +04:00
if ( strncmp ( buff , BATADV_GW_MODE_OFF_NAME ,
strlen ( BATADV_GW_MODE_OFF_NAME ) ) = = 0 )
2012-06-04 00:19:18 +04:00
gw_mode_tmp = BATADV_GW_MODE_OFF ;
2010-12-13 14:19:28 +03:00
2012-06-04 00:19:11 +04:00
if ( strncmp ( buff , BATADV_GW_MODE_CLIENT_NAME ,
strlen ( BATADV_GW_MODE_CLIENT_NAME ) ) = = 0 )
2012-06-04 00:19:18 +04:00
gw_mode_tmp = BATADV_GW_MODE_CLIENT ;
2010-12-13 14:19:28 +03:00
2012-06-04 00:19:11 +04:00
if ( strncmp ( buff , BATADV_GW_MODE_SERVER_NAME ,
strlen ( BATADV_GW_MODE_SERVER_NAME ) ) = = 0 )
2012-06-04 00:19:18 +04:00
gw_mode_tmp = BATADV_GW_MODE_SERVER ;
2010-12-13 14:19:28 +03:00
if ( gw_mode_tmp < 0 ) {
2012-05-16 22:23:22 +04:00
batadv_info ( net_dev ,
" Invalid parameter for 'gw mode' setting received: %s \n " ,
buff ) ;
2010-12-13 14:19:28 +03:00
return - EINVAL ;
}
if ( atomic_read ( & bat_priv - > gw_mode ) = = gw_mode_tmp )
return count ;
switch ( atomic_read ( & bat_priv - > gw_mode ) ) {
2012-06-04 00:19:18 +04:00
case BATADV_GW_MODE_CLIENT :
2012-06-04 00:19:11 +04:00
curr_gw_mode_str = BATADV_GW_MODE_CLIENT_NAME ;
2010-12-13 14:19:28 +03:00
break ;
2012-06-04 00:19:18 +04:00
case BATADV_GW_MODE_SERVER :
2012-06-04 00:19:11 +04:00
curr_gw_mode_str = BATADV_GW_MODE_SERVER_NAME ;
2010-12-13 14:19:28 +03:00
break ;
default :
2012-06-04 00:19:11 +04:00
curr_gw_mode_str = BATADV_GW_MODE_OFF_NAME ;
2010-12-13 14:19:28 +03:00
break ;
}
2012-05-16 22:23:22 +04:00
batadv_info ( net_dev , " Changing gw mode from: %s to: %s \n " ,
curr_gw_mode_str , buff ) ;
2010-12-13 14:19:28 +03:00
2012-05-12 04:09:29 +04:00
batadv_gw_deselect ( bat_priv ) ;
2013-07-13 02:06:00 +04:00
/* always call batadv_gw_check_client_stop() before changing the gateway
* state
*/
batadv_gw_check_client_stop ( bat_priv ) ;
2012-04-15 09:58:06 +04:00
atomic_set ( & bat_priv - > gw_mode , ( unsigned int ) gw_mode_tmp ) ;
2010-12-13 14:19:28 +03:00
return count ;
}
2012-05-12 20:33:52 +04:00
static ssize_t batadv_show_gw_bwidth ( struct kobject * kobj ,
struct attribute * attr , char * buff )
2010-12-13 14:19:28 +03:00
{
2012-06-06 00:31:31 +04:00
struct batadv_priv * bat_priv = batadv_kobj_to_batpriv ( kobj ) ;
2010-12-13 14:19:28 +03:00
int down , up ;
int gw_bandwidth = atomic_read ( & bat_priv - > gw_bandwidth ) ;
2012-05-12 04:09:30 +04:00
batadv_gw_bandwidth_to_kbit ( gw_bandwidth , & down , & up ) ;
2010-12-13 14:19:28 +03:00
return sprintf ( buff , " %i%s/%i%s \n " ,
( down > 2048 ? down / 1024 : down ) ,
( down > 2048 ? " MBit " : " KBit " ) ,
( up > 2048 ? up / 1024 : up ) ,
( up > 2048 ? " MBit " : " KBit " ) ) ;
}
2012-05-12 20:33:52 +04:00
static ssize_t batadv_store_gw_bwidth ( struct kobject * kobj ,
struct attribute * attr , char * buff ,
size_t count )
2010-12-13 14:19:28 +03:00
{
2012-05-12 20:33:52 +04:00
struct net_device * net_dev = batadv_kobj_to_netdev ( kobj ) ;
2010-12-13 14:19:28 +03:00
if ( buff [ count - 1 ] = = ' \n ' )
buff [ count - 1 ] = ' \0 ' ;
2012-05-12 04:09:30 +04:00
return batadv_gw_bandwidth_set ( net_dev , buff , count ) ;
2010-12-13 14:19:28 +03:00
}
2012-06-04 00:19:07 +04:00
BATADV_ATTR_SIF_BOOL ( aggregated_ogms , S_IRUGO | S_IWUSR , NULL ) ;
BATADV_ATTR_SIF_BOOL ( bonding , S_IRUGO | S_IWUSR , NULL ) ;
2012-01-22 23:00:27 +04:00
# ifdef CONFIG_BATMAN_ADV_BLA
2012-06-04 00:19:07 +04:00
BATADV_ATTR_SIF_BOOL ( bridge_loop_avoidance , S_IRUGO | S_IWUSR , NULL ) ;
2012-01-22 23:00:27 +04:00
# endif
2012-08-08 20:50:57 +04:00
# ifdef CONFIG_BATMAN_ADV_DAT
BATADV_ATTR_SIF_BOOL ( distributed_arp_table , S_IRUGO | S_IWUSR , NULL ) ;
# endif
2012-06-04 00:19:07 +04:00
BATADV_ATTR_SIF_BOOL ( fragmentation , S_IRUGO | S_IWUSR , batadv_update_min_mtu ) ;
BATADV_ATTR_SIF_BOOL ( ap_isolation , S_IRUGO | S_IWUSR , NULL ) ;
static BATADV_ATTR ( vis_mode , S_IRUGO | S_IWUSR , batadv_show_vis_mode ,
batadv_store_vis_mode ) ;
static BATADV_ATTR ( routing_algo , S_IRUGO , batadv_show_bat_algo , NULL ) ;
static BATADV_ATTR ( gw_mode , S_IRUGO | S_IWUSR , batadv_show_gw_mode ,
batadv_store_gw_mode ) ;
2012-06-04 00:19:17 +04:00
BATADV_ATTR_SIF_UINT ( orig_interval , S_IRUGO | S_IWUSR , 2 * BATADV_JITTER ,
INT_MAX , NULL ) ;
BATADV_ATTR_SIF_UINT ( hop_penalty , S_IRUGO | S_IWUSR , 0 , BATADV_TQ_MAX_VALUE ,
2012-06-04 00:19:07 +04:00
NULL ) ;
2012-06-04 00:19:17 +04:00
BATADV_ATTR_SIF_UINT ( gw_sel_class , S_IRUGO | S_IWUSR , 1 , BATADV_TQ_MAX_VALUE ,
2012-06-04 00:19:07 +04:00
batadv_post_gw_deselect ) ;
static BATADV_ATTR ( gw_bandwidth , S_IRUGO | S_IWUSR , batadv_show_gw_bwidth ,
batadv_store_gw_bwidth ) ;
2010-12-13 14:19:28 +03:00
# ifdef CONFIG_BATMAN_ADV_DEBUG
2012-06-04 00:19:22 +04:00
BATADV_ATTR_SIF_UINT ( log_level , S_IRUGO | S_IWUSR , 0 , BATADV_DBG_ALL , NULL ) ;
2010-12-13 14:19:28 +03:00
# endif
2013-01-25 14:12:38 +04:00
# ifdef CONFIG_BATMAN_ADV_NC
BATADV_ATTR_SIF_BOOL ( network_coding , S_IRUGO | S_IWUSR , NULL ) ;
# endif
2010-12-13 14:19:28 +03:00
2012-06-06 00:31:29 +04:00
static struct batadv_attribute * batadv_mesh_attrs [ ] = {
2012-05-12 20:33:52 +04:00
& batadv_attr_aggregated_ogms ,
& batadv_attr_bonding ,
2012-01-22 23:00:27 +04:00
# ifdef CONFIG_BATMAN_ADV_BLA
2012-05-12 20:33:52 +04:00
& batadv_attr_bridge_loop_avoidance ,
2012-08-08 20:50:57 +04:00
# endif
# ifdef CONFIG_BATMAN_ADV_DAT
& batadv_attr_distributed_arp_table ,
2012-01-22 23:00:27 +04:00
# endif
2012-05-12 20:33:52 +04:00
& batadv_attr_fragmentation ,
& batadv_attr_ap_isolation ,
& batadv_attr_vis_mode ,
& batadv_attr_routing_algo ,
& batadv_attr_gw_mode ,
& batadv_attr_orig_interval ,
& batadv_attr_hop_penalty ,
& batadv_attr_gw_sel_class ,
& batadv_attr_gw_bandwidth ,
2010-12-13 14:19:28 +03:00
# ifdef CONFIG_BATMAN_ADV_DEBUG
2012-05-12 20:33:52 +04:00
& batadv_attr_log_level ,
2013-01-25 14:12:38 +04:00
# endif
# ifdef CONFIG_BATMAN_ADV_NC
& batadv_attr_network_coding ,
2010-12-13 14:19:28 +03:00
# endif
NULL ,
} ;
2012-05-12 04:09:24 +04:00
int batadv_sysfs_add_meshif ( struct net_device * dev )
2010-12-13 14:19:28 +03:00
{
struct kobject * batif_kobject = & dev - > dev . kobj ;
2012-06-06 00:31:31 +04:00
struct batadv_priv * bat_priv = netdev_priv ( dev ) ;
2012-06-06 00:31:29 +04:00
struct batadv_attribute * * bat_attr ;
2010-12-13 14:19:28 +03:00
int err ;
2012-06-04 00:19:09 +04:00
bat_priv - > mesh_obj = kobject_create_and_add ( BATADV_SYSFS_IF_MESH_SUBDIR ,
2010-12-13 14:19:28 +03:00
batif_kobject ) ;
if ( ! bat_priv - > mesh_obj ) {
2012-05-16 22:23:22 +04:00
batadv_err ( dev , " Can't add sysfs directory: %s/%s \n " , dev - > name ,
2012-06-04 00:19:09 +04:00
BATADV_SYSFS_IF_MESH_SUBDIR ) ;
2010-12-13 14:19:28 +03:00
goto out ;
}
2012-05-12 20:33:52 +04:00
for ( bat_attr = batadv_mesh_attrs ; * bat_attr ; + + bat_attr ) {
2010-12-13 14:19:28 +03:00
err = sysfs_create_file ( bat_priv - > mesh_obj ,
& ( ( * bat_attr ) - > attr ) ) ;
if ( err ) {
2012-05-16 22:23:22 +04:00
batadv_err ( dev , " Can't add sysfs file: %s/%s/%s \n " ,
2012-06-04 00:19:09 +04:00
dev - > name , BATADV_SYSFS_IF_MESH_SUBDIR ,
2012-05-16 22:23:22 +04:00
( ( * bat_attr ) - > attr ) . name ) ;
2010-12-13 14:19:28 +03:00
goto rem_attr ;
}
}
return 0 ;
rem_attr :
2012-05-12 20:33:52 +04:00
for ( bat_attr = batadv_mesh_attrs ; * bat_attr ; + + bat_attr )
2010-12-13 14:19:28 +03:00
sysfs_remove_file ( bat_priv - > mesh_obj , & ( ( * bat_attr ) - > attr ) ) ;
kobject_put ( bat_priv - > mesh_obj ) ;
bat_priv - > mesh_obj = NULL ;
out :
return - ENOMEM ;
}
2012-05-12 04:09:24 +04:00
void batadv_sysfs_del_meshif ( struct net_device * dev )
2010-12-13 14:19:28 +03:00
{
2012-06-06 00:31:31 +04:00
struct batadv_priv * bat_priv = netdev_priv ( dev ) ;
2012-06-06 00:31:29 +04:00
struct batadv_attribute * * bat_attr ;
2010-12-13 14:19:28 +03:00
2012-05-12 20:33:52 +04:00
for ( bat_attr = batadv_mesh_attrs ; * bat_attr ; + + bat_attr )
2010-12-13 14:19:28 +03:00
sysfs_remove_file ( bat_priv - > mesh_obj , & ( ( * bat_attr ) - > attr ) ) ;
kobject_put ( bat_priv - > mesh_obj ) ;
bat_priv - > mesh_obj = NULL ;
}
2012-05-12 20:33:52 +04:00
static ssize_t batadv_show_mesh_iface ( struct kobject * kobj ,
struct attribute * attr , char * buff )
2010-12-13 14:19:28 +03:00
{
2012-05-12 20:33:52 +04:00
struct net_device * net_dev = batadv_kobj_to_netdev ( kobj ) ;
2012-06-06 00:31:31 +04:00
struct batadv_hard_iface * hard_iface ;
2010-12-13 14:19:28 +03:00
ssize_t length ;
2012-06-04 00:19:19 +04:00
const char * ifname ;
2010-12-13 14:19:28 +03:00
2012-06-06 00:31:31 +04:00
hard_iface = batadv_hardif_get_by_netdev ( net_dev ) ;
2011-02-18 15:33:20 +03:00
if ( ! hard_iface )
2010-12-13 14:19:28 +03:00
return 0 ;
2012-06-04 00:19:19 +04:00
if ( hard_iface - > if_status = = BATADV_IF_NOT_IN_USE )
ifname = " none " ;
else
ifname = hard_iface - > soft_iface - > name ;
length = sprintf ( buff , " %s \n " , ifname ) ;
2010-12-13 14:19:28 +03:00
2012-05-12 15:48:54 +04:00
batadv_hardif_free_ref ( hard_iface ) ;
2010-12-13 14:19:28 +03:00
return length ;
}
2012-05-12 20:33:52 +04:00
static ssize_t batadv_store_mesh_iface ( struct kobject * kobj ,
struct attribute * attr , char * buff ,
size_t count )
2010-12-13 14:19:28 +03:00
{
2012-05-12 20:33:52 +04:00
struct net_device * net_dev = batadv_kobj_to_netdev ( kobj ) ;
2012-06-06 00:31:31 +04:00
struct batadv_hard_iface * hard_iface ;
2010-12-13 14:19:28 +03:00
int status_tmp = - 1 ;
2011-02-10 17:33:51 +03:00
int ret = count ;
2010-12-13 14:19:28 +03:00
2012-06-06 00:31:31 +04:00
hard_iface = batadv_hardif_get_by_netdev ( net_dev ) ;
2011-02-18 15:33:20 +03:00
if ( ! hard_iface )
2010-12-13 14:19:28 +03:00
return count ;
if ( buff [ count - 1 ] = = ' \n ' )
buff [ count - 1 ] = ' \0 ' ;
if ( strlen ( buff ) > = IFNAMSIZ ) {
2012-03-07 12:07:45 +04:00
pr_err ( " Invalid parameter for 'mesh_iface' setting received: interface name too long '%s' \n " ,
buff ) ;
2012-05-12 15:48:54 +04:00
batadv_hardif_free_ref ( hard_iface ) ;
2010-12-13 14:19:28 +03:00
return - EINVAL ;
}
if ( strncmp ( buff , " none " , 4 ) = = 0 )
2012-06-04 00:19:19 +04:00
status_tmp = BATADV_IF_NOT_IN_USE ;
2010-12-13 14:19:28 +03:00
else
2012-06-04 00:19:19 +04:00
status_tmp = BATADV_IF_I_WANT_YOU ;
2010-12-13 14:19:28 +03:00
2011-02-18 15:33:20 +03:00
if ( hard_iface - > if_status = = status_tmp )
goto out ;
if ( ( hard_iface - > soft_iface ) & &
( strncmp ( hard_iface - > soft_iface - > name , buff , IFNAMSIZ ) = = 0 ) )
2011-02-10 17:33:51 +03:00
goto out ;
2010-12-13 14:19:28 +03:00
2013-05-28 19:32:32 +04:00
rtnl_lock ( ) ;
2011-05-03 15:10:06 +04:00
2012-06-04 00:19:19 +04:00
if ( status_tmp = = BATADV_IF_NOT_IN_USE ) {
2013-02-11 13:10:24 +04:00
batadv_hardif_disable_interface ( hard_iface ,
BATADV_IF_CLEANUP_AUTO ) ;
2011-05-03 15:10:06 +04:00
goto unlock ;
2010-12-13 14:19:28 +03:00
}
/* if the interface already is in use */
2012-06-04 00:19:19 +04:00
if ( hard_iface - > if_status ! = BATADV_IF_NOT_IN_USE )
2013-02-11 13:10:24 +04:00
batadv_hardif_disable_interface ( hard_iface ,
BATADV_IF_CLEANUP_AUTO ) ;
2010-12-13 14:19:28 +03:00
2012-05-12 04:09:31 +04:00
ret = batadv_hardif_enable_interface ( hard_iface , buff ) ;
2010-12-13 14:19:28 +03:00
2011-05-03 15:10:06 +04:00
unlock :
rtnl_unlock ( ) ;
2011-02-10 17:33:51 +03:00
out :
2012-05-12 15:48:54 +04:00
batadv_hardif_free_ref ( hard_iface ) ;
2010-12-13 14:19:28 +03:00
return ret ;
}
2012-05-12 20:33:52 +04:00
static ssize_t batadv_show_iface_status ( struct kobject * kobj ,
struct attribute * attr , char * buff )
2010-12-13 14:19:28 +03:00
{
2012-05-12 20:33:52 +04:00
struct net_device * net_dev = batadv_kobj_to_netdev ( kobj ) ;
2012-06-06 00:31:31 +04:00
struct batadv_hard_iface * hard_iface ;
2010-12-13 14:19:28 +03:00
ssize_t length ;
2012-06-06 00:31:31 +04:00
hard_iface = batadv_hardif_get_by_netdev ( net_dev ) ;
2011-02-18 15:33:20 +03:00
if ( ! hard_iface )
2010-12-13 14:19:28 +03:00
return 0 ;
2011-02-18 15:33:20 +03:00
switch ( hard_iface - > if_status ) {
2012-06-04 00:19:19 +04:00
case BATADV_IF_TO_BE_REMOVED :
2010-12-13 14:19:28 +03:00
length = sprintf ( buff , " disabling \n " ) ;
break ;
2012-06-04 00:19:19 +04:00
case BATADV_IF_INACTIVE :
2010-12-13 14:19:28 +03:00
length = sprintf ( buff , " inactive \n " ) ;
break ;
2012-06-04 00:19:19 +04:00
case BATADV_IF_ACTIVE :
2010-12-13 14:19:28 +03:00
length = sprintf ( buff , " active \n " ) ;
break ;
2012-06-04 00:19:19 +04:00
case BATADV_IF_TO_BE_ACTIVATED :
2010-12-13 14:19:28 +03:00
length = sprintf ( buff , " enabling \n " ) ;
break ;
2012-06-04 00:19:19 +04:00
case BATADV_IF_NOT_IN_USE :
2010-12-13 14:19:28 +03:00
default :
length = sprintf ( buff , " not in use \n " ) ;
break ;
}
2012-05-12 15:48:54 +04:00
batadv_hardif_free_ref ( hard_iface ) ;
2010-12-13 14:19:28 +03:00
return length ;
}
2012-06-04 00:19:07 +04:00
static BATADV_ATTR ( mesh_iface , S_IRUGO | S_IWUSR , batadv_show_mesh_iface ,
batadv_store_mesh_iface ) ;
static BATADV_ATTR ( iface_status , S_IRUGO , batadv_show_iface_status , NULL ) ;
2010-12-13 14:19:28 +03:00
2012-06-06 00:31:29 +04:00
static struct batadv_attribute * batadv_batman_attrs [ ] = {
2012-05-12 20:33:52 +04:00
& batadv_attr_mesh_iface ,
& batadv_attr_iface_status ,
2010-12-13 14:19:28 +03:00
NULL ,
} ;
2012-05-12 04:09:24 +04:00
int batadv_sysfs_add_hardif ( struct kobject * * hardif_obj , struct net_device * dev )
2010-12-13 14:19:28 +03:00
{
struct kobject * hardif_kobject = & dev - > dev . kobj ;
2012-06-06 00:31:29 +04:00
struct batadv_attribute * * bat_attr ;
2010-12-13 14:19:28 +03:00
int err ;
2012-06-04 00:19:09 +04:00
* hardif_obj = kobject_create_and_add ( BATADV_SYSFS_IF_BAT_SUBDIR ,
hardif_kobject ) ;
2010-12-13 14:19:28 +03:00
if ( ! * hardif_obj ) {
2012-05-16 22:23:22 +04:00
batadv_err ( dev , " Can't add sysfs directory: %s/%s \n " , dev - > name ,
2012-06-04 00:19:09 +04:00
BATADV_SYSFS_IF_BAT_SUBDIR ) ;
2010-12-13 14:19:28 +03:00
goto out ;
}
2012-05-12 20:33:52 +04:00
for ( bat_attr = batadv_batman_attrs ; * bat_attr ; + + bat_attr ) {
2010-12-13 14:19:28 +03:00
err = sysfs_create_file ( * hardif_obj , & ( ( * bat_attr ) - > attr ) ) ;
if ( err ) {
2012-05-16 22:23:22 +04:00
batadv_err ( dev , " Can't add sysfs file: %s/%s/%s \n " ,
2012-06-04 00:19:09 +04:00
dev - > name , BATADV_SYSFS_IF_BAT_SUBDIR ,
2012-05-16 22:23:22 +04:00
( ( * bat_attr ) - > attr ) . name ) ;
2010-12-13 14:19:28 +03:00
goto rem_attr ;
}
}
return 0 ;
rem_attr :
2012-05-12 20:33:52 +04:00
for ( bat_attr = batadv_batman_attrs ; * bat_attr ; + + bat_attr )
2010-12-13 14:19:28 +03:00
sysfs_remove_file ( * hardif_obj , & ( ( * bat_attr ) - > attr ) ) ;
out :
return - ENOMEM ;
}
2012-05-12 04:09:24 +04:00
void batadv_sysfs_del_hardif ( struct kobject * * hardif_obj )
2010-12-13 14:19:28 +03:00
{
kobject_put ( * hardif_obj ) ;
* hardif_obj = NULL ;
}
2011-04-26 20:26:01 +04:00
2012-06-06 00:31:31 +04:00
int batadv_throw_uevent ( struct batadv_priv * bat_priv , enum batadv_uev_type type ,
2012-06-04 00:19:22 +04:00
enum batadv_uev_action action , const char * data )
2011-04-26 20:26:01 +04:00
{
2012-05-05 15:27:28 +04:00
int ret = - ENOMEM ;
2011-04-26 20:26:01 +04:00
struct kobject * bat_kobj ;
char * uevent_env [ 4 ] = { NULL , NULL , NULL , NULL } ;
2013-01-12 15:19:06 +04:00
bat_kobj = & bat_priv - > soft_iface - > dev . kobj ;
2011-04-26 20:26:01 +04:00
2012-06-04 00:19:07 +04:00
uevent_env [ 0 ] = kmalloc ( strlen ( BATADV_UEV_TYPE_VAR ) +
2012-05-12 20:33:52 +04:00
strlen ( batadv_uev_type_str [ type ] ) + 1 ,
2011-04-26 20:26:01 +04:00
GFP_ATOMIC ) ;
if ( ! uevent_env [ 0 ] )
goto out ;
2012-06-04 00:19:07 +04:00
sprintf ( uevent_env [ 0 ] , " %s%s " , BATADV_UEV_TYPE_VAR ,
batadv_uev_type_str [ type ] ) ;
2011-04-26 20:26:01 +04:00
2012-06-04 00:19:07 +04:00
uevent_env [ 1 ] = kmalloc ( strlen ( BATADV_UEV_ACTION_VAR ) +
2012-05-12 20:33:52 +04:00
strlen ( batadv_uev_action_str [ action ] ) + 1 ,
2011-04-26 20:26:01 +04:00
GFP_ATOMIC ) ;
if ( ! uevent_env [ 1 ] )
goto out ;
2012-06-04 00:19:07 +04:00
sprintf ( uevent_env [ 1 ] , " %s%s " , BATADV_UEV_ACTION_VAR ,
2012-05-12 20:33:52 +04:00
batadv_uev_action_str [ action ] ) ;
2011-04-26 20:26:01 +04:00
/* If the event is DEL, ignore the data field */
2012-06-04 00:19:22 +04:00
if ( action ! = BATADV_UEV_DEL ) {
2012-06-04 00:19:07 +04:00
uevent_env [ 2 ] = kmalloc ( strlen ( BATADV_UEV_DATA_VAR ) +
2011-04-26 20:26:01 +04:00
strlen ( data ) + 1 , GFP_ATOMIC ) ;
if ( ! uevent_env [ 2 ] )
goto out ;
2012-06-04 00:19:07 +04:00
sprintf ( uevent_env [ 2 ] , " %s%s " , BATADV_UEV_DATA_VAR , data ) ;
2011-04-26 20:26:01 +04:00
}
ret = kobject_uevent_env ( bat_kobj , KOBJ_CHANGE , uevent_env ) ;
out :
kfree ( uevent_env [ 0 ] ) ;
kfree ( uevent_env [ 1 ] ) ;
kfree ( uevent_env [ 2 ] ) ;
if ( ret )
2012-06-04 00:19:22 +04:00
batadv_dbg ( BATADV_DBG_BATMAN , bat_priv ,
2012-05-12 15:48:58 +04:00
" Impossible to send uevent for (%s,%s,%s) event (err: %d) \n " ,
2012-05-12 20:33:52 +04:00
batadv_uev_type_str [ type ] ,
batadv_uev_action_str [ action ] ,
2012-06-04 00:19:22 +04:00
( action = = BATADV_UEV_DEL ? " NULL " : data ) , ret ) ;
2011-04-26 20:26:01 +04:00
return ret ;
}