~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/batman-adv/sysfs.c

Version: ~ [ linux-5.12-rc1 ] ~ [ linux-5.11.2 ] ~ [ linux-5.10.19 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.101 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.177 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.222 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.258 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.258 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* Copyright (C) 2010-2016  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 
 18 #include "sysfs.h"
 19 #include "main.h"
 20 
 21 #include <linux/atomic.h>
 22 #include <linux/compiler.h>
 23 #include <linux/device.h>
 24 #include <linux/errno.h>
 25 #include <linux/fs.h>
 26 #include <linux/if.h>
 27 #include <linux/if_vlan.h>
 28 #include <linux/kref.h>
 29 #include <linux/kernel.h>
 30 #include <linux/netdevice.h>
 31 #include <linux/printk.h>
 32 #include <linux/rculist.h>
 33 #include <linux/rcupdate.h>
 34 #include <linux/rtnetlink.h>
 35 #include <linux/slab.h>
 36 #include <linux/stat.h>
 37 #include <linux/stddef.h>
 38 #include <linux/string.h>
 39 #include <linux/stringify.h>
 40 
 41 #include "distributed-arp-table.h"
 42 #include "gateway_client.h"
 43 #include "gateway_common.h"
 44 #include "bridge_loop_avoidance.h"
 45 #include "hard-interface.h"
 46 #include "network-coding.h"
 47 #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         return to_net_dev(dev);
 55 }
 56 
 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         return netdev_priv(net_dev);
 62 }
 63 
 64 /**
 65  * batadv_vlan_kobj_to_batpriv - convert a vlan kobj in the associated batpriv
 66  * @obj: kobject to covert
 67  *
 68  * Return: the associated batadv_priv struct.
 69  */
 70 static struct batadv_priv *batadv_vlan_kobj_to_batpriv(struct kobject *obj)
 71 {
 72         /* VLAN specific attributes are located in the root sysfs folder if they
 73          * refer to the untagged VLAN..
 74          */
 75         if (!strcmp(BATADV_SYSFS_IF_MESH_SUBDIR, obj->name))
 76                 return batadv_kobj_to_batpriv(obj);
 77 
 78         /* ..while the attributes for the tagged vlans are located in
 79          * the in the corresponding "vlan%VID" subfolder
 80          */
 81         return batadv_kobj_to_batpriv(obj->parent);
 82 }
 83 
 84 /**
 85  * 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  * @obj: kobject to covert
 88  *
 89  * Return: the associated softif_vlan struct if found, NULL otherwise.
 90  */
 91 static struct batadv_softif_vlan *
 92 batadv_kobj_to_vlan(struct batadv_priv *bat_priv, struct kobject *obj)
 93 {
 94         struct batadv_softif_vlan *vlan_tmp, *vlan = NULL;
 95 
 96         rcu_read_lock();
 97         hlist_for_each_entry_rcu(vlan_tmp, &bat_priv->softif_vlan_list, list) {
 98                 if (vlan_tmp->kobj != obj)
 99                         continue;
100 
101                 if (!kref_get_unless_zero(&vlan_tmp->refcount))
102                         continue;
103 
104                 vlan = vlan_tmp;
105                 break;
106         }
107         rcu_read_unlock();
108 
109         return vlan;
110 }
111 
112 #define BATADV_UEV_TYPE_VAR     "BATTYPE="
113 #define BATADV_UEV_ACTION_VAR   "BATACTION="
114 #define BATADV_UEV_DATA_VAR     "BATDATA="
115 
116 static char *batadv_uev_action_str[] = {
117         "add",
118         "del",
119         "change",
120         "loopdetect",
121 };
122 
123 static char *batadv_uev_type_str[] = {
124         "gw",
125         "bla",
126 };
127 
128 /* Use this, if you have customized show and store functions for vlan attrs */
129 #define BATADV_ATTR_VLAN(_name, _mode, _show, _store)   \
130 struct batadv_attribute batadv_attr_vlan_##_name = {    \
131         .attr = {.name = __stringify(_name),            \
132                  .mode = _mode },                       \
133         .show   = _show,                                \
134         .store  = _store,                               \
135 }
136 
137 /* Use this, if you have customized show and store functions */
138 #define BATADV_ATTR(_name, _mode, _show, _store)        \
139 struct batadv_attribute batadv_attr_##_name = {         \
140         .attr = {.name = __stringify(_name),            \
141                  .mode = _mode },                       \
142         .show   = _show,                                \
143         .store  = _store,                               \
144 }
145 
146 #define BATADV_ATTR_SIF_STORE_BOOL(_name, _post_func)                   \
147 ssize_t batadv_store_##_name(struct kobject *kobj,                      \
148                              struct attribute *attr, char *buff,        \
149                              size_t count)                              \
150 {                                                                       \
151         struct net_device *net_dev = batadv_kobj_to_netdev(kobj);       \
152         struct batadv_priv *bat_priv = netdev_priv(net_dev);            \
153                                                                         \
154         return __batadv_store_bool_attr(buff, count, _post_func, attr,  \
155                                         &bat_priv->_name, net_dev);     \
156 }
157 
158 #define BATADV_ATTR_SIF_SHOW_BOOL(_name)                                \
159 ssize_t batadv_show_##_name(struct kobject *kobj,                       \
160                             struct attribute *attr, char *buff)         \
161 {                                                                       \
162         struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);    \
163                                                                         \
164         return sprintf(buff, "%s\n",                                    \
165                        atomic_read(&bat_priv->_name) == 0 ?             \
166                        "disabled" : "enabled");                         \
167 }                                                                       \
168 
169 /* Use this, if you are going to turn a [name] in the soft-interface
170  * (bat_priv) on or off
171  */
172 #define BATADV_ATTR_SIF_BOOL(_name, _mode, _post_func)                  \
173         static BATADV_ATTR_SIF_STORE_BOOL(_name, _post_func)            \
174         static BATADV_ATTR_SIF_SHOW_BOOL(_name)                         \
175         static BATADV_ATTR(_name, _mode, batadv_show_##_name,           \
176                            batadv_store_##_name)
177 
178 #define BATADV_ATTR_SIF_STORE_UINT(_name, _var, _min, _max, _post_func) \
179 ssize_t batadv_store_##_name(struct kobject *kobj,                      \
180                              struct attribute *attr, char *buff,        \
181                              size_t count)                              \
182 {                                                                       \
183         struct net_device *net_dev = batadv_kobj_to_netdev(kobj);       \
184         struct batadv_priv *bat_priv = netdev_priv(net_dev);            \
185                                                                         \
186         return __batadv_store_uint_attr(buff, count, _min, _max,        \
187                                         _post_func, attr,               \
188                                         &bat_priv->_var, net_dev);      \
189 }
190 
191 #define BATADV_ATTR_SIF_SHOW_UINT(_name, _var)                          \
192 ssize_t batadv_show_##_name(struct kobject *kobj,                       \
193                             struct attribute *attr, char *buff)         \
194 {                                                                       \
195         struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);    \
196                                                                         \
197         return sprintf(buff, "%i\n", atomic_read(&bat_priv->_var));     \
198 }                                                                       \
199 
200 /* Use this, if you are going to set [name] in the soft-interface
201  * (bat_priv) to an unsigned integer value
202  */
203 #define BATADV_ATTR_SIF_UINT(_name, _var, _mode, _min, _max, _post_func)\
204         static BATADV_ATTR_SIF_STORE_UINT(_name, _var, _min, _max, _post_func)\
205         static BATADV_ATTR_SIF_SHOW_UINT(_name, _var)                   \
206         static BATADV_ATTR(_name, _mode, batadv_show_##_name,           \
207                            batadv_store_##_name)
208 
209 #define BATADV_ATTR_VLAN_STORE_BOOL(_name, _post_func)                  \
210 ssize_t batadv_store_vlan_##_name(struct kobject *kobj,                 \
211                                   struct attribute *attr, char *buff,   \
212                                   size_t count)                         \
213 {                                                                       \
214         struct batadv_priv *bat_priv = batadv_vlan_kobj_to_batpriv(kobj);\
215         struct batadv_softif_vlan *vlan = batadv_kobj_to_vlan(bat_priv, \
216                                                               kobj);    \
217         size_t res = __batadv_store_bool_attr(buff, count, _post_func,  \
218                                               attr, &vlan->_name,       \
219                                               bat_priv->soft_iface);    \
220                                                                         \
221         batadv_softif_vlan_put(vlan);                                   \
222         return res;                                                     \
223 }
224 
225 #define BATADV_ATTR_VLAN_SHOW_BOOL(_name)                               \
226 ssize_t batadv_show_vlan_##_name(struct kobject *kobj,                  \
227                                  struct attribute *attr, char *buff)    \
228 {                                                                       \
229         struct batadv_priv *bat_priv = batadv_vlan_kobj_to_batpriv(kobj);\
230         struct batadv_softif_vlan *vlan = batadv_kobj_to_vlan(bat_priv, \
231                                                               kobj);    \
232         size_t res = sprintf(buff, "%s\n",                              \
233                              atomic_read(&vlan->_name) == 0 ?           \
234                              "disabled" : "enabled");                   \
235                                                                         \
236         batadv_softif_vlan_put(vlan);                                   \
237         return res;                                                     \
238 }
239 
240 /* Use this, if you are going to turn a [name] in the vlan struct on or off */
241 #define BATADV_ATTR_VLAN_BOOL(_name, _mode, _post_func)                 \
242         static BATADV_ATTR_VLAN_STORE_BOOL(_name, _post_func)           \
243         static BATADV_ATTR_VLAN_SHOW_BOOL(_name)                        \
244         static BATADV_ATTR_VLAN(_name, _mode, batadv_show_vlan_##_name, \
245                                 batadv_store_vlan_##_name)
246 
247 #define BATADV_ATTR_HIF_STORE_UINT(_name, _var, _min, _max, _post_func) \
248 ssize_t batadv_store_##_name(struct kobject *kobj,                      \
249                              struct attribute *attr, char *buff,        \
250                              size_t count)                              \
251 {                                                                       \
252         struct net_device *net_dev = batadv_kobj_to_netdev(kobj);       \
253         struct batadv_hard_iface *hard_iface;                           \
254         ssize_t length;                                                 \
255                                                                         \
256         hard_iface = batadv_hardif_get_by_netdev(net_dev);              \
257         if (!hard_iface)                                                \
258                 return 0;                                               \
259                                                                         \
260         length = __batadv_store_uint_attr(buff, count, _min, _max,      \
261                                           _post_func, attr,             \
262                                           &hard_iface->_var, net_dev);  \
263                                                                         \
264         batadv_hardif_put(hard_iface);                          \
265         return length;                                                  \
266 }
267 
268 #define BATADV_ATTR_HIF_SHOW_UINT(_name, _var)                          \
269 ssize_t batadv_show_##_name(struct kobject *kobj,                       \
270                             struct attribute *attr, char *buff)         \
271 {                                                                       \
272         struct net_device *net_dev = batadv_kobj_to_netdev(kobj);       \
273         struct batadv_hard_iface *hard_iface;                           \
274         ssize_t length;                                                 \
275                                                                         \
276         hard_iface = batadv_hardif_get_by_netdev(net_dev);              \
277         if (!hard_iface)                                                \
278                 return 0;                                               \
279                                                                         \
280         length = sprintf(buff, "%i\n", atomic_read(&hard_iface->_var)); \
281                                                                         \
282         batadv_hardif_put(hard_iface);                          \
283         return length;                                                  \
284 }
285 
286 /* Use this, if you are going to set [name] in hard_iface to an
287  * unsigned integer value
288  */
289 #define BATADV_ATTR_HIF_UINT(_name, _var, _mode, _min, _max, _post_func)\
290         static BATADV_ATTR_HIF_STORE_UINT(_name, _var, _min,            \
291                                           _max, _post_func)             \
292         static BATADV_ATTR_HIF_SHOW_UINT(_name, _var)                   \
293         static BATADV_ATTR(_name, _mode, batadv_show_##_name,           \
294                            batadv_store_##_name)
295 
296 static int batadv_store_bool_attr(char *buff, size_t count,
297                                   struct net_device *net_dev,
298                                   const char *attr_name, atomic_t *attr,
299                                   bool *changed)
300 {
301         int enabled = -1;
302 
303         *changed = false;
304 
305         if (buff[count - 1] == '\n')
306                 buff[count - 1] = '\0';
307 
308         if ((strncmp(buff, "1", 2) == 0) ||
309             (strncmp(buff, "enable", 7) == 0) ||
310             (strncmp(buff, "enabled", 8) == 0))
311                 enabled = 1;
312 
313         if ((strncmp(buff, "", 2) == 0) ||
314             (strncmp(buff, "disable", 8) == 0) ||
315             (strncmp(buff, "disabled", 9) == 0))
316                 enabled = 0;
317 
318         if (enabled < 0) {
319                 batadv_info(net_dev, "%s: Invalid parameter received: %s\n",
320                             attr_name, buff);
321                 return -EINVAL;
322         }
323 
324         if (atomic_read(attr) == enabled)
325                 return count;
326 
327         batadv_info(net_dev, "%s: Changing from: %s to: %s\n", attr_name,
328                     atomic_read(attr) == 1 ? "enabled" : "disabled",
329                     enabled == 1 ? "enabled" : "disabled");
330 
331         *changed = true;
332 
333         atomic_set(attr, (unsigned int)enabled);
334         return count;
335 }
336 
337 static inline ssize_t
338 __batadv_store_bool_attr(char *buff, size_t count,
339                          void (*post_func)(struct net_device *),
340                          struct attribute *attr,
341                          atomic_t *attr_store, struct net_device *net_dev)
342 {
343         bool changed;
344         int ret;
345 
346         ret = batadv_store_bool_attr(buff, count, net_dev, attr->name,
347                                      attr_store, &changed);
348         if (post_func && changed)
349                 post_func(net_dev);
350 
351         return ret;
352 }
353 
354 static int batadv_store_uint_attr(const char *buff, size_t count,
355                                   struct net_device *net_dev,
356                                   const char *attr_name,
357                                   unsigned int min, unsigned int max,
358                                   atomic_t *attr)
359 {
360         unsigned long uint_val;
361         int ret;
362 
363         ret = kstrtoul(buff, 10, &uint_val);
364         if (ret) {
365                 batadv_info(net_dev, "%s: Invalid parameter received: %s\n",
366                             attr_name, buff);
367                 return -EINVAL;
368         }
369 
370         if (uint_val < min) {
371                 batadv_info(net_dev, "%s: Value is too small: %lu min: %u\n",
372                             attr_name, uint_val, min);
373                 return -EINVAL;
374         }
375 
376         if (uint_val > max) {
377                 batadv_info(net_dev, "%s: Value is too big: %lu max: %u\n",
378                             attr_name, uint_val, max);
379                 return -EINVAL;
380         }
381 
382         if (atomic_read(attr) == uint_val)
383                 return count;
384 
385         batadv_info(net_dev, "%s: Changing from: %i to: %lu\n",
386                     attr_name, atomic_read(attr), uint_val);
387 
388         atomic_set(attr, uint_val);
389         return count;
390 }
391 
392 static inline ssize_t
393 __batadv_store_uint_attr(const char *buff, size_t count,
394                          int min, int max,
395                          void (*post_func)(struct net_device *),
396                          const struct attribute *attr,
397                          atomic_t *attr_store, struct net_device *net_dev)
398 {
399         int ret;
400 
401         ret = batadv_store_uint_attr(buff, count, net_dev, attr->name, min, max,
402                                      attr_store);
403         if (post_func && ret)
404                 post_func(net_dev);
405 
406         return ret;
407 }
408 
409 static ssize_t batadv_show_bat_algo(struct kobject *kobj,
410                                     struct attribute *attr, char *buff)
411 {
412         struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
413 
414         return sprintf(buff, "%s\n", bat_priv->bat_algo_ops->name);
415 }
416 
417 static void batadv_post_gw_reselect(struct net_device *net_dev)
418 {
419         struct batadv_priv *bat_priv = netdev_priv(net_dev);
420 
421         batadv_gw_reselect(bat_priv);
422 }
423 
424 static ssize_t batadv_show_gw_mode(struct kobject *kobj, struct attribute *attr,
425                                    char *buff)
426 {
427         struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
428         int bytes_written;
429 
430         switch (atomic_read(&bat_priv->gw_mode)) {
431         case BATADV_GW_MODE_CLIENT:
432                 bytes_written = sprintf(buff, "%s\n",
433                                         BATADV_GW_MODE_CLIENT_NAME);
434                 break;
435         case BATADV_GW_MODE_SERVER:
436                 bytes_written = sprintf(buff, "%s\n",
437                                         BATADV_GW_MODE_SERVER_NAME);
438                 break;
439         default:
440                 bytes_written = sprintf(buff, "%s\n",
441                                         BATADV_GW_MODE_OFF_NAME);
442                 break;
443         }
444 
445         return bytes_written;
446 }
447 
448 static ssize_t batadv_store_gw_mode(struct kobject *kobj,
449                                     struct attribute *attr, char *buff,
450                                     size_t count)
451 {
452         struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
453         struct batadv_priv *bat_priv = netdev_priv(net_dev);
454         char *curr_gw_mode_str;
455         int gw_mode_tmp = -1;
456 
457         if (buff[count - 1] == '\n')
458                 buff[count - 1] = '\0';
459 
460         if (strncmp(buff, BATADV_GW_MODE_OFF_NAME,
461                     strlen(BATADV_GW_MODE_OFF_NAME)) == 0)
462                 gw_mode_tmp = BATADV_GW_MODE_OFF;
463 
464         if (strncmp(buff, BATADV_GW_MODE_CLIENT_NAME,
465                     strlen(BATADV_GW_MODE_CLIENT_NAME)) == 0)
466                 gw_mode_tmp = BATADV_GW_MODE_CLIENT;
467 
468         if (strncmp(buff, BATADV_GW_MODE_SERVER_NAME,
469                     strlen(BATADV_GW_MODE_SERVER_NAME)) == 0)
470                 gw_mode_tmp = BATADV_GW_MODE_SERVER;
471 
472         if (gw_mode_tmp < 0) {
473                 batadv_info(net_dev,
474                             "Invalid parameter for 'gw mode' setting received: %s\n",
475                             buff);
476                 return -EINVAL;
477         }
478 
479         if (atomic_read(&bat_priv->gw_mode) == gw_mode_tmp)
480                 return count;
481 
482         switch (atomic_read(&bat_priv->gw_mode)) {
483         case BATADV_GW_MODE_CLIENT:
484                 curr_gw_mode_str = BATADV_GW_MODE_CLIENT_NAME;
485                 break;
486         case BATADV_GW_MODE_SERVER:
487                 curr_gw_mode_str = BATADV_GW_MODE_SERVER_NAME;
488                 break;
489         default:
490                 curr_gw_mode_str = BATADV_GW_MODE_OFF_NAME;
491                 break;
492         }
493 
494         batadv_info(net_dev, "Changing gw mode from: %s to: %s\n",
495                     curr_gw_mode_str, buff);
496 
497         /* Invoking batadv_gw_reselect() is not enough to really de-select the
498          * current GW. It will only instruct the gateway client code to perform
499          * a re-election the next time that this is needed.
500          *
501          * When gw client mode is being switched off the current GW must be
502          * de-selected explicitly otherwise no GW_ADD uevent is thrown on
503          * client mode re-activation. This is operation is performed in
504          * batadv_gw_check_client_stop().
505          */
506         batadv_gw_reselect(bat_priv);
507         /* always call batadv_gw_check_client_stop() before changing the gateway
508          * state
509          */
510         batadv_gw_check_client_stop(bat_priv);
511         atomic_set(&bat_priv->gw_mode, (unsigned int)gw_mode_tmp);
512         batadv_gw_tvlv_container_update(bat_priv);
513         return count;
514 }
515 
516 static ssize_t batadv_show_gw_bwidth(struct kobject *kobj,
517                                      struct attribute *attr, char *buff)
518 {
519         struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
520         u32 down, up;
521 
522         down = atomic_read(&bat_priv->gw.bandwidth_down);
523         up = atomic_read(&bat_priv->gw.bandwidth_up);
524 
525         return sprintf(buff, "%u.%u/%u.%u MBit\n", down / 10,
526                        down % 10, up / 10, up % 10);
527 }
528 
529 static ssize_t batadv_store_gw_bwidth(struct kobject *kobj,
530                                       struct attribute *attr, char *buff,
531                                       size_t count)
532 {
533         struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
534 
535         if (buff[count - 1] == '\n')
536                 buff[count - 1] = '\0';
537 
538         return batadv_gw_bandwidth_set(net_dev, buff, count);
539 }
540 
541 /**
542  * batadv_show_isolation_mark - print the current isolation mark/mask
543  * @kobj: kobject representing the private mesh sysfs directory
544  * @attr: the batman-adv attribute the user is interacting with
545  * @buff: the buffer that will contain the data to send back to the user
546  *
547  * Return: the number of bytes written into 'buff' on success or a negative
548  * error code in case of failure
549  */
550 static ssize_t batadv_show_isolation_mark(struct kobject *kobj,
551                                           struct attribute *attr, char *buff)
552 {
553         struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
554 
555         return sprintf(buff, "%#.8x/%#.8x\n", bat_priv->isolation_mark,
556                        bat_priv->isolation_mark_mask);
557 }
558 
559 /**
560  * batadv_store_isolation_mark - parse and store the isolation mark/mask entered
561  *  by the user
562  * @kobj: kobject representing the private mesh sysfs directory
563  * @attr: the batman-adv attribute the user is interacting with
564  * @buff: the buffer containing the user data
565  * @count: number of bytes in the buffer
566  *
567  * Return: 'count' on success or a negative error code in case of failure
568  */
569 static ssize_t batadv_store_isolation_mark(struct kobject *kobj,
570                                            struct attribute *attr, char *buff,
571                                            size_t count)
572 {
573         struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
574         struct batadv_priv *bat_priv = netdev_priv(net_dev);
575         u32 mark, mask;
576         char *mask_ptr;
577 
578         /* parse the mask if it has been specified, otherwise assume the mask is
579          * the biggest possible
580          */
581         mask = 0xFFFFFFFF;
582         mask_ptr = strchr(buff, '/');
583         if (mask_ptr) {
584                 *mask_ptr = '\0';
585                 mask_ptr++;
586 
587                 /* the mask must be entered in hex base as it is going to be a
588                  * bitmask and not a prefix length
589                  */
590                 if (kstrtou32(mask_ptr, 16, &mask) < 0)
591                         return -EINVAL;
592         }
593 
594         /* the mark can be entered in any base */
595         if (kstrtou32(buff, 0, &mark) < 0)
596                 return -EINVAL;
597 
598         bat_priv->isolation_mark_mask = mask;
599         /* erase bits not covered by the mask */
600         bat_priv->isolation_mark = mark & bat_priv->isolation_mark_mask;
601 
602         batadv_info(net_dev,
603                     "New skb mark for extended isolation: %#.8x/%#.8x\n",
604                     bat_priv->isolation_mark, bat_priv->isolation_mark_mask);
605 
606         return count;
607 }
608 
609 BATADV_ATTR_SIF_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL);
610 BATADV_ATTR_SIF_BOOL(bonding, S_IRUGO | S_IWUSR, NULL);
611 #ifdef CONFIG_BATMAN_ADV_BLA
612 BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR,
613                      batadv_bla_status_update);
614 #endif
615 #ifdef CONFIG_BATMAN_ADV_DAT
616 BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR,
617                      batadv_dat_status_update);
618 #endif
619 BATADV_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, batadv_update_min_mtu);
620 static BATADV_ATTR(routing_algo, S_IRUGO, batadv_show_bat_algo, NULL);
621 static BATADV_ATTR(gw_mode, S_IRUGO | S_IWUSR, batadv_show_gw_mode,
622                    batadv_store_gw_mode);
623 BATADV_ATTR_SIF_UINT(orig_interval, orig_interval, S_IRUGO | S_IWUSR,
624                      2 * BATADV_JITTER, INT_MAX, NULL);
625 BATADV_ATTR_SIF_UINT(hop_penalty, hop_penalty, S_IRUGO | S_IWUSR, 0,
626                      BATADV_TQ_MAX_VALUE, NULL);
627 BATADV_ATTR_SIF_UINT(gw_sel_class, gw_sel_class, S_IRUGO | S_IWUSR, 1,
628                      BATADV_TQ_MAX_VALUE, batadv_post_gw_reselect);
629 static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth,
630                    batadv_store_gw_bwidth);
631 #ifdef CONFIG_BATMAN_ADV_MCAST
632 BATADV_ATTR_SIF_BOOL(multicast_mode, S_IRUGO | S_IWUSR, NULL);
633 #endif
634 #ifdef CONFIG_BATMAN_ADV_DEBUG
635 BATADV_ATTR_SIF_UINT(log_level, log_level, S_IRUGO | S_IWUSR, 0,
636                      BATADV_DBG_ALL, NULL);
637 #endif
638 #ifdef CONFIG_BATMAN_ADV_NC
639 BATADV_ATTR_SIF_BOOL(network_coding, S_IRUGO | S_IWUSR,
640                      batadv_nc_status_update);
641 #endif
642 static BATADV_ATTR(isolation_mark, S_IRUGO | S_IWUSR,
643                    batadv_show_isolation_mark, batadv_store_isolation_mark);
644 
645 static struct batadv_attribute *batadv_mesh_attrs[] = {
646         &batadv_attr_aggregated_ogms,
647         &batadv_attr_bonding,
648 #ifdef CONFIG_BATMAN_ADV_BLA
649         &batadv_attr_bridge_loop_avoidance,
650 #endif
651 #ifdef CONFIG_BATMAN_ADV_DAT
652         &batadv_attr_distributed_arp_table,
653 #endif
654 #ifdef CONFIG_BATMAN_ADV_MCAST
655         &batadv_attr_multicast_mode,
656 #endif
657         &batadv_attr_fragmentation,
658         &batadv_attr_routing_algo,
659         &batadv_attr_gw_mode,
660         &batadv_attr_orig_interval,
661         &batadv_attr_hop_penalty,
662         &batadv_attr_gw_sel_class,
663         &batadv_attr_gw_bandwidth,
664 #ifdef CONFIG_BATMAN_ADV_DEBUG
665         &batadv_attr_log_level,
666 #endif
667 #ifdef CONFIG_BATMAN_ADV_NC
668         &batadv_attr_network_coding,
669 #endif
670         &batadv_attr_isolation_mark,
671         NULL,
672 };
673 
674 BATADV_ATTR_VLAN_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL);
675 
676 /* array of vlan specific sysfs attributes */
677 static struct batadv_attribute *batadv_vlan_attrs[] = {
678         &batadv_attr_vlan_ap_isolation,
679         NULL,
680 };
681 
682 int batadv_sysfs_add_meshif(struct net_device *dev)
683 {
684         struct kobject *batif_kobject = &dev->dev.kobj;
685         struct batadv_priv *bat_priv = netdev_priv(dev);
686         struct batadv_attribute **bat_attr;
687         int err;
688 
689         bat_priv->mesh_obj = kobject_create_and_add(BATADV_SYSFS_IF_MESH_SUBDIR,
690                                                     batif_kobject);
691         if (!bat_priv->mesh_obj) {
692                 batadv_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
693                            BATADV_SYSFS_IF_MESH_SUBDIR);
694                 goto out;
695         }
696 
697         for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr) {
698                 err = sysfs_create_file(bat_priv->mesh_obj,
699                                         &((*bat_attr)->attr));
700                 if (err) {
701                         batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n",
702                                    dev->name, BATADV_SYSFS_IF_MESH_SUBDIR,
703                                    ((*bat_attr)->attr).name);
704                         goto rem_attr;
705                 }
706         }
707 
708         return 0;
709 
710 rem_attr:
711         for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr)
712                 sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
713 
714         kobject_put(bat_priv->mesh_obj);
715         bat_priv->mesh_obj = NULL;
716 out:
717         return -ENOMEM;
718 }
719 
720 void batadv_sysfs_del_meshif(struct net_device *dev)
721 {
722         struct batadv_priv *bat_priv = netdev_priv(dev);
723         struct batadv_attribute **bat_attr;
724 
725         for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr)
726                 sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
727 
728         kobject_put(bat_priv->mesh_obj);
729         bat_priv->mesh_obj = NULL;
730 }
731 
732 /**
733  * batadv_sysfs_add_vlan - add all the needed sysfs objects for the new vlan
734  * @dev: netdev of the mesh interface
735  * @vlan: private data of the newly added VLAN interface
736  *
737  * Return: 0 on success and -ENOMEM if any of the structure allocations fails.
738  */
739 int batadv_sysfs_add_vlan(struct net_device *dev,
740                           struct batadv_softif_vlan *vlan)
741 {
742         char vlan_subdir[sizeof(BATADV_SYSFS_VLAN_SUBDIR_PREFIX) + 5];
743         struct batadv_priv *bat_priv = netdev_priv(dev);
744         struct batadv_attribute **bat_attr;
745         int err;
746 
747         if (vlan->vid & BATADV_VLAN_HAS_TAG) {
748                 sprintf(vlan_subdir, BATADV_SYSFS_VLAN_SUBDIR_PREFIX "%hu",
749                         vlan->vid & VLAN_VID_MASK);
750 
751                 vlan->kobj = kobject_create_and_add(vlan_subdir,
752                                                     bat_priv->mesh_obj);
753                 if (!vlan->kobj) {
754                         batadv_err(dev, "Can't add sysfs directory: %s/%s\n",
755                                    dev->name, vlan_subdir);
756                         goto out;
757                 }
758         } else {
759                 /* the untagged LAN uses the root folder to store its "VLAN
760                  * specific attributes"
761                  */
762                 vlan->kobj = bat_priv->mesh_obj;
763                 kobject_get(bat_priv->mesh_obj);
764         }
765 
766         for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr) {
767                 err = sysfs_create_file(vlan->kobj,
768                                         &((*bat_attr)->attr));
769                 if (err) {
770                         batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n",
771                                    dev->name, vlan_subdir,
772                                    ((*bat_attr)->attr).name);
773                         goto rem_attr;
774                 }
775         }
776 
777         return 0;
778 
779 rem_attr:
780         for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr)
781                 sysfs_remove_file(vlan->kobj, &((*bat_attr)->attr));
782 
783         kobject_put(vlan->kobj);
784         vlan->kobj = NULL;
785 out:
786         return -ENOMEM;
787 }
788 
789 /**
790  * batadv_sysfs_del_vlan - remove all the sysfs objects for a given VLAN
791  * @bat_priv: the bat priv with all the soft interface information
792  * @vlan: the private data of the VLAN to destroy
793  */
794 void batadv_sysfs_del_vlan(struct batadv_priv *bat_priv,
795                            struct batadv_softif_vlan *vlan)
796 {
797         struct batadv_attribute **bat_attr;
798 
799         for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr)
800                 sysfs_remove_file(vlan->kobj, &((*bat_attr)->attr));
801 
802         kobject_put(vlan->kobj);
803         vlan->kobj = NULL;
804 }
805 
806 static ssize_t batadv_show_mesh_iface(struct kobject *kobj,
807                                       struct attribute *attr, char *buff)
808 {
809         struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
810         struct batadv_hard_iface *hard_iface;
811         ssize_t length;
812         const char *ifname;
813 
814         hard_iface = batadv_hardif_get_by_netdev(net_dev);
815         if (!hard_iface)
816                 return 0;
817 
818         if (hard_iface->if_status == BATADV_IF_NOT_IN_USE)
819                 ifname =  "none";
820         else
821                 ifname = hard_iface->soft_iface->name;
822 
823         length = sprintf(buff, "%s\n", ifname);
824 
825         batadv_hardif_put(hard_iface);
826 
827         return length;
828 }
829 
830 static ssize_t batadv_store_mesh_iface(struct kobject *kobj,
831                                        struct attribute *attr, char *buff,
832                                        size_t count)
833 {
834         struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
835         struct net *net = dev_net(net_dev);
836         struct batadv_hard_iface *hard_iface;
837         int status_tmp = -1;
838         int ret = count;
839 
840         hard_iface = batadv_hardif_get_by_netdev(net_dev);
841         if (!hard_iface)
842                 return count;
843 
844         if (buff[count - 1] == '\n')
845                 buff[count - 1] = '\0';
846 
847         if (strlen(buff) >= IFNAMSIZ) {
848                 pr_err("Invalid parameter for 'mesh_iface' setting received: interface name too long '%s'\n",
849                        buff);
850                 batadv_hardif_put(hard_iface);
851                 return -EINVAL;
852         }
853 
854         if (strncmp(buff, "none", 4) == 0)
855                 status_tmp = BATADV_IF_NOT_IN_USE;
856         else
857                 status_tmp = BATADV_IF_I_WANT_YOU;
858 
859         if (hard_iface->if_status == status_tmp)
860                 goto out;
861 
862         if ((hard_iface->soft_iface) &&
863             (strncmp(hard_iface->soft_iface->name, buff, IFNAMSIZ) == 0))
864                 goto out;
865 
866         rtnl_lock();
867 
868         if (status_tmp == BATADV_IF_NOT_IN_USE) {
869                 batadv_hardif_disable_interface(hard_iface,
870                                                 BATADV_IF_CLEANUP_AUTO);
871                 goto unlock;
872         }
873 
874         /* if the interface already is in use */
875         if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
876                 batadv_hardif_disable_interface(hard_iface,
877                                                 BATADV_IF_CLEANUP_AUTO);
878 
879         ret = batadv_hardif_enable_interface(hard_iface, net, buff);
880 
881 unlock:
882         rtnl_unlock();
883 out:
884         batadv_hardif_put(hard_iface);
885         return ret;
886 }
887 
888 static ssize_t batadv_show_iface_status(struct kobject *kobj,
889                                         struct attribute *attr, char *buff)
890 {
891         struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
892         struct batadv_hard_iface *hard_iface;
893         ssize_t length;
894 
895         hard_iface = batadv_hardif_get_by_netdev(net_dev);
896         if (!hard_iface)
897                 return 0;
898 
899         switch (hard_iface->if_status) {
900         case BATADV_IF_TO_BE_REMOVED:
901                 length = sprintf(buff, "disabling\n");
902                 break;
903         case BATADV_IF_INACTIVE:
904                 length = sprintf(buff, "inactive\n");
905                 break;
906         case BATADV_IF_ACTIVE:
907                 length = sprintf(buff, "active\n");
908                 break;
909         case BATADV_IF_TO_BE_ACTIVATED:
910                 length = sprintf(buff, "enabling\n");
911                 break;
912         case BATADV_IF_NOT_IN_USE:
913         default:
914                 length = sprintf(buff, "not in use\n");
915                 break;
916         }
917 
918         batadv_hardif_put(hard_iface);
919 
920         return length;
921 }
922 
923 #ifdef CONFIG_BATMAN_ADV_BATMAN_V
924 
925 /**
926  * batadv_store_throughput_override - parse and store throughput override
927  *  entered by the user
928  * @kobj: kobject representing the private mesh sysfs directory
929  * @attr: the batman-adv attribute the user is interacting with
930  * @buff: the buffer containing the user data
931  * @count: number of bytes in the buffer
932  *
933  * Return: 'count' on success or a negative error code in case of failure
934  */
935 static ssize_t batadv_store_throughput_override(struct kobject *kobj,
936                                                 struct attribute *attr,
937                                                 char *buff, size_t count)
938 {
939         struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
940         struct batadv_hard_iface *hard_iface;
941         u32 tp_override;
942         u32 old_tp_override;
943         bool ret;
944 
945         hard_iface = batadv_hardif_get_by_netdev(net_dev);
946         if (!hard_iface)
947                 return -EINVAL;
948 
949         if (buff[count - 1] == '\n')
950                 buff[count - 1] = '\0';
951 
952         ret = batadv_parse_throughput(net_dev, buff, "throughput_override",
953                                       &tp_override);
954         if (!ret)
955                 return count;
956 
957         old_tp_override = atomic_read(&hard_iface->bat_v.throughput_override);
958         if (old_tp_override == tp_override)
959                 goto out;
960 
961         batadv_info(net_dev, "%s: Changing from: %u.%u MBit to: %u.%u MBit\n",
962                     "throughput_override",
963                     old_tp_override / 10, old_tp_override % 10,
964                     tp_override / 10, tp_override % 10);
965 
966         atomic_set(&hard_iface->bat_v.throughput_override, tp_override);
967 
968 out:
969         batadv_hardif_put(hard_iface);
970         return count;
971 }
972 
973 static ssize_t batadv_show_throughput_override(struct kobject *kobj,
974                                                struct attribute *attr,
975                                                char *buff)
976 {
977         struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
978         struct batadv_hard_iface *hard_iface;
979         u32 tp_override;
980 
981         hard_iface = batadv_hardif_get_by_netdev(net_dev);
982         if (!hard_iface)
983                 return -EINVAL;
984 
985         tp_override = atomic_read(&hard_iface->bat_v.throughput_override);
986 
987         return sprintf(buff, "%u.%u MBit\n", tp_override / 10,
988                        tp_override % 10);
989 }
990 
991 #endif
992 
993 static BATADV_ATTR(mesh_iface, S_IRUGO | S_IWUSR, batadv_show_mesh_iface,
994                    batadv_store_mesh_iface);
995 static BATADV_ATTR(iface_status, S_IRUGO, batadv_show_iface_status, NULL);
996 #ifdef CONFIG_BATMAN_ADV_BATMAN_V
997 BATADV_ATTR_HIF_UINT(elp_interval, bat_v.elp_interval, S_IRUGO | S_IWUSR,
998                      2 * BATADV_JITTER, INT_MAX, NULL);
999 static BATADV_ATTR(throughput_override, S_IRUGO | S_IWUSR,
1000                    batadv_show_throughput_override,
1001                    batadv_store_throughput_override);
1002 #endif
1003 
1004 static struct batadv_attribute *batadv_batman_attrs[] = {
1005         &batadv_attr_mesh_iface,
1006         &batadv_attr_iface_status,
1007 #ifdef CONFIG_BATMAN_ADV_BATMAN_V
1008         &batadv_attr_elp_interval,
1009         &batadv_attr_throughput_override,
1010 #endif
1011         NULL,
1012 };
1013 
1014 int batadv_sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev)
1015 {
1016         struct kobject *hardif_kobject = &dev->dev.kobj;
1017         struct batadv_attribute **bat_attr;
1018         int err;
1019 
1020         *hardif_obj = kobject_create_and_add(BATADV_SYSFS_IF_BAT_SUBDIR,
1021                                              hardif_kobject);
1022 
1023         if (!*hardif_obj) {
1024                 batadv_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
1025                            BATADV_SYSFS_IF_BAT_SUBDIR);
1026                 goto out;
1027         }
1028 
1029         for (bat_attr = batadv_batman_attrs; *bat_attr; ++bat_attr) {
1030                 err = sysfs_create_file(*hardif_obj, &((*bat_attr)->attr));
1031                 if (err) {
1032                         batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n",
1033                                    dev->name, BATADV_SYSFS_IF_BAT_SUBDIR,
1034                                    ((*bat_attr)->attr).name);
1035                         goto rem_attr;
1036                 }
1037         }
1038 
1039         return 0;
1040 
1041 rem_attr:
1042         for (bat_attr = batadv_batman_attrs; *bat_attr; ++bat_attr)
1043                 sysfs_remove_file(*hardif_obj, &((*bat_attr)->attr));
1044 out:
1045         return -ENOMEM;
1046 }
1047 
1048 void batadv_sysfs_del_hardif(struct kobject **hardif_obj)
1049 {
1050         kobject_put(*hardif_obj);
1051         *hardif_obj = NULL;
1052 }
1053 
1054 int batadv_throw_uevent(struct batadv_priv *bat_priv, enum batadv_uev_type type,
1055                         enum batadv_uev_action action, const char *data)
1056 {
1057         int ret = -ENOMEM;
1058         struct kobject *bat_kobj;
1059         char *uevent_env[4] = { NULL, NULL, NULL, NULL };
1060 
1061         bat_kobj = &bat_priv->soft_iface->dev.kobj;
1062 
1063         uevent_env[0] = kasprintf(GFP_ATOMIC,
1064                                   "%s%s", BATADV_UEV_TYPE_VAR,
1065                                   batadv_uev_type_str[type]);
1066         if (!uevent_env[0])
1067                 goto out;
1068 
1069         uevent_env[1] = kasprintf(GFP_ATOMIC,
1070                                   "%s%s", BATADV_UEV_ACTION_VAR,
1071                                   batadv_uev_action_str[action]);
1072         if (!uevent_env[1])
1073                 goto out;
1074 
1075         /* If the event is DEL, ignore the data field */
1076         if (action != BATADV_UEV_DEL) {
1077                 uevent_env[2] = kasprintf(GFP_ATOMIC,
1078                                           "%s%s", BATADV_UEV_DATA_VAR, data);
1079                 if (!uevent_env[2])
1080                         goto out;
1081         }
1082 
1083         ret = kobject_uevent_env(bat_kobj, KOBJ_CHANGE, uevent_env);
1084 out:
1085         kfree(uevent_env[0]);
1086         kfree(uevent_env[1]);
1087         kfree(uevent_env[2]);
1088 
1089         if (ret)
1090                 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1091                            "Impossible to send uevent for (%s,%s,%s) event (err: %d)\n",
1092                            batadv_uev_type_str[type],
1093                            batadv_uev_action_str[action],
1094                            (action == BATADV_UEV_DEL ? "NULL" : data), ret);
1095         return ret;
1096 }
1097 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp