sysfs.c 26.3 KB
Newer Older
1
/* Copyright (C) 2010-2015 B.A.T.M.A.N. contributors:
2 3 4 5 6 7 8 9 10 11 12 13 14
 *
 * 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
15
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 17
 */

18
#include "sysfs.h"
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
#include "main.h"

#include <linux/atomic.h>
#include <linux/compiler.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/if.h>
#include <linux/if_vlan.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/printk.h>
#include <linux/rculist.h>
#include <linux/rcupdate.h>
#include <linux/rtnetlink.h>
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/stddef.h>
#include <linux/string.h>
#include <linux/stringify.h>

40
#include "distributed-arp-table.h"
41 42
#include "gateway_client.h"
#include "gateway_common.h"
43
#include "bridge_loop_avoidance.h"
44
#include "hard-interface.h"
45 46
#include "network-coding.h"
#include "packet.h"
47
#include "soft-interface.h"
48

49
static struct net_device *batadv_kobj_to_netdev(struct kobject *obj)
50 51
{
	struct device *dev = container_of(obj->parent, struct device, kobj);
52

53 54 55
	return to_net_dev(dev);
}

56
static struct batadv_priv *batadv_kobj_to_batpriv(struct kobject *obj)
57
{
58
	struct net_device *net_dev = batadv_kobj_to_netdev(obj);
59

60 61
	return netdev_priv(net_dev);
}
62

63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
/**
 * batadv_vlan_kobj_to_batpriv - convert a vlan kobj in the associated batpriv
 * @obj: kobject to covert
 *
 * Returns the associated batadv_priv struct.
 */
static struct batadv_priv *batadv_vlan_kobj_to_batpriv(struct kobject *obj)
{
	/* VLAN specific attributes are located in the root sysfs folder if they
	 * refer to the untagged VLAN..
	 */
	if (!strcmp(BATADV_SYSFS_IF_MESH_SUBDIR, obj->name))
		return batadv_kobj_to_batpriv(obj);

	/* ..while the attributes for the tagged vlans are located in
	 * the in the corresponding "vlan%VID" subfolder
	 */
	return batadv_kobj_to_batpriv(obj->parent);
}

/**
 * batadv_kobj_to_vlan - convert a kobj in the associated softif_vlan struct
 * @obj: kobject to covert
 *
 * Returns the associated softif_vlan struct if found, NULL otherwise.
 */
static struct batadv_softif_vlan *
batadv_kobj_to_vlan(struct batadv_priv *bat_priv, struct kobject *obj)
{
	struct batadv_softif_vlan *vlan_tmp, *vlan = NULL;

	rcu_read_lock();
	hlist_for_each_entry_rcu(vlan_tmp, &bat_priv->softif_vlan_list, list) {
		if (vlan_tmp->kobj != obj)
			continue;

		if (!atomic_inc_not_zero(&vlan_tmp->refcount))
			continue;

		vlan = vlan_tmp;
		break;
	}
	rcu_read_unlock();

	return vlan;
}

110 111 112
#define BATADV_UEV_TYPE_VAR	"BATTYPE="
#define BATADV_UEV_ACTION_VAR	"BATACTION="
#define BATADV_UEV_DATA_VAR	"BATDATA="
113

114
static char *batadv_uev_action_str[] = {
115 116 117 118 119
	"add",
	"del",
	"change"
};

120
static char *batadv_uev_type_str[] = {
121 122 123
	"gw"
};

124 125 126 127 128 129 130
/* Use this, if you have customized show and store functions for vlan attrs */
#define BATADV_ATTR_VLAN(_name, _mode, _show, _store)	\
struct batadv_attribute batadv_attr_vlan_##_name = {	\
	.attr = {.name = __stringify(_name),		\
		 .mode = _mode },			\
	.show   = _show,				\
	.store  = _store,				\
131
}
132

133
/* Use this, if you have customized show and store functions */
134
#define BATADV_ATTR(_name, _mode, _show, _store)	\
135
struct batadv_attribute batadv_attr_##_name = {		\
136 137 138 139
	.attr = {.name = __stringify(_name),		\
		 .mode = _mode },			\
	.show   = _show,				\
	.store  = _store,				\
140
}
141

