Merge branch 'stable-4.6' of git://git.infradead.org/users/pcmoore/audit
[cascardo/linux.git] / net / batman-adv / sysfs.c
index fe87777..e7cf513 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2010-2015 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2010-201 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner
  *
@@ -25,6 +25,7 @@
 #include <linux/fs.h>
 #include <linux/if.h>
 #include <linux/if_vlan.h>
+#include <linux/kref.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
 #include <linux/printk.h>
@@ -64,7 +65,7 @@ static struct batadv_priv *batadv_kobj_to_batpriv(struct kobject *obj)
  * batadv_vlan_kobj_to_batpriv - convert a vlan kobj in the associated batpriv
  * @obj: kobject to covert
  *
- * Returns the associated batadv_priv struct.
+ * Return: the associated batadv_priv struct.
  */
 static struct batadv_priv *batadv_vlan_kobj_to_batpriv(struct kobject *obj)
 {
@@ -82,9 +83,10 @@ static struct batadv_priv *batadv_vlan_kobj_to_batpriv(struct kobject *obj)
 
 /**
  * batadv_kobj_to_vlan - convert a kobj in the associated softif_vlan struct
+ * @bat_priv: the bat priv with all the soft interface information
  * @obj: kobject to covert
  *
- * Returns the associated softif_vlan struct if found, NULL otherwise.
+ * Return: the associated softif_vlan struct if found, NULL otherwise.
  */
 static struct batadv_softif_vlan *
 batadv_kobj_to_vlan(struct batadv_priv *bat_priv, struct kobject *obj)
@@ -96,7 +98,7 @@ batadv_kobj_to_vlan(struct batadv_priv *bat_priv, struct kobject *obj)
                if (vlan_tmp->kobj != obj)
                        continue;
 
-               if (!atomic_inc_not_zero(&vlan_tmp->refcount))
+               if (!kref_get_unless_zero(&vlan_tmp->refcount))
                        continue;
 
                vlan = vlan_tmp;
@@ -214,7 +216,7 @@ ssize_t batadv_store_vlan_##_name(struct kobject *kobj,                     \
                                              attr, &vlan->_name,       \
                                              bat_priv->soft_iface);    \
                                                                        \
-       batadv_softif_vlan_free_ref(vlan);                              \
+       batadv_softif_vlan_put(vlan);                                   \
        return res;                                                     \
 }
 
@@ -229,7 +231,7 @@ ssize_t batadv_show_vlan_##_name(struct kobject *kobj,                      \
                             atomic_read(&vlan->_name) == 0 ?           \
                             "disabled" : "enabled");                   \
                                                                        \
-       batadv_softif_vlan_free_ref(vlan);                              \
+       batadv_softif_vlan_put(vlan);                                   \
        return res;                                                     \
 }
 
