sysfs.c 23.2 KB
Newer Older
1
/* Copyright (C) 2010-2013 B.A.T.M.A.N. contributors:
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
 *
 * 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"
21
#include "sysfs.h"
22
#include "translation-table.h"
23
#include "distributed-arp-table.h"
24
#include "network-coding.h"
25 26
#include "originator.h"
#include "hard-interface.h"
27
#include "soft-interface.h"
28 29 30
#include "gateway_common.h"
#include "gateway_client.h"

31
static struct net_device *batadv_kobj_to_netdev(struct kobject *obj)
32 33 34 35 36
{
	struct device *dev = container_of(obj->parent, struct device, kobj);
	return to_net_dev(dev);
}

37
static struct batadv_priv *batadv_kobj_to_batpriv(struct kobject *obj)
38
{
39
	struct net_device *net_dev = batadv_kobj_to_netdev(obj);
40 41
	return netdev_priv(net_dev);
}
42

43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 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
/**
 * 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;
}

90 91 92
#define BATADV_UEV_TYPE_VAR	"BATTYPE="
#define BATADV_UEV_ACTION_VAR	"BATACTION="
#define BATADV_UEV_DATA_VAR	"BATDATA="
93

94
static char *batadv_uev_action_str[] = {
95 96 97 98 99
	"add",
	"del",
	"change"
};

100
static char *batadv_uev_type_str[] = {
101 102 103
	"gw"
};

104 105 106 107 108 109 110 111 112
/* 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,				\
};

113
/* Use this, if you have customized show and store functions */
114
#define BATADV_ATTR(_name, _mode, _show, _store)	\
115
struct batadv_attribute batadv_attr_##_name = {		\
116 117 118 119
	.attr = {.name = __stringify(_name),		\
		 .mode = _mode },			\
	.show   = _show,				\
	.store  = _store,				\
120 121
};

122
#define BATADV_ATTR_SIF_STORE_BOOL(_name, _post_func)			\
123 124 125
ssize_t batadv_store_##_name(struct kobject *kobj,			\
			     struct attribute *attr, char *buff,	\
			     size_t count)				\
126
{									\
127
	struct net_device *net_dev = batadv_kobj_to_netdev(kobj);	\
128
	struct batadv_priv *bat_priv = netdev_priv(net_dev);		\
129 130
	return __batadv_store_bool_attr(buff, count, _post_func, attr,	\
					&bat_priv->_name, net_dev);	\
131 132
}

133
#define BATADV_ATTR_SIF_SHOW_BOOL(_name)				\
134 135
ssize_t batadv_show_##_name(struct kobject *kobj,			\
			    struct attribute *attr, char *buff)		\
136
{									\
137
	struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);	\
138 139 140 141 142
	return sprintf(buff, "%s\n",					\
		       atomic_read(&bat_priv->_name) == 0 ?		\
		       "disabled" : "enabled");				\
}									\

143
/* Use this, if you are going to turn a [name] in the soft-interface
144 145
 * (bat_priv) on or off
 */
146 147 148 149 150
#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)
151 152


153
#define BATADV_ATTR_SIF_STORE_UINT(_name, _min, _max, _post_func)	\
154 155 156
ssize_t batadv_store_##_name(struct kobject *kobj,			\
			     struct attribute *attr, char *buff,	\
			     size_t count)				\
157
{									\
158
	struct net_device *net_dev = batadv_kobj_to_netdev(kobj);	\
159
	struct batadv_priv *bat_priv = netdev_priv(net_dev);		\
160 161 162
	return __batadv_store_uint_attr(buff, count, _min, _max,	\
					_post_func, attr,		\
					&bat_priv->_name, net_dev);	\
163 164
}

165
#define BATADV_ATTR_SIF_SHOW_UINT(_name)				\
166 167
ssize_t batadv_show_##_name(struct kobject *kobj,			\
			    struct attribute *attr, char *buff)		\
168
{									\
169
	struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);	\
170 171 172
	return sprintf(buff, "%i\n", atomic_read(&bat_priv->_name));	\
}									\

173
/* Use this, if you are going to set [name] in the soft-interface
174 175
 * (bat_priv) to an unsigned integer value
 */
176 177 178 179 180
#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)
181

182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
#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);	\
	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");			\
	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)
217