142
#define BATADV_ATTR_SIF_STORE_BOOL(_name, _post_func)			\
143 144 145
ssize_t batadv_store_##_name(struct kobject *kobj,			\
			     struct attribute *attr, char *buff,	\
			     size_t count)				\
146
{									\
147
	struct net_device *net_dev = batadv_kobj_to_netdev(kobj);	\
148
	struct batadv_priv *bat_priv = netdev_priv(net_dev);		\
149
									\
150 151
	return __batadv_store_bool_attr(buff, count, _post_func, attr,	\
					&bat_priv->_name, net_dev);	\
152 153
}

154
#define BATADV_ATTR_SIF_SHOW_BOOL(_name)				\
155 156
ssize_t batadv_show_##_name(struct kobject *kobj,			\
			    struct attribute *attr, char *buff)		\
157
{									\
158
	struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);	\
159
									\
160 161 162 163 164
	return sprintf(buff, "%s\n",					\
		       atomic_read(&bat_priv->_name) == 0 ?		\
		       "disabled" : "enabled");				\
}									\

165
/* Use this, if you are going to turn a [name] in the soft-interface
166 167
 * (bat_priv) on or off
 */
168 169 170 171 172
#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)
173

174
#define BATADV_ATTR_SIF_STORE_UINT(_name, _var, _min, _max, _post_func)	\
175 176 177
ssize_t batadv_store_##_name(struct kobject *kobj,			\
			     struct attribute *attr, char *buff,	\
			     size_t count)				\
178
{									\
179
	struct net_device *net_dev = batadv_kobj_to_netdev(kobj);	\
180
	struct batadv_priv *bat_priv = netdev_priv(net_dev);		\
181
									\
182 183
	return __batadv_store_uint_attr(buff, count, _min, _max,	\
					_post_func, attr,		\
184
					&bat_priv->_var, net_dev);	\
185 186
}

187
#define BATADV_ATTR_SIF_SHOW_UINT(_name, _var)				\
188 189
ssize_t batadv_show_##_name(struct kobject *kobj,			\
			    struct attribute *attr, char *buff)		\
190
{									\
191
	struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);	\
192
									\
193
	return sprintf(buff, "%i\n", atomic_read(&bat_priv->_var));	\
194 195
}									\

196
/* Use this, if you are going to set [name] in the soft-interface
197 198
 * (bat_priv) to an unsigned integer value
 */
199 200 201
#define BATADV_ATTR_SIF_UINT(_name, _var, _mode, _min, _max, _post_func)\
	static BATADV_ATTR_SIF_STORE_UINT(_name, _var, _min, _max, _post_func)\
	static BATADV_ATTR_SIF_SHOW_UINT(_name, _var)			\
202 203
	static BATADV_ATTR(_name, _mode, batadv_show_##_name,		\
			   batadv_store_##_name)
204

205 206 207 208 209 210 211 212 213 214 215
#define BATADV_ATTR_VLAN_STORE_BOOL(_name, _post_func)			\
ssize_t batadv_store_vlan_##_name(struct kobject *kobj,			\
				  struct attribute *attr, char *buff,	\
				  size_t count)				\
{									\
	struct batadv_priv *bat_priv = batadv_vlan_kobj_to_batpriv(kobj);\
	struct batadv_softif_vlan *vlan = batadv_kobj_to_vlan(bat_priv,	\
							      kobj);	\
	size_t res = __batadv_store_bool_attr(buff, count, _post_func,	\
					      attr, &vlan->_name,	\
					      bat_priv->soft_iface);	\
216
									\
217 218 219 220 221 222 223 224 225 226 227 228 229 230
	batadv_softif_vlan_free_ref(vlan);				\
	return res;							\
}

#define BATADV_ATTR_VLAN_SHOW_BOOL(_name)				\
ssize_t batadv_show_vlan_##_name(struct kobject *kobj,			\
				 struct attribute *attr, char *buff)	\
{									\
	struct batadv_priv *bat_priv = batadv_vlan_kobj_to_batpriv(kobj);\
	struct batadv_softif_vlan *vlan = batadv_kobj_to_vlan(bat_priv,	\
							      kobj);	\
	size_t res = sprintf(buff, "%s\n",				\
			     atomic_read(&vlan->_name) == 0 ?		\
			     "disabled" : "enabled");			\
231
									\
232 233 234 235 236 237 238 239 240 241
	batadv_softif_vlan_free_ref(vlan);				\
	return res;							\
}

