sysfs.c 26.5 KB
Newer Older
1
/* Copyright (C) 2010-2016  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
#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>
28
#include <linux/kref.h>
29 30 31 32 33 34 35 36 37 38 39 40
#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>

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

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

54 55 56
	return to_net_dev(dev);
}

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

61 62
	return netdev_priv(net_dev);
}
63

64 65 66 67
/**
 * batadv_vlan_kobj_to_batpriv - convert a vlan kobj in the associated batpriv
 * @obj: kobject to covert
 *
68
 * Return: the associated batadv_priv struct.
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
 */
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
86
 * @bat_priv: the bat priv with all the soft interface information
87 88
 * @obj: kobject to covert
 *
89
 * Return: the associated softif_vlan struct if found, NULL otherwise.
90 91 92 93 94 95 96 97 98 99 100
 */
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;

101
		if (!kref_get_unless_zero(&vlan_tmp->refcount))
102 103 104 105 106 107 108 109 110 111
			continue;

		vlan = vlan_tmp;
		break;
	}
	rcu_read_unlock();

	return vlan;
}

112 113 114
#define BATADV_UEV_TYPE_VAR	"BATTYPE="
#define BATADV_UEV_ACTION_VAR	"BATACTION="
#define BATADV_UEV_DATA_VAR	"BATDATA="
115

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

122
static char *batadv_uev_type_str[] = {
123 124 125
	"gw"
};

126 127 128 129 130 131 132
/* 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,				\
133
}
134

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

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

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

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

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

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

198
/* Use this, if you are going to set [name] in the soft-interface
199 200
 * (bat_priv) to an unsigned integer value
 */
201 202 203
#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)			\
204 205
	static BATADV_ATTR(_name, _mode, batadv_show_##_name,		\
			   batadv_store_##_name)
206

207 208 209 210 211 212 213 214 215 216 217
#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);	\
218
									\
219 220 221 222 223 224 225 226 227 228 229 230 231 232
	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");			\
233
									\
234 235 236 237 238 239 240 241 242 243
	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)
244

245 246
static int batadv_store_bool_attr(char *buff, size_t count,
				  struct net_device *net_dev,
247 248
				  const char *attr_name, atomic_t *attr,
				  bool *changed)
249 250 251
{
	int enabled = -1;

252 253
	*changed = false;

254 255 256 257 258 259 260 261 262 263 264 265 266 267
	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) {
268 269
		batadv_info(net_dev, "%s: Invalid parameter received: %s\n",
			    attr_name, buff);
270 271 272 273 274 275
		return -EINVAL;
	}

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

276 277 278
	batadv_info(net_dev, "%s: Changing from: %s to: %s\n", attr_name,
		    atomic_read(attr) == 1 ? "enabled" : "disabled",
		    enabled == 1 ? "enabled" : "disabled");
279

280 281
	*changed = true;

282
	atomic_set(attr, (unsigned int)enabled);
283 284 285
	return count;
}

286 287 288 289 290
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)
291
{
292
	bool changed;
293 294
	int ret;

295
	ret = batadv_store_bool_attr(buff, count, net_dev, attr->name,
296 297
				     attr_store, &changed);
	if (post_func && changed)
298 299 300 301 302
		post_func(net_dev);

	return ret;
}

303 304 305 306 307
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)
308 309 310 311
{
	unsigned long uint_val;
	int ret;

312
	ret = kstrtoul(buff, 10, &uint_val);
313
	if (ret) {
314 315
		batadv_info(net_dev, "%s: Invalid parameter received: %s\n",
			    attr_name, buff);
316 317 318 319
		return -EINVAL;
	}

	if (uint_val < min) {
320 321
		batadv_info(net_dev, "%s: Value is too small: %lu min: %u\n",
			    attr_name, uint_val, min);
322 323 324 325
		return -EINVAL;
	}

	if (uint_val > max) {
326 327
		batadv_info(net_dev, "%s: Value is too big: %lu max: %u\n",
			    attr_name, uint_val, max);
328 329 330 331 332 333
		return -EINVAL;
	}

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

334 335
	batadv_info(net_dev, "%s: Changing from: %i to: %lu\n",
		    attr_name, atomic_read(attr), uint_val);
336 337 338 339 340

	atomic_set(attr, uint_val);
	return count;
}

