diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2016-07-03 07:31:37 -0400 |
---|---|---|
committer | Simon Wunderlich <sw@simonwunderlich.de> | 2016-08-09 01:54:37 -0400 |
commit | d34f05507db245bef819b684ad84f9e0f9bb003d (patch) | |
tree | eed54f54f6c9e5e314e5055a754a566b800aac06 | |
parent | b60620cf567b79da46096a0ba29b39f23b6e7f1c (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.h | 56 | ||||
-rw-r--r-- | net/batman-adv/netlink.c | 23 | ||||
-rw-r--r-- | net/batman-adv/netlink.h | 3 | ||||
-rw-r--r-- | net/batman-adv/packet.h | 36 | ||||
-rw-r--r-- | net/batman-adv/translation-table.c | 377 | ||||
-rw-r--r-- | net/batman-adv/translation-table.h | 4 |
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 | */ | ||
50 | enum 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 | ||
44 | struct genl_family batadv_netlink_family = { | 45 | struct 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 | */ |
85 | static int | 94 | int |
86 | batadv_netlink_get_ifindex(const struct nlmsghdr *nlh, int attrtype) | 95 | batadv_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 | ||
26 | struct nlmsghdr; | ||
27 | |||
26 | void batadv_netlink_register(void); | 28 | void batadv_netlink_register(void); |
27 | void batadv_netlink_unregister(void); | 29 | void batadv_netlink_unregister(void); |
30 | int batadv_netlink_get_ifindex(const struct nlmsghdr *nlh, int attrtype); | ||
28 | 31 | ||
29 | int batadv_netlink_tpmeter_notify(struct batadv_priv *bat_priv, const u8 *dst, | 32 | int 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 | */ | ||
156 | enum 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 | */ | ||
1128 | static int | ||
1129 | batadv_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 | */ | ||
1185 | static int | ||
1186 | batadv_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 | */ | ||
1218 | int 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 | |||
1111 | static void | 1276 | static void |
1112 | batadv_tt_local_set_pending(struct batadv_priv *bat_priv, | 1277 | batadv_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 | */ | ||
1934 | static int | ||
1935 | batadv_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 | */ | ||
1996 | static int | ||
1997 | batadv_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 | */ | ||
2040 | static int | ||
2041 | batadv_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 | */ | ||
2074 | int 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 | ||
25 | struct netlink_callback; | ||
25 | struct net_device; | 26 | struct net_device; |
26 | struct seq_file; | 27 | struct seq_file; |
28 | struct sk_buff; | ||
27 | 29 | ||
28 | int batadv_tt_init(struct batadv_priv *bat_priv); | 30 | int batadv_tt_init(struct batadv_priv *bat_priv); |
29 | bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr, | 31 | bool 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); |
34 | int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset); | 36 | int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset); |
35 | int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset); | 37 | int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset); |
38 | int batadv_tt_local_dump(struct sk_buff *msg, struct netlink_callback *cb); | ||
39 | int batadv_tt_global_dump(struct sk_buff *msg, struct netlink_callback *cb); | ||
36 | void batadv_tt_global_del_orig(struct batadv_priv *bat_priv, | 40 | void 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); |