/* Use this, if you are going to turn a [name] in the vlan struct on or off */
#define BATADV_ATTR_VLAN_BOOL(_name, _mode, _post_func)			\
	static BATADV_ATTR_VLAN_STORE_BOOL(_name, _post_func)		\
	static BATADV_ATTR_VLAN_SHOW_BOOL(_name)			\
	static BATADV_ATTR_VLAN(_name, _mode, batadv_show_vlan_##_name,	\
				batadv_store_vlan_##_name)
242

243 244 245
static int batadv_store_bool_attr(char *buff, size_t count,
				  struct net_device *net_dev,
				  const char *attr_name, atomic_t *attr)
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
{
	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) {
263 264
		batadv_info(net_dev, "%s: Invalid parameter received: %s\n",
			    attr_name, buff);
265 266 267 268 269 270
		return -EINVAL;
	}

	if (atomic_read(attr) == enabled)
		return count;

271 272 273
	batadv_info(net_dev, "%s: Changing from: %s to: %s\n", attr_name,
		    atomic_read(attr) == 1 ? "enabled" : "disabled",
		    enabled == 1 ? "enabled" : "disabled");
274

275
	atomic_set(attr, (unsigned int)enabled);
276 277 278
	return count;
}

279 280 281 282 283
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)
284 285 286
{
	int ret;

287 288
	ret = batadv_store_bool_attr(buff, count, net_dev, attr->name,
				     attr_store);
289 290 291 292 293 294
	if (post_func && ret)
		post_func(net_dev);

	return ret;
}

295 296 297 298 299
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)
300 301 302 303
{
	unsigned long uint_val;
	int ret;

304
	ret = kstrtoul(buff, 10, &uint_val);
305
	if (ret) {
306 307
		batadv_info(net_dev, "%s: Invalid parameter received: %s\n",
			    attr_name, buff);
308 309 310 311
		return -EINVAL;
	}

	if (uint_val < min) {
312 313
		batadv_info(net_dev, "%s: Value is too small: %lu min: %u\n",
			    attr_name, uint_val, min);
314 315 316 317
		return -EINVAL;
	}

	if (uint_val > max) {
318 319
		batadv_info(net_dev, "%s: Value is too big: %lu max: %u\n",
			    attr_name, uint_val, max);
320 321 322 323 324 325
		return -EINVAL;
	}

	if (atomic_read(attr) == uint_val)
		return count;

326 327
	batadv_info(net_dev, "%s: Changing from: %i to: %lu\n",
		    attr_name, atomic_read(attr), uint_val);
328 329 330 331 332

	atomic_set(attr, uint_val);
	return count;
}

333 334 335 336 337 338
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)
339 340 341
{
	int ret;

342 343
	ret = batadv_store_uint_attr(buff, count, net_dev, attr->name, min, max,
				     attr_store);
344 345 346 347 348 349
	if (post_func && ret)
		post_func(net_dev);

	return ret;
}

350 351
static ssize_t batadv_show_bat_algo(struct kobject *kobj,
				    struct attribute *attr, char *buff)
352
{
353
	struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
354

355 356 357
	return sprintf(buff, "%s\n", bat_priv->bat_algo_ops->name);
}

358
static void batadv_post_gw_reselect(struct net_device *net_dev)
359
{
360
	struct batadv_priv *bat_priv = netdev_priv(net_dev);
361

362
	batadv_gw_reselect(bat_priv);
363 364
}

365 366
static ssize_t batadv_show_gw_mode(struct kobject *kobj, struct attribute *attr,
				   char *buff)
367
{
368
	struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
369 370 371
	int bytes_written;

	switch (atomic_read(&bat_priv->gw_mode)) {
372
	case BATADV_GW_MODE_CLIENT:
373 374
		bytes_written = sprintf(buff, "%s\n",
					BATADV_GW_MODE_CLIENT_NAME);
375
		break;
376
	case BATADV_GW_MODE_SERVER:
377 378
		bytes_written = sprintf(buff, "%s\n",
					BATADV_GW_MODE_SERVER_NAME);
379 380
		break;
	default:
381 382
		bytes_written = sprintf(buff, "%s\n",
					BATADV_GW_MODE_OFF_NAME);
383 384 385 386 387 388
		break;
	}

	return bytes_written;
}