341 342 343 344 345 346
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)
347 348 349
{
	int ret;

350 351
	ret = batadv_store_uint_attr(buff, count, net_dev, attr->name, min, max,
				     attr_store);
352 353 354 355 356 357
	if (post_func && ret)
		post_func(net_dev);

	return ret;
}

358 359
static ssize_t batadv_show_bat_algo(struct kobject *kobj,
				    struct attribute *attr, char *buff)
360
{
361
	struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
362

363 364 365
	return sprintf(buff, "%s\n", bat_priv->bat_algo_ops->name);
}

366
static void batadv_post_gw_reselect(struct net_device *net_dev)
367
{
368
	struct batadv_priv *bat_priv = netdev_priv(net_dev);
369

370
	batadv_gw_reselect(bat_priv);
371 372
}

373 374
static ssize_t batadv_show_gw_mode(struct kobject *kobj, struct attribute *attr,
				   char *buff)
375
{
376
	struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
377 378 379
	int bytes_written;

	switch (atomic_read(&bat_priv->gw_mode)) {
380
	case BATADV_GW_MODE_CLIENT:
381 382
		bytes_written = sprintf(buff, "%s\n",
					BATADV_GW_MODE_CLIENT_NAME);
383
		break;
384
	case BATADV_GW_MODE_SERVER:
385 386
		bytes_written = sprintf(buff, "%s\n",
					BATADV_GW_MODE_SERVER_NAME);
387 388
		break;
	default:
389 390
		bytes_written = sprintf(buff, "%s\n",
					BATADV_GW_MODE_OFF_NAME);
391 392 393 394 395 396
		break;
	}

	return bytes_written;
}

397 398 399
static ssize_t batadv_store_gw_mode(struct kobject *kobj,
				    struct attribute *attr, char *buff,
				    size_t count)
400
{
401
	struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
402
	struct batadv_priv *bat_priv = netdev_priv(net_dev);
403 404 405 406 407 408
	char *curr_gw_mode_str;
	int gw_mode_tmp = -1;

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

409 410
	if (strncmp(buff, BATADV_GW_MODE_OFF_NAME,
		    strlen(BATADV_GW_MODE_OFF_NAME)) == 0)
411
		gw_mode_tmp = BATADV_GW_MODE_OFF;
412

413 414
	if (strncmp(buff, BATADV_GW_MODE_CLIENT_NAME,
		    strlen(BATADV_GW_MODE_CLIENT_NAME)) == 0)
415
		gw_mode_tmp = BATADV_GW_MODE_CLIENT;
416

417 418
	if (strncmp(buff, BATADV_GW_MODE_SERVER_NAME,
		    strlen(BATADV_GW_MODE_SERVER_NAME)) == 0)
419
		gw_mode_tmp = BATADV_GW_MODE_SERVER;
420 421

	if (gw_mode_tmp < 0) {
422 423 424
		batadv_info(net_dev,
			    "Invalid parameter for 'gw mode' setting received: %s\n",
			    buff);
425 426 427 428 429 430 431
		return -EINVAL;
	}

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

	switch (atomic_read(&bat_priv->gw_mode)) {
432
	case BATADV_GW_MODE_CLIENT:
433
		curr_gw_mode_str = BATADV_GW_MODE_CLIENT_NAME;
434
		break;
435
	case BATADV_GW_MODE_SERVER:
436
		curr_gw_mode_str = BATADV_GW_MODE_SERVER_NAME;
437 438
		break;
	default:
439
		curr_gw_mode_str = BATADV_GW_MODE_OFF_NAME;
440 441 442
		break;
	}

443 444
	batadv_info(net_dev, "Changing gw mode from: %s to: %s\n",
		    curr_gw_mode_str, buff);
445

446 447 448 449 450 451 452 453 454
	/* 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().
	 */
455
	batadv_gw_reselect(bat_priv);
456 457 458 459
	/* always call batadv_gw_check_client_stop() before changing the gateway
	 * state
	 */
	batadv_gw_check_client_stop(bat_priv);
460
	atomic_set(&bat_priv->gw_mode, (unsigned int)gw_mode_tmp);
461
	batadv_gw_tvlv_container_update(bat_priv);
462 463 464
	return count;
}

