aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2016-07-03 07:31:37 -0400
committerSimon Wunderlich <sw@simonwunderlich.de>2016-08-09 01:54:37 -0400
commitd34f05507db245bef819b684ad84f9e0f9bb003d (patch)
treeeed54f54f6c9e5e314e5055a754a566b800aac06
parentb60620cf567b79da46096a0ba29b39f23b6e7f1c (diff)
batman-adv: netlink: add translation table query
This adds the commands BATADV_CMD_GET_TRANSTABLE_LOCAL and BATADV_CMD_GET_TRANSTABLE_GLOBAL, which correspond to the transtable_local and transtable_global debugfs files. The batadv_tt_client_flags enum is moved to the UAPI to expose it as part of the netlink API. Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net> Signed-off-by: Andrew Lunn <andrew@lunn.ch> [sven.eckelmann@open-mesh.com: add policy for attributes, fix includes] Signed-off-by: Sven Eckelmann <sven.eckelmann@open-mesh.com> [sw@simonwunderlich.de: fix VID attributes content] Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de> Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch>
-rw-r--r--include/uapi/linux/batman_adv.h56
-rw-r--r--net/batman-adv/netlink.c23
-rw-r--r--net/batman-adv/netlink.h3
-rw-r--r--net/batman-adv/packet.h36
-rw-r--r--net/batman-adv/translation-table.c377
-rw-r--r--net/batman-adv/translation-table.h4
6 files changed, 462 insertions, 37 deletions
diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h
index 8abcbca14b6a..1168d058cd2b 100644
--- a/include/uapi/linux/batman_adv.h
+++ b/include/uapi/linux/batman_adv.h
@@ -23,6 +23,42 @@
23#define BATADV_NL_MCAST_GROUP_TPMETER "tpmeter" 23#define BATADV_NL_MCAST_GROUP_TPMETER "tpmeter"
24 24
25/** 25/**
26 * enum batadv_tt_client_flags - TT client specific flags
27 * @BATADV_TT_CLIENT_DEL: the client has to be deleted from the table
28 * @BATADV_TT_CLIENT_ROAM: the client roamed to/from another node and the new
29 * update telling its new real location has not been received/sent yet
30 * @BATADV_TT_CLIENT_WIFI: this client is connected through a wifi interface.
31 * This information is used by the "AP Isolation" feature
32 * @BATADV_TT_CLIENT_ISOLA: this client is considered "isolated". This
33 * information is used by the Extended Isolation feature
34 * @BATADV_TT_CLIENT_NOPURGE: this client should never be removed from the table
35 * @BATADV_TT_CLIENT_NEW: this client has been added to the local table but has
36 * not been announced yet
37 * @BATADV_TT_CLIENT_PENDING: this client is marked for removal but it is kept
38 * in the table for one more originator interval for consistency purposes
39 * @BATADV_TT_CLIENT_TEMP: this global client has been detected to be part of
40 * the network but no nnode has already announced it
41 *
42 * Bits from 0 to 7 are called _remote flags_ because they are sent on the wire.
43 * Bits from 8 to 15 are called _local flags_ because they are used for local
44 * computations only.
45 *
46 * Bits from 4 to 7 - a subset of remote flags - are ensured to be in sync with
47 * the other nodes in the network. To achieve this goal these flags are included
48 * in the TT CRC computation.
49 */
50enum batadv_tt_client_flags {
51 BATADV_TT_CLIENT_DEL = (1 << 0),
52 BATADV_TT_CLIENT_ROAM = (1 << 1),
53 BATADV_TT_CLIENT_WIFI = (1 << 4),
54 BATADV_TT_CLIENT_ISOLA = (1 << 5),
55 BATADV_TT_CLIENT_NOPURGE = (1 << 8),
56 BATADV_TT_CLIENT_NEW = (1 << 9),
57 BATADV_TT_CLIENT_PENDING = (1 << 10),
58 BATADV_TT_CLIENT_TEMP = (1 << 11),
59};
60
61/**
26 * enum batadv_nl_attrs - batman-adv netlink attributes 62 * enum batadv_nl_attrs - batman-adv netlink attributes
27 * 63 *
28 * @BATADV_ATTR_UNSPEC: unspecified attribute to catch errors 64 * @BATADV_ATTR_UNSPEC: unspecified attribute to catch errors
@@ -41,6 +77,14 @@
41 * @BATADV_ATTR_TPMETER_COOKIE: session cookie to match tp_meter session 77 * @BATADV_ATTR_TPMETER_COOKIE: session cookie to match tp_meter session
42 * @BATADV_ATTR_PAD: attribute used for padding for 64-bit alignment 78 * @BATADV_ATTR_PAD: attribute used for padding for 64-bit alignment
43 * @BATADV_ATTR_ACTIVE: Flag indicating if the hard interface is active 79 * @BATADV_ATTR_ACTIVE: Flag indicating if the hard interface is active
80 * @BATADV_ATTR_TT_ADDRESS: Client MAC address
81 * @BATADV_ATTR_TT_TTVN: Translation table version
82 * @BATADV_ATTR_TT_LAST_TTVN: Previous translation table version
83 * @BATADV_ATTR_TT_CRC32: CRC32 over translation table
84 * @BATADV_ATTR_TT_VID: VLAN ID
85 * @BATADV_ATTR_TT_FLAGS: Translation table client flags
86 * @BATADV_ATTR_FLAG_BEST: Flags indicating entry is the best
87 * @BATADV_ATTR_LAST_SEEN_MSECS: Time in milliseconds since last seen
44 * @__BATADV_ATTR_AFTER_LAST: internal use 88 * @__BATADV_ATTR_AFTER_LAST: internal use
45 * @NUM_BATADV_ATTR: total number of batadv_nl_attrs available 89 * @NUM_BATADV_ATTR: total number of batadv_nl_attrs available
46 * @BATADV_ATTR_MAX: highest attribute number currently defined 90 * @BATADV_ATTR_MAX: highest attribute number currently defined
@@ -62,6 +106,14 @@ enum batadv_nl_attrs {
62 BATADV_ATTR_TPMETER_COOKIE, 106 BATADV_ATTR_TPMETER_COOKIE,
63 BATADV_ATTR_PAD, 107 BATADV_ATTR_PAD,
64 BATADV_ATTR_ACTIVE, 108 BATADV_ATTR_ACTIVE,
109 BATADV_ATTR_TT_ADDRESS,
110 BATADV_ATTR_TT_TTVN,
111 BATADV_ATTR_TT_LAST_TTVN,
112 BATADV_ATTR_TT_CRC32,
113 BATADV_ATTR_TT_VID,
114 BATADV_ATTR_TT_FLAGS,
115 BATADV_ATTR_FLAG_BEST,
116 BATADV_ATTR_LAST_SEEN_MSECS,
65 /* add attributes above here, update the policy in netlink.c */ 117 /* add attributes above here, update the policy in netlink.c */
66 __BATADV_ATTR_AFTER_LAST, 118 __BATADV_ATTR_AFTER_LAST,
67 NUM_BATADV_ATTR = __BATADV_ATTR_AFTER_LAST, 119 NUM_BATADV_ATTR = __BATADV_ATTR_AFTER_LAST,
@@ -77,6 +129,8 @@ enum batadv_nl_attrs {
77 * @BATADV_CMD_TP_METER_CANCEL: Cancel a tp meter session 129 * @BATADV_CMD_TP_METER_CANCEL: Cancel a tp meter session
78 * @BATADV_CMD_GET_ROUTING_ALGOS: Query the list of routing algorithms. 130 * @BATADV_CMD_GET_ROUTING_ALGOS: Query the list of routing algorithms.
79 * @BATADV_CMD_GET_HARDIFS: Query list of hard interfaces 131 * @BATADV_CMD_GET_HARDIFS: Query list of hard interfaces
132 * @BATADV_CMD_GET_TRANSTABLE_LOCAL: Query list of local translations
133 * @BATADV_CMD_GET_TRANSTABLE_GLOBAL Query list of global translations
80 * @__BATADV_CMD_AFTER_LAST: internal use 134 * @__BATADV_CMD_AFTER_LAST: internal use
81 * @BATADV_CMD_MAX: highest used command number 135 * @BATADV_CMD_MAX: highest used command number
82 */ 136 */
@@ -87,6 +141,8 @@ enum batadv_nl_commands {
87 BATADV_CMD_TP_METER_CANCEL, 141 BATADV_CMD_TP_METER_CANCEL,
88 BATADV_CMD_GET_ROUTING_ALGOS, 142 BATADV_CMD_GET_ROUTING_ALGOS,
89 BATADV_CMD_GET_HARDIFS, 143 BATADV_CMD_GET_HARDIFS,
144 BATADV_CMD_GET_TRANSTABLE_LOCAL,
145 BATADV_CMD_GET_TRANSTABLE_GLOBAL,
90 /* add new commands above here */ 146 /* add new commands above here */
91 __BATADV_CMD_AFTER_LAST, 147 __BATADV_CMD_AFTER_LAST,
92 BATADV_CMD_MAX = __BATADV_CMD_AFTER_LAST - 1 148 BATADV_CMD_MAX = __BATADV_CMD_AFTER_LAST - 1
diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c
index 3f872d6eec57..14360ec16513 100644
--- a/net/batman-adv/netlink.c
+++ b/net/batman-adv/netlink.c
@@ -40,6 +40,7 @@
40#include "hard-interface.h" 40#include "hard-interface.h"
41#include "soft-interface.h" 41#include "soft-interface.h"
42#include "tp_meter.h" 42#include "tp_meter.h"
43#include "translation-table.h"
43 44
44struct genl_family batadv_netlink_family = { 45struct genl_family batadv_netlink_family = {
45 .id = GENL_ID_GENERATE, 46 .id = GENL_ID_GENERATE,
@@ -73,6 +74,14 @@ static struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = {
73 [BATADV_ATTR_TPMETER_BYTES] = { .type = NLA_U64 }, 74 [BATADV_ATTR_TPMETER_BYTES] = { .type = NLA_U64 },
74 [BATADV_ATTR_TPMETER_COOKIE] = { .type = NLA_U32 }, 75 [BATADV_ATTR_TPMETER_COOKIE] = { .type = NLA_U32 },
75 [BATADV_ATTR_ACTIVE] = { .type = NLA_FLAG }, 76 [BATADV_ATTR_ACTIVE] = { .type = NLA_FLAG },
77 [BATADV_ATTR_TT_ADDRESS] = { .len = ETH_ALEN },
78 [BATADV_ATTR_TT_TTVN] = { .type = NLA_U8 },
79 [BATADV_ATTR_TT_LAST_TTVN] = { .type = NLA_U8 },
80 [BATADV_ATTR_TT_CRC32] = { .type = NLA_U32 },
81 [BATADV_ATTR_TT_VID] = { .type = NLA_U16 },
82 [BATADV_ATTR_TT_FLAGS] = { .type = NLA_U32 },
83 [BATADV_ATTR_FLAG_BEST] = { .type = NLA_FLAG },
84 [BATADV_ATTR_LAST_SEEN_MSECS] = { .type = NLA_U32 },
76}; 85};
77 86
78/** 87/**
@@ -82,7 +91,7 @@ static struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = {
82 * 91 *
83 * Return: interface index, or 0. 92 * Return: interface index, or 0.
84 */ 93 */
85static int 94int
86batadv_netlink_get_ifindex(const struct nlmsghdr *nlh, int attrtype) 95batadv_netlink_get_ifindex(const struct nlmsghdr *nlh, int attrtype)
87{ 96{
88 struct nlattr *attr = nlmsg_find_attr(nlh, GENL_HDRLEN, attrtype); 97 struct nlattr *attr = nlmsg_find_attr(nlh, GENL_HDRLEN, attrtype);
@@ -530,6 +539,18 @@ static struct genl_ops batadv_netlink_ops[] = {
530 .policy = batadv_netlink_policy, 539 .policy = batadv_netlink_policy,
531 .dumpit = batadv_netlink_dump_hardifs, 540 .dumpit = batadv_netlink_dump_hardifs,
532 }, 541 },
542 {
543 .cmd = BATADV_CMD_GET_TRANSTABLE_LOCAL,
544 .flags = GENL_ADMIN_PERM,
545 .policy = batadv_netlink_policy,
546 .dumpit = batadv_tt_local_dump,
547 },
548 {
549 .cmd = BATADV_CMD_GET_TRANSTABLE_GLOBAL,
550 .flags = GENL_ADMIN_PERM,
551 .policy = batadv_netlink_policy,
552 .dumpit = batadv_tt_global_dump,
553 },
533}; 554};
534 555
535/** 556/**
diff --git a/net/batman-adv/netlink.h b/net/batman-adv/netlink.h
index b399f49504df..52eb16281aba 100644
--- a/net/batman-adv/netlink.h
+++ b/net/batman-adv/netlink.h
@@ -23,8 +23,11 @@
23#include <linux/types.h> 23#include <linux/types.h>
24#include <net/genetlink.h> 24#include <net/genetlink.h>
25 25
26struct nlmsghdr;
27
26void batadv_netlink_register(void); 28void batadv_netlink_register(void);
27void batadv_netlink_unregister(void); 29void batadv_netlink_unregister(void);
30int batadv_netlink_get_ifindex(const struct nlmsghdr *nlh, int attrtype);
28 31
29int batadv_netlink_tpmeter_notify(struct batadv_priv *bat_priv, const u8 *dst, 32int batadv_netlink_tpmeter_notify(struct batadv_priv *bat_priv, const u8 *dst,
30 u8 result, u32 test_time, u64 total_bytes, 33 u8 result, u32 test_time, u64 total_bytes,
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index 6b011ff64dd8..6afc0b86950e 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -129,42 +129,6 @@ enum batadv_tt_data_flags {
129}; 129};
130 130
131/** 131/**
132 * enum batadv_tt_client_flags - TT client specific flags
133 * @BATADV_TT_CLIENT_DEL: the client has to be deleted from the table
134 * @BATADV_TT_CLIENT_ROAM: the client roamed to/from another node and the new
135 * update telling its new real location has not been received/sent yet
136 * @BATADV_TT_CLIENT_WIFI: this client is connected through a wifi interface.
137 * This information is used by the "AP Isolation" feature
138 * @BATADV_TT_CLIENT_ISOLA: this client is considered "isolated". This
139 * information is used by the Extended Isolation feature
140 * @BATADV_TT_CLIENT_NOPURGE: this client should never be removed from the table
141 * @BATADV_TT_CLIENT_NEW: this client has been added to the local table but has
142 * not been announced yet
143 * @BATADV_TT_CLIENT_PENDING: this client is marked for removal but it is kept
144 * in the table for one more originator interval for consistency purposes
145 * @BATADV_TT_CLIENT_TEMP: this global client has been detected to be part of
146 * the network but no nnode has already announced it
147 *
148 * Bits from 0 to 7 are called _remote flags_ because they are sent on the wire.
149 * Bits from 8 to 15 are called _local flags_ because they are used for local
150 * computations only.
151 *
152 * Bits from 4 to 7 - a subset of remote flags - are ensured to be in sync with
153 * the other nodes in the network. To achieve this goal these flags are included
154 * in the TT CRC computation.
155 */
156enum batadv_tt_client_flags {
157 BATADV_TT_CLIENT_DEL = BIT(0),
158 BATADV_TT_CLIENT_ROAM = BIT(1),
159 BATADV_TT_CLIENT_WIFI = BIT(4),
160 BATADV_TT_CLIENT_ISOLA = BIT(5),
161 BATADV_TT_CLIENT_NOPURGE = BIT(8),
162 BATADV_TT_CLIENT_NEW = BIT(9),
163 BATADV_TT_CLIENT_PENDING = BIT(10),
164 BATADV_TT_CLIENT_TEMP = BIT(11),
165};
166
167/**
168 * enum batadv_vlan_flags - flags for the four MSB of any vlan ID field 132 * enum batadv_vlan_flags - flags for the four MSB of any vlan ID field
169 * @BATADV_VLAN_HAS_TAG: whether the field contains a valid vlan tag or not 133 * @BATADV_VLAN_HAS_TAG: whether the field contains a valid vlan tag or not
170 */ 134 */
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index af2bfef6dca8..20804078293c 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -37,20 +37,27 @@
37#include <linux/list.h> 37#include <linux/list.h>
38#include <linux/lockdep.h> 38#include <linux/lockdep.h>
39#include <linux/netdevice.h> 39#include <linux/netdevice.h>
40#include <linux/netlink.h>
40#include <linux/rculist.h> 41#include <linux/rculist.h>
41#include <linux/rcupdate.h> 42#include <linux/rcupdate.h>
42#include <linux/seq_file.h> 43#include <linux/seq_file.h>
44#include <linux/skbuff.h>
43#include <linux/slab.h> 45#include <linux/slab.h>
44#include <linux/spinlock.h> 46#include <linux/spinlock.h>
45#include <linux/stddef.h> 47#include <linux/stddef.h>
46#include <linux/string.h> 48#include <linux/string.h>
47#include <linux/workqueue.h> 49#include <linux/workqueue.h>
50#include <net/genetlink.h>
51#include <net/netlink.h>
52#include <net/sock.h>
53#include <uapi/linux/batman_adv.h>
48 54
49#include "bridge_loop_avoidance.h" 55#include "bridge_loop_avoidance.h"
50#include "hard-interface.h" 56#include "hard-interface.h"
51#include "hash.h" 57#include "hash.h"
52#include "log.h" 58#include "log.h"
53#include "multicast.h" 59#include "multicast.h"
60#include "netlink.h"
54#include "originator.h" 61#include "originator.h"
55#include "packet.h" 62#include "packet.h"
56#include "soft-interface.h" 63#include "soft-interface.h"
@@ -1108,6 +1115,164 @@ out:
1108 return 0; 1115 return 0;
1109} 1116}
1110 1117
1118/**
1119 * batadv_tt_local_dump_entry - Dump one TT local entry into a message
1120 * @msg :Netlink message to dump into
1121 * @portid: Port making netlink request
1122 * @seq: Sequence number of netlink message
1123 * @bat_priv: The bat priv with all the soft interface information
1124 * @common: tt local & tt global common data
1125 *
1126 * Return: Error code, or 0 on success
1127 */
1128static int
1129batadv_tt_local_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
1130 struct batadv_priv *bat_priv,
1131 struct batadv_tt_common_entry *common)
1132{
1133 void *hdr;
1134 struct batadv_softif_vlan *vlan;
1135 struct batadv_tt_local_entry *local;
1136 unsigned int last_seen_msecs;
1137 u32 crc;
1138
1139 local = container_of(common, struct batadv_tt_local_entry, common);
1140 last_seen_msecs = jiffies_to_msecs(jiffies - local->last_seen);
1141
1142 vlan = batadv_softif_vlan_get(bat_priv, common->vid);
1143 if (!vlan)
1144 return 0;
1145
1146 crc = vlan->tt.crc;
1147
1148 batadv_softif_vlan_put(vlan);
1149
1150 hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family,
1151 NLM_F_MULTI,
1152 BATADV_CMD_GET_TRANSTABLE_LOCAL);
1153 if (!hdr)
1154 return -ENOBUFS;
1155
1156 if (nla_put(msg, BATADV_ATTR_TT_ADDRESS, ETH_ALEN, common->addr) ||
1157 nla_put_u32(msg, BATADV_ATTR_TT_CRC32, crc) ||
1158 nla_put_u16(msg, BATADV_ATTR_TT_VID, common->vid) ||
1159 nla_put_u32(msg, BATADV_ATTR_TT_FLAGS, common->flags))
1160 goto nla_put_failure;
1161
1162 if (!(common->flags & BATADV_TT_CLIENT_NOPURGE) &&
1163 nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS, last_seen_msecs))
1164 goto nla_put_failure;
1165
1166 genlmsg_end(msg, hdr);
1167 return 0;
1168
1169 nla_put_failure:
1170 genlmsg_cancel(msg, hdr);
1171 return -EMSGSIZE;
1172}
1173
1174/**
1175 * batadv_tt_local_dump_bucket - Dump one TT local bucket into a message
1176 * @msg: Netlink message to dump into
1177 * @portid: Port making netlink request
1178 * @seq: Sequence number of netlink message
1179 * @bat_priv: The bat priv with all the soft interface information
1180 * @head: Pointer to the list containing the local tt entries
1181 * @idx_s: Number of entries to skip
1182 *
1183 * Return: Error code, or 0 on success
1184 */
1185static int
1186batadv_tt_local_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
1187 struct batadv_priv *bat_priv,
1188 struct hlist_head *head, int *idx_s)
1189{
1190 struct batadv_tt_common_entry *common;
1191 int idx = 0;
1192
1193 rcu_read_lock();
1194 hlist_for_each_entry_rcu(common, head, hash_entry) {
1195 if (idx++ < *idx_s)
1196 continue;
1197
1198 if (batadv_tt_local_dump_entry(msg, portid, seq, bat_priv,
1199 common)) {
1200 rcu_read_unlock();
1201 *idx_s = idx - 1;
1202 return -EMSGSIZE;
1203 }
1204 }
1205 rcu_read_unlock();
1206
1207 *idx_s = 0;
1208 return 0;
1209}
1210
1211/**
1212 * batadv_tt_local_dump - Dump TT local entries into a message
1213 * @msg: Netlink message to dump into
1214 * @cb: Parameters from query
1215 *
1216 * Return: Error code, or 0 on success
1217 */
1218int batadv_tt_local_dump(struct sk_buff *msg, struct netlink_callback *cb)
1219{
1220 struct net *net = sock_net(cb->skb->sk);
1221 struct net_device *soft_iface;
1222 struct batadv_priv *bat_priv;
1223 struct batadv_hard_iface *primary_if = NULL;
1224 struct batadv_hashtable *hash;
1225 struct hlist_head *head;
1226 int ret;
1227 int ifindex;
1228 int bucket = cb->args[0];
1229 int idx = cb->args[1];
1230 int portid = NETLINK_CB(cb->skb).portid;
1231
1232 ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_MESH_IFINDEX);
1233 if (!ifindex)
1234 return -EINVAL;
1235
1236 soft_iface = dev_get_by_index(net, ifindex);
1237 if (!soft_iface || !batadv_softif_is_valid(soft_iface)) {
1238 ret = -ENODEV;
1239 goto out;
1240 }
1241
1242 bat_priv = netdev_priv(soft_iface);
1243
1244 primary_if = batadv_primary_if_get_selected(bat_priv);
1245 if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
1246 ret = -ENOENT;
1247 goto out;
1248 }
1249
1250 hash = bat_priv->tt.local_hash;
1251
1252 while (bucket < hash->size) {
1253 head = &hash->table[bucket];
1254
1255 if (batadv_tt_local_dump_bucket(msg, portid, cb->nlh->nlmsg_seq,
1256 bat_priv, head, &idx))
1257 break;
1258
1259 bucket++;
1260 }
1261
1262 ret = msg->len;
1263
1264 out:
1265 if (primary_if)
1266 batadv_hardif_put(primary_if);
1267 if (soft_iface)
1268 dev_put(soft_iface);
1269
1270 cb->args[0] = bucket;
1271 cb->args[1] = idx;
1272
1273 return ret;
1274}
1275
1111static void 1276static void
1112batadv_tt_local_set_pending(struct batadv_priv *bat_priv, 1277batadv_tt_local_set_pending(struct batadv_priv *bat_priv,
1113 struct batadv_tt_local_entry *tt_local_entry, 1278 struct batadv_tt_local_entry *tt_local_entry,
@@ -1756,6 +1921,218 @@ out:
1756} 1921}
1757 1922
1758/** 1923/**
1924 * batadv_tt_global_dump_subentry - Dump all TT local entries into a message
1925 * @msg: Netlink message to dump into
1926 * @portid: Port making netlink request
1927 * @seq: Sequence number of netlink message
1928 * @common: tt local & tt global common data
1929 * @orig: Originator node announcing a non-mesh client
1930 * @best: Is the best originator for the TT entry
1931 *
1932 * Return: Error code, or 0 on success
1933 */
1934static int
1935batadv_tt_global_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq,
1936 struct batadv_tt_common_entry *common,
1937 struct batadv_tt_orig_list_entry *orig,
1938 bool best)
1939{
1940 void *hdr;
1941 struct batadv_orig_node_vlan *vlan;
1942 u8 last_ttvn;
1943 u32 crc;
1944
1945 vlan = batadv_orig_node_vlan_get(orig->orig_node,
1946 common->vid);
1947 if (!vlan)
1948 return 0;
1949
1950 crc = vlan->tt.crc;
1951
1952 batadv_orig_node_vlan_put(vlan);
1953
1954 hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family,
1955 NLM_F_MULTI,
1956 BATADV_CMD_GET_TRANSTABLE_GLOBAL);
1957 if (!hdr)
1958 return -ENOBUFS;
1959
1960 last_ttvn = atomic_read(&orig->orig_node->last_ttvn);
1961
1962 if (nla_put(msg, BATADV_ATTR_TT_ADDRESS, ETH_ALEN, common->addr) ||
1963 nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN,
1964 orig->orig_node->orig) ||
1965 nla_put_u8(msg, BATADV_ATTR_TT_TTVN, orig->ttvn) ||
1966 nla_put_u8(msg, BATADV_ATTR_TT_LAST_TTVN, last_ttvn) ||
1967 nla_put_u32(msg, BATADV_ATTR_TT_CRC32, crc) ||
1968 nla_put_u16(msg, BATADV_ATTR_TT_VID, common->vid) ||
1969 nla_put_u32(msg, BATADV_ATTR_TT_FLAGS, common->flags))
1970 goto nla_put_failure;
1971
1972 if (best && nla_put_flag(msg, BATADV_ATTR_FLAG_BEST))
1973 goto nla_put_failure;
1974
1975 genlmsg_end(msg, hdr);
1976 return 0;
1977
1978 nla_put_failure:
1979 genlmsg_cancel(msg, hdr);
1980 return -EMSGSIZE;
1981}
1982
1983/**
1984 * batadv_tt_global_dump_entry - Dump one TT global entry into a message
1985 * @msg: Netlink message to dump into
1986 * @portid: Port making netlink request
1987 * @seq: Sequence number of netlink message
1988 * @bat_priv: The bat priv with all the soft interface information
1989 * @common: tt local & tt global common data
1990 * @sub_s: Number of entries to skip
1991 *
1992 * This function assumes the caller holds rcu_read_lock().
1993 *
1994 * Return: Error code, or 0 on success
1995 */
1996static int
1997batadv_tt_global_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
1998 struct batadv_priv *bat_priv,
1999 struct batadv_tt_common_entry *common, int *sub_s)
2000{
2001 struct batadv_tt_orig_list_entry *orig_entry, *best_entry;
2002 struct batadv_tt_global_entry *global;
2003 struct hlist_head *head;
2004 int sub = 0;
2005 bool best;
2006
2007 global = container_of(common, struct batadv_tt_global_entry, common);
2008 best_entry = batadv_transtable_best_orig(bat_priv, global);
2009 head = &global->orig_list;
2010
2011 hlist_for_each_entry_rcu(orig_entry, head, list) {
2012 if (sub++ < *sub_s)
2013 continue;
2014
2015 best = (orig_entry == best_entry);
2016
2017 if (batadv_tt_global_dump_subentry(msg, portid, seq, common,
2018 orig_entry, best)) {
2019 *sub_s = sub - 1;
2020 return -EMSGSIZE;
2021 }
2022 }
2023
2024 *sub_s = 0;
2025 return 0;
2026}
2027
2028/**
2029 * batadv_tt_global_dump_bucket - Dump one TT local bucket into a message
2030 * @msg: Netlink message to dump into
2031 * @portid: Port making netlink request
2032 * @seq: Sequence number of netlink message
2033 * @bat_priv: The bat priv with all the soft interface information
2034 * @head: Pointer to the list containing the global tt entries
2035 * @idx_s: Number of entries to skip
2036 * @sub: Number of entries to skip
2037 *
2038 * Return: Error code, or 0 on success
2039 */
2040static int
2041batadv_tt_global_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
2042 struct batadv_priv *bat_priv,
2043 struct hlist_head *head, int *idx_s, int *sub)
2044{
2045 struct batadv_tt_common_entry *common;
2046 int idx = 0;
2047
2048 rcu_read_lock();
2049 hlist_for_each_entry_rcu(common, head, hash_entry) {
2050 if (idx++ < *idx_s)
2051 continue;
2052
2053 if (batadv_tt_global_dump_entry(msg, portid, seq, bat_priv,
2054 common, sub)) {
2055 rcu_read_unlock();
2056 *idx_s = idx - 1;
2057 return -EMSGSIZE;
2058 }
2059 }
2060 rcu_read_unlock();
2061
2062 *idx_s = 0;
2063 *sub = 0;
2064 return 0;
2065}
2066
2067/**
2068 * batadv_tt_global_dump - Dump TT global entries into a message
2069 * @msg: Netlink message to dump into
2070 * @cb: Parameters from query
2071 *
2072 * Return: Error code, or length of message on success
2073 */
2074int batadv_tt_global_dump(struct sk_buff *msg, struct netlink_callback *cb)
2075{
2076 struct net *net = sock_net(cb->skb->sk);
2077 struct net_device *soft_iface;
2078 struct batadv_priv *bat_priv;
2079 struct batadv_hard_iface *primary_if = NULL;
2080 struct batadv_hashtable *hash;
2081 struct hlist_head *head;
2082 int ret;
2083 int ifindex;
2084 int bucket = cb->args[0];
2085 int idx = cb->args[1];
2086 int sub = cb->args[2];
2087 int portid = NETLINK_CB(cb->skb).portid;
2088
2089 ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_MESH_IFINDEX);
2090 if (!ifindex)
2091 return -EINVAL;
2092
2093 soft_iface = dev_get_by_index(net, ifindex);
2094 if (!soft_iface || !batadv_softif_is_valid(soft_iface)) {
2095 ret = -ENODEV;
2096 goto out;
2097 }
2098
2099 bat_priv = netdev_priv(soft_iface);
2100
2101 primary_if = batadv_primary_if_get_selected(bat_priv);
2102 if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
2103 ret = -ENOENT;
2104 goto out;
2105 }
2106
2107 hash = bat_priv->tt.global_hash;
2108
2109 while (bucket < hash->size) {
2110 head = &hash->table[bucket];
2111
2112 if (batadv_tt_global_dump_bucket(msg, portid,
2113 cb->nlh->nlmsg_seq, bat_priv,
2114 head, &idx, &sub))
2115 break;
2116
2117 bucket++;
2118 }
2119
2120 ret = msg->len;
2121
2122 out:
2123 if (primary_if)
2124 batadv_hardif_put(primary_if);
2125 if (soft_iface)
2126 dev_put(soft_iface);
2127
2128 cb->args[0] = bucket;
2129 cb->args[1] = idx;
2130 cb->args[2] = sub;
2131
2132 return ret;
2133}
2134
2135/**
1759 * _batadv_tt_global_del_orig_entry - remove and free an orig_entry 2136 * _batadv_tt_global_del_orig_entry - remove and free an orig_entry
1760 * @tt_global_entry: the global entry to remove the orig_entry from 2137 * @tt_global_entry: the global entry to remove the orig_entry from
1761 * @orig_entry: the orig entry to remove and free 2138 * @orig_entry: the orig entry to remove and free
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h
index 02b0f85527cc..783fdba84db2 100644
--- a/net/batman-adv/translation-table.h
+++ b/net/batman-adv/translation-table.h
@@ -22,8 +22,10 @@
22 22
23#include <linux/types.h> 23#include <linux/types.h>
24 24
25struct netlink_callback;
25struct net_device; 26struct net_device;
26struct seq_file; 27struct seq_file;
28struct sk_buff;
27 29
28int batadv_tt_init(struct batadv_priv *bat_priv); 30int batadv_tt_init(struct batadv_priv *bat_priv);
29bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr, 31bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr,
@@ -33,6 +35,8 @@ u16 batadv_tt_local_remove(struct batadv_priv *bat_priv,
33 const char *message, bool roaming); 35 const char *message, bool roaming);
34int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset); 36int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset);
35int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset); 37int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset);
38int batadv_tt_local_dump(struct sk_buff *msg, struct netlink_callback *cb);
39int batadv_tt_global_dump(struct sk_buff *msg, struct netlink_callback *cb);
36void batadv_tt_global_del_orig(struct batadv_priv *bat_priv, 40void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
37 struct batadv_orig_node *orig_node, 41 struct batadv_orig_node *orig_node,
38 s32 match_vid, const char *message); 42 s32 match_vid, const char *message);