389 390 391
static ssize_t batadv_store_gw_mode(struct kobject *kobj,
				    struct attribute *attr, char *buff,
				    size_t count)
392
{
393
	struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
394
	struct batadv_priv *bat_priv = netdev_priv(net_dev);
395 396 397 398 399 400
	char *curr_gw_mode_str;
	int gw_mode_tmp = -1;

	if (buff[count - 1] == '\n')
		buff[count - 1] = '\0';

401 402
	if (strncmp(buff, BATADV_GW_MODE_OFF_NAME,
		    strlen(BATADV_GW_MODE_OFF_NAME)) == 0)
403
		gw_mode_tmp = BATADV_GW_MODE_OFF;
404

405 406
	if (strncmp(buff, BATADV_GW_MODE_CLIENT_NAME,
		    strlen(BATADV_GW_MODE_CLIENT_NAME)) == 0)
407
		gw_mode_tmp = BATADV_GW_MODE_CLIENT;
408

409 410
	if (strncmp(buff, BATADV_GW_MODE_SERVER_NAME,
		    strlen(BATADV_GW_MODE_SERVER_NAME)) == 0)
411
		gw_mode_tmp = BATADV_GW_MODE_SERVER;
412 413

	if (gw_mode_tmp < 0) {
414 415 416
		batadv_info(net_dev,
			    "Invalid parameter for 'gw mode' setting received: %s\n",
			    buff);
417 418 419 420 421 422 423
		return -EINVAL;
	}

	if (atomic_read(&bat_priv->gw_mode) == gw_mode_tmp)
		return count;

	switch (atomic_read(&bat_priv->gw_mode)) {
424
	case BATADV_GW_MODE_CLIENT:
425
		curr_gw_mode_str = BATADV_GW_MODE_CLIENT_NAME;
426
		break;
427
	case BATADV_GW_MODE_SERVER:
428
		curr_gw_mode_str = BATADV_GW_MODE_SERVER_NAME;
429 430
		break;
	default:
431
		curr_gw_mode_str = BATADV_GW_MODE_OFF_NAME;
432 433 434
		break;
	}

435 436
	batadv_info(net_dev, "Changing gw mode from: %s to: %s\n",
		    curr_gw_mode_str, buff);
437

438 439 440 441 442 443 444 445 446
	/* Invoking batadv_gw_reselect() is not enough to really de-select the
	 * current GW. It will only instruct the gateway client code to perform
	 * a re-election the next time that this is needed.
	 *
	 * When gw client mode is being switched off the current GW must be
	 * de-selected explicitly otherwise no GW_ADD uevent is thrown on
	 * client mode re-activation. This is operation is performed in
	 * batadv_gw_check_client_stop().
	 */
447
	batadv_gw_reselect(bat_priv);
448 449 450 451
	/* always call batadv_gw_check_client_stop() before changing the gateway
	 * state
	 */
	batadv_gw_check_client_stop(bat_priv);
452
	atomic_set(&bat_priv->gw_mode, (unsigned int)gw_mode_tmp);
453
	batadv_gw_tvlv_container_update(bat_priv);
454 455 456
	return count;
}

457 458
static ssize_t batadv_show_gw_bwidth(struct kobject *kobj,
				     struct attribute *attr, char *buff)
459
{
460
	struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
461
	u32 down, up;
462 463 464 465 466 467

	down = atomic_read(&bat_priv->gw.bandwidth_down);
	up = atomic_read(&bat_priv->gw.bandwidth_up);

	return sprintf(buff, "%u.%u/%u.%u MBit\n", down / 10,
		       down % 10, up / 10, up % 10);
468 469
}

470 471 472
static ssize_t batadv_store_gw_bwidth(struct kobject *kobj,
				      struct attribute *attr, char *buff,
				      size_t count)
473
{
474
	struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
475 476 477 478

	if (buff[count - 1] == '\n')
		buff[count - 1] = '\0';

479
	return batadv_gw_bandwidth_set(net_dev, buff, count);
480 481
}