465 466
static ssize_t batadv_show_gw_bwidth(struct kobject *kobj,
				     struct attribute *attr, char *buff)
467
{
468
	struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
469
	u32 down, up;
470 471 472 473 474 475

	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);
476 477
}

478 479 480
static ssize_t batadv_store_gw_bwidth(struct kobject *kobj,
				      struct attribute *attr, char *buff,
				      size_t count)
481
{
482
	struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
483 484 485 486

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

487
	return batadv_gw_bandwidth_set(net_dev, buff, count);
488 489
}

490 491 492 493 494 495
/**
 * 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
 *
496
 * Return: the number of bytes written into 'buff' on success or a negative
497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515
 * 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
 *
516
 * Return: 'count' on success or a negative error code in case of failure
517 518 519 520 521 522 523
 */
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);
524
	u32 mark, mask;
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 550 551 552 553 554 555 556 557
	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;
}

558 559
BATADV_ATTR_SIF_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL);
BATADV_ATTR_SIF_BOOL(bonding, S_IRUGO | S_IWUSR, NULL);
560
#ifdef CONFIG_BATMAN_ADV_BLA
561 562
BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR,
		     batadv_bla_status_update);
563
#endif
564
#ifdef CONFIG_BATMAN_ADV_DAT
565 566
BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR,
		     batadv_dat_status_update);
567
#endif
568 569 570 571
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);
572 573 574 575 576 577
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);
578 579
static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth,
		   batadv_store_gw_bwidth);
580 581 582
#ifdef CONFIG_BATMAN_ADV_MCAST
BATADV_ATTR_SIF_BOOL(multicast_mode, S_IRUGO | S_IWUSR, NULL);
#endif
583
#ifdef CONFIG_BATMAN_ADV_DEBUG
584 585
BATADV_ATTR_SIF_UINT(log_level, log_level, S_IRUGO | S_IWUSR, 0,
		     BATADV_DBG_ALL, NULL);
586
#endif
587
#ifdef CONFIG_BATMAN_ADV_NC
588 589
BATADV_ATTR_SIF_BOOL(network_coding, S_IRUGO | S_IWUSR,
		     batadv_nc_status_update);
590
#endif
591 592
static BATADV_ATTR(isolation_mark, S_IRUGO | S_IWUSR,
		   batadv_show_isolation_mark, batadv_store_isolation_mark);
593

594
static struct batadv_attribute *batadv_mesh_attrs[] = {
595 596
	&batadv_attr_aggregated_ogms,
	&batadv_attr_bonding,
597
#ifdef CONFIG_BATMAN_ADV_BLA
598
	&batadv_attr_bridge_loop_avoidance,
599 600 601
#endif
#ifdef CONFIG_BATMAN_ADV_DAT
	&batadv_attr_distributed_arp_table,
602 603 604
#endif
#ifdef CONFIG_BATMAN_ADV_MCAST
	&batadv_attr_multicast_mode,
605
#endif
606 607 608 609 610 611 612
	&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,
613
#ifdef CONFIG_BATMAN_ADV_DEBUG
614
	&batadv_attr_log_level,
615 616 617
#endif
#ifdef CONFIG_BATMAN_ADV_NC
	&batadv_attr_network_coding,
618
#endif
619
	&batadv_attr_isolation_mark,
620 621 622
	NULL,
};

623 624
BATADV_ATTR_VLAN_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL);

625
/* array of vlan specific sysfs attributes */
626
static struct batadv_attribute *batadv_vlan_attrs[] = {
627
	&batadv_attr_vlan_ap_isolation,
628 629 630
	NULL,
};