218 219 220
static int batadv_store_bool_attr(char *buff, size_t count,
				  struct net_device *net_dev,
				  const char *attr_name, atomic_t *attr)
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
{
	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) {
238 239
		batadv_info(net_dev, "%s: Invalid parameter received: %s\n",
			    attr_name, buff);
240 241 242 243 244 245
		return -EINVAL;
	}

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

246 247 248
	batadv_info(net_dev, "%s: Changing from: %s to: %s\n", attr_name,
		    atomic_read(attr) == 1 ? "enabled" : "disabled",
		    enabled == 1 ? "enabled" : "disabled");
249

250
	atomic_set(attr, (unsigned int)enabled);
251 252 253
	return count;
}

254 255 256 257 258
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)
259 260 261
{
	int ret;

262 263
	ret = batadv_store_bool_attr(buff, count, net_dev, attr->name,
				     attr_store);
264 265 266 267 268 269
	if (post_func && ret)
		post_func(net_dev);

	return ret;
}

270 271 272 273 274
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)
275 276 277 278
{
	unsigned long uint_val;
	int ret;

279
	ret = kstrtoul(buff, 10, &uint_val);
280
	if (ret) {
281 282
		batadv_info(net_dev, "%s: Invalid parameter received: %s\n",
			    attr_name, buff);
283 284 285 286
		return -EINVAL;
	}

	if (uint_val < min) {
287 288
		batadv_info(net_dev, "%s: Value is too small: %lu min: %u\n",
			    attr_name, uint_val, min);
289 290 291 292
		return -EINVAL;
	}

	if (uint_val > max) {
293 294
		batadv_info(net_dev, "%s: Value is too big: %lu max: %u\n",
			    attr_name, uint_val, max);
295 296 297 298 299 300
		return -EINVAL;
	}

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

301 302
	batadv_info(net_dev, "%s: Changing from: %i to: %lu\n",
		    attr_name, atomic_read(attr), uint_val);
303 304 305 306 307

	atomic_set(attr, uint_val);
	return count;
}

308 309 310 311 312 313
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)
314 315 316
{
	int ret;

317 318
	ret = batadv_store_uint_attr(buff, count, net_dev, attr->name, min, max,
				     attr_store);
319 320 321 322 323 324
	if (post_func && ret)
		post_func(net_dev);

	return ret;
}

325 326
static ssize_t batadv_show_bat_algo(struct kobject *kobj,
				    struct attribute *attr, char *buff)
327
{
328
	struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
329 330 331
	return sprintf(buff, "%s\n", bat_priv->bat_algo_ops->name);
}

332
static void batadv_post_gw_deselect(struct net_device *net_dev)
333
{
334
	struct batadv_priv *bat_priv = netdev_priv(net_dev);
335
	batadv_gw_deselect(bat_priv);
336 337
}

338 339
static ssize_t batadv_show_gw_mode(struct kobject *kobj, struct attribute *attr,
				   char *buff)
340
{
341
	struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
342 343 344
	int bytes_written;

	switch (atomic_read(&bat_priv->gw_mode)) {
345
	case BATADV_GW_MODE_CLIENT:
346 347
		bytes_written = sprintf(buff, "%s\n",
					BATADV_GW_MODE_CLIENT_NAME);
348
		break;
349
	case BATADV_GW_MODE_SERVER:
350 351
		bytes_written = sprintf(buff, "%s\n",
					BATADV_GW_MODE_SERVER_NAME);
352 353
		break;
	default:
354 355
		bytes_written = sprintf(buff, "%s\n",
					BATADV_GW_MODE_OFF_NAME);
356 357 358 359 360 361
		break;
	}

	return bytes_written;
}

362 363 364
static ssize_t batadv_store_gw_mode(struct kobject *kobj,
				    struct attribute *attr, char *buff,
				    size_t count)