482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515
/**
 * batadv_show_isolation_mark - print the current isolation mark/mask
 * @kobj: kobject representing the private mesh sysfs directory
 * @attr: the batman-adv attribute the user is interacting with
 * @buff: the buffer that will contain the data to send back to the user
 *
 * Returns the number of bytes written into 'buff' on success or a negative
 * error code in case of failure
 */
static ssize_t batadv_show_isolation_mark(struct kobject *kobj,
					  struct attribute *attr, char *buff)
{
	struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);

	return sprintf(buff, "%#.8x/%#.8x\n", bat_priv->isolation_mark,
		       bat_priv->isolation_mark_mask);
}

/**
 * batadv_store_isolation_mark - parse and store the isolation mark/mask entered
 *  by the user
 * @kobj: kobject representing the private mesh sysfs directory
 * @attr: the batman-adv attribute the user is interacting with
 * @buff: the buffer containing the user data
 * @count: number of bytes in the buffer
 *
 * Returns 'count' on success or a negative error code in case of failure
 */
static ssize_t batadv_store_isolation_mark(struct kobject *kobj,
					   struct attribute *attr, char *buff,
					   size_t count)
{
	struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
	struct batadv_priv *bat_priv = netdev_priv(net_dev);
516
	u32 mark, mask;
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549
	char *mask_ptr;

	/* parse the mask if it has been specified, otherwise assume the mask is
	 * the biggest possible
	 */
	mask = 0xFFFFFFFF;
	mask_ptr = strchr(buff, '/');
	if (mask_ptr) {
		*mask_ptr = '\0';
		mask_ptr++;

		/* the mask must be entered in hex base as it is going to be a
		 * bitmask and not a prefix length
		 */
		if (kstrtou32(mask_ptr, 16, &mask) < 0)
			return -EINVAL;
	}

	/* the mark can be entered in any base */
	if (kstrtou32(buff, 0, &mark) < 0)
		return -EINVAL;

	bat_priv->isolation_mark_mask = mask;
	/* erase bits not covered by the mask */
	bat_priv->isolation_mark = mark & bat_priv->isolation_mark_mask;

	batadv_info(net_dev,
		    "New skb mark for extended isolation: %#.8x/%#.8x\n",
		    bat_priv->isolation_mark, bat_priv->isolation_mark_mask);

	return count;
}

550 551
BATADV_ATTR_SIF_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL);
BATADV_ATTR_SIF_BOOL(bonding, S_IRUGO | S_IWUSR, NULL);
552
#ifdef CONFIG_BATMAN_ADV_BLA
553 554
BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR,
		     batadv_bla_status_update);
555
#endif
556
#ifdef CONFIG_BATMAN_ADV_DAT
557 558
BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR,
		     batadv_dat_status_update);
559
#endif
560 561 562 563
BATADV_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, batadv_update_min_mtu);
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);
564 565 566 567 568 569
BATADV_ATTR_SIF_UINT(orig_interval, orig_interval, S_IRUGO | S_IWUSR,
		     2 * BATADV_JITTER, INT_MAX, NULL);
BATADV_ATTR_SIF_UINT(hop_penalty, hop_penalty, S_IRUGO | S_IWUSR, 0,
		     BATADV_TQ_MAX_VALUE, NULL);
BATADV_ATTR_SIF_UINT(gw_sel_class, gw_sel_class, S_IRUGO | S_IWUSR, 1,
		     BATADV_TQ_MAX_VALUE, batadv_post_gw_reselect);
570 571
static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth,
		   batadv_store_gw_bwidth);
572 573 574
#ifdef CONFIG_BATMAN_ADV_MCAST
BATADV_ATTR_SIF_BOOL(multicast_mode, S_IRUGO | S_IWUSR, NULL);
#endif
575
#ifdef CONFIG_BATMAN_ADV_DEBUG
576 577
BATADV_ATTR_SIF_UINT(log_level, log_level, S_IRUGO | S_IWUSR, 0,
		     BATADV_DBG_ALL, NULL);
578
#endif
579
#ifdef CONFIG_BATMAN_ADV_NC
580 581
BATADV_ATTR_SIF_BOOL(network_coding, S_IRUGO | S_IWUSR,
		     batadv_nc_status_update);
