sysfs.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955
  1. /* Copyright (C) 2010-2015 B.A.T.M.A.N. contributors:
  2. *
  3. * Marek Lindner
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of version 2 of the GNU General Public
  7. * License as published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * 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. #include "sysfs.h"
  18. #include "main.h"
  19. #include <linux/atomic.h>
  20. #include <linux/compiler.h>
  21. #include <linux/device.h>
  22. #include <linux/errno.h>
  23. #include <linux/fs.h>
  24. #include <linux/if.h>
  25. #include <linux/if_vlan.h>
  26. #include <linux/kernel.h>
  27. #include <linux/netdevice.h>
  28. #include <linux/printk.h>
  29. #include <linux/rculist.h>
  30. #include <linux/rcupdate.h>
  31. #include <linux/rtnetlink.h>
  32. #include <linux/slab.h>
  33. #include <linux/stat.h>
  34. #include <linux/stddef.h>
  35. #include <linux/string.h>
  36. #include <linux/stringify.h>
  37. #include "distributed-arp-table.h"
  38. #include "gateway_client.h"
  39. #include "gateway_common.h"
  40. #include "hard-interface.h"
  41. #include "network-coding.h"
  42. #include "packet.h"
  43. #include "soft-interface.h"
  44. static struct net_device *batadv_kobj_to_netdev(struct kobject *obj)
  45. {
  46. struct device *dev = container_of(obj->parent, struct device, kobj);
  47. return to_net_dev(dev);
  48. }
  49. static struct batadv_priv *batadv_kobj_to_batpriv(struct kobject *obj)
  50. {
  51. struct net_device *net_dev = batadv_kobj_to_netdev(obj);
  52. return netdev_priv(net_dev);
  53. }
  54. /**
  55. * batadv_vlan_kobj_to_batpriv - convert a vlan kobj in the associated batpriv
  56. * @obj: kobject to covert
  57. *
  58. * Returns the associated batadv_priv struct.
  59. */
  60. static struct batadv_priv *batadv_vlan_kobj_to_batpriv(struct kobject *obj)
  61. {
  62. /* VLAN specific attributes are located in the root sysfs folder if they
  63. * refer to the untagged VLAN..
  64. */
  65. if (!strcmp(BATADV_SYSFS_IF_MESH_SUBDIR, obj->name))
  66. return batadv_kobj_to_batpriv(obj);
  67. /* ..while the attributes for the tagged vlans are located in
  68. * the in the corresponding "vlan%VID" subfolder
  69. */
  70. return batadv_kobj_to_batpriv(obj->parent);
  71. }
  72. /**
  73. * batadv_kobj_to_vlan - convert a kobj in the associated softif_vlan struct
  74. * @obj: kobject to covert
  75. *
  76. * Returns the associated softif_vlan struct if found, NULL otherwise.
  77. */
  78. static struct batadv_softif_vlan *
  79. batadv_kobj_to_vlan(struct batadv_priv *bat_priv, struct kobject *obj)
  80. {
  81. struct batadv_softif_vlan *vlan_tmp, *vlan = NULL;
  82. rcu_read_lock();
  83. hlist_for_each_entry_rcu(vlan_tmp, &bat_priv->softif_vlan_list, list) {
  84. if (vlan_tmp->kobj != obj)
  85. continue;
  86. if (!atomic_inc_not_zero(&vlan_tmp->refcount))
  87. continue;
  88. vlan = vlan_tmp;
  89. break;
  90. }
  91. rcu_read_unlock();
  92. return vlan;
  93. }
  94. #define BATADV_UEV_TYPE_VAR "BATTYPE="
  95. #define BATADV_UEV_ACTION_VAR "BATACTION="
  96. #define BATADV_UEV_DATA_VAR "BATDATA="
  97. static char *batadv_uev_action_str[] = {
  98. "add",
  99. "del",
  100. "change"
  101. };
  102. static char *batadv_uev_type_str[] = {
  103. "gw"
  104. };
  105. /* Use this, if you have customized show and store functions for vlan attrs */
  106. #define BATADV_ATTR_VLAN(_name, _mode, _show, _store) \
  107. struct batadv_attribute batadv_attr_vlan_##_name = { \
  108. .attr = {.name = __stringify(_name), \
  109. .mode = _mode }, \
  110. .show = _show, \
  111. .store = _store, \
  112. }
  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. .attr = {.name = __stringify(_name), \
  117. .mode = _mode }, \
  118. .show = _show, \
  119. .store = _store, \
  120. }
  121. #define BATADV_ATTR_SIF_STORE_BOOL(_name, _post_func) \
  122. ssize_t batadv_store_##_name(struct kobject *kobj, \
  123. struct attribute *attr, char *buff, \
  124. size_t count) \
  125. { \
  126. struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \
  127. struct batadv_priv *bat_priv = netdev_priv(net_dev); \
  128. \
  129. return __batadv_store_bool_attr(buff, count, _post_func, attr, \
  130. &bat_priv->_name, net_dev); \
  131. }
  132. #define BATADV_ATTR_SIF_SHOW_BOOL(_name) \
  133. ssize_t batadv_show_##_name(struct kobject *kobj, \
  134. struct attribute *attr, char *buff) \
  135. { \
  136. struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); \
  137. \
  138. return sprintf(buff, "%s\n", \
  139. atomic_read(&bat_priv->_name) == 0 ? \
  140. "disabled" : "enabled"); \
  141. } \
  142. /* Use this, if you are going to turn a [name] in the soft-interface
  143. * (bat_priv) on or off
  144. */
  145. #define BATADV_ATTR_SIF_BOOL(_name, _mode, _post_func) \
  146. static BATADV_ATTR_SIF_STORE_BOOL(_name, _post_func) \
  147. static BATADV_ATTR_SIF_SHOW_BOOL(_name) \
  148. static BATADV_ATTR(_name, _mode, batadv_show_##_name, \
  149. batadv_store_##_name)
  150. #define BATADV_ATTR_SIF_STORE_UINT(_name, _var, _min, _max, _post_func) \
  151. ssize_t batadv_store_##_name(struct kobject *kobj, \
  152. struct attribute *attr, char *buff, \
  153. size_t count) \
  154. { \
  155. struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \
  156. struct batadv_priv *bat_priv = netdev_priv(net_dev); \
  157. \
  158. return __batadv_store_uint_attr(buff, count, _min, _max, \
  159. _post_func, attr, \
  160. &bat_priv->_var, net_dev); \
  161. }
  162. #define BATADV_ATTR_SIF_SHOW_UINT(_name, _var) \
  163. ssize_t batadv_show_##_name(struct kobject *kobj, \
  164. struct attribute *attr, char *buff) \
  165. { \
  166. struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); \
  167. \
  168. return sprintf(buff, "%i\n", atomic_read(&bat_priv->_var)); \
  169. } \
  170. /* Use this, if you are going to set [name] in the soft-interface
  171. * (bat_priv) to an unsigned integer value
  172. */
  173. #define BATADV_ATTR_SIF_UINT(_name, _var, _mode, _min, _max, _post_func)\
  174. static BATADV_ATTR_SIF_STORE_UINT(_name, _var, _min, _max, _post_func)\
  175. static BATADV_ATTR_SIF_SHOW_UINT(_name, _var) \
  176. static BATADV_ATTR(_name, _mode, batadv_show_##_name, \
  177. batadv_store_##_name)
  178. #define BATADV_ATTR_VLAN_STORE_BOOL(_name, _post_func) \
  179. ssize_t batadv_store_vlan_##_name(struct kobject *kobj, \
  180. struct attribute *attr, char *buff, \
  181. size_t count) \
  182. { \
  183. struct batadv_priv *bat_priv = batadv_vlan_kobj_to_batpriv(kobj);\
  184. struct batadv_softif_vlan *vlan = batadv_kobj_to_vlan(bat_priv, \
  185. kobj); \
  186. size_t res = __batadv_store_bool_attr(buff, count, _post_func, \
  187. attr, &vlan->_name, \
  188. bat_priv->soft_iface); \
  189. \
  190. batadv_softif_vlan_free_ref(vlan); \
  191. return res; \
  192. }
  193. #define BATADV_ATTR_VLAN_SHOW_BOOL(_name) \
  194. ssize_t batadv_show_vlan_##_name(struct kobject *kobj, \
  195. struct attribute *attr, char *buff) \
  196. { \
  197. struct batadv_priv *bat_priv = batadv_vlan_kobj_to_batpriv(kobj);\
  198. struct batadv_softif_vlan *vlan = batadv_kobj_to_vlan(bat_priv, \
  199. kobj); \
  200. size_t res = sprintf(buff, "%s\n", \
  201. atomic_read(&vlan->_name) == 0 ? \
  202. "disabled" : "enabled"); \
  203. \
  204. batadv_softif_vlan_free_ref(vlan); \
  205. return res; \
  206. }
  207. /* Use this, if you are going to turn a [name] in the vlan struct on or off */
  208. #define BATADV_ATTR_VLAN_BOOL(_name, _mode, _post_func) \
  209. static BATADV_ATTR_VLAN_STORE_BOOL(_name, _post_func) \
  210. static BATADV_ATTR_VLAN_SHOW_BOOL(_name) \
  211. static BATADV_ATTR_VLAN(_name, _mode, batadv_show_vlan_##_name, \
  212. batadv_store_vlan_##_name)
  213. static int batadv_store_bool_attr(char *buff, size_t count,
  214. struct net_device *net_dev,
  215. const char *attr_name, atomic_t *attr)
  216. {
  217. int enabled = -1;
  218. if (buff[count - 1] == '\n')
  219. buff[count - 1] = '\0';
  220. if ((strncmp(buff, "1", 2) == 0) ||
  221. (strncmp(buff, "enable", 7) == 0) ||
  222. (strncmp(buff, "enabled", 8) == 0))
  223. enabled = 1;
  224. if ((strncmp(buff, "0", 2) == 0) ||
  225. (strncmp(buff, "disable", 8) == 0) ||
  226. (strncmp(buff, "disabled", 9) == 0))
  227. enabled = 0;
  228. if (enabled < 0) {
  229. batadv_info(net_dev, "%s: Invalid parameter received: %s\n",
  230. attr_name, buff);
  231. return -EINVAL;
  232. }
  233. if (atomic_read(attr) == enabled)
  234. return count;
  235. batadv_info(net_dev, "%s: Changing from: %s to: %s\n", attr_name,
  236. atomic_read(attr) == 1 ? "enabled" : "disabled",
  237. enabled == 1 ? "enabled" : "disabled");
  238. atomic_set(attr, (unsigned int)enabled);
  239. return count;
  240. }
  241. static inline ssize_t
  242. __batadv_store_bool_attr(char *buff, size_t count,
  243. void (*post_func)(struct net_device *),
  244. struct attribute *attr,
  245. atomic_t *attr_store, struct net_device *net_dev)
  246. {
  247. int ret;
  248. ret = batadv_store_bool_attr(buff, count, net_dev, attr->name,
  249. attr_store);
  250. if (post_func && ret)
  251. post_func(net_dev);
  252. return ret;
  253. }
  254. static int batadv_store_uint_attr(const char *buff, size_t count,
  255. struct net_device *net_dev,
  256. const char *attr_name,
  257. unsigned int min, unsigned int max,
  258. atomic_t *attr)
  259. {
  260. unsigned long uint_val;
  261. int ret;
  262. ret = kstrtoul(buff, 10, &uint_val);
  263. if (ret) {
  264. batadv_info(net_dev, "%s: Invalid parameter received: %s\n",
  265. attr_name, buff);
  266. return -EINVAL;
  267. }
  268. if (uint_val < min) {
  269. batadv_info(net_dev, "%s: Value is too small: %lu min: %u\n",
  270. attr_name, uint_val, min);
  271. return -EINVAL;
  272. }
  273. if (uint_val > max) {
  274. batadv_info(net_dev, "%s: Value is too big: %lu max: %u\n",
  275. attr_name, uint_val, max);
  276. return -EINVAL;
  277. }
  278. if (atomic_read(attr) == uint_val)
  279. return count;
  280. batadv_info(net_dev, "%s: Changing from: %i to: %lu\n",
  281. attr_name, atomic_read(attr), uint_val);
  282. atomic_set(attr, uint_val);
  283. return count;
  284. }
  285. static inline ssize_t
  286. __batadv_store_uint_attr(const char *buff, size_t count,
  287. int min, int max,
  288. void (*post_func)(struct net_device *),
  289. const struct attribute *attr,
  290. atomic_t *attr_store, struct net_device *net_dev)
  291. {
  292. int ret;
  293. ret = batadv_store_uint_attr(buff, count, net_dev, attr->name, min, max,
  294. attr_store);
  295. if (post_func && ret)
  296. post_func(net_dev);
  297. return ret;
  298. }
  299. static ssize_t batadv_show_bat_algo(struct kobject *kobj,
  300. struct attribute *attr, char *buff)
  301. {
  302. struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
  303. return sprintf(buff, "%s\n", bat_priv->bat_algo_ops->name);
  304. }
  305. static void batadv_post_gw_reselect(struct net_device *net_dev)
  306. {
  307. struct batadv_priv *bat_priv = netdev_priv(net_dev);
  308. batadv_gw_reselect(bat_priv);
  309. }
  310. static ssize_t batadv_show_gw_mode(struct kobject *kobj, struct attribute *attr,
  311. char *buff)
  312. {
  313. struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
  314. int bytes_written;
  315. switch (atomic_read(&bat_priv->gw_mode)) {
  316. case BATADV_GW_MODE_CLIENT:
  317. bytes_written = sprintf(buff, "%s\n",
  318. BATADV_GW_MODE_CLIENT_NAME);
  319. break;
  320. case BATADV_GW_MODE_SERVER:
  321. bytes_written = sprintf(buff, "%s\n",
  322. BATADV_GW_MODE_SERVER_NAME);
  323. break;
  324. default:
  325. bytes_written = sprintf(buff, "%s\n",
  326. BATADV_GW_MODE_OFF_NAME);
  327. break;
  328. }
  329. return bytes_written;
  330. }
  331. static ssize_t batadv_store_gw_mode(struct kobject *kobj,
  332. struct attribute *attr, char *buff,
  333. size_t count)
  334. {
  335. struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
  336. struct batadv_priv *bat_priv = netdev_priv(net_dev);
  337. char *curr_gw_mode_str;
  338. int gw_mode_tmp = -1;
  339. if (buff[count - 1] == '\n')
  340. buff[count - 1] = '\0';
  341. if (strncmp(buff, BATADV_GW_MODE_OFF_NAME,
  342. strlen(BATADV_GW_MODE_OFF_NAME)) == 0)
  343. gw_mode_tmp = BATADV_GW_MODE_OFF;
  344. if (strncmp(buff, BATADV_GW_MODE_CLIENT_NAME,
  345. strlen(BATADV_GW_MODE_CLIENT_NAME)) == 0)
  346. gw_mode_tmp = BATADV_GW_MODE_CLIENT;
  347. if (strncmp(buff, BATADV_GW_MODE_SERVER_NAME,
  348. strlen(BATADV_GW_MODE_SERVER_NAME)) == 0)
  349. gw_mode_tmp = BATADV_GW_MODE_SERVER;
  350. if (gw_mode_tmp < 0) {
  351. batadv_info(net_dev,
  352. "Invalid parameter for 'gw mode' setting received: %s\n",
  353. buff);
  354. return -EINVAL;
  355. }
  356. if (atomic_read(&bat_priv->gw_mode) == gw_mode_tmp)
  357. return count;
  358. switch (atomic_read(&bat_priv->gw_mode)) {
  359. case BATADV_GW_MODE_CLIENT:
  360. curr_gw_mode_str = BATADV_GW_MODE_CLIENT_NAME;
  361. break;
  362. case BATADV_GW_MODE_SERVER:
  363. curr_gw_mode_str = BATADV_GW_MODE_SERVER_NAME;
  364. break;
  365. default:
  366. curr_gw_mode_str = BATADV_GW_MODE_OFF_NAME;
  367. break;
  368. }
  369. batadv_info(net_dev, "Changing gw mode from: %s to: %s\n",
  370. curr_gw_mode_str, buff);
  371. /* Invoking batadv_gw_reselect() is not enough to really de-select the
  372. * current GW. It will only instruct the gateway client code to perform
  373. * a re-election the next time that this is needed.
  374. *
  375. * When gw client mode is being switched off the current GW must be
  376. * de-selected explicitly otherwise no GW_ADD uevent is thrown on
  377. * client mode re-activation. This is operation is performed in
  378. * batadv_gw_check_client_stop().
  379. */
  380. batadv_gw_reselect(bat_priv);
  381. /* always call batadv_gw_check_client_stop() before changing the gateway
  382. * state
  383. */
  384. batadv_gw_check_client_stop(bat_priv);
  385. atomic_set(&bat_priv->gw_mode, (unsigned int)gw_mode_tmp);
  386. batadv_gw_tvlv_container_update(bat_priv);
  387. return count;
  388. }
  389. static ssize_t batadv_show_gw_bwidth(struct kobject *kobj,
  390. struct attribute *attr, char *buff)
  391. {
  392. struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
  393. u32 down, up;
  394. down = atomic_read(&bat_priv->gw.bandwidth_down);
  395. up = atomic_read(&bat_priv->gw.bandwidth_up);
  396. return sprintf(buff, "%u.%u/%u.%u MBit\n", down / 10,
  397. down % 10, up / 10, up % 10);
  398. }
  399. static ssize_t batadv_store_gw_bwidth(struct kobject *kobj,
  400. struct attribute *attr, char *buff,
  401. size_t count)
  402. {
  403. struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
  404. if (buff[count - 1] == '\n')
  405. buff[count - 1] = '\0';
  406. return batadv_gw_bandwidth_set(net_dev, buff, count);
  407. }
  408. /**
  409. * batadv_show_isolation_mark - print the current isolation mark/mask
  410. * @kobj: kobject representing the private mesh sysfs directory
  411. * @attr: the batman-adv attribute the user is interacting with
  412. * @buff: the buffer that will contain the data to send back to the user
  413. *
  414. * Returns the number of bytes written into 'buff' on success or a negative
  415. * error code in case of failure
  416. */
  417. static ssize_t batadv_show_isolation_mark(struct kobject *kobj,
  418. struct attribute *attr, char *buff)
  419. {
  420. struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
  421. return sprintf(buff, "%#.8x/%#.8x\n", bat_priv->isolation_mark,
  422. bat_priv->isolation_mark_mask);
  423. }
  424. /**
  425. * batadv_store_isolation_mark - parse and store the isolation mark/mask entered
  426. * by the user
  427. * @kobj: kobject representing the private mesh sysfs directory
  428. * @attr: the batman-adv attribute the user is interacting with
  429. * @buff: the buffer containing the user data
  430. * @count: number of bytes in the buffer
  431. *
  432. * Returns 'count' on success or a negative error code in case of failure
  433. */
  434. static ssize_t batadv_store_isolation_mark(struct kobject *kobj,
  435. struct attribute *attr, char *buff,
  436. size_t count)
  437. {
  438. struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
  439. struct batadv_priv *bat_priv = netdev_priv(net_dev);
  440. u32 mark, mask;
  441. char *mask_ptr;
  442. /* parse the mask if it has been specified, otherwise assume the mask is
  443. * the biggest possible
  444. */
  445. mask = 0xFFFFFFFF;
  446. mask_ptr = strchr(buff, '/');
  447. if (mask_ptr) {
  448. *mask_ptr = '\0';
  449. mask_ptr++;
  450. /* the mask must be entered in hex base as it is going to be a
  451. * bitmask and not a prefix length
  452. */
  453. if (kstrtou32(mask_ptr, 16, &mask) < 0)
  454. return -EINVAL;
  455. }
  456. /* the mark can be entered in any base */
  457. if (kstrtou32(buff, 0, &mark) < 0)
  458. return -EINVAL;
  459. bat_priv->isolation_mark_mask = mask;
  460. /* erase bits not covered by the mask */
  461. bat_priv->isolation_mark = mark & bat_priv->isolation_mark_mask;
  462. batadv_info(net_dev,
  463. "New skb mark for extended isolation: %#.8x/%#.8x\n",
  464. bat_priv->isolation_mark, bat_priv->isolation_mark_mask);
  465. return count;
  466. }
  467. BATADV_ATTR_SIF_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL);
  468. BATADV_ATTR_SIF_BOOL(bonding, S_IRUGO | S_IWUSR, NULL);
  469. #ifdef CONFIG_BATMAN_ADV_BLA
  470. BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR, NULL);
  471. #endif
  472. #ifdef CONFIG_BATMAN_ADV_DAT
  473. BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR,
  474. batadv_dat_status_update);
  475. #endif
  476. BATADV_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, batadv_update_min_mtu);
  477. static BATADV_ATTR(routing_algo, S_IRUGO, batadv_show_bat_algo, NULL);
  478. static BATADV_ATTR(gw_mode, S_IRUGO | S_IWUSR, batadv_show_gw_mode,
  479. batadv_store_gw_mode);
  480. BATADV_ATTR_SIF_UINT(orig_interval, orig_interval, S_IRUGO | S_IWUSR,
  481. 2 * BATADV_JITTER, INT_MAX, NULL);
  482. BATADV_ATTR_SIF_UINT(hop_penalty, hop_penalty, S_IRUGO | S_IWUSR, 0,
  483. BATADV_TQ_MAX_VALUE, NULL);
  484. BATADV_ATTR_SIF_UINT(gw_sel_class, gw_sel_class, S_IRUGO | S_IWUSR, 1,
  485. BATADV_TQ_MAX_VALUE, batadv_post_gw_reselect);
  486. static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth,
  487. batadv_store_gw_bwidth);
  488. #ifdef CONFIG_BATMAN_ADV_MCAST
  489. BATADV_ATTR_SIF_BOOL(multicast_mode, S_IRUGO | S_IWUSR, NULL);
  490. #endif
  491. #ifdef CONFIG_BATMAN_ADV_DEBUG
  492. BATADV_ATTR_SIF_UINT(log_level, log_level, S_IRUGO | S_IWUSR, 0,
  493. BATADV_DBG_ALL, NULL);
  494. #endif
  495. #ifdef CONFIG_BATMAN_ADV_NC
  496. BATADV_ATTR_SIF_BOOL(network_coding, S_IRUGO | S_IWUSR,
  497. batadv_nc_status_update);
  498. #endif
  499. static BATADV_ATTR(isolation_mark, S_IRUGO | S_IWUSR,
  500. batadv_show_isolation_mark, batadv_store_isolation_mark);
  501. static struct batadv_attribute *batadv_mesh_attrs[] = {
  502. &batadv_attr_aggregated_ogms,
  503. &batadv_attr_bonding,
  504. #ifdef CONFIG_BATMAN_ADV_BLA
  505. &batadv_attr_bridge_loop_avoidance,
  506. #endif
  507. #ifdef CONFIG_BATMAN_ADV_DAT
  508. &batadv_attr_distributed_arp_table,
  509. #endif
  510. #ifdef CONFIG_BATMAN_ADV_MCAST
  511. &batadv_attr_multicast_mode,
  512. #endif
  513. &batadv_attr_fragmentation,
  514. &batadv_attr_routing_algo,
  515. &batadv_attr_gw_mode,
  516. &batadv_attr_orig_interval,
  517. &batadv_attr_hop_penalty,
  518. &batadv_attr_gw_sel_class,
  519. &batadv_attr_gw_bandwidth,
  520. #ifdef CONFIG_BATMAN_ADV_DEBUG
  521. &batadv_attr_log_level,
  522. #endif
  523. #ifdef CONFIG_BATMAN_ADV_NC
  524. &batadv_attr_network_coding,
  525. #endif
  526. &batadv_attr_isolation_mark,
  527. NULL,
  528. };
  529. BATADV_ATTR_VLAN_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL);
  530. /**
  531. * batadv_vlan_attrs - array of vlan specific sysfs attributes
  532. */
  533. static struct batadv_attribute *batadv_vlan_attrs[] = {
  534. &batadv_attr_vlan_ap_isolation,
  535. NULL,
  536. };
  537. int batadv_sysfs_add_meshif(struct net_device *dev)
  538. {
  539. struct kobject *batif_kobject = &dev->dev.kobj;
  540. struct batadv_priv *bat_priv = netdev_priv(dev);
  541. struct batadv_attribute **bat_attr;
  542. int err;
  543. bat_priv->mesh_obj = kobject_create_and_add(BATADV_SYSFS_IF_MESH_SUBDIR,
  544. batif_kobject);
  545. if (!bat_priv->mesh_obj) {
  546. batadv_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
  547. BATADV_SYSFS_IF_MESH_SUBDIR);
  548. goto out;
  549. }
  550. for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr) {
  551. err = sysfs_create_file(bat_priv->mesh_obj,
  552. &((*bat_attr)->attr));
  553. if (err) {
  554. batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n",
  555. dev->name, BATADV_SYSFS_IF_MESH_SUBDIR,
  556. ((*bat_attr)->attr).name);
  557. goto rem_attr;
  558. }
  559. }
  560. return 0;
  561. rem_attr:
  562. for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr)
  563. sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
  564. kobject_put(bat_priv->mesh_obj);
  565. bat_priv->mesh_obj = NULL;
  566. out:
  567. return -ENOMEM;
  568. }
  569. void batadv_sysfs_del_meshif(struct net_device *dev)
  570. {
  571. struct batadv_priv *bat_priv = netdev_priv(dev);
  572. struct batadv_attribute **bat_attr;
  573. for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr)
  574. sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
  575. kobject_put(bat_priv->mesh_obj);
  576. bat_priv->mesh_obj = NULL;
  577. }
  578. /**
  579. * batadv_sysfs_add_vlan - add all the needed sysfs objects for the new vlan
  580. * @dev: netdev of the mesh interface
  581. * @vlan: private data of the newly added VLAN interface
  582. *
  583. * Returns 0 on success and -ENOMEM if any of the structure allocations fails.
  584. */
  585. int batadv_sysfs_add_vlan(struct net_device *dev,
  586. struct batadv_softif_vlan *vlan)
  587. {
  588. char vlan_subdir[sizeof(BATADV_SYSFS_VLAN_SUBDIR_PREFIX) + 5];
  589. struct batadv_priv *bat_priv = netdev_priv(dev);
  590. struct batadv_attribute **bat_attr;
  591. int err;
  592. if (vlan->vid & BATADV_VLAN_HAS_TAG) {
  593. sprintf(vlan_subdir, BATADV_SYSFS_VLAN_SUBDIR_PREFIX "%hu",
  594. vlan->vid & VLAN_VID_MASK);
  595. vlan->kobj = kobject_create_and_add(vlan_subdir,
  596. bat_priv->mesh_obj);
  597. if (!vlan->kobj) {
  598. batadv_err(dev, "Can't add sysfs directory: %s/%s\n",
  599. dev->name, vlan_subdir);
  600. goto out;
  601. }
  602. } else {
  603. /* the untagged LAN uses the root folder to store its "VLAN
  604. * specific attributes"
  605. */
  606. vlan->kobj = bat_priv->mesh_obj;
  607. kobject_get(bat_priv->mesh_obj);
  608. }
  609. for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr) {
  610. err = sysfs_create_file(vlan->kobj,
  611. &((*bat_attr)->attr));
  612. if (err) {
  613. batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n",
  614. dev->name, vlan_subdir,
  615. ((*bat_attr)->attr).name);
  616. goto rem_attr;
  617. }
  618. }
  619. return 0;
  620. rem_attr:
  621. for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr)
  622. sysfs_remove_file(vlan->kobj, &((*bat_attr)->attr));
  623. kobject_put(vlan->kobj);
  624. vlan->kobj = NULL;
  625. out:
  626. return -ENOMEM;
  627. }
  628. /**
  629. * batadv_sysfs_del_vlan - remove all the sysfs objects for a given VLAN
  630. * @bat_priv: the bat priv with all the soft interface information
  631. * @vlan: the private data of the VLAN to destroy
  632. */
  633. void batadv_sysfs_del_vlan(struct batadv_priv *bat_priv,
  634. struct batadv_softif_vlan *vlan)
  635. {
  636. struct batadv_attribute **bat_attr;
  637. for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr)
  638. sysfs_remove_file(vlan->kobj, &((*bat_attr)->attr));
  639. kobject_put(vlan->kobj);
  640. vlan->kobj = NULL;
  641. }
  642. static ssize_t batadv_show_mesh_iface(struct kobject *kobj,
  643. struct attribute *attr, char *buff)
  644. {
  645. struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
  646. struct batadv_hard_iface *hard_iface;
  647. ssize_t length;
  648. const char *ifname;
  649. hard_iface = batadv_hardif_get_by_netdev(net_dev);
  650. if (!hard_iface)
  651. return 0;
  652. if (hard_iface->if_status == BATADV_IF_NOT_IN_USE)
  653. ifname = "none";
  654. else
  655. ifname = hard_iface->soft_iface->name;
  656. length = sprintf(buff, "%s\n", ifname);
  657. batadv_hardif_free_ref(hard_iface);
  658. return length;
  659. }
  660. static ssize_t batadv_store_mesh_iface(struct kobject *kobj,
  661. struct attribute *attr, char *buff,
  662. size_t count)
  663. {
  664. struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
  665. struct batadv_hard_iface *hard_iface;
  666. int status_tmp = -1;
  667. int ret = count;
  668. hard_iface = batadv_hardif_get_by_netdev(net_dev);
  669. if (!hard_iface)
  670. return count;
  671. if (buff[count - 1] == '\n')
  672. buff[count - 1] = '\0';
  673. if (strlen(buff) >= IFNAMSIZ) {
  674. pr_err("Invalid parameter for 'mesh_iface' setting received: interface name too long '%s'\n",
  675. buff);
  676. batadv_hardif_free_ref(hard_iface);
  677. return -EINVAL;
  678. }
  679. if (strncmp(buff, "none", 4) == 0)
  680. status_tmp = BATADV_IF_NOT_IN_USE;
  681. else
  682. status_tmp = BATADV_IF_I_WANT_YOU;
  683. if (hard_iface->if_status == status_tmp)
  684. goto out;
  685. if ((hard_iface->soft_iface) &&
  686. (strncmp(hard_iface->soft_iface->name, buff, IFNAMSIZ) == 0))
  687. goto out;
  688. rtnl_lock();
  689. if (status_tmp == BATADV_IF_NOT_IN_USE) {
  690. batadv_hardif_disable_interface(hard_iface,
  691. BATADV_IF_CLEANUP_AUTO);
  692. goto unlock;
  693. }
  694. /* if the interface already is in use */
  695. if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
  696. batadv_hardif_disable_interface(hard_iface,
  697. BATADV_IF_CLEANUP_AUTO);
  698. ret = batadv_hardif_enable_interface(hard_iface, buff);
  699. unlock:
  700. rtnl_unlock();
  701. out:
  702. batadv_hardif_free_ref(hard_iface);
  703. return ret;
  704. }
  705. static ssize_t batadv_show_iface_status(struct kobject *kobj,
  706. struct attribute *attr, char *buff)
  707. {
  708. struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
  709. struct batadv_hard_iface *hard_iface;
  710. ssize_t length;
  711. hard_iface = batadv_hardif_get_by_netdev(net_dev);
  712. if (!hard_iface)
  713. return 0;
  714. switch (hard_iface->if_status) {
  715. case BATADV_IF_TO_BE_REMOVED:
  716. length = sprintf(buff, "disabling\n");
  717. break;
  718. case BATADV_IF_INACTIVE:
  719. length = sprintf(buff, "inactive\n");
  720. break;
  721. case BATADV_IF_ACTIVE:
  722. length = sprintf(buff, "active\n");
  723. break;
  724. case BATADV_IF_TO_BE_ACTIVATED:
  725. length = sprintf(buff, "enabling\n");
  726. break;
  727. case BATADV_IF_NOT_IN_USE:
  728. default:
  729. length = sprintf(buff, "not in use\n");
  730. break;
  731. }
  732. batadv_hardif_free_ref(hard_iface);
  733. return length;
  734. }
  735. static BATADV_ATTR(mesh_iface, S_IRUGO | S_IWUSR, batadv_show_mesh_iface,
  736. batadv_store_mesh_iface);
  737. static BATADV_ATTR(iface_status, S_IRUGO, batadv_show_iface_status, NULL);
  738. static struct batadv_attribute *batadv_batman_attrs[] = {
  739. &batadv_attr_mesh_iface,
  740. &batadv_attr_iface_status,
  741. NULL,
  742. };
  743. int batadv_sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev)
  744. {
  745. struct kobject *hardif_kobject = &dev->dev.kobj;
  746. struct batadv_attribute **bat_attr;
  747. int err;
  748. *hardif_obj = kobject_create_and_add(BATADV_SYSFS_IF_BAT_SUBDIR,
  749. hardif_kobject);
  750. if (!*hardif_obj) {
  751. batadv_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
  752. BATADV_SYSFS_IF_BAT_SUBDIR);
  753. goto out;
  754. }
  755. for (bat_attr = batadv_batman_attrs; *bat_attr; ++bat_attr) {
  756. err = sysfs_create_file(*hardif_obj, &((*bat_attr)->attr));
  757. if (err) {
  758. batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n",
  759. dev->name, BATADV_SYSFS_IF_BAT_SUBDIR,
  760. ((*bat_attr)->attr).name);
  761. goto rem_attr;
  762. }
  763. }
  764. return 0;
  765. rem_attr:
  766. for (bat_attr = batadv_batman_attrs; *bat_attr; ++bat_attr)
  767. sysfs_remove_file(*hardif_obj, &((*bat_attr)->attr));
  768. out:
  769. return -ENOMEM;
  770. }
  771. void batadv_sysfs_del_hardif(struct kobject **hardif_obj)
  772. {
  773. kobject_put(*hardif_obj);
  774. *hardif_obj = NULL;
  775. }
  776. int batadv_throw_uevent(struct batadv_priv *bat_priv, enum batadv_uev_type type,
  777. enum batadv_uev_action action, const char *data)
  778. {
  779. int ret = -ENOMEM;
  780. struct kobject *bat_kobj;
  781. char *uevent_env[4] = { NULL, NULL, NULL, NULL };
  782. bat_kobj = &bat_priv->soft_iface->dev.kobj;
  783. uevent_env[0] = kasprintf(GFP_ATOMIC,
  784. "%s%s", BATADV_UEV_TYPE_VAR,
  785. batadv_uev_type_str[type]);
  786. if (!uevent_env[0])
  787. goto out;
  788. uevent_env[1] = kasprintf(GFP_ATOMIC,
  789. "%s%s", BATADV_UEV_ACTION_VAR,
  790. batadv_uev_action_str[action]);
  791. if (!uevent_env[1])
  792. goto out;
  793. /* If the event is DEL, ignore the data field */
  794. if (action != BATADV_UEV_DEL) {
  795. uevent_env[2] = kasprintf(GFP_ATOMIC,
  796. "%s%s", BATADV_UEV_DATA_VAR, data);
  797. if (!uevent_env[2])
  798. goto out;
  799. }
  800. ret = kobject_uevent_env(bat_kobj, KOBJ_CHANGE, uevent_env);
  801. out:
  802. kfree(uevent_env[0]);
  803. kfree(uevent_env[1]);
  804. kfree(uevent_env[2]);
  805. if (ret)
  806. batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
  807. "Impossible to send uevent for (%s,%s,%s) event (err: %d)\n",
  808. batadv_uev_type_str[type],
  809. batadv_uev_action_str[action],
  810. (action == BATADV_UEV_DEL ? "NULL" : data), ret);
  811. return ret;
  812. }