365
{
366
	struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
367
	struct batadv_priv *bat_priv = netdev_priv(net_dev);
368 369 370 371 372 373
	char *curr_gw_mode_str;
	int gw_mode_tmp = -1;

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

374 375
	if (strncmp(buff, BATADV_GW_MODE_OFF_NAME,
		    strlen(BATADV_GW_MODE_OFF_NAME)) == 0)
376
		gw_mode_tmp = BATADV_GW_MODE_OFF;
377

378 379
	if (strncmp(buff, BATADV_GW_MODE_CLIENT_NAME,
		    strlen(BATADV_GW_MODE_CLIENT_NAME)) == 0)
380
		gw_mode_tmp = BATADV_GW_MODE_CLIENT;
381

382 383
	if (strncmp(buff, BATADV_GW_MODE_SERVER_NAME,
		    strlen(BATADV_GW_MODE_SERVER_NAME)) == 0)
384
		gw_mode_tmp = BATADV_GW_MODE_SERVER;
385 386

	if (gw_mode_tmp < 0) {
387 388 389
		batadv_info(net_dev,
			    "Invalid parameter for 'gw mode' setting received: %s\n",
			    buff);
390 391 392 393 394 395 396
		return -EINVAL;
	}

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

	switch (atomic_read(&bat_priv->gw_mode)) {
397
	case BATADV_GW_MODE_CLIENT:
398
		curr_gw_mode_str = BATADV_GW_MODE_CLIENT_NAME;
399
		break;
400
	case BATADV_GW_MODE_SERVER:
401
		curr_gw_mode_str = BATADV_GW_MODE_SERVER_NAME;
402 403
		break;
	default:
404
		curr_gw_mode_str = BATADV_GW_MODE_OFF_NAME;
405 406 407
		break;
	}

408 409
	batadv_info(net_dev, "Changing gw mode from: %s to: %s\n",
		    curr_gw_mode_str, buff);
410

411
	batadv_gw_deselect(bat_priv);
412 413 414 415
	/* always call batadv_gw_check_client_stop() before changing the gateway
	 * state
	 */
	batadv_gw_check_client_stop(bat_priv);
416
	atomic_set(&bat_priv->gw_mode, (unsigned int)gw_mode_tmp);
417
	batadv_gw_tvlv_container_update(bat_priv);
418 419 420
	return count;
}

421 422
static ssize_t batadv_show_gw_bwidth(struct kobject *kobj,
				     struct attribute *attr, char *buff)
423
{
424
	struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
425 426 427 428 429 430 431
	uint32_t down, up;

	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);
432 433
}

434 435 436
static ssize_t batadv_store_gw_bwidth(struct kobject *kobj,
				      struct attribute *attr, char *buff,
				      size_t count)
437
{
438
	struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
439 440 441 442

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

443
	return batadv_gw_bandwidth_set(net_dev, buff, count);
444 445
}

446 447
BATADV_ATTR_SIF_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL);
BATADV_ATTR_SIF_BOOL(bonding, S_IRUGO | S_IWUSR, NULL);
448
#ifdef CONFIG_BATMAN_ADV_BLA
449
BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR, NULL);
450
#endif
451
#ifdef CONFIG_BATMAN_ADV_DAT
452 453
BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR,
		     batadv_dat_status_update);
454
#endif
455 456 457 458 459
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(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);
460 461 462
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,
463
		     NULL);
464
BATADV_ATTR_SIF_UINT(gw_sel_class, S_IRUGO | S_IWUSR, 1, BATADV_TQ_MAX_VALUE,
465 466 467
		     batadv_post_gw_deselect);
static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth,
		   batadv_store_gw_bwidth);
468
#ifdef CONFIG_BATMAN_ADV_DEBUG
469
BATADV_ATTR_SIF_UINT(log_level, S_IRUGO | S_IWUSR, 0, BATADV_DBG_ALL, NULL);
470
#endif
471
#ifdef CONFIG_BATMAN_ADV_NC
472 473
BATADV_ATTR_SIF_BOOL(network_coding, S_IRUGO | S_IWUSR,
		     batadv_nc_status_update);
474
#endif
475

476
static struct batadv_attribute *batadv_mesh_attrs[] = {
477 478
	&batadv_attr_aggregated_ogms,
	&batadv_attr_bonding,
479
#ifdef CONFIG_BATMAN_ADV_BLA
480
	&batadv_attr_bridge_loop_avoidance,
481 482 483
#endif
#ifdef CONFIG_BATMAN_ADV_DAT
	&batadv_attr_distributed_arp_table,
484
#endif
485 486 487 488 489 490 491 492
	&batadv_attr_fragmentation,
	&batadv_attr_ap_isolation,
	&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,
493
#ifdef CONFIG_BATMAN_ADV_DEBUG
494
	&batadv_attr_log_level,
495 496 497
#endif
#ifdef CONFIG_BATMAN_ADV_NC
	&batadv_attr_network_coding,
498 499 500 501
#endif
	NULL,
};

502 503 504 505 506 507 508
/**
 * batadv_vlan_attrs - array of vlan specific sysfs attributes
 */