582
#endif
583 584
static BATADV_ATTR(isolation_mark, S_IRUGO | S_IWUSR,
		   batadv_show_isolation_mark, batadv_store_isolation_mark);
585

586
static struct batadv_attribute *batadv_mesh_attrs[] = {
587 588
	&batadv_attr_aggregated_ogms,
	&batadv_attr_bonding,
589
#ifdef CONFIG_BATMAN_ADV_BLA
590
	&batadv_attr_bridge_loop_avoidance,
591 592 593
#endif
#ifdef CONFIG_BATMAN_ADV_DAT
	&batadv_attr_distributed_arp_table,
594 595 596
#endif
#ifdef CONFIG_BATMAN_ADV_MCAST
	&batadv_attr_multicast_mode,
597
#endif
598 599 600 601 602 603 604
	&batadv_attr_fragmentation,
	&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,
605
#ifdef CONFIG_BATMAN_ADV_DEBUG
606
	&batadv_attr_log_level,
607 608 609
#endif
#ifdef CONFIG_BATMAN_ADV_NC
	&batadv_attr_network_coding,
610
#endif
611
	&batadv_attr_isolation_mark,
612 613 614
	NULL,
};

615 616
BATADV_ATTR_VLAN_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL);

617 618 619 620
/**
 * batadv_vlan_attrs - array of vlan specific sysfs attributes
 */
static struct batadv_attribute *batadv_vlan_attrs[] = {
621
	&batadv_attr_vlan_ap_isolation,
622 623 624
	NULL,
};

625
int batadv_sysfs_add_meshif(struct net_device *dev)
626 627
{
	struct kobject *batif_kobject = &dev->dev.kobj;
628
	struct batadv_priv *bat_priv = netdev_priv(dev);
629
	struct batadv_attribute **bat_attr;
630 631
	int err;

632
	bat_priv->mesh_obj = kobject_create_and_add(BATADV_SYSFS_IF_MESH_SUBDIR,
633 634
						    batif_kobject);
	if (!bat_priv->mesh_obj) {
635
		batadv_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
636
			   BATADV_SYSFS_IF_MESH_SUBDIR);
637 638 639
		goto out;
	}

640
	for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr) {
641 642 643
		err = sysfs_create_file(bat_priv->mesh_obj,
					&((*bat_attr)->attr));
		if (err) {
644
			batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n",
645
				   dev->name, BATADV_SYSFS_IF_MESH_SUBDIR,
646
				   ((*bat_attr)->attr).name);
647 648 649 650 651 652 653
			goto rem_attr;
		}
	}

	return 0;

rem_attr:
654
	for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr)
655 656 657 658 659 660 661 662
		sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));

	kobject_put(bat_priv->mesh_obj);
	bat_priv->mesh_obj = NULL;
out:
	return -ENOMEM;
}

663
void batadv_sysfs_del_meshif(struct net_device *dev)
664
{
665
	struct batadv_priv *bat_priv = netdev_priv(dev);
666
	struct batadv_attribute **bat_attr;
667

668
	for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr)
669 670 671 672 673 674
		sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));

	kobject_put(bat_priv->mesh_obj);
	bat_priv->mesh_obj = NULL;
}

675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748
/**
 * batadv_sysfs_add_vlan - add all the needed sysfs objects for the new vlan
 * @dev: netdev of the mesh interface
 * @vlan: private data of the newly added VLAN interface
 *
 * Returns 0 on success and -ENOMEM if any of the structure allocations fails.
 */
int batadv_sysfs_add_vlan(struct net_device *dev,
			  struct batadv_softif_vlan *vlan)
{
	char vlan_subdir[sizeof(BATADV_SYSFS_VLAN_SUBDIR_PREFIX) + 5];
	struct batadv_priv *bat_priv = netdev_priv(dev);
	struct batadv_attribute **bat_attr;
	int err;

	if (vlan->vid & BATADV_VLAN_HAS_TAG) {
		sprintf(vlan_subdir, BATADV_SYSFS_VLAN_SUBDIR_PREFIX "%hu",
			vlan->vid & VLAN_VID_MASK);

		vlan->kobj = kobject_create_and_add(vlan_subdir,
						    bat_priv->mesh_obj);
		if (!vlan->kobj) {
			batadv_err(dev, "Can't add sysfs directory: %s/%s\n",
				   dev->name, vlan_subdir);
			goto out;
		}
	} else {
		/* the untagged LAN uses the root folder to store its "VLAN
		 * specific attributes"
		 */
		vlan->kobj = bat_priv->mesh_obj;
		kobject_get(bat_priv->mesh_obj);
	}

	for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr) {
		err = sysfs_create_file(vlan->kobj,
					&((*bat_attr)->attr));
		if (err) {
			batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n",
				   dev->name, vlan_subdir,
				   ((*bat_attr)->attr).name);
			goto rem_attr;
		}
	}

	return 0;

rem_attr:
	for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr)
		sysfs_remove_file(vlan->kobj, &((*bat_attr)->attr));

	kobject_put(vlan->kobj);
	vlan->kobj = NULL;
out:
	return -ENOMEM;
}

/**
 * batadv_sysfs_del_vlan - remove all the sysfs objects for a given VLAN
 * @bat_priv: the bat priv with all the soft interface information
 * @vlan: the private data of the VLAN to destroy
 */
void batadv_sysfs_del_vlan(struct batadv_priv *bat_priv,
			   struct batadv_softif_vlan *vlan)
{
	struct batadv_attribute **bat_attr;

	for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr)
		sysfs_remove_file(vlan->kobj, &((*bat_attr)->attr));

	kobject_put(vlan->kobj);
	vlan->kobj = NULL;
}

749 750
static ssize_t batadv_show_mesh_iface(struct kobject *kobj,
				      struct attribute *attr, char *buff)
751
{
752
	struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
753
	struct batadv_hard_iface *hard_iface;
754
	ssize_t length;
755
	const char *ifname;
756

757
	hard_iface = batadv_hardif_get_by_netdev(net_dev);
758
	if (!hard_iface)
759 760
		return 0;

761 762 763 764 765 766
	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);
767

768
	batadv_hardif_free_ref(hard_iface);
769 770 771 772

	return length;
}

773 774 775
static ssize_t batadv_store_mesh_iface(struct kobject *kobj,
				       struct attribute *attr, char *buff,
				       size_t count)
776
{
777
	struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
778
	struct batadv_hard_iface *hard_iface;
779
	int status_tmp = -1;
780
	int ret = count;
781

782
	hard_iface = batadv_hardif_get_by_netdev(net_dev);
783
	if (!hard_iface)
784 785 786 787 788 789
		return count;

	if (buff[count - 1] == '\n')
		buff[count - 1] = '\0';

	if (strlen(buff) >= IFNAMSIZ) {
790 791
		pr_err("Invalid parameter for 'mesh_iface' setting received: interface name too long '%s'\n",
		       buff);
792
		batadv_hardif_free_ref(hard_iface);
793 794 795 796
		return -EINVAL;
	}

	if (strncmp(buff, "none", 4) == 0)
797
		status_tmp = BATADV_IF_NOT_IN_USE;
798
	else
799
		status_tmp = BATADV_IF_I_WANT_YOU;
800

801 802 803 804 805
	if (hard_iface->if_status == status_tmp)
		goto out;

	if ((hard_iface->soft_iface) &&
	    (strncmp(hard_iface->soft_iface->name, buff, IFNAMSIZ) == 0))
806
		goto out;
807

808
	rtnl_lock();
809

810
	if (status_tmp == BATADV_IF_NOT_IN_USE) {
811 812
		batadv_hardif_disable_interface(hard_iface,
						BATADV_IF_CLEANUP_AUTO);
813
		goto unlock;
814 815 816
	}

	/* if the interface already is in use */
817
	if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
818 819
		batadv_hardif_disable_interface(hard_iface,
						BATADV_IF_CLEANUP_AUTO);
820

821
	ret = batadv_hardif_enable_interface(hard_iface, buff);
822

823 824
unlock:
	rtnl_unlock();
825
out:
826
	batadv_hardif_free_ref(hard_iface);
827 828 829
	return ret;
}

830 831
static ssize_t batadv_show_iface_status(struct kobject *kobj,
					struct attribute *attr, char *buff)