@@ -240,6 +242,55 @@ ssize_t batadv_show_vlan_##_name(struct kobject *kobj,                     \
        static BATADV_ATTR_VLAN(_name, _mode, batadv_show_vlan_##_name, \
                                batadv_store_vlan_##_name)
 
+#define BATADV_ATTR_HIF_STORE_UINT(_name, _var, _min, _max, _post_func)        \
+ssize_t batadv_store_##_name(struct kobject *kobj,                     \
+                            struct attribute *attr, char *buff,        \
+                            size_t count)                              \
+{                                                                      \
+       struct net_device *net_dev = batadv_kobj_to_netdev(kobj);       \
+       struct batadv_hard_iface *hard_iface;                           \
+       ssize_t length;                                                 \
+                                                                       \
+       hard_iface = batadv_hardif_get_by_netdev(net_dev);              \
+       if (!hard_iface)                                                \
+               return 0;                                               \
+                                                                       \
+       length = __batadv_store_uint_attr(buff, count, _min, _max,      \
+                                         _post_func, attr,             \
+                                         &hard_iface->_var, net_dev);  \
+                                                                       \
+       batadv_hardif_put(hard_iface);                          \
+       return length;                                                  \
+}
+
+#define BATADV_ATTR_HIF_SHOW_UINT(_name, _var)                         \
+ssize_t batadv_show_##_name(struct kobject *kobj,                      \
+                           struct attribute *attr, char *buff)         \
+{                                                                      \
+       struct net_device *net_dev = batadv_kobj_to_netdev(kobj);       \
+       struct batadv_hard_iface *hard_iface;                           \
+       ssize_t length;                                                 \
+                                                                       \
+       hard_iface = batadv_hardif_get_by_netdev(net_dev);              \
+       if (!hard_iface)                                                \
+               return 0;                                               \
+                                                                       \
+       length = sprintf(buff, "%i\n", atomic_read(&hard_iface->_var)); \
+                                                                       \
+       batadv_hardif_put(hard_iface);                          \
+       return length;                                                  \
+}
+
+/* Use this, if you are going to set [name] in hard_iface to an
+ * unsigned integer value
+ */
+#define BATADV_ATTR_HIF_UINT(_name, _var, _mode, _min, _max, _post_func)\
+       static BATADV_ATTR_HIF_STORE_UINT(_name, _var, _min,            \
+                                         _max, _post_func)             \
+       static BATADV_ATTR_HIF_SHOW_UINT(_name, _var)                   \
+       static BATADV_ATTR(_name, _mode, batadv_show_##_name,           \
+                          batadv_store_##_name)
+
 static int batadv_store_bool_attr(char *buff, size_t count,
                                  struct net_device *net_dev,
                                  const char *attr_name, atomic_t *attr,
@@ -491,7 +542,7 @@ static ssize_t batadv_store_gw_bwidth(struct kobject *kobj,
  * @attr: the batman-adv attribute the user is interacting with
  * @buff: the buffer that will contain the data to send back to the user
  *
- * Returns the number of bytes written into 'buff' on success or a negative
+ * Return: the number of bytes written into 'buff' on success or a negative
  * error code in case of failure
  */
 static ssize_t batadv_show_isolation_mark(struct kobject *kobj,
@@ -511,7 +562,7 @@ static ssize_t batadv_show_isolation_mark(struct kobject *kobj,
  * @buff: the buffer containing the user data
  * @count: number of bytes in the buffer
  *
- * Returns 'count' on success or a negative error code in case of failure
+ * Return: 'count' on success or a negative error code in case of failure
  */
 static ssize_t batadv_store_isolation_mark(struct kobject *kobj,
                                           struct attribute *attr, char *buff,
@@ -620,9 +671,7 @@ static struct batadv_attribute *batadv_mesh_attrs[] = {
 
 BATADV_ATTR_VLAN_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL);
 
-/**
- * batadv_vlan_attrs - array of vlan specific sysfs attributes
- */
+/* array of vlan specific sysfs attributes */
 static struct batadv_attribute *batadv_vlan_attrs[] = {
        &batadv_attr_vlan_ap_isolation,
        NULL,
@@ -683,7 +732,7 @@ void batadv_sysfs_del_meshif(struct net_device *dev)
  * @dev: netdev of the mesh interface
  * @vlan: private data of the newly added VLAN interface
  *
- * Returns 0 on success and -ENOMEM if any of the structure allocations fails.
+ * Return: 0 on success and -ENOMEM if any of the structure allocations fails.
  */
 int batadv_sysfs_add_vlan(struct net_device *dev,
                          struct batadv_softif_vlan *vlan)
@@ -771,7 +820,7 @@ static ssize_t batadv_show_mesh_iface(struct kobject *kobj,
 
        length = sprintf(buff, "%s\n", ifname);
 
-       batadv_hardif_free_ref(hard_iface);
+       batadv_hardif_put(hard_iface);
 
        return length;
 }
@@ -795,7 +844,7 @@ static ssize_t batadv_store_mesh_iface(struct kobject *kobj,
        if (strlen(buff) >= IFNAMSIZ) {
                pr_err("Invalid parameter for 'mesh_iface' setting received: interface name too long '%s'\n",
                       buff);
-               batadv_hardif_free_ref(hard_iface);
+               batadv_hardif_put(hard_iface);
                return -EINVAL;
        }
 
@@ -829,7 +878,7 @@ static ssize_t batadv_store_mesh_iface(struct kobject *kobj,
 unlock:
        rtnl_unlock();
 out:
-       batadv_hardif_free_ref(hard_iface);
+       batadv_hardif_put(hard_iface);
        return ret;
 }
 
@@ -863,18 +912,99 @@ static ssize_t batadv_show_iface_status(struct kobject *kobj,
                break;
        }
 
-       batadv_hardif_free_ref(hard_iface);
+       batadv_hardif_put(hard_iface);
 
        return length;
 }
 
+#ifdef CONFIG_BATMAN_ADV_BATMAN_V
+
+/**
+ * batadv_store_throughput_override - parse and store throughput override
+ *  entered by the user
+ * @kobj: kobject representing the private mesh sysfs directory
+ * @attr: the batman-adv attribute the user is interacting with
+ * @buff: the buffer containing the user data
+ * @count: number of bytes in the buffer
+ *
+ * Return: 'count' on success or a negative error code in case of failure
+ */
+static ssize_t batadv_store_throughput_override(struct kobject *kobj,
+                                               struct attribute *attr,
+                                               char *buff, size_t count)
+{
+       struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
+       struct batadv_hard_iface *hard_iface;
+       u32 tp_override;
+       u32 old_tp_override;
+       bool ret;
+
+       hard_iface = batadv_hardif_get_by_netdev(net_dev);
+       if (!hard_iface)
+               return -EINVAL;
+
+       if (buff[count - 1] == '\n')
+               buff[count - 1] = '\0';
+
+       ret = batadv_parse_throughput(net_dev, buff, "throughput_override",
+                                     &tp_override);
+       if (!ret)
+               return count;
+
+       old_tp_override = atomic_read(&hard_iface->bat_v.throughput_override);
+       if (old_tp_override == tp_override)
+               goto out;
+
+       batadv_info(net_dev, "%s: Changing from: %u.%u MBit to: %u.%u MBit\n",
+                   "throughput_override",
+                   old_tp_override / 10, old_tp_override % 10,
+                   tp_override / 10, tp_override % 10);
+
+       atomic_set(&hard_iface->bat_v.throughput_override, tp_override);
+
+out:
+       batadv_hardif_put(hard_iface);
+       return count;
+}
+
+static ssize_t batadv_show_throughput_override(struct kobject *kobj,
+                                              struct attribute *attr,
+                                              char *buff)
+{
+       struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
+       struct batadv_hard_iface *hard_iface;
+       u32 tp_override;
+
+       hard_iface = batadv_hardif_get_by_netdev(net_dev);
+       if (!hard_iface)
+               return -EINVAL;
+
+       tp_override = atomic_read(&hard_iface->bat_v.throughput_override);
+
+       return sprintf(buff, "%u.%u MBit\n", tp_override / 10,
+                      tp_override % 10);
+}
+
+#endif
+
 static BATADV_ATTR(mesh_iface, S_IRUGO | S_IWUSR, batadv_show_mesh_iface,
                   batadv_store_mesh_iface);
 static BATADV_ATTR(iface_status, S_IRUGO, batadv_show_iface_status, NULL);
+#ifdef CONFIG_BATMAN_ADV_BATMAN_V
+BATADV_ATTR_HIF_UINT(elp_interval, bat_v.elp_interval, S_IRUGO | S_IWUSR,
+                    2 * BATADV_JITTER, INT_MAX, NULL);
+static BATADV_ATTR(throughput_override, S_IRUGO | S_IWUSR,
+                  batadv_show_throughput_override,
+                  batadv_store_throughput_override);
+#endif
 
 static struct batadv_attribute *batadv_batman_attrs[] = {
        &batadv_attr_mesh_iface,
        &batadv_attr_iface_status,
+#ifdef CONFIG_BATMAN_ADV_BATMAN_V
+       &batadv_attr_elp_interval,
+       &batadv_attr_throughput_override,
+#endif
        NULL,
 };