static struct batadv_attribute *batadv_vlan_attrs[] = {
	NULL,
};

509
int batadv_sysfs_add_meshif(struct net_device *dev)
510 511
{
	struct kobject *batif_kobject = &dev->dev.kobj;
512
	struct batadv_priv *bat_priv = netdev_priv(dev);
513
	struct batadv_attribute **bat_attr;
514 515
	int err;

516
	bat_priv->mesh_obj = kobject_create_and_add(BATADV_SYSFS_IF_MESH_SUBDIR,
517 518
						    batif_kobject);
	if (!bat_priv->mesh_obj) {
519
		batadv_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
520
			   BATADV_SYSFS_IF_MESH_SUBDIR);
521 522 523
		goto out;
	}

524
	for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr) {
525 526 527
		err = sysfs_create_file(bat_priv->mesh_obj,
					&((*bat_attr)->attr));
		if (err) {
528
			batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n",
529
				   dev->name, BATADV_SYSFS_IF_MESH_SUBDIR,
530
				   ((*bat_attr)->attr).name);
531 532 533 534 535 536 537
			goto rem_attr;
		}
	}

	return 0;

rem_attr:
538
	for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr)
539 540 541 542 543 544 545 546
		sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));

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

547
void batadv_sysfs_del_meshif(struct net_device *dev)
548
{
549
	struct batadv_priv *bat_priv = netdev_priv(dev);
550
	struct batadv_attribute **bat_attr;
551

552
	for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr)
553 554 555 556 557 558
		sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));

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

559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632
/**
 * 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;
}

633 634
static ssize_t batadv_show_mesh_iface(struct kobject *kobj,
				      struct attribute *attr, char *buff)
635
{
636
	struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
637
	struct batadv_hard_iface *hard_iface;
638
	ssize_t length;
639
	const char *ifname;
640

641
	hard_iface = batadv_hardif_get_by_netdev(net_dev);
642
	if (!hard_iface)
643 644
		return 0;

645 646 647 648 649 650
	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);
651

652
	batadv_hardif_free_ref(hard_iface);
653 654 655 656

	return length;
}

657 658 659
static ssize_t batadv_store_mesh_iface(struct kobject *kobj,
				       struct attribute *attr, char *buff,
				       size_t count)
660
{
661
	struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
662
	struct batadv_hard_iface *hard_iface;
663
	int status_tmp = -1;
664
	int ret = count;
665

666
	hard_iface = batadv_hardif_get_by_netdev(net_dev);
667
	if (!hard_iface)
668 669 670 671 672 673
		return count;

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

	if (strlen(buff) >= IFNAMSIZ) {
674 675
		pr_err("Invalid parameter for 'mesh_iface' setting received: interface name too long '%s'\n",
		       buff);
676
		batadv_hardif_free_ref(hard_iface);
677 678 679 680
		return -EINVAL;
	}

	if (strncmp(buff, "none", 4) == 0)
681
		status_tmp = BATADV_IF_NOT_IN_USE;
682
	else
683
		status_tmp = BATADV_IF_I_WANT_YOU;
684

685 686 687 688 689
	if (hard_iface->if_status == status_tmp)
		goto out;

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

692
	rtnl_lock();
693

694
	if (status_tmp == BATADV_IF_NOT_IN_USE) {
695 696
		batadv_hardif_disable_interface(hard_iface,
						BATADV_IF_CLEANUP_AUTO);
697
		goto unlock;
698 699 700
	}

	/* if the interface already is in use */
701
	if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
702 703
		batadv_hardif_disable_interface(hard_iface,
						BATADV_IF_CLEANUP_AUTO);
704

705
	ret = batadv_hardif_enable_interface(hard_iface, buff);
706

707 708
unlock:
	rtnl_unlock();
709
out:
710
	batadv_hardif_free_ref(hard_iface);
711 712 713
	return ret;
}

714 715
static ssize_t batadv_show_iface_status(struct kobject *kobj,
					struct attribute *attr, char *buff)
