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

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

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

~ [ 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