832
{
833
	struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
834
	struct batadv_hard_iface *hard_iface;
835 836
	ssize_t length;

837
	hard_iface = batadv_hardif_get_by_netdev(net_dev);
838
	if (!hard_iface)
839 840
		return 0;

841
	switch (hard_iface->if_status) {
842
	case BATADV_IF_TO_BE_REMOVED:
843 844
		length = sprintf(buff, "disabling\n");
		break;
845
	case BATADV_IF_INACTIVE:
846 847
		length = sprintf(buff, "inactive\n");
		break;
848
	case BATADV_IF_ACTIVE:
849 850
		length = sprintf(buff, "active\n");
		break;
851
	case BATADV_IF_TO_BE_ACTIVATED:
852 853
		length = sprintf(buff, "enabling\n");
		break;
854
	case BATADV_IF_NOT_IN_USE:
855 856 857 858 859
	default:
		length = sprintf(buff, "not in use\n");
		break;
	}

860
	batadv_hardif_free_ref(hard_iface);
861 862 863 864

	return length;
}

865 866 867
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);
868

869
static struct batadv_attribute *batadv_batman_attrs[] = {
870 871
	&batadv_attr_mesh_iface,
	&batadv_attr_iface_status,
872 873 874
	NULL,
};

875
int batadv_sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev)
876 877
{
	struct kobject *hardif_kobject = &dev->dev.kobj;
878
	struct batadv_attribute **bat_attr;
879 880
	int err;

881 882
	*hardif_obj = kobject_create_and_add(BATADV_SYSFS_IF_BAT_SUBDIR,
					     hardif_kobject);
883 884

	if (!*hardif_obj) {
885
		batadv_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
886
			   BATADV_SYSFS_IF_BAT_SUBDIR);
887 888 889
		goto out;
	}

890
	for (bat_attr = batadv_batman_attrs; *bat_attr; ++bat_attr) {
891 892
		err = sysfs_create_file(*hardif_obj, &((*bat_attr)->attr));
		if (err) {
893
			batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n",
894
				   dev->name, BATADV_SYSFS_IF_BAT_SUBDIR,
895
				   ((*bat_attr)->attr).name);
896 897 898 899 900 901 902
			goto rem_attr;
		}
	}

	return 0;

rem_attr:
903
	for (bat_attr = batadv_batman_attrs; *bat_attr; ++bat_attr)
904 905 906 907 908
		sysfs_remove_file(*hardif_obj, &((*bat_attr)->attr));
out:
	return -ENOMEM;
}

909
void batadv_sysfs_del_hardif(struct kobject **hardif_obj)
910 911 912 913
{
	kobject_put(*hardif_obj);
	*hardif_obj = NULL;
}
914

915
int batadv_throw_uevent(struct batadv_priv *bat_priv, enum batadv_uev_type type,
916
			enum batadv_uev_action action, const char *data)
917
{
918
	int ret = -ENOMEM;
919 920 921
	struct kobject *bat_kobj;
	char *uevent_env[4] = { NULL, NULL, NULL, NULL };

922
	bat_kobj = &bat_priv->soft_iface->dev.kobj;
923

H
Himangi Saraogi 已提交
924 925 926
	uevent_env[0] = kasprintf(GFP_ATOMIC,
				  "%s%s", BATADV_UEV_TYPE_VAR,
				  batadv_uev_type_str[type]);
927 928 929
	if (!uevent_env[0])
		goto out;

H
Himangi Saraogi 已提交
930 931 932
	uevent_env[1] = kasprintf(GFP_ATOMIC,
				  "%s%s", BATADV_UEV_ACTION_VAR,
				  batadv_uev_action_str[action]);
933 934 935 936
	if (!uevent_env[1])
		goto out;

	/* If the event is DEL, ignore the data field */
937
	if (action != BATADV_UEV_DEL) {
H
Himangi Saraogi 已提交
938 939
		uevent_env[2] = kasprintf(GFP_ATOMIC,
					  "%s%s", BATADV_UEV_DATA_VAR, data);
940 941 942 943 944 945 946 947 948 949 950
		if (!uevent_env[2])
			goto out;
	}

	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)
951
		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
952
			   "Impossible to send uevent for (%s,%s,%s) event (err: %d)\n",
953 954
			   batadv_uev_type_str[type],
			   batadv_uev_action_str[action],
955
			   (action == BATADV_UEV_DEL ? "NULL" : data), ret);
956 957
	return ret;
}