631
int batadv_sysfs_add_meshif(struct net_device *dev)
632 633
{
	struct kobject *batif_kobject = &dev->dev.kobj;
634
	struct batadv_priv *bat_priv = netdev_priv(dev);
635
	struct batadv_attribute **bat_attr;
636 637
	int err;

638
	bat_priv->mesh_obj = kobject_create_and_add(BATADV_SYSFS_IF_MESH_SUBDIR,
639 640
						    batif_kobject);
	if (!bat_priv->mesh_obj) {
641
		batadv_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
642
			   BATADV_SYSFS_IF_MESH_SUBDIR);
643 644 645
		goto out;
	}

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

	return 0;

rem_attr:
660
	for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr)
661 662 663 664 665 666 667 668
		sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));

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

669
void batadv_sysfs_del_meshif(struct net_device *dev)
670
{
671
	struct batadv_priv *bat_priv = netdev_priv(dev);
672
	struct batadv_attribute **bat_attr;
673

674
	for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr)
675 676 677 678 679 680
		sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));

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

681 682 683 684 685
/**
 * 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
 *
686
 * Return: 0 on success and -ENOMEM if any of the structure allocations fails.
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 749 750 751 752 753 754
 */
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;
}

755 756
static ssize_t batadv_show_mesh_iface(struct kobject *kobj,
				      struct attribute *attr, char *buff)
757
{
758
	struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
759
	struct batadv_hard_iface *hard_iface;
760
	ssize_t length;
761
	const char *ifname;
762

763
	hard_iface = batadv_hardif_get_by_netdev(net_dev);
764
	if (!hard_iface)
765 766
		return 0;

767 768 769 770 771 772
	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);
773

774
	batadv_hardif_free_ref(hard_iface);
775 776 777 778

	return length;
}

779 780 781
static ssize_t batadv_store_mesh_iface(struct kobject *kobj,
				       struct attribute *attr, char *buff,
				       size_t count)
782
{
783
	struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
784
	struct batadv_hard_iface *hard_iface;
785
	int status_tmp = -1;
786
	int ret = count;
787

788
	hard_iface = batadv_hardif_get_by_netdev(net_dev);
789
	if (!hard_iface)
790 791 792 793 794 795
		return count;

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

	if (strlen(buff) >= IFNAMSIZ) {
796 797
		pr_err("Invalid parameter for 'mesh_iface' setting received: interface name too long '%s'\n",
		       buff);
798
		batadv_hardif_free_ref(hard_iface);
799 800 801 802
		return -EINVAL;
	}

	if (strncmp(buff, "none", 4) == 0)
803
		status_tmp = BATADV_IF_NOT_IN_USE;
804
	else
805
		status_tmp = BATADV_IF_I_WANT_YOU;
806

807 808 809 810 811
	if (hard_iface->if_status == status_tmp)
		goto out;

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

814
	rtnl_lock();
815

816
	if (status_tmp == BATADV_IF_NOT_IN_USE) {
817 818
		batadv_hardif_disable_interface(hard_iface,
						BATADV_IF_CLEANUP_AUTO);
819
		goto unlock;
820 821 822
	}

	/* if the interface already is in use */
823
	if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
824 825
		batadv_hardif_disable_interface(hard_iface,
						BATADV_IF_CLEANUP_AUTO);
826

827
	ret = batadv_hardif_enable_interface(hard_iface, buff);
828

829 830
unlock:
	rtnl_unlock();
831
out:
832
	batadv_hardif_free_ref(hard_iface);
833 834 835
	return ret;
}

836 837
static ssize_t batadv_show_iface_status(struct kobject *kobj,
					struct attribute *attr, char *buff)
