|
@@ -28,11 +28,15 @@
|
|
#include <linux/list.h>
|
|
#include <linux/list.h>
|
|
#include <linux/lockdep.h>
|
|
#include <linux/lockdep.h>
|
|
#include <linux/netdevice.h>
|
|
#include <linux/netdevice.h>
|
|
|
|
+#include <linux/netlink.h>
|
|
#include <linux/rculist.h>
|
|
#include <linux/rculist.h>
|
|
#include <linux/seq_file.h>
|
|
#include <linux/seq_file.h>
|
|
|
|
+#include <linux/skbuff.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/spinlock.h>
|
|
#include <linux/spinlock.h>
|
|
#include <linux/workqueue.h>
|
|
#include <linux/workqueue.h>
|
|
|
|
+#include <net/sock.h>
|
|
|
|
+#include <uapi/linux/batman_adv.h>
|
|
|
|
|
|
#include "bat_algo.h"
|
|
#include "bat_algo.h"
|
|
#include "distributed-arp-table.h"
|
|
#include "distributed-arp-table.h"
|
|
@@ -42,8 +46,10 @@
|
|
#include "hash.h"
|
|
#include "hash.h"
|
|
#include "log.h"
|
|
#include "log.h"
|
|
#include "multicast.h"
|
|
#include "multicast.h"
|
|
|
|
+#include "netlink.h"
|
|
#include "network-coding.h"
|
|
#include "network-coding.h"
|
|
#include "routing.h"
|
|
#include "routing.h"
|
|
|
|
+#include "soft-interface.h"
|
|
#include "translation-table.h"
|
|
#include "translation-table.h"
|
|
|
|
|
|
/* hash class keys */
|
|
/* hash class keys */
|
|
@@ -720,6 +726,83 @@ int batadv_hardif_neigh_seq_print_text(struct seq_file *seq, void *offset)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * batadv_hardif_neigh_dump - Dump to netlink the neighbor infos for a specific
|
|
|
|
+ * outgoing interface
|
|
|
|
+ * @msg: message to dump into
|
|
|
|
+ * @cb: parameters for the dump
|
|
|
|
+ *
|
|
|
|
+ * Return: 0 or error value
|
|
|
|
+ */
|
|
|
|
+int batadv_hardif_neigh_dump(struct sk_buff *msg, struct netlink_callback *cb)
|
|
|
|
+{
|
|
|
|
+ struct net *net = sock_net(cb->skb->sk);
|
|
|
|
+ struct net_device *soft_iface;
|
|
|
|
+ struct net_device *hard_iface = NULL;
|
|
|
|
+ struct batadv_hard_iface *hardif = BATADV_IF_DEFAULT;
|
|
|
|
+ struct batadv_priv *bat_priv;
|
|
|
|
+ struct batadv_hard_iface *primary_if = NULL;
|
|
|
|
+ int ret;
|
|
|
|
+ int ifindex, hard_ifindex;
|
|
|
|
+
|
|
|
|
+ ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_MESH_IFINDEX);
|
|
|
|
+ if (!ifindex)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ soft_iface = dev_get_by_index(net, ifindex);
|
|
|
|
+ if (!soft_iface || !batadv_softif_is_valid(soft_iface)) {
|
|
|
|
+ ret = -ENODEV;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ bat_priv = netdev_priv(soft_iface);
|
|
|
|
+
|
|
|
|
+ primary_if = batadv_primary_if_get_selected(bat_priv);
|
|
|
|
+ if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
|
|
|
|
+ ret = -ENOENT;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ hard_ifindex = batadv_netlink_get_ifindex(cb->nlh,
|
|
|
|
+ BATADV_ATTR_HARD_IFINDEX);
|
|
|
|
+ if (hard_ifindex) {
|
|
|
|
+ hard_iface = dev_get_by_index(net, hard_ifindex);
|
|
|
|
+ if (hard_iface)
|
|
|
|
+ hardif = batadv_hardif_get_by_netdev(hard_iface);
|
|
|
|
+
|
|
|
|
+ if (!hardif) {
|
|
|
|
+ ret = -ENODEV;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (hardif->soft_iface != soft_iface) {
|
|
|
|
+ ret = -ENOENT;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!bat_priv->algo_ops->neigh.dump) {
|
|
|
|
+ ret = -EOPNOTSUPP;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ bat_priv->algo_ops->neigh.dump(msg, cb, bat_priv, hardif);
|
|
|
|
+
|
|
|
|
+ ret = msg->len;
|
|
|
|
+
|
|
|
|
+ out:
|
|
|
|
+ if (hardif)
|
|
|
|
+ batadv_hardif_put(hardif);
|
|
|
|
+ if (hard_iface)
|
|
|
|
+ dev_put(hard_iface);
|
|
|
|
+ if (primary_if)
|
|
|
|
+ batadv_hardif_put(primary_if);
|
|
|
|
+ if (soft_iface)
|
|
|
|
+ dev_put(soft_iface);
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* batadv_orig_ifinfo_release - release orig_ifinfo from lists and queue for
|
|
* batadv_orig_ifinfo_release - release orig_ifinfo from lists and queue for
|
|
* free after rcu grace period
|
|
* free after rcu grace period
|
|
@@ -1330,6 +1413,83 @@ out:
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * batadv_orig_dump - Dump to netlink the originator infos for a specific
|
|
|
|
+ * outgoing interface
|
|
|
|
+ * @msg: message to dump into
|
|
|
|
+ * @cb: parameters for the dump
|
|
|
|
+ *
|
|
|
|
+ * Return: 0 or error value
|
|
|
|
+ */
|
|
|
|
+int batadv_orig_dump(struct sk_buff *msg, struct netlink_callback *cb)
|
|
|
|
+{
|
|
|
|
+ struct net *net = sock_net(cb->skb->sk);
|
|
|
|
+ struct net_device *soft_iface;
|
|
|
|
+ struct net_device *hard_iface = NULL;
|
|
|
|
+ struct batadv_hard_iface *hardif = BATADV_IF_DEFAULT;
|
|
|
|
+ struct batadv_priv *bat_priv;
|
|
|
|
+ struct batadv_hard_iface *primary_if = NULL;
|
|
|
|
+ int ret;
|
|
|
|
+ int ifindex, hard_ifindex;
|
|
|
|
+
|
|
|
|
+ ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_MESH_IFINDEX);
|
|
|
|
+ if (!ifindex)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ soft_iface = dev_get_by_index(net, ifindex);
|
|
|
|
+ if (!soft_iface || !batadv_softif_is_valid(soft_iface)) {
|
|
|
|
+ ret = -ENODEV;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ bat_priv = netdev_priv(soft_iface);
|
|
|
|
+
|
|
|
|
+ primary_if = batadv_primary_if_get_selected(bat_priv);
|
|
|
|
+ if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
|
|
|
|
+ ret = -ENOENT;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ hard_ifindex = batadv_netlink_get_ifindex(cb->nlh,
|
|
|
|
+ BATADV_ATTR_HARD_IFINDEX);
|
|
|
|
+ if (hard_ifindex) {
|
|
|
|
+ hard_iface = dev_get_by_index(net, hard_ifindex);
|
|
|
|
+ if (hard_iface)
|
|
|
|
+ hardif = batadv_hardif_get_by_netdev(hard_iface);
|
|
|
|
+
|
|
|
|
+ if (!hardif) {
|
|
|
|
+ ret = -ENODEV;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (hardif->soft_iface != soft_iface) {
|
|
|
|
+ ret = -ENOENT;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!bat_priv->algo_ops->orig.dump) {
|
|
|
|
+ ret = -EOPNOTSUPP;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ bat_priv->algo_ops->orig.dump(msg, cb, bat_priv, hardif);
|
|
|
|
+
|
|
|
|
+ ret = msg->len;
|
|
|
|
+
|
|
|
|
+ out:
|
|
|
|
+ if (hardif)
|
|
|
|
+ batadv_hardif_put(hardif);
|
|
|
|
+ if (hard_iface)
|
|
|
|
+ dev_put(hard_iface);
|
|
|
|
+ if (primary_if)
|
|
|
|
+ batadv_hardif_put(primary_if);
|
|
|
|
+ if (soft_iface)
|
|
|
|
+ dev_put(soft_iface);
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface,
|
|
int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface,
|
|
int max_if_num)
|
|
int max_if_num)
|
|
{
|
|
{
|