716
{
717
	struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
718
	struct batadv_hard_iface *hard_iface;
719 720
	ssize_t length;

721
	hard_iface = batadv_hardif_get_by_netdev(net_dev);
722
	if (!hard_iface)
723 724
		return 0;

725
	switch (hard_iface->if_status) {
726
	case BATADV_IF_TO_BE_REMOVED:
727 728
		length = sprintf(buff, "disabling\n");
		break;
729
	case BATADV_IF_INACTIVE:
730 731
		length = sprintf(buff, "inactive\n");
		break;
732
	case BATADV_IF_ACTIVE:
733 734
		length = sprintf(buff, "active\n");
		break;
735
	case BATADV_IF_TO_BE_ACTIVATED:
736 737
		length = sprintf(buff, "enabling\n");
		break;
738
	case BATADV_IF_NOT_IN_USE:
739 740 741 742 743
	default:
		length = sprintf(buff, "not in use\n");
		break;
	}

744
	batadv_hardif_free_ref(hard_iface);
745 746 747 748

	return length;
}

749 750 751
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);
752

753
static struct batadv_attribute *batadv_batman_attrs[] = {
754 755
	&batadv_attr_mesh_iface,
	&batadv_attr_iface_status,
756 757 758
	NULL,
};

759
int batadv_sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev)
760 761
{
	struct kobject *hardif_kobject = &dev->dev.kobj;
762
	struct batadv_attribute **bat_attr;
763 764
	int err;

765 766
	*hardif_obj = kobject_create_and_add(BATADV_SYSFS_IF_BAT_SUBDIR,
					     hardif_kobject);
767 768

	if (!*hardif_obj) {
769
		batadv_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
770
			   BATADV_SYSFS_IF_BAT_SUBDIR);
771 772 773
		goto out;
	}

774
	for (bat_attr = batadv_batman_attrs; *bat_attr; ++bat_attr) {
775 776
		err = sysfs_create_file(*hardif_obj, &((*bat_attr)->attr));
		if (err) {
777
			batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n",
778
				   dev->name, BATADV_SYSFS_IF_BAT_SUBDIR,
779
				   ((*bat_attr)->attr).name);
780 781 782 783 784 785 786
			goto rem_attr;
		}
	}

	return 0;

rem_attr:
787
	for (bat_attr = batadv_batman_attrs; *bat_attr; ++bat_attr)
788 789 790 791 792
		sysfs_remove_file(*hardif_obj, &((*bat_attr)->attr));
out:
	return -ENOMEM;
}

793
void batadv_sysfs_del_hardif(struct kobject **hardif_obj)
794 795 796 797
{
	kobject_put(*hardif_obj);
	*hardif_obj = NULL;
}
798

799
int batadv_throw_uevent(struct batadv_priv *bat_priv, enum batadv_uev_type type,
800
			enum batadv_uev_action action, const char *data)
801
{
802
	int ret = -ENOMEM;
803 804 805
	struct kobject *bat_kobj;
	char *uevent_env[4] = { NULL, NULL, NULL, NULL };

806
	bat_kobj = &bat_priv->soft_iface->dev.kobj;
807

808
	uevent_env[0] = kmalloc(strlen(BATADV_UEV_TYPE_VAR) +
809
				strlen(batadv_uev_type_str[type]) + 1,
810 811 812 813
				GFP_ATOMIC);
	if (!uevent_env[0])
		goto out;

814 815
	sprintf(uevent_env[0], "%s%s", BATADV_UEV_TYPE_VAR,
		batadv_uev_type_str[type]);
816

817
	uevent_env[1] = kmalloc(strlen(BATADV_UEV_ACTION_VAR) +
818
				strlen(batadv_uev_action_str[action]) + 1,
819 820 821 822
				GFP_ATOMIC);
	if (!uevent_env[1])
		goto out;

823
	sprintf(uevent_env[1], "%s%s", BATADV_UEV_ACTION_VAR,
824
		batadv_uev_action_str[action]);
825 826

	/* If the event is DEL, ignore the data field */
827
	if (action != BATADV_UEV_DEL) {
828
		uevent_env[2] = kmalloc(strlen(BATADV_UEV_DATA_VAR) +
829 830 831 832
					strlen(data) + 1, GFP_ATOMIC);
		if (!uevent_env[2])
			goto out;

833
		sprintf(uevent_env[2], "%s%s", BATADV_UEV_DATA_VAR, data);
834 835 836 837 838 839 840 841 842
	}

	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)
843
		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
844
			   "Impossible to send uevent for (%s,%s,%s) event (err: %d)\n",
845 846
			   batadv_uev_type_str[type],
			   batadv_uev_action_str[action],
847
			   (action == BATADV_UEV_DEL ? "NULL" : data), ret);
848 849
	return ret;
}