838
{
839
	struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
840
	struct batadv_hard_iface *hard_iface;
841 842
	ssize_t length;

843
	hard_iface = batadv_hardif_get_by_netdev(net_dev);
844
	if (!hard_iface)
845 846
		return 0;

847
	switch (hard_iface->if_status) {
848
	case BATADV_IF_TO_BE_REMOVED:
849 850
		length = sprintf(buff, "disabling\n");
		break;
851
	case BATADV_IF_INACTIVE:
852 853
		length = sprintf(buff, "inactive\n");
		break;
854
	case BATADV_IF_ACTIVE:
855 856
		length = sprintf(buff, "active\n");
		break;
857
	case BATADV_IF_TO_BE_ACTIVATED:
858 859
		length = sprintf(buff, "enabling\n");
		break;
860
	case BATADV_IF_NOT_IN_USE:
861 862 863 864 865
	default:
		length = sprintf(buff, "not in use\n");
		break;
	}

866
	batadv_hardif_free_ref(hard_iface);
867 868 869 870

	return length;
}

871 872 873
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);
874

875
static struct batadv_attribute *batadv_batman_attrs[] = {
876 877
	&batadv_attr_mesh_iface,
	&batadv_attr_iface_status,
878 879 880
	NULL,
};

881
int batadv_sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev)
882 883
{
	struct kobject *hardif_kobject = &dev->dev.kobj;
884
	struct batadv_attribute **bat_attr;
885 886
	int err;

887 888
	*hardif_obj = kobject_create_and_add(BATADV_SYSFS_IF_BAT_SUBDIR,
					     hardif_kobject);
889 890

	if (!*hardif_obj) {
891
		batadv_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
892
			   BATADV_SYSFS_IF_BAT_SUBDIR);
893 894 895
		goto out;
	}

896
	for (bat_attr = batadv_batman_attrs; *bat_attr; ++bat_attr) {
897 898
		err = sysfs_create_file(*hardif_obj, &((*bat_attr)->attr));
		if (err) {
899
			batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n",
900
				   dev->name, BATADV_SYSFS_IF_BAT_SUBDIR,
901
				   ((*bat_attr)->attr).name);
902 903 904 905 906 907 908
			goto rem_attr;
		}
	}

	return 0;

rem_attr:
909
	for (bat_attr = batadv_batman_attrs; *bat_attr; ++bat_attr)
910 911 912 913 914
		sysfs_remove_file(*hardif_obj, &((*bat_attr)->attr));
out:
	return -ENOMEM;
}

915
void batadv_sysfs_del_hardif(struct kobject **hardif_obj)
916 917 918 919
{
	kobject_put(*hardif_obj);
	*hardif_obj = NULL;
}
920

921
int batadv_throw_uevent(struct batadv_priv *bat_priv, enum batadv_uev_type type,
922
			enum batadv_uev_action action, const char *data)
923
{
924
	int ret = -ENOMEM;
925 926 927
	struct kobject *bat_kobj;
	char *uevent_env[4] = { NULL, NULL, NULL, NULL };

928
	bat_kobj = &bat_priv->soft_iface->dev.kobj;
929

H
Himangi Saraogi 已提交
930 931 932
	uevent_env[0] = kasprintf(GFP_ATOMIC,
				  "%s%s", BATADV_UEV_TYPE_VAR,
				  batadv_uev_type_str[type]);
933 934 935
	if (!uevent_env[0])
		goto out;

H
Himangi Saraogi 已提交
936 937 938
	uevent_env[1] = kasprintf(GFP_ATOMIC,
				  "%s%s", BATADV_UEV_ACTION_VAR,
				  batadv_uev_action_str[action]);
939 940 941 942
	if (!uevent_env[1])
		goto out;

	/* If the event is DEL, ignore the data field */
943
	if (action != BATADV_UEV_DEL) {
H
Himangi Saraogi 已提交
944 945
		uevent_env[2] = kasprintf(GFP_ATOMIC,
					  "%s%s", BATADV_UEV_DATA_VAR, data);
946 947 948 949 950 951 952 953 954 955 956
		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)
957
		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
958
			   "Impossible to send uevent for (%s,%s,%s) event (err: %d)\n",
959 960
			   batadv_uev_type_str[type],
			   batadv_uev_action_str[action],
961
			   (action == BATADV_UEV_DEL ? "NULL" : data), ret);
962 963
	return ret;
}