From sven at narfation.org Thu Dec 6 07:31:59 2018 From: sven at narfation.org (Sven Eckelmann) Date: Thu, 6 Dec 2018 07:31:59 +0100 Subject: [B.A.T.M.A.N.] [PATCH maint] batctl: Fix parsing of optional debug table command parameters Message-ID: <20181206063159.4070-1-sven@narfation.org> The commands which should have no support for -t/-u/-m/-i were allowed to accept these parameters but commands which should have accepted them were denying them. Fixes: cd2b4047ead9 ("batctl: Convert debug table to command infrastructure") Reported-by: Andreas Ziegler Signed-off-by: Sven Eckelmann --- debug.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/debug.c b/debug.c index 2979dff..316312f 100644 --- a/debug.c +++ b/debug.c @@ -89,7 +89,7 @@ int handle_debug_table(struct state *state, int argc, char **argv) } break; case 't': - if (debug_table->option_watch_interval) { + if (!debug_table->option_watch_interval) { fprintf(stderr, "Error - unrecognised option '-%c'\n", optchar); debug_table_usage(state); return EXIT_FAILURE; @@ -105,7 +105,7 @@ int handle_debug_table(struct state *state, int argc, char **argv) read_opt |= SKIP_HEADER; break; case 'u': - if (debug_table->option_unicast_only) { + if (!debug_table->option_unicast_only) { fprintf(stderr, "Error - unrecognised option '-%c'\n", optchar); debug_table_usage(state); return EXIT_FAILURE; @@ -114,7 +114,7 @@ int handle_debug_table(struct state *state, int argc, char **argv) read_opt |= UNICAST_ONLY; break; case 'm': - if (debug_table->option_multicast_only) { + if (!debug_table->option_multicast_only) { fprintf(stderr, "Error - unrecognised option '-%c'\n", optchar); debug_table_usage(state); return EXIT_FAILURE; @@ -123,7 +123,7 @@ int handle_debug_table(struct state *state, int argc, char **argv) read_opt |= MULTICAST_ONLY; break; case 'i': - if (debug_table->option_orig_iface) { + if (!debug_table->option_orig_iface) { fprintf(stderr, "Error - unrecognised option '-%c'\n", optchar); debug_table_usage(state); return EXIT_FAILURE; -- 2.19.2 From sven at narfation.org Thu Dec 6 07:36:20 2018 From: sven at narfation.org (Sven Eckelmann) Date: Thu, 6 Dec 2018 07:36:20 +0100 Subject: [B.A.T.M.A.N.] [PATCH] batman-adv: Allow to disable depmod Message-ID: <20181206063620.5191-1-sven@narfation.org> On some build systems, the actual call to depmod is not expected and only the installation of the module is expected. Just allow to overwrite this call with a different (dummy) executable. Signed-off-by: Sven Eckelmann --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d665c0ba..08ac8f65 100644 --- a/Makefile +++ b/Makefile @@ -45,6 +45,7 @@ export KERNELPATH RM ?= rm -f CP := cp -fpR LN := ln -sf +DEPMOD := depmod -a REVISION= $(shell if [ -d "$(PWD)/.git" ]; then \ echo $$(git --git-dir="$(PWD)/.git" describe --always --dirty --match "v*" |sed 's/^v//' 2> /dev/null || echo "[unknown]"); \ @@ -90,7 +91,7 @@ clean: install: config $(MAKE) -C $(KERNELPATH) $(BUILD_FLAGS) modules_install - depmod -a + $(DEPMOD) config: $(PWD)/gen-compat-autoconf.sh $(PWD)/compat-autoconf.h -- 2.19.2 From sven at narfation.org Fri Dec 7 14:58:27 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 14:58:27 +0100 Subject: [B.A.T.M.A.N.] [RFC v3 00/19] batman-adv: netlink restructuring, part 2 Message-ID: <20181207135846.6152-1-sven@narfation.org> Hi, Jiri Pirko called the batman-adv configuration interface a while back "a huge mistake" [1] and suggested genl as alternative. The first reimplementation [2] (based on the team/devlink design) was rejected. This second implementation is now using a nl80211-like design. The objects which can now be modified/queried are: * mesh/soft-interface (BATADV_CMD_GET_MESH/BATADV_CMD_SET_MESH) * slave/hard-interface (BATADV_CMD_GET_HARDIF/BATADV_CMD_SET_HARDIF) * vlan (BATADV_CMD_GET_VLAN/BATADV_CMD_SET_VLAN) Such a set messages automatically triggers a *_SET_* "reply" via the config multicast group. The same behavior was also added to the sysfs interface. I would like to ask the other developers to check whether their configuration values are represented correctly. And please also check whether the current implementation might collide with some other features which you might have in your pipeline. v3: * correctly assign kernel-doc for BATADV_GW_MODE_CLIENT * fix validation check for gw.sel_class * fix setting of BATADV_ATTR_ORIG_INTERVAL * Cc the (most likely) responsible developers for each setting to more directly ask them for feedback v2: * rewrite everything in a more nl80211-like message/attribute format. Kind regards, Sven [1] https://www.open-mesh.org/issues/300 [2] https://patchwork.open-mesh.org/cover/17610/ Sven Eckelmann (19): batman-adv: Move common genl doit code pre/post hooks batman-adv: Prepare framework for mesh genl config batman-adv: Prepare framework for hardif genl config batman-adv: Prepare framework for vlan genl config batman-adv: Add aggregated_ogms mesh genl configuration batman-adv: Add ap_isolation mesh/vlan genl configuration batman-adv: Add bonding mesh genl configuration batman-adv: Add bridge_loop_avoidance mesh genl configuration batman-adv: Add distributed_arp_table mesh genl configuration batman-adv: Add fragmentation mesh genl configuration batman-adv: Add gateway mesh genl configuration batman-adv: Add hop_penalty mesh genl configuration batman-adv: Add log_level mesh genl configuration batman-adv: Add multicast_mode mesh genl configuration batman-adv: Add network_coding mesh genl configuration batman-adv: Add orig_interval mesh genl configuration batman-adv: Add elp_interval hardif genl configuration batman-adv: Add throughput_override hardif genl configuration batman-adv: Trigger genl notification on sysfs config change include/uapi/linux/batman_adv.h | 188 +++++- net/batman-adv/gateway_client.c | 1 - net/batman-adv/gateway_common.c | 1 + net/batman-adv/gateway_common.h | 6 - net/batman-adv/netlink.c | 1074 +++++++++++++++++++++++++++---- net/batman-adv/netlink.h | 6 + net/batman-adv/soft-interface.c | 2 +- net/batman-adv/sysfs.c | 64 +- 8 files changed, 1195 insertions(+), 147 deletions(-) -- 2.19.2 From sven at narfation.org Fri Dec 7 14:58:28 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 14:58:28 +0100 Subject: [B.A.T.M.A.N.] [RFC v3 01/19] batman-adv: Move common genl doit code pre/post hooks In-Reply-To: <20181207135846.6152-1-sven@narfation.org> References: <20181207135846.6152-1-sven@narfation.org> Message-ID: <20181207135846.6152-2-sven@narfation.org> The commit ff4c92d85c6f ("genetlink: introduce pre_doit/post_doit hooks") intoduced a mechanism to run specific code for doit hooks before/after the hooks are run. Since all doit hooks are requiring the batadv softif, it should be retrieved/freed in these helpers to simplify the code. Signed-off-by: Sven Eckelmann --- net/batman-adv/netlink.c | 140 +++++++++++++++++++++++++++------------ 1 file changed, 97 insertions(+), 43 deletions(-) diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index 2dc3304c..b20801a3 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -20,8 +20,10 @@ #include "main.h" #include +#include #include #include +#include #include #include #include @@ -54,6 +56,8 @@ #include "tp_meter.h" #include "translation-table.h" +struct net; + struct genl_family batadv_netlink_family; /* multicast groups */ @@ -61,6 +65,18 @@ enum batadv_netlink_multicast_groups { BATADV_NL_MCGRP_TPMETER, }; +/** + * enum batadv_genl_ops_flags - flags for genl_ops's internal_flags + */ +enum batadv_genl_ops_flags { + /** + * @BATADV_FLAG_NEED_MESH: request requires valid soft interface in + * attribute BATADV_ATTR_MESH_IFINDEX and expects a pointer to it to be + * safed in info->user_ptr[0] + */ + BATADV_FLAG_NEED_MESH = BIT(0), +}; + static const struct genl_multicast_group batadv_netlink_mcgrps[] = { [BATADV_NL_MCGRP_TPMETER] = { .name = BATADV_NL_MCAST_GROUP_TPMETER }, }; @@ -329,40 +345,24 @@ int batadv_netlink_tpmeter_notify(struct batadv_priv *bat_priv, const u8 *dst, static int batadv_netlink_tp_meter_start(struct sk_buff *skb, struct genl_info *info) { - struct net *net = genl_info_net(info); - struct net_device *soft_iface; - struct batadv_priv *bat_priv; + struct batadv_priv *bat_priv = info->user_ptr[0]; struct sk_buff *msg = NULL; u32 test_length; void *msg_head; - int ifindex; u32 cookie; u8 *dst; int ret; - if (!info->attrs[BATADV_ATTR_MESH_IFINDEX]) - return -EINVAL; - if (!info->attrs[BATADV_ATTR_ORIG_ADDRESS]) return -EINVAL; if (!info->attrs[BATADV_ATTR_TPMETER_TEST_TIME]) return -EINVAL; - ifindex = nla_get_u32(info->attrs[BATADV_ATTR_MESH_IFINDEX]); - if (!ifindex) - return -EINVAL; - dst = nla_data(info->attrs[BATADV_ATTR_ORIG_ADDRESS]); test_length = nla_get_u32(info->attrs[BATADV_ATTR_TPMETER_TEST_TIME]); - soft_iface = dev_get_by_index(net, ifindex); - if (!soft_iface || !batadv_softif_is_valid(soft_iface)) { - ret = -ENODEV; - goto out; - } - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) { ret = -ENOMEM; @@ -377,15 +377,11 @@ batadv_netlink_tp_meter_start(struct sk_buff *skb, struct genl_info *info) goto out; } - bat_priv = netdev_priv(soft_iface); batadv_tp_start(bat_priv, dst, test_length, &cookie); ret = batadv_netlink_tp_meter_put(msg, cookie); out: - if (soft_iface) - dev_put(soft_iface); - if (ret) { if (msg) nlmsg_free(msg); @@ -406,38 +402,17 @@ batadv_netlink_tp_meter_start(struct sk_buff *skb, struct genl_info *info) static int batadv_netlink_tp_meter_cancel(struct sk_buff *skb, struct genl_info *info) { - struct net *net = genl_info_net(info); - struct net_device *soft_iface; - struct batadv_priv *bat_priv; - int ifindex; + struct batadv_priv *bat_priv = info->user_ptr[0]; u8 *dst; int ret = 0; - if (!info->attrs[BATADV_ATTR_MESH_IFINDEX]) - return -EINVAL; - if (!info->attrs[BATADV_ATTR_ORIG_ADDRESS]) return -EINVAL; - ifindex = nla_get_u32(info->attrs[BATADV_ATTR_MESH_IFINDEX]); - if (!ifindex) - return -EINVAL; - dst = nla_data(info->attrs[BATADV_ATTR_ORIG_ADDRESS]); - 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); batadv_tp_stop(bat_priv, dst, BATADV_TP_REASON_CANCEL); -out: - if (soft_iface) - dev_put(soft_iface); - return ret; } @@ -545,6 +520,81 @@ batadv_netlink_dump_hardifs(struct sk_buff *msg, struct netlink_callback *cb) return msg->len; } +/** + * batadv_get_softif_from_info() - Retrieve soft interface from genl attributes + * @net: the applicable net namespace + * @info: receiver information + * + * Return: Pointer to soft interface on success, error pointer on error + */ +static struct batadv_priv * +batadv_get_softif_from_info(struct net *net, struct genl_info *info) +{ + struct net_device *soft_iface; + int ifindex; + + if (!info->attrs[BATADV_ATTR_MESH_IFINDEX]) + return ERR_PTR(-EINVAL); + + ifindex = nla_get_u32(info->attrs[BATADV_ATTR_MESH_IFINDEX]); + + soft_iface = dev_get_by_index(net, ifindex); + if (!soft_iface) + return ERR_PTR(-ENODEV); + + if (!batadv_softif_is_valid(soft_iface)) + goto err_put_softif; + + return netdev_priv(soft_iface); + +err_put_softif: + dev_put(soft_iface); + + return ERR_PTR(-EINVAL); +} + +/** + * batadv_pre_doit() - Prepare batman-adv genl doit request + * @ops: requested netlink operation + * @skb: Netlink message with request data + * @info: receiver information + * + * Return: 0 on success or negative error number in case of failure + */ +static int batadv_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, + struct genl_info *info) +{ + struct batadv_priv *bat_priv; + + if (ops->internal_flags & BATADV_FLAG_NEED_MESH) { + bat_priv = batadv_get_softif_from_info(genl_info_net(info), + info); + if (IS_ERR(bat_priv)) + return PTR_ERR(bat_priv); + + info->user_ptr[0] = bat_priv; + } + + return 0; +} + +/** + * batadv_post_doit() - End batman-adv genl doit request + * @ops: requested netlink operation + * @skb: Netlink message with request data + * @info: receiver information + */ +static void batadv_post_doit(const struct genl_ops *ops, struct sk_buff *skb, + struct genl_info *info) +{ + struct batadv_priv *bat_priv; + + if (ops->internal_flags & BATADV_FLAG_NEED_MESH && info->user_ptr[0]) { + bat_priv = info->user_ptr[0]; + dev_put(bat_priv->soft_iface); + } +} + static const struct genl_ops batadv_netlink_ops[] = { { .cmd = BATADV_CMD_GET_MESH_INFO, @@ -557,12 +607,14 @@ static const struct genl_ops batadv_netlink_ops[] = { .flags = GENL_ADMIN_PERM, .policy = batadv_netlink_policy, .doit = batadv_netlink_tp_meter_start, + .internal_flags = BATADV_FLAG_NEED_MESH, }, { .cmd = BATADV_CMD_TP_METER_CANCEL, .flags = GENL_ADMIN_PERM, .policy = batadv_netlink_policy, .doit = batadv_netlink_tp_meter_cancel, + .internal_flags = BATADV_FLAG_NEED_MESH, }, { .cmd = BATADV_CMD_GET_ROUTING_ALGOS, @@ -639,6 +691,8 @@ struct genl_family batadv_netlink_family __ro_after_init = { .version = 1, .maxattr = BATADV_ATTR_MAX, .netnsok = true, + .pre_doit = batadv_pre_doit, + .post_doit = batadv_post_doit, .module = THIS_MODULE, .ops = batadv_netlink_ops, .n_ops = ARRAY_SIZE(batadv_netlink_ops), -- 2.19.2 From sven at narfation.org Fri Dec 7 14:58:29 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 14:58:29 +0100 Subject: [B.A.T.M.A.N.] [RFC v3 02/19] batman-adv: Prepare framework for mesh genl config In-Reply-To: <20181207135846.6152-1-sven@narfation.org> References: <20181207135846.6152-1-sven@narfation.org> Message-ID: <20181207135846.6152-3-sven@narfation.org> The batman-adv configuration interface was implemented solely using sysfs. This approach was condemned by non-batadv developers as "huge mistake". Instead a netlink/genl based implementation was suggested. The main objects for this configuration is the mesh/soft-interface object. Its actual object in memory already contains most of the available configuration settings. The genl interface reflects this by allowing to get/set it using the mesh specific commands. The BATADV_CMD_GET_MESH_INFO (or short version BATADV_CMD_GET_MESH) is reused as get command because it already provides the content of other information from the mesh/soft-interface which are not yet configuration specific. The set command BATADV_CMD_SET_MESH will also notify interested userspace listeners of the "config" mcast group using the BATADV_CMD_SET_MESH command message type that settings might have been changed and what the current values are. Signed-off-by: Sven Eckelmann --- include/uapi/linux/batman_adv.h | 16 +++- net/batman-adv/netlink.c | 159 +++++++++++++++++++------------- 2 files changed, 110 insertions(+), 65 deletions(-) diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h index 324a0e11..2d6a175e 100644 --- a/include/uapi/linux/batman_adv.h +++ b/include/uapi/linux/batman_adv.h @@ -27,6 +27,7 @@ #define BATADV_NL_NAME "batadv" +#define BATADV_NL_MCAST_GROUP_CONFIG "config" #define BATADV_NL_MCAST_GROUP_TPMETER "tpmeter" /** @@ -372,10 +373,14 @@ enum batadv_nl_commands { BATADV_CMD_UNSPEC, /** - * @BATADV_CMD_GET_MESH_INFO: Query basic information about batman-adv - * device + * @BATADV_CMD_GET_MESH: Get attributes from softif/mesh */ - BATADV_CMD_GET_MESH_INFO, + BATADV_CMD_GET_MESH, + + /** + * @BATADV_CMD_GET_MESH_INFO: Alias for @BATADV_CMD_GET_MESH + */ + BATADV_CMD_GET_MESH_INFO = BATADV_CMD_GET_MESH, /** * @BATADV_CMD_TP_METER: Start a tp meter session @@ -443,6 +448,11 @@ enum batadv_nl_commands { */ BATADV_CMD_GET_MCAST_FLAGS, + /** + * @BATADV_CMD_SET_MESH: Set attributes for softif/mesh + */ + BATADV_CMD_SET_MESH, + /* add new commands above here */ /** diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index b20801a3..d89761f8 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -62,6 +62,7 @@ struct genl_family batadv_netlink_family; /* multicast groups */ enum batadv_netlink_multicast_groups { + BATADV_NL_MCGRP_CONFIG, BATADV_NL_MCGRP_TPMETER, }; @@ -78,6 +79,7 @@ enum batadv_genl_ops_flags { }; static const struct genl_multicast_group batadv_netlink_mcgrps[] = { + [BATADV_NL_MCGRP_CONFIG] = { .name = BATADV_NL_MCAST_GROUP_CONFIG }, [BATADV_NL_MCGRP_TPMETER] = { .name = BATADV_NL_MCAST_GROUP_TPMETER }, }; @@ -138,20 +140,29 @@ batadv_netlink_get_ifindex(const struct nlmsghdr *nlh, int attrtype) } /** - * batadv_netlink_mesh_info_put() - fill in generic information about mesh - * interface - * @msg: netlink message to be sent back - * @soft_iface: interface for which the data should be taken + * batadv_netlink_mesh_put() - Fill message with mesh attributes + * @msg: Netlink message to dump into + * @bat_priv: the bat priv with all the soft interface information + * @cmd: type of message to generate + * @portid: Port making netlink request + * @seq: sequence number for message + * @flags: Additional flags for message * - * Return: 0 on success, < 0 on error + * Return: 0 on success or negative error number in case of failure */ -static int -batadv_netlink_mesh_info_put(struct sk_buff *msg, struct net_device *soft_iface) +static int batadv_netlink_mesh_put(struct sk_buff *msg, + struct batadv_priv *bat_priv, + enum batadv_nl_commands cmd, + u32 portid, u32 seq, int flags) { - struct batadv_priv *bat_priv = netdev_priv(soft_iface); + struct net_device *soft_iface = bat_priv->soft_iface; struct batadv_hard_iface *primary_if = NULL; struct net_device *hard_iface; - int ret = -ENOBUFS; + void *hdr; + + hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, flags, cmd); + if (!hdr) + return -ENOBUFS; if (nla_put_string(msg, BATADV_ATTR_VERSION, BATADV_SOURCE_VERSION) || nla_put_string(msg, BATADV_ATTR_ALGO_NAME, @@ -162,16 +173,16 @@ batadv_netlink_mesh_info_put(struct sk_buff *msg, struct net_device *soft_iface) soft_iface->dev_addr) || nla_put_u8(msg, BATADV_ATTR_TT_TTVN, (u8)atomic_read(&bat_priv->tt.vn))) - goto out; + goto nla_put_failure; #ifdef CONFIG_BATMAN_ADV_BLA if (nla_put_u16(msg, BATADV_ATTR_BLA_CRC, ntohs(bat_priv->bla.claim_dest.group))) - goto out; + goto nla_put_failure; #endif if (batadv_mcast_mesh_info_put(msg, bat_priv)) - goto out; + goto nla_put_failure; primary_if = batadv_primary_if_get_selected(bat_priv); if (primary_if && primary_if->if_status == BATADV_IF_ACTIVE) { @@ -183,77 +194,94 @@ batadv_netlink_mesh_info_put(struct sk_buff *msg, struct net_device *soft_iface) hard_iface->name) || nla_put(msg, BATADV_ATTR_HARD_ADDRESS, ETH_ALEN, hard_iface->dev_addr)) - goto out; + goto nla_put_failure; } - ret = 0; + batadv_hardif_put(primary_if); - out: + genlmsg_end(msg, hdr); + return 0; + +nla_put_failure: if (primary_if) batadv_hardif_put(primary_if); - return ret; + genlmsg_cancel(msg, hdr); + return -EMSGSIZE; } /** - * batadv_netlink_get_mesh_info() - handle incoming BATADV_CMD_GET_MESH_INFO - * netlink request - * @skb: received netlink message - * @info: receiver information + * batadv_netlink_notify_mesh() - send softif attributes to listener + * @bat_priv: the bat priv with all the soft interface information * * Return: 0 on success, < 0 on error */ -static int -batadv_netlink_get_mesh_info(struct sk_buff *skb, struct genl_info *info) +static int batadv_netlink_notify_mesh(struct batadv_priv *bat_priv) { - struct net *net = genl_info_net(info); - struct net_device *soft_iface; - struct sk_buff *msg = NULL; - void *msg_head; - int ifindex; + struct sk_buff *msg; int ret; - if (!info->attrs[BATADV_ATTR_MESH_IFINDEX]) - return -EINVAL; - - ifindex = nla_get_u32(info->attrs[BATADV_ATTR_MESH_IFINDEX]); - if (!ifindex) - return -EINVAL; + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; - soft_iface = dev_get_by_index(net, ifindex); - if (!soft_iface || !batadv_softif_is_valid(soft_iface)) { - ret = -ENODEV; - goto out; + ret = batadv_netlink_mesh_put(msg, bat_priv, BATADV_CMD_SET_MESH, + 0, 0, 0); + if (ret < 0) { + nlmsg_free(msg); + return ret; } - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); - if (!msg) { - ret = -ENOMEM; - goto out; - } + genlmsg_multicast_netns(&batadv_netlink_family, + dev_net(bat_priv->soft_iface), msg, 0, + BATADV_NL_MCGRP_CONFIG, GFP_KERNEL); - msg_head = genlmsg_put(msg, info->snd_portid, info->snd_seq, - &batadv_netlink_family, 0, - BATADV_CMD_GET_MESH_INFO); - if (!msg_head) { - ret = -ENOBUFS; - goto out; - } + return 0; +} - ret = batadv_netlink_mesh_info_put(msg, soft_iface); +/** + * batadv_netlink_get_mesh() - Get softif attributes + * @skb: Netlink message with request data + * @info: receiver information + * + * Return: 0 on success or negative error number in case of failure + */ +static int batadv_netlink_get_mesh(struct sk_buff *skb, struct genl_info *info) +{ + struct batadv_priv *bat_priv = info->user_ptr[0]; + struct sk_buff *msg; + int ret; - out: - if (soft_iface) - dev_put(soft_iface); + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; - if (ret) { - if (msg) - nlmsg_free(msg); + ret = batadv_netlink_mesh_put(msg, bat_priv, BATADV_CMD_GET_MESH, + info->snd_portid, info->snd_seq, 0); + if (ret < 0) { + nlmsg_free(msg); return ret; } - genlmsg_end(msg, msg_head); - return genlmsg_reply(msg, info); + ret = genlmsg_reply(msg, info); + + return ret; +} + +/** + * batadv_netlink_set_mesh() - Set softif attributes + * @skb: Netlink message with request data + * @info: receiver information + * + * Return: 0 on success or negative error number in case of failure + */ +static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info) +{ + struct batadv_priv *bat_priv = info->user_ptr[0]; + + batadv_netlink_notify_mesh(bat_priv); + + return 0; } /** @@ -597,10 +625,11 @@ static void batadv_post_doit(const struct genl_ops *ops, struct sk_buff *skb, static const struct genl_ops batadv_netlink_ops[] = { { - .cmd = BATADV_CMD_GET_MESH_INFO, - .flags = GENL_ADMIN_PERM, + .cmd = BATADV_CMD_GET_MESH, + /* can be retrieved by unprivileged users */ .policy = batadv_netlink_policy, - .doit = batadv_netlink_get_mesh_info, + .doit = batadv_netlink_get_mesh, + .internal_flags = BATADV_FLAG_NEED_MESH, }, { .cmd = BATADV_CMD_TP_METER, @@ -682,7 +711,13 @@ static const struct genl_ops batadv_netlink_ops[] = { .policy = batadv_netlink_policy, .dumpit = batadv_mcast_flags_dump, }, - + { + .cmd = BATADV_CMD_SET_MESH, + .flags = GENL_ADMIN_PERM, + .policy = batadv_netlink_policy, + .doit = batadv_netlink_set_mesh, + .internal_flags = BATADV_FLAG_NEED_MESH, + }, }; struct genl_family batadv_netlink_family __ro_after_init = { -- 2.19.2 From sven at narfation.org Fri Dec 7 14:58:30 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 14:58:30 +0100 Subject: [B.A.T.M.A.N.] [RFC v3 03/19] batman-adv: Prepare framework for hardif genl config In-Reply-To: <20181207135846.6152-1-sven@narfation.org> References: <20181207135846.6152-1-sven@narfation.org> Message-ID: <20181207135846.6152-4-sven@narfation.org> The batman-adv configuration interface was implemented solely using sysfs. This approach was condemned by non-batadv developers as "huge mistake". Instead a netlink/genl based implementation was suggested. Beside the mesh/soft-interface specific configuration, the slave/hard-interface have B.A.T.M.A.N. V specific configuration settings. The genl interface reflects this by allowing to get/set it using the hard-interface specific commands. The BATADV_CMD_GET_HARDIFS (or short version BATADV_CMD_GET_HARDIF) is reused as get command because it already allow to dump the content of other information from the slave/hard-interface which are not yet configuration specific. The set command BATADV_CMD_SET_HARDIF will also notify interested userspace listeners of the "config" mcast group using the BATADV_CMD_SET_HARDIF command message type that settings might have been changed and what the current values are. Signed-off-by: Sven Eckelmann --- include/uapi/linux/batman_adv.h | 16 ++- net/batman-adv/netlink.c | 237 +++++++++++++++++++++++++++++--- 2 files changed, 230 insertions(+), 23 deletions(-) diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h index 2d6a175e..eb5097df 100644 --- a/include/uapi/linux/batman_adv.h +++ b/include/uapi/linux/batman_adv.h @@ -398,9 +398,15 @@ enum batadv_nl_commands { BATADV_CMD_GET_ROUTING_ALGOS, /** - * @BATADV_CMD_GET_HARDIFS: Query list of hard interfaces + * @BATADV_CMD_GET_HARDIF: Get attributes from a hardif of the + * current softif */ - BATADV_CMD_GET_HARDIFS, + BATADV_CMD_GET_HARDIF, + + /** + * @BATADV_CMD_GET_HARDIFS: Alias for @BATADV_CMD_GET_HARDIF + */ + BATADV_CMD_GET_HARDIFS = BATADV_CMD_GET_HARDIF, /** * @BATADV_CMD_GET_TRANSTABLE_LOCAL: Query list of local translations @@ -453,6 +459,12 @@ enum batadv_nl_commands { */ BATADV_CMD_SET_MESH, + /** + * @BATADV_CMD_SET_HARDIF: Set attributes for hardif of the + * current softif + */ + BATADV_CMD_SET_HARDIF, + /* add new commands above here */ /** diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index d89761f8..68116eb8 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -76,6 +77,13 @@ enum batadv_genl_ops_flags { * safed in info->user_ptr[0] */ BATADV_FLAG_NEED_MESH = BIT(0), + + /** + * @BATADV_FLAG_NEED_HARDIF: request requires valid hard interface in + * attribute BATADV_ATTR_HARD_IFINDEX and expects a pointer to it to be + * safed in info->user_ptr[1] + */ + BATADV_FLAG_NEED_HARDIF = BIT(1), }; static const struct genl_multicast_group batadv_netlink_mcgrps[] = { @@ -445,29 +453,38 @@ batadv_netlink_tp_meter_cancel(struct sk_buff *skb, struct genl_info *info) } /** - * batadv_netlink_dump_hardif_entry() - Dump one hard interface into a message + * batadv_netlink_hardif_put() - Fill message with hardif attributes * @msg: Netlink message to dump into + * @bat_priv: the bat priv with all the soft interface information + * @hard_iface: hard interface which was modified + * @cmd: type of message to generate * @portid: Port making netlink request + * @seq: sequence number for message + * @flags: Additional flags for message * @cb: Control block containing additional options - * @hard_iface: Hard interface to dump * - * Return: error code, or 0 on success + * Return: 0 on success or negative error number in case of failure */ -static int -batadv_netlink_dump_hardif_entry(struct sk_buff *msg, u32 portid, - struct netlink_callback *cb, - struct batadv_hard_iface *hard_iface) +static int batadv_netlink_hardif_put(struct sk_buff *msg, + struct batadv_priv *bat_priv, + struct batadv_hard_iface *hard_iface, + enum batadv_nl_commands cmd, + u32 portid, u32 seq, int flags, + struct netlink_callback *cb) { struct net_device *net_dev = hard_iface->net_dev; void *hdr; - hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq, - &batadv_netlink_family, NLM_F_MULTI, - BATADV_CMD_GET_HARDIFS); + hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, flags, cmd); if (!hdr) - return -EMSGSIZE; + return -ENOBUFS; + + if (cb) + genl_dump_check_consistent(cb, hdr); - genl_dump_check_consistent(cb, hdr); + if (nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, + bat_priv->soft_iface->ifindex)) + goto nla_put_failure; if (nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, net_dev->ifindex) || @@ -485,24 +502,107 @@ batadv_netlink_dump_hardif_entry(struct sk_buff *msg, u32 portid, genlmsg_end(msg, hdr); return 0; - nla_put_failure: +nla_put_failure: genlmsg_cancel(msg, hdr); return -EMSGSIZE; } /** - * batadv_netlink_dump_hardifs() - Dump all hard interface into a messages + * batadv_netlink_notify_hardif() - send hardif attributes to listener + * @bat_priv: the bat priv with all the soft interface information + * @hard_iface: hard interface which was modified + * + * Return: 0 on success, < 0 on error + */ +static int batadv_netlink_notify_hardif(struct batadv_priv *bat_priv, + struct batadv_hard_iface *hard_iface) +{ + struct sk_buff *msg; + int ret; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + ret = batadv_netlink_hardif_put(msg, bat_priv, hard_iface, + BATADV_CMD_SET_HARDIF, 0, 0, 0, NULL); + if (ret < 0) { + nlmsg_free(msg); + return ret; + } + + genlmsg_multicast_netns(&batadv_netlink_family, + dev_net(bat_priv->soft_iface), msg, 0, + BATADV_NL_MCGRP_CONFIG, GFP_KERNEL); + + return 0; +} + +/** + * batadv_netlink_get_hardif() - Get hardif attributes + * @skb: Netlink message with request data + * @info: receiver information + * + * Return: 0 on success or negative error number in case of failure + */ +static int batadv_netlink_get_hardif(struct sk_buff *skb, + struct genl_info *info) +{ + struct batadv_hard_iface *hard_iface = info->user_ptr[1]; + struct batadv_priv *bat_priv = info->user_ptr[0]; + struct sk_buff *msg; + int ret; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + ret = batadv_netlink_hardif_put(msg, bat_priv, hard_iface, + BATADV_CMD_GET_HARDIF, + info->snd_portid, info->snd_seq, 0, + NULL); + if (ret < 0) { + nlmsg_free(msg); + return ret; + } + + ret = genlmsg_reply(msg, info); + + return ret; +} + +/** + * batadv_netlink_set_hardif() - Set hardif attributes + * @skb: Netlink message with request data + * @info: receiver information + * + * Return: 0 on success or negative error number in case of failure + */ +static int batadv_netlink_set_hardif(struct sk_buff *skb, + struct genl_info *info) +{ + struct batadv_hard_iface *hard_iface = info->user_ptr[1]; + struct batadv_priv *bat_priv = info->user_ptr[0]; + + batadv_netlink_notify_hardif(bat_priv, hard_iface); + + return 0; +} + +/** + * batadv_netlink_dump_hardif() - Dump all hard interface into a messages * @msg: Netlink message to dump into * @cb: Parameters from query * * Return: error code, or length of reply message on success */ static int -batadv_netlink_dump_hardifs(struct sk_buff *msg, struct netlink_callback *cb) +batadv_netlink_dump_hardif(struct sk_buff *msg, struct netlink_callback *cb) { struct net *net = sock_net(cb->skb->sk); struct net_device *soft_iface; struct batadv_hard_iface *hard_iface; + struct batadv_priv *bat_priv; int ifindex; int portid = NETLINK_CB(cb->skb).portid; int skip = cb->args[0]; @@ -522,6 +622,8 @@ batadv_netlink_dump_hardifs(struct sk_buff *msg, struct netlink_callback *cb) return -ENODEV; } + bat_priv = netdev_priv(soft_iface); + rtnl_lock(); cb->seq = batadv_hardif_generation << 1 | 1; @@ -532,8 +634,10 @@ batadv_netlink_dump_hardifs(struct sk_buff *msg, struct netlink_callback *cb) if (i++ < skip) continue; - if (batadv_netlink_dump_hardif_entry(msg, portid, cb, - hard_iface)) { + if (batadv_netlink_hardif_put(msg, bat_priv, hard_iface, + BATADV_CMD_GET_HARDIF, + portid, cb->nlh->nlmsg_seq, + NLM_F_MULTI, cb)) { i--; break; } @@ -581,6 +685,48 @@ batadv_get_softif_from_info(struct net *net, struct genl_info *info) return ERR_PTR(-EINVAL); } +/** + * batadv_get_hardif_from_info() - Retrieve hardif from genl attributes + * @bat_priv: the bat priv with all the soft interface information + * @net: the applicable net namespace + * @info: receiver information + * + * Return: Pointer to hard interface on success, error pointer on error + */ +static struct batadv_hard_iface * +batadv_get_hardif_from_info(struct batadv_priv *bat_priv, struct net *net, + struct genl_info *info) +{ + struct batadv_hard_iface *hard_iface; + struct net_device *hard_dev; + unsigned int hardif_index; + + if (!info->attrs[BATADV_ATTR_HARD_IFINDEX]) + return ERR_PTR(-EINVAL); + + hardif_index = nla_get_u32(info->attrs[BATADV_ATTR_HARD_IFINDEX]); + + hard_dev = dev_get_by_index(net, hardif_index); + if (!hard_dev) + return ERR_PTR(-ENODEV); + + hard_iface = batadv_hardif_get_by_netdev(hard_dev); + if (!hard_iface) + goto err_put_harddev; + + if (hard_iface->soft_iface != bat_priv->soft_iface) + goto err_put_hardif; + + return hard_iface; + +err_put_hardif: + batadv_hardif_put(hard_iface); +err_put_harddev: + dev_put(hard_dev); + + return ERR_PTR(-EINVAL); +} + /** * batadv_pre_doit() - Prepare batman-adv genl doit request * @ops: requested netlink operation @@ -592,7 +738,16 @@ batadv_get_softif_from_info(struct net *net, struct genl_info *info) static int batadv_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, struct genl_info *info) { - struct batadv_priv *bat_priv; + struct batadv_hard_iface *hard_iface; + struct batadv_priv *bat_priv = NULL; + int ret; + + if (WARN_ON(ops->internal_flags & BATADV_FLAG_NEED_HARDIF)) + return -EINVAL; + + if (WARN_ON((ops->internal_flags & BATADV_FLAG_NEED_HARDIF) && + (~ops->internal_flags & BATADV_FLAG_NEED_MESH))) + return -EINVAL; if (ops->internal_flags & BATADV_FLAG_NEED_MESH) { bat_priv = batadv_get_softif_from_info(genl_info_net(info), @@ -603,7 +758,25 @@ static int batadv_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, info->user_ptr[0] = bat_priv; } + if (ops->internal_flags & BATADV_FLAG_NEED_HARDIF) { + hard_iface = batadv_get_hardif_from_info(bat_priv, + genl_info_net(info), + info); + if (IS_ERR(hard_iface)) { + ret = PTR_ERR(hard_iface); + goto err_put_softif; + } + + info->user_ptr[1] = hard_iface; + } + return 0; + +err_put_softif: + if (bat_priv) + dev_put(bat_priv->soft_iface); + + return ret; } /** @@ -615,7 +788,18 @@ static int batadv_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, static void batadv_post_doit(const struct genl_ops *ops, struct sk_buff *skb, struct genl_info *info) { + struct batadv_hard_iface *hard_iface; struct batadv_priv *bat_priv; + struct net_device *hard_dev; + + if (ops->internal_flags & BATADV_FLAG_NEED_HARDIF && + info->user_ptr[1]) { + hard_iface = info->user_ptr[1]; + hard_dev = hard_iface->net_dev; + + batadv_hardif_put(hard_iface); + dev_put(hard_dev); + } if (ops->internal_flags & BATADV_FLAG_NEED_MESH && info->user_ptr[0]) { bat_priv = info->user_ptr[0]; @@ -652,10 +836,13 @@ static const struct genl_ops batadv_netlink_ops[] = { .dumpit = batadv_algo_dump, }, { - .cmd = BATADV_CMD_GET_HARDIFS, - .flags = GENL_ADMIN_PERM, + .cmd = BATADV_CMD_GET_HARDIF, + /* can be retrieved by unprivileged users */ .policy = batadv_netlink_policy, - .dumpit = batadv_netlink_dump_hardifs, + .dumpit = batadv_netlink_dump_hardif, + .doit = batadv_netlink_get_hardif, + .internal_flags = BATADV_FLAG_NEED_MESH | + BATADV_FLAG_NEED_HARDIF, }, { .cmd = BATADV_CMD_GET_TRANSTABLE_LOCAL, @@ -718,6 +905,14 @@ static const struct genl_ops batadv_netlink_ops[] = { .doit = batadv_netlink_set_mesh, .internal_flags = BATADV_FLAG_NEED_MESH, }, + { + .cmd = BATADV_CMD_SET_HARDIF, + .flags = GENL_ADMIN_PERM, + .policy = batadv_netlink_policy, + .doit = batadv_netlink_set_hardif, + .internal_flags = BATADV_FLAG_NEED_MESH | + BATADV_FLAG_NEED_HARDIF, + }, }; struct genl_family batadv_netlink_family __ro_after_init = { -- 2.19.2 From sven at narfation.org Fri Dec 7 14:58:31 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 14:58:31 +0100 Subject: [B.A.T.M.A.N.] [RFC v3 04/19] batman-adv: Prepare framework for vlan genl config In-Reply-To: <20181207135846.6152-1-sven@narfation.org> References: <20181207135846.6152-1-sven@narfation.org> Message-ID: <20181207135846.6152-5-sven@narfation.org> The batman-adv configuration interface was implemented solely using sysfs. This approach was condemned by non-batadv developers as "huge mistake". Instead a netlink/genl based implementation was suggested. Beside the mesh/soft-interface specific configuration, the VLANs on top of the mesh/soft-interface have configuration settings. The genl interface reflects this by allowing to get/set it using the vlan specific commands BATADV_CMD_GET_VLAN/BATADV_CMD_SET_VLAN. The set command BATADV_CMD_SET_MESH will also notify interested userspace listeners of the "config" mcast group using the BATADV_CMD_SET_VLAN command message type that settings might have been changed and what the current values are. Signed-off-by: Sven Eckelmann --- include/uapi/linux/batman_adv.h | 17 +++ net/batman-adv/netlink.c | 193 +++++++++++++++++++++++++++++++- 2 files changed, 208 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h index eb5097df..865cdf90 100644 --- a/include/uapi/linux/batman_adv.h +++ b/include/uapi/linux/batman_adv.h @@ -345,6 +345,11 @@ enum batadv_nl_attrs { */ BATADV_ATTR_MCAST_FLAGS_PRIV, + /** + * @BATADV_ATTR_VLANID: VLAN id on top of soft interface + */ + BATADV_ATTR_VLANID, + /* add attributes above here, update the policy in netlink.c */ /** @@ -465,6 +470,18 @@ enum batadv_nl_commands { */ BATADV_CMD_SET_HARDIF, + /** + * @BATADV_CMD_GET_VLAN: Get attributes from a VLAN of the + * current softif + */ + BATADV_CMD_GET_VLAN, + + /** + * @BATADV_CMD_SET_VLAN: Set attributes for VLAN of the + * current softif + */ + BATADV_CMD_SET_VLAN, + /* add new commands above here */ /** diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index 68116eb8..30ed0672 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -84,6 +85,13 @@ enum batadv_genl_ops_flags { * safed in info->user_ptr[1] */ BATADV_FLAG_NEED_HARDIF = BIT(1), + + /** + * @BATADV_FLAG_NEED_VLAN: request requires valid vlan in + * attribute BATADV_ATTR_VLANID and expects a pointer to it to be + * safed in info->user_ptr[1] + */ + BATADV_FLAG_NEED_VLAN = BIT(2), }; static const struct genl_multicast_group batadv_netlink_mcgrps[] = { @@ -130,6 +138,7 @@ static const struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = { [BATADV_ATTR_DAT_CACHE_VID] = { .type = NLA_U16 }, [BATADV_ATTR_MCAST_FLAGS] = { .type = NLA_U32 }, [BATADV_ATTR_MCAST_FLAGS_PRIV] = { .type = NLA_U32 }, + [BATADV_ATTR_VLANID] = { .type = NLA_U16 }, }; /** @@ -652,6 +661,123 @@ batadv_netlink_dump_hardif(struct sk_buff *msg, struct netlink_callback *cb) return msg->len; } +/** + * batadv_netlink_vlan_put() - Fill message with vlan attributes + * @msg: Netlink message to dump into + * @bat_priv: the bat priv with all the soft interface information + * @vlan: vlan which was modified + * @cmd: type of message to generate + * @portid: Port making netlink request + * @seq: sequence number for message + * @flags: Additional flags for message + * + * Return: 0 on success or negative error number in case of failure + */ +static int batadv_netlink_vlan_put(struct sk_buff *msg, + struct batadv_priv *bat_priv, + struct batadv_softif_vlan *vlan, + enum batadv_nl_commands cmd, + u32 portid, u32 seq, int flags) +{ + void *hdr; + + hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, flags, cmd); + if (!hdr) + return -ENOBUFS; + + if (nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, + bat_priv->soft_iface->ifindex)) + goto nla_put_failure; + + if (nla_put_u32(msg, BATADV_ATTR_VLANID, vlan->vid & VLAN_VID_MASK)) + goto nla_put_failure; + + genlmsg_end(msg, hdr); + return 0; + +nla_put_failure: + genlmsg_cancel(msg, hdr); + return -EMSGSIZE; +} + +/** + * batadv_netlink_notify_vlan() - send vlan attributes to listener + * @bat_priv: the bat priv with all the soft interface information + * @vlan: vlan which was modified + * + * Return: 0 on success, < 0 on error + */ +static int batadv_netlink_notify_vlan(struct batadv_priv *bat_priv, + struct batadv_softif_vlan *vlan) +{ + struct sk_buff *msg; + int ret; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + ret = batadv_netlink_vlan_put(msg, bat_priv, vlan, + BATADV_CMD_SET_VLAN, 0, 0, 0); + if (ret < 0) { + nlmsg_free(msg); + return ret; + } + + genlmsg_multicast_netns(&batadv_netlink_family, + dev_net(bat_priv->soft_iface), msg, 0, + BATADV_NL_MCGRP_CONFIG, GFP_KERNEL); + + return 0; +} + +/** + * batadv_netlink_get_vlan() - Get vlan attributes + * @skb: Netlink message with request data + * @info: receiver information + * + * Return: 0 on success or negative error number in case of failure + */ +static int batadv_netlink_get_vlan(struct sk_buff *skb, struct genl_info *info) +{ + struct batadv_softif_vlan *vlan = info->user_ptr[1]; + struct batadv_priv *bat_priv = info->user_ptr[0]; + struct sk_buff *msg; + int ret; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + ret = batadv_netlink_vlan_put(msg, bat_priv, vlan, BATADV_CMD_GET_VLAN, + info->snd_portid, info->snd_seq, 0); + if (ret < 0) { + nlmsg_free(msg); + return ret; + } + + ret = genlmsg_reply(msg, info); + + return ret; +} + +/** + * batadv_netlink_set_vlan() - Get vlan attributes + * @skb: Netlink message with request data + * @info: receiver information + * + * Return: 0 on success or negative error number in case of failure + */ +static int batadv_netlink_set_vlan(struct sk_buff *skb, struct genl_info *info) +{ + struct batadv_softif_vlan *vlan = info->user_ptr[1]; + struct batadv_priv *bat_priv = info->user_ptr[0]; + + batadv_netlink_notify_vlan(bat_priv, vlan); + + return 0; +} + /** * batadv_get_softif_from_info() - Retrieve soft interface from genl attributes * @net: the applicable net namespace @@ -727,6 +853,33 @@ batadv_get_hardif_from_info(struct batadv_priv *bat_priv, struct net *net, return ERR_PTR(-EINVAL); } +/** + * batadv_get_vlan_from_info() - Retrieve vlan from genl attributes + * @bat_priv: the bat priv with all the soft interface information + * @net: the applicable net namespace + * @info: receiver information + * + * Return: Pointer to vlan on success, error pointer on error + */ +static struct batadv_softif_vlan * +batadv_get_vlan_from_info(struct batadv_priv *bat_priv, struct net *net, + struct genl_info *info) +{ + struct batadv_softif_vlan *vlan; + u16 vid; + + if (!info->attrs[BATADV_ATTR_VLANID]) + return ERR_PTR(-EINVAL); + + vid = nla_get_u16(info->attrs[BATADV_ATTR_VLANID]); + + vlan = batadv_softif_vlan_get(bat_priv, vid | BATADV_VLAN_HAS_TAG); + if (!vlan) + return ERR_PTR(-ENOENT); + + return vlan; +} + /** * batadv_pre_doit() - Prepare batman-adv genl doit request * @ops: requested netlink operation @@ -740,12 +893,15 @@ static int batadv_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, { struct batadv_hard_iface *hard_iface; struct batadv_priv *bat_priv = NULL; + struct batadv_softif_vlan *vlan; int ret; - if (WARN_ON(ops->internal_flags & BATADV_FLAG_NEED_HARDIF)) + if (WARN_ON((ops->internal_flags & BATADV_FLAG_NEED_HARDIF) && + (ops->internal_flags & BATADV_FLAG_NEED_VLAN))) return -EINVAL; - if (WARN_ON((ops->internal_flags & BATADV_FLAG_NEED_HARDIF) && + if (WARN_ON(((ops->internal_flags & BATADV_FLAG_NEED_HARDIF) || + (ops->internal_flags & BATADV_FLAG_NEED_VLAN)) && (~ops->internal_flags & BATADV_FLAG_NEED_MESH))) return -EINVAL; @@ -770,6 +926,17 @@ static int batadv_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, info->user_ptr[1] = hard_iface; } + if (ops->internal_flags & BATADV_FLAG_NEED_VLAN) { + vlan = batadv_get_vlan_from_info(bat_priv, genl_info_net(info), + info); + if (IS_ERR(vlan)) { + ret = PTR_ERR(vlan); + goto err_put_softif; + } + + info->user_ptr[1] = vlan; + } + return 0; err_put_softif: @@ -789,6 +956,7 @@ static void batadv_post_doit(const struct genl_ops *ops, struct sk_buff *skb, struct genl_info *info) { struct batadv_hard_iface *hard_iface; + struct batadv_softif_vlan *vlan; struct batadv_priv *bat_priv; struct net_device *hard_dev; @@ -801,6 +969,11 @@ static void batadv_post_doit(const struct genl_ops *ops, struct sk_buff *skb, dev_put(hard_dev); } + if (ops->internal_flags & BATADV_FLAG_NEED_VLAN && info->user_ptr[1]) { + vlan = info->user_ptr[1]; + batadv_softif_vlan_put(vlan); + } + if (ops->internal_flags & BATADV_FLAG_NEED_MESH && info->user_ptr[0]) { bat_priv = info->user_ptr[0]; dev_put(bat_priv->soft_iface); @@ -913,6 +1086,22 @@ static const struct genl_ops batadv_netlink_ops[] = { .internal_flags = BATADV_FLAG_NEED_MESH | BATADV_FLAG_NEED_HARDIF, }, + { + .cmd = BATADV_CMD_GET_VLAN, + /* can be retrieved by unprivileged users */ + .policy = batadv_netlink_policy, + .doit = batadv_netlink_get_vlan, + .internal_flags = BATADV_FLAG_NEED_MESH | + BATADV_FLAG_NEED_VLAN, + }, + { + .cmd = BATADV_CMD_SET_VLAN, + .flags = GENL_ADMIN_PERM, + .policy = batadv_netlink_policy, + .doit = batadv_netlink_set_vlan, + .internal_flags = BATADV_FLAG_NEED_MESH | + BATADV_FLAG_NEED_VLAN, + }, }; struct genl_family batadv_netlink_family __ro_after_init = { -- 2.19.2 From sven at narfation.org Fri Dec 7 14:58:32 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 14:58:32 +0100 Subject: [B.A.T.M.A.N.] [RFC v3 05/19] batman-adv: Add aggregated_ogms mesh genl configuration In-Reply-To: <20181207135846.6152-1-sven@narfation.org> References: <20181207135846.6152-1-sven@narfation.org> Message-ID: <20181207135846.6152-6-sven@narfation.org> The mesh interface can delay OGM messages to aggregate different ogms together in a single OGM packet. The BATADV_CMD_SET_MESH/BATADV_CMD_GET_MESH commands allow to set/get the configuration of this feature using the BATADV_ATTR_AGGREGATED_OGMS attribute. Setting the u8 to zero will disable this feature and setting it to something else is enabling this feature. Signed-off-by: Sven Eckelmann --- Cc: Marek Lindner --- include/uapi/linux/batman_adv.h | 6 ++++++ net/batman-adv/netlink.c | 12 ++++++++++++ 2 files changed, 18 insertions(+) diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h index 865cdf90..a01d90ed 100644 --- a/include/uapi/linux/batman_adv.h +++ b/include/uapi/linux/batman_adv.h @@ -350,6 +350,12 @@ enum batadv_nl_attrs { */ BATADV_ATTR_VLANID, + /** + * @BATADV_ATTR_AGGREGATED_OGMS: whether the batman protocol messages + * of the mesh mesh interface shall be aggregated or not. + */ + BATADV_ATTR_AGGREGATED_OGMS, + /* add attributes above here, update the policy in netlink.c */ /** diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index 30ed0672..862d47c4 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -139,6 +139,7 @@ static const struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = { [BATADV_ATTR_MCAST_FLAGS] = { .type = NLA_U32 }, [BATADV_ATTR_MCAST_FLAGS_PRIV] = { .type = NLA_U32 }, [BATADV_ATTR_VLANID] = { .type = NLA_U16 }, + [BATADV_ATTR_AGGREGATED_OGMS] = { .type = NLA_U8 }, }; /** @@ -214,6 +215,10 @@ static int batadv_netlink_mesh_put(struct sk_buff *msg, goto nla_put_failure; } + if (nla_put_u8(msg, BATADV_ATTR_AGGREGATED_OGMS, + !!atomic_read(&bat_priv->aggregated_ogms))) + goto nla_put_failure; + batadv_hardif_put(primary_if); genlmsg_end(msg, hdr); @@ -295,6 +300,13 @@ static int batadv_netlink_get_mesh(struct sk_buff *skb, struct genl_info *info) static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info) { struct batadv_priv *bat_priv = info->user_ptr[0]; + struct nlattr *attr; + + if (info->attrs[BATADV_ATTR_AGGREGATED_OGMS]) { + attr = info->attrs[BATADV_ATTR_AGGREGATED_OGMS]; + + atomic_set(&bat_priv->aggregated_ogms, !!nla_get_u8(attr)); + } batadv_netlink_notify_mesh(bat_priv); -- 2.19.2 From sven at narfation.org Fri Dec 7 14:58:33 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 14:58:33 +0100 Subject: [B.A.T.M.A.N.] [RFC v3 06/19] batman-adv: Add ap_isolation mesh/vlan genl configuration In-Reply-To: <20181207135846.6152-1-sven@narfation.org> References: <20181207135846.6152-1-sven@narfation.org> Message-ID: <20181207135846.6152-7-sven@narfation.org> The mesh interface can drop messages between clients to implement a mesh-wide AP isolation. The BATADV_CMD_SET_MESH/BATADV_CMD_GET_MESH and BATADV_CMD_SET_VLAN/BATADV_CMD_GET_VLAN commands allow to set/get the configuration of this feature using the BATADV_ATTR_AP_ISOLATION attribute. Setting the u8 to zero will disable this feature and setting it to something else is enabling this feature. This feature also requires that skbuff which should be handled as isolated are marked. The BATADV_CMD_SET_MESH/BATADV_CMD_GET_MESH commands allow to set/get the mark/mask using the u32 attributes BATADV_ATTR_ISOLATION_MARK and BATADV_ATTR_ISOLATION_MASK. Signed-off-by: Sven Eckelmann --- Cc: Antonio Quartulli --- include/uapi/linux/batman_adv.h | 18 +++++++ net/batman-adv/netlink.c | 88 +++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h index a01d90ed..75738032 100644 --- a/include/uapi/linux/batman_adv.h +++ b/include/uapi/linux/batman_adv.h @@ -356,6 +356,24 @@ enum batadv_nl_attrs { */ BATADV_ATTR_AGGREGATED_OGMS, + /** + * @BATADV_ATTR_AP_ISOLATION: whether the data traffic going from a + * wireless client to another wireless client will be silently dropped. + */ + BATADV_ATTR_AP_ISOLATION, + + /** + * @BATADV_ATTR_ISOLATION_MARK: the isolation mark which is used to + * classify clients as "isolated" by the Extended Isolation feature. + */ + BATADV_ATTR_ISOLATION_MARK, + + /** + * @BATADV_ATTR_ISOLATION_MASK: the isolation (bit)mask which is used to + * classify clients as "isolated" by the Extended Isolation feature. + */ + BATADV_ATTR_ISOLATION_MASK, + /* add attributes above here, update the policy in netlink.c */ /** diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index 862d47c4..217c4b30 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -140,6 +140,9 @@ static const struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = { [BATADV_ATTR_MCAST_FLAGS_PRIV] = { .type = NLA_U32 }, [BATADV_ATTR_VLANID] = { .type = NLA_U16 }, [BATADV_ATTR_AGGREGATED_OGMS] = { .type = NLA_U8 }, + [BATADV_ATTR_AP_ISOLATION] = { .type = NLA_U8 }, + [BATADV_ATTR_ISOLATION_MARK] = { .type = NLA_U32 }, + [BATADV_ATTR_ISOLATION_MASK] = { .type = NLA_U32 }, }; /** @@ -157,6 +160,51 @@ batadv_netlink_get_ifindex(const struct nlmsghdr *nlh, int attrtype) return attr ? nla_get_u32(attr) : 0; } +/** + * batadv_netlink_mesh_put_ap_isolation() - Add ap_isolation softif attribute + * @msg: Netlink message to dump into + * @bat_priv: the bat priv with all the soft interface information + * + * Return: 0 on success or negative error number in case of failure + */ +static int batadv_netlink_mesh_put_ap_isolation(struct sk_buff *msg, + struct batadv_priv *bat_priv) +{ + struct batadv_softif_vlan *vlan; + u8 ap_isolation; + + vlan = batadv_softif_vlan_get(bat_priv, BATADV_NO_FLAGS); + if (!vlan) + return 0; + + ap_isolation = atomic_read(&vlan->ap_isolation); + batadv_softif_vlan_put(vlan); + + return nla_put_u8(msg, BATADV_ATTR_AP_ISOLATION, !!ap_isolation); +} + +/** + * batadv_option_set_ap_isolation() - Set ap_isolation from genl msg + * @attr: parsed BATADV_ATTR_AP_ISOLATION attribute + * @bat_priv: the bat priv with all the soft interface information + * + * Return: 0 on success or negative error number in case of failure + */ +static int batadv_netlink_set_mesh_ap_isolation(struct nlattr *attr, + struct batadv_priv *bat_priv) +{ + struct batadv_softif_vlan *vlan; + + vlan = batadv_softif_vlan_get(bat_priv, BATADV_NO_FLAGS); + if (!vlan) + return -ENOENT; + + atomic_set(&vlan->ap_isolation, !!nla_get_u8(attr)); + batadv_softif_vlan_put(vlan); + + return 0; +} + /** * batadv_netlink_mesh_put() - Fill message with mesh attributes * @msg: Netlink message to dump into @@ -219,6 +267,17 @@ static int batadv_netlink_mesh_put(struct sk_buff *msg, !!atomic_read(&bat_priv->aggregated_ogms))) goto nla_put_failure; + if (batadv_netlink_mesh_put_ap_isolation(msg, bat_priv)) + goto nla_put_failure; + + if (nla_put_u32(msg, BATADV_ATTR_ISOLATION_MARK, + bat_priv->isolation_mark)) + goto nla_put_failure; + + if (nla_put_u32(msg, BATADV_ATTR_ISOLATION_MASK, + bat_priv->isolation_mark_mask)) + goto nla_put_failure; + batadv_hardif_put(primary_if); genlmsg_end(msg, hdr); @@ -308,6 +367,24 @@ static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info) atomic_set(&bat_priv->aggregated_ogms, !!nla_get_u8(attr)); } + if (info->attrs[BATADV_ATTR_AP_ISOLATION]) { + attr = info->attrs[BATADV_ATTR_AP_ISOLATION]; + + batadv_netlink_set_mesh_ap_isolation(attr, bat_priv); + } + + if (info->attrs[BATADV_ATTR_ISOLATION_MARK]) { + attr = info->attrs[BATADV_ATTR_ISOLATION_MARK]; + + bat_priv->isolation_mark = nla_get_u32(attr); + } + + if (info->attrs[BATADV_ATTR_ISOLATION_MASK]) { + attr = info->attrs[BATADV_ATTR_ISOLATION_MASK]; + + bat_priv->isolation_mark_mask = nla_get_u32(attr); + } + batadv_netlink_notify_mesh(bat_priv); return 0; @@ -704,6 +781,10 @@ static int batadv_netlink_vlan_put(struct sk_buff *msg, if (nla_put_u32(msg, BATADV_ATTR_VLANID, vlan->vid & VLAN_VID_MASK)) goto nla_put_failure; + if (nla_put_u8(msg, BATADV_ATTR_AP_ISOLATION, + !!atomic_read(&vlan->ap_isolation))) + goto nla_put_failure; + genlmsg_end(msg, hdr); return 0; @@ -784,6 +865,13 @@ static int batadv_netlink_set_vlan(struct sk_buff *skb, struct genl_info *info) { struct batadv_softif_vlan *vlan = info->user_ptr[1]; struct batadv_priv *bat_priv = info->user_ptr[0]; + struct nlattr *attr; + + if (info->attrs[BATADV_ATTR_AP_ISOLATION]) { + attr = info->attrs[BATADV_ATTR_AP_ISOLATION]; + + atomic_set(&vlan->ap_isolation, !!nla_get_u8(attr)); + } batadv_netlink_notify_vlan(bat_priv, vlan); -- 2.19.2 From sven at narfation.org Fri Dec 7 14:58:34 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 14:58:34 +0100 Subject: [B.A.T.M.A.N.] [RFC v3 07/19] batman-adv: Add bonding mesh genl configuration In-Reply-To: <20181207135846.6152-1-sven@narfation.org> References: <20181207135846.6152-1-sven@narfation.org> Message-ID: <20181207135846.6152-8-sven@narfation.org> The mesh interface can use multiple slave/hard-interface ports at the same time to transport the traffic to other nodes. The BATADV_CMD_SET_MESH/BATADV_CMD_GET_MESH commands allow to set/get the configuration of this feature using the BATADV_ATTR_BONDING attribute. Setting the u8 to zero will disable this feature and setting it to something else is enabling this feature. Signed-off-by: Sven Eckelmann --- Cc: Simon Wunderlich --- include/uapi/linux/batman_adv.h | 6 ++++++ net/batman-adv/netlink.c | 11 +++++++++++ 2 files changed, 17 insertions(+) diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h index 75738032..d209c468 100644 --- a/include/uapi/linux/batman_adv.h +++ b/include/uapi/linux/batman_adv.h @@ -374,6 +374,12 @@ enum batadv_nl_attrs { */ BATADV_ATTR_ISOLATION_MASK, + /** + * @BATADV_ATTR_BONDING: whether the data traffic going through the + * mesh will be sent using multiple interfaces at the same time. + */ + BATADV_ATTR_BONDING, + /* add attributes above here, update the policy in netlink.c */ /** diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index 217c4b30..a836a8f1 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -143,6 +143,7 @@ static const struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = { [BATADV_ATTR_AP_ISOLATION] = { .type = NLA_U8 }, [BATADV_ATTR_ISOLATION_MARK] = { .type = NLA_U32 }, [BATADV_ATTR_ISOLATION_MASK] = { .type = NLA_U32 }, + [BATADV_ATTR_BONDING] = { .type = NLA_U8 }, }; /** @@ -278,6 +279,10 @@ static int batadv_netlink_mesh_put(struct sk_buff *msg, bat_priv->isolation_mark_mask)) goto nla_put_failure; + if (nla_put_u8(msg, BATADV_ATTR_BONDING, + !!atomic_read(&bat_priv->bonding))) + goto nla_put_failure; + batadv_hardif_put(primary_if); genlmsg_end(msg, hdr); @@ -385,6 +390,12 @@ static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info) bat_priv->isolation_mark_mask = nla_get_u32(attr); } + if (info->attrs[BATADV_ATTR_BONDING]) { + attr = info->attrs[BATADV_ATTR_BONDING]; + + atomic_set(&bat_priv->bonding, !!nla_get_u8(attr)); + } + batadv_netlink_notify_mesh(bat_priv); return 0; -- 2.19.2 From sven at narfation.org Fri Dec 7 14:58:35 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 14:58:35 +0100 Subject: [B.A.T.M.A.N.] [RFC v3 08/19] batman-adv: Add bridge_loop_avoidance mesh genl configuration In-Reply-To: <20181207135846.6152-1-sven@narfation.org> References: <20181207135846.6152-1-sven@narfation.org> Message-ID: <20181207135846.6152-9-sven@narfation.org> The mesh interface can try to detect loops in the same mesh caused by (indirectly) bridged mesh/soft-interfaces of different nodes. Some of the loops can also be resolved without breaking the mesh. The BATADV_CMD_SET_MESH/BATADV_CMD_GET_MESH commands allow to set/get the configuration of this feature using the BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE attribute. Setting the u8 to zero will disable this feature and setting it to something else is enabling this feature. Signed-off-by: Sven Eckelmann --- Cc: Simon Wunderlich --- include/uapi/linux/batman_adv.h | 7 +++++++ net/batman-adv/netlink.c | 17 +++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h index d209c468..711379ef 100644 --- a/include/uapi/linux/batman_adv.h +++ b/include/uapi/linux/batman_adv.h @@ -380,6 +380,13 @@ enum batadv_nl_attrs { */ BATADV_ATTR_BONDING, + /** + * @BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE: whether the bridge loop avoidance + * feature is enabled. This feature detects and avoids loops between + * the mesh and devices bridged with the soft interface + */ + BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE, + /* add attributes above here, update the policy in netlink.c */ /** diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index a836a8f1..95181808 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -144,6 +144,7 @@ static const struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = { [BATADV_ATTR_ISOLATION_MARK] = { .type = NLA_U32 }, [BATADV_ATTR_ISOLATION_MASK] = { .type = NLA_U32 }, [BATADV_ATTR_BONDING] = { .type = NLA_U8 }, + [BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE] = { .type = NLA_U8 }, }; /** @@ -283,6 +284,12 @@ static int batadv_netlink_mesh_put(struct sk_buff *msg, !!atomic_read(&bat_priv->bonding))) goto nla_put_failure; +#ifdef CONFIG_BATMAN_ADV_BLA + if (nla_put_u8(msg, BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE, + !!atomic_read(&bat_priv->bridge_loop_avoidance))) + goto nla_put_failure; +#endif /* CONFIG_BATMAN_ADV_BLA */ + batadv_hardif_put(primary_if); genlmsg_end(msg, hdr); @@ -396,6 +403,16 @@ static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info) atomic_set(&bat_priv->bonding, !!nla_get_u8(attr)); } +#ifdef CONFIG_BATMAN_ADV_BLA + if (info->attrs[BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE]) { + attr = info->attrs[BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE]; + + atomic_set(&bat_priv->bridge_loop_avoidance, + !!nla_get_u8(attr)); + batadv_bla_status_update(bat_priv->soft_iface); + } +#endif /* CONFIG_BATMAN_ADV_BLA */ + batadv_netlink_notify_mesh(bat_priv); return 0; -- 2.19.2 From sven at narfation.org Fri Dec 7 14:58:36 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 14:58:36 +0100 Subject: [B.A.T.M.A.N.] [RFC v3 09/19] batman-adv: Add distributed_arp_table mesh genl configuration In-Reply-To: <20181207135846.6152-1-sven@narfation.org> References: <20181207135846.6152-1-sven@narfation.org> Message-ID: <20181207135846.6152-10-sven@narfation.org> The mesh interface can use a distributed hash table to answer ARP requests without flooding the request through the whole mesh. The BATADV_CMD_SET_MESH/BATADV_CMD_GET_MESH commands allow to set/get the configuration of this feature using the BATADV_ATTR_DISTRIBUTED_ARP_TABLE attribute. Setting the u8 to zero will disable this feature and setting it to something else is enabling this feature. Signed-off-by: Sven Eckelmann --- Cc: Antonio Quartulli --- include/uapi/linux/batman_adv.h | 8 ++++++++ net/batman-adv/netlink.c | 17 +++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h index 711379ef..618c727c 100644 --- a/include/uapi/linux/batman_adv.h +++ b/include/uapi/linux/batman_adv.h @@ -387,6 +387,14 @@ enum batadv_nl_attrs { */ BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE, + /** + * @BATADV_ATTR_DISTRIBUTED_ARP_TABLE: whether the distributed arp table + * feature is enabled. This feature uses a distributed hash table to + * answer ARP requests without flooding the request through the whole + * mesh. + */ + BATADV_ATTR_DISTRIBUTED_ARP_TABLE, + /* add attributes above here, update the policy in netlink.c */ /** diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index 95181808..d93039b2 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -145,6 +145,7 @@ static const struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = { [BATADV_ATTR_ISOLATION_MASK] = { .type = NLA_U32 }, [BATADV_ATTR_BONDING] = { .type = NLA_U8 }, [BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE] = { .type = NLA_U8 }, + [BATADV_ATTR_DISTRIBUTED_ARP_TABLE] = { .type = NLA_U8 }, }; /** @@ -290,6 +291,12 @@ static int batadv_netlink_mesh_put(struct sk_buff *msg, goto nla_put_failure; #endif /* CONFIG_BATMAN_ADV_BLA */ +#ifdef CONFIG_BATMAN_ADV_DAT + if (nla_put_u8(msg, BATADV_ATTR_DISTRIBUTED_ARP_TABLE, + !!atomic_read(&bat_priv->distributed_arp_table))) + goto nla_put_failure; +#endif /* CONFIG_BATMAN_ADV_DAT */ + batadv_hardif_put(primary_if); genlmsg_end(msg, hdr); @@ -413,6 +420,16 @@ static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info) } #endif /* CONFIG_BATMAN_ADV_BLA */ +#ifdef CONFIG_BATMAN_ADV_DAT + if (info->attrs[BATADV_ATTR_DISTRIBUTED_ARP_TABLE]) { + attr = info->attrs[BATADV_ATTR_DISTRIBUTED_ARP_TABLE]; + + atomic_set(&bat_priv->distributed_arp_table, + !!nla_get_u8(attr)); + batadv_dat_status_update(bat_priv->soft_iface); + } +#endif /* CONFIG_BATMAN_ADV_DAT */ + batadv_netlink_notify_mesh(bat_priv); return 0; -- 2.19.2 From sven at narfation.org Fri Dec 7 14:58:37 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 14:58:37 +0100 Subject: [B.A.T.M.A.N.] [RFC v3 10/19] batman-adv: Add fragmentation mesh genl configuration In-Reply-To: <20181207135846.6152-1-sven@narfation.org> References: <20181207135846.6152-1-sven@narfation.org> Message-ID: <20181207135846.6152-11-sven@narfation.org> The mesh interface can fragment unicast packets when the packet size exceeds the outgoing slave/hard-interface MTU. The BATADV_CMD_SET_MESH/BATADV_CMD_GET_MESH commands allow to set/get the configuration of this feature using the BATADV_ATTR_FRAGMENTATION attribute. Setting the u8 to zero will disable this feature and setting it to something else is enabling this feature. Signed-off-by: Sven Eckelmann --- Cc: Andreas Langer Cc: Martin Hundeboll Cc: Marek Lindner --- include/uapi/linux/batman_adv.h | 7 +++++++ net/batman-adv/netlink.c | 12 ++++++++++++ 2 files changed, 19 insertions(+) diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h index 618c727c..5c58d3b6 100644 --- a/include/uapi/linux/batman_adv.h +++ b/include/uapi/linux/batman_adv.h @@ -395,6 +395,13 @@ enum batadv_nl_attrs { */ BATADV_ATTR_DISTRIBUTED_ARP_TABLE, + /** + * @BATADV_ATTR_FRAGMENTATION: whether the data traffic going through + * the mesh will be fragmented or silently discarded if the packet size + * exceeds the outgoing interface MTU. + */ + BATADV_ATTR_FRAGMENTATION, + /* add attributes above here, update the policy in netlink.c */ /** diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index d93039b2..d7d5f196 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -146,6 +146,7 @@ static const struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = { [BATADV_ATTR_BONDING] = { .type = NLA_U8 }, [BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE] = { .type = NLA_U8 }, [BATADV_ATTR_DISTRIBUTED_ARP_TABLE] = { .type = NLA_U8 }, + [BATADV_ATTR_FRAGMENTATION] = { .type = NLA_U8 }, }; /** @@ -297,6 +298,10 @@ static int batadv_netlink_mesh_put(struct sk_buff *msg, goto nla_put_failure; #endif /* CONFIG_BATMAN_ADV_DAT */ + if (nla_put_u8(msg, BATADV_ATTR_FRAGMENTATION, + !!atomic_read(&bat_priv->fragmentation))) + goto nla_put_failure; + batadv_hardif_put(primary_if); genlmsg_end(msg, hdr); @@ -430,6 +435,13 @@ static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info) } #endif /* CONFIG_BATMAN_ADV_DAT */ + if (info->attrs[BATADV_ATTR_FRAGMENTATION]) { + attr = info->attrs[BATADV_ATTR_FRAGMENTATION]; + + atomic_set(&bat_priv->fragmentation, !!nla_get_u8(attr)); + batadv_update_min_mtu(bat_priv->soft_iface); + } + batadv_netlink_notify_mesh(bat_priv); return 0; -- 2.19.2 From sven at narfation.org Fri Dec 7 14:58:38 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 14:58:38 +0100 Subject: [B.A.T.M.A.N.] [RFC v3 11/19] batman-adv: Add gateway mesh genl configuration In-Reply-To: <20181207135846.6152-1-sven@narfation.org> References: <20181207135846.6152-1-sven@narfation.org> Message-ID: <20181207135846.6152-12-sven@narfation.org> The mesh/soft-interface can optimize the handling of DHCP packets. Instead of flooding them through the whole mesh, it can be forwarded as unicast to a specific gateway server. The originator which injects the packets in the mesh has to select (based on sel_class thresholds) a responsible gateway server. This is done by switching this originator to the gw_mode client. The servers announce their forwarding bandwidth (download/upload) when the gw_mode server was selected. The BATADV_CMD_SET_MESH/BATADV_CMD_GET_MESH commands allow to set/get the configuration of this feature using the attributes: * u8 BATADV_ATTR_GW_MODE (0 == off, 1 == client, 2 == server) * u32 BATADV_ATTR_GW_BANDWIDTH_DOWN (in 100 kbit/s steps) * u32 BATADV_ATTR_GW_BANDWIDTH_UP (in 100 kbit/s steps) * u32 BATADV_ATTR_GW_SEL_CLASS Signed-off-by: Sven Eckelmann --- Cc: Marek Lindner Cc: Antonio Quartulli --- include/uapi/linux/batman_adv.h | 40 ++++++++++++++ net/batman-adv/gateway_client.c | 1 - net/batman-adv/gateway_common.c | 1 + net/batman-adv/gateway_common.h | 6 --- net/batman-adv/netlink.c | 92 +++++++++++++++++++++++++++++++++ net/batman-adv/soft-interface.c | 2 +- net/batman-adv/sysfs.c | 1 + 7 files changed, 135 insertions(+), 8 deletions(-) diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h index 5c58d3b6..0d45e807 100644 --- a/include/uapi/linux/batman_adv.h +++ b/include/uapi/linux/batman_adv.h @@ -139,6 +139,20 @@ enum batadv_mcast_flags_priv { BATADV_MCAST_FLAGS_QUERIER_IPV6_SHADOWING = (1 << 4), }; +/** + * enum batadv_gw_modes - gateway mode of node + */ +enum batadv_gw_modes { + /** @BATADV_GW_MODE_OFF: gw mode disabled */ + BATADV_GW_MODE_OFF, + + /** @BATADV_GW_MODE_CLIENT: send DHCP requests to gw servers */ + BATADV_GW_MODE_CLIENT, + + /** @BATADV_GW_MODE_SERVER: announce itself as gatway server */ + BATADV_GW_MODE_SERVER, +}; + /** * enum batadv_nl_attrs - batman-adv netlink attributes */ @@ -402,6 +416,32 @@ enum batadv_nl_attrs { */ BATADV_ATTR_FRAGMENTATION, + /** + * @BATADV_ATTR_GW_BANDWIDTH_DOWN: defines the download bandwidth which + * is propagated by this node if %BATADV_ATTR_GW_BANDWIDTH_MODE was set + * to 'server'. + */ + BATADV_ATTR_GW_BANDWIDTH_DOWN, + + /** + * @BATADV_ATTR_GW_BANDWIDTH_UP: defines the upload bandwidth which + * is propagated by this node if %BATADV_ATTR_GW_BANDWIDTH_MODE was set + * to 'server'. + */ + BATADV_ATTR_GW_BANDWIDTH_UP, + + /** + * @BATADV_ATTR_GW_MODE: defines the state of the gateway features. + * Possible values are specified in enum batadv_gw_modes + */ + BATADV_ATTR_GW_MODE, + + /** + * @BATADV_ATTR_GW_SEL_CLASS: defines the selection criteria this node + * will use to choose a gateway if gw_mode was set to 'client'. + */ + BATADV_ATTR_GW_SEL_CLASS, + /* add attributes above here, update the policy in netlink.c */ /** diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 9d8e5eda..2373903c 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -47,7 +47,6 @@ #include #include -#include "gateway_common.h" #include "hard-interface.h" #include "log.h" #include "netlink.h" diff --git a/net/batman-adv/gateway_common.c b/net/batman-adv/gateway_common.c index 936c107f..08b62271 100644 --- a/net/batman-adv/gateway_common.c +++ b/net/batman-adv/gateway_common.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "gateway_client.h" #include "log.h" diff --git a/net/batman-adv/gateway_common.h b/net/batman-adv/gateway_common.h index 80afb279..cd1c5f54 100644 --- a/net/batman-adv/gateway_common.h +++ b/net/batman-adv/gateway_common.h @@ -25,12 +25,6 @@ struct net_device; -enum batadv_gw_modes { - BATADV_GW_MODE_OFF, - BATADV_GW_MODE_CLIENT, - BATADV_GW_MODE_SERVER, -}; - /** * enum batadv_bandwidth_units - bandwidth unit types */ diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index d7d5f196..e79a61a6 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -51,6 +51,7 @@ #include "bridge_loop_avoidance.h" #include "distributed-arp-table.h" #include "gateway_client.h" +#include "gateway_common.h" #include "hard-interface.h" #include "multicast.h" #include "originator.h" @@ -147,6 +148,10 @@ static const struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = { [BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE] = { .type = NLA_U8 }, [BATADV_ATTR_DISTRIBUTED_ARP_TABLE] = { .type = NLA_U8 }, [BATADV_ATTR_FRAGMENTATION] = { .type = NLA_U8 }, + [BATADV_ATTR_GW_BANDWIDTH_DOWN] = { .type = NLA_U32 }, + [BATADV_ATTR_GW_BANDWIDTH_UP] = { .type = NLA_U32 }, + [BATADV_ATTR_GW_MODE] = { .type = NLA_U8 }, + [BATADV_ATTR_GW_SEL_CLASS] = { .type = NLA_U32 }, }; /** @@ -302,6 +307,28 @@ static int batadv_netlink_mesh_put(struct sk_buff *msg, !!atomic_read(&bat_priv->fragmentation))) goto nla_put_failure; + if (nla_put_u32(msg, BATADV_ATTR_GW_BANDWIDTH_DOWN, + atomic_read(&bat_priv->gw.bandwidth_down))) + goto nla_put_failure; + + if (nla_put_u32(msg, BATADV_ATTR_GW_BANDWIDTH_UP, + atomic_read(&bat_priv->gw.bandwidth_up))) + goto nla_put_failure; + + if (nla_put_u8(msg, BATADV_ATTR_GW_MODE, + atomic_read(&bat_priv->gw.mode))) + goto nla_put_failure; + + if (bat_priv->algo_ops->gw.get_best_gw_node && + bat_priv->algo_ops->gw.is_eligible) { + /* GW selection class is not available if the routing algorithm + * in use does not implement the GW API + */ + if (nla_put_u32(msg, BATADV_ATTR_GW_SEL_CLASS, + atomic_read(&bat_priv->gw.sel_class))) + goto nla_put_failure; + } + batadv_hardif_put(primary_if); genlmsg_end(msg, hdr); @@ -442,6 +469,71 @@ static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info) batadv_update_min_mtu(bat_priv->soft_iface); } + if (info->attrs[BATADV_ATTR_GW_BANDWIDTH_DOWN]) { + attr = info->attrs[BATADV_ATTR_GW_BANDWIDTH_DOWN]; + + atomic_set(&bat_priv->gw.bandwidth_down, nla_get_u32(attr)); + batadv_gw_tvlv_container_update(bat_priv); + } + + if (info->attrs[BATADV_ATTR_GW_BANDWIDTH_UP]) { + attr = info->attrs[BATADV_ATTR_GW_BANDWIDTH_UP]; + + atomic_set(&bat_priv->gw.bandwidth_up, nla_get_u32(attr)); + batadv_gw_tvlv_container_update(bat_priv); + } + + if (info->attrs[BATADV_ATTR_GW_MODE]) { + u8 gw_mode; + + attr = info->attrs[BATADV_ATTR_GW_MODE]; + gw_mode = nla_get_u8(attr); + + if (gw_mode <= BATADV_GW_MODE_SERVER) { + /* Invoking batadv_gw_reselect() is not enough to really + * de-select the current GW. It will only instruct the + * gateway client code to perform a re-election the next + * time that this is needed. + * + * When gw client mode is being switched off the current + * GW must be de-selected explicitly otherwise no GW_ADD + * uevent is thrown on client mode re-activation. This + * is operation is performed in + * batadv_gw_check_client_stop(). + */ + batadv_gw_reselect(bat_priv); + + /* always call batadv_gw_check_client_stop() before + * changing the gateway state + */ + batadv_gw_check_client_stop(bat_priv); + atomic_set(&bat_priv->gw.mode, gw_mode); + batadv_gw_tvlv_container_update(bat_priv); + } + } + + if (info->attrs[BATADV_ATTR_GW_SEL_CLASS] && + bat_priv->algo_ops->gw.get_best_gw_node && + bat_priv->algo_ops->gw.is_eligible) { + /* setting the GW selection class is allowed only if the routing + * algorithm in use implements the GW API + */ + + u32 sel_class_max = 0xffffffffu; + u32 sel_class; + + attr = info->attrs[BATADV_ATTR_GW_SEL_CLASS]; + sel_class = nla_get_u32(attr); + + if (!bat_priv->algo_ops->gw.store_sel_class) + sel_class_max = BATADV_TQ_MAX_VALUE; + + if (sel_class >= 1 && sel_class <= sel_class_max) { + atomic_set(&bat_priv->gw.sel_class, sel_class); + batadv_gw_reselect(bat_priv); + } + } + batadv_netlink_notify_mesh(bat_priv); return 0; diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 5db5a0a4..d158ac70 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -50,13 +50,13 @@ #include #include #include +#include #include "bat_algo.h" #include "bridge_loop_avoidance.h" #include "debugfs.h" #include "distributed-arp-table.h" #include "gateway_client.h" -#include "gateway_common.h" #include "hard-interface.h" #include "multicast.h" #include "network-coding.h" diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c index 09427fc6..344e5787 100644 --- a/net/batman-adv/sysfs.c +++ b/net/batman-adv/sysfs.c @@ -40,6 +40,7 @@ #include #include #include +#include #include "bridge_loop_avoidance.h" #include "distributed-arp-table.h" -- 2.19.2 From sven at narfation.org Fri Dec 7 14:58:39 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 14:58:39 +0100 Subject: [B.A.T.M.A.N.] [RFC v3 12/19] batman-adv: Add hop_penalty mesh genl configuration In-Reply-To: <20181207135846.6152-1-sven@narfation.org> References: <20181207135846.6152-1-sven@narfation.org> Message-ID: <20181207135846.6152-13-sven@narfation.org> The TQ (B.A.T.M.A.N. IV) and throughput values (B.A.T.M.A.N. V) are reduced when they are forwarded. One of the reductions is the penalty for traversing an additional hop. This hop_penalty (0-255) defines the percentage of reduction (0-100%). The BATADV_CMD_SET_MESH/BATADV_CMD_GET_MESH commands allow to set/get the configuration of this feature using the u8 BATADV_ATTR_HOP_PENALTY attribute. Signed-off-by: Sven Eckelmann --- Cc: Linus Lüssing Cc: Marek Lindner Cc: Antonio Quartulli Cc: Simon Wunderlich --- include/uapi/linux/batman_adv.h | 6 ++++++ net/batman-adv/netlink.c | 11 +++++++++++ 2 files changed, 17 insertions(+) diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h index 0d45e807..7cc69802 100644 --- a/include/uapi/linux/batman_adv.h +++ b/include/uapi/linux/batman_adv.h @@ -442,6 +442,12 @@ enum batadv_nl_attrs { */ BATADV_ATTR_GW_SEL_CLASS, + /** + * @BATADV_ATTR_HOP_PENALTY: defines the penalty which will be applied + * to an originator message's tq-field on every hop. + */ + BATADV_ATTR_HOP_PENALTY, + /* add attributes above here, update the policy in netlink.c */ /** diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index e79a61a6..bbea6ac0 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -152,6 +152,7 @@ static const struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = { [BATADV_ATTR_GW_BANDWIDTH_UP] = { .type = NLA_U32 }, [BATADV_ATTR_GW_MODE] = { .type = NLA_U8 }, [BATADV_ATTR_GW_SEL_CLASS] = { .type = NLA_U32 }, + [BATADV_ATTR_HOP_PENALTY] = { .type = NLA_U8 }, }; /** @@ -329,6 +330,10 @@ static int batadv_netlink_mesh_put(struct sk_buff *msg, goto nla_put_failure; } + if (nla_put_u8(msg, BATADV_ATTR_HOP_PENALTY, + atomic_read(&bat_priv->hop_penalty))) + goto nla_put_failure; + batadv_hardif_put(primary_if); genlmsg_end(msg, hdr); @@ -534,6 +539,12 @@ static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info) } } + if (info->attrs[BATADV_ATTR_HOP_PENALTY]) { + attr = info->attrs[BATADV_ATTR_HOP_PENALTY]; + + atomic_set(&bat_priv->hop_penalty, nla_get_u8(attr)); + } + batadv_netlink_notify_mesh(bat_priv); return 0; -- 2.19.2 From sven at narfation.org Fri Dec 7 14:58:40 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 14:58:40 +0100 Subject: [B.A.T.M.A.N.] [RFC v3 13/19] batman-adv: Add log_level mesh genl configuration In-Reply-To: <20181207135846.6152-1-sven@narfation.org> References: <20181207135846.6152-1-sven@narfation.org> Message-ID: <20181207135846.6152-14-sven@narfation.org> In contrast to other modules, batman-adv allows to set the debug message verbosity per mesh/soft-interface and not per module (via modparam). The BATADV_CMD_SET_MESH/BATADV_CMD_GET_MESH commands allow to set/get the configuration of this feature using the u32 (bitmask) BATADV_ATTR_LOG_LEVEL attribute. Signed-off-by: Sven Eckelmann --- Cc: Marek Lindner --- include/uapi/linux/batman_adv.h | 6 ++++++ net/batman-adv/netlink.c | 17 +++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h index 7cc69802..efc06449 100644 --- a/include/uapi/linux/batman_adv.h +++ b/include/uapi/linux/batman_adv.h @@ -448,6 +448,12 @@ enum batadv_nl_attrs { */ BATADV_ATTR_HOP_PENALTY, + /** + * @BATADV_ATTR_LOG_LEVEL: bitmask with to define which debug messages + * should be send to the debug log/trace ring buffer + */ + BATADV_ATTR_LOG_LEVEL, + /* add attributes above here, update the policy in netlink.c */ /** diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index bbea6ac0..8e3a1b6e 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -53,6 +53,7 @@ #include "gateway_client.h" #include "gateway_common.h" #include "hard-interface.h" +#include "log.h" #include "multicast.h" #include "originator.h" #include "soft-interface.h" @@ -153,6 +154,7 @@ static const struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = { [BATADV_ATTR_GW_MODE] = { .type = NLA_U8 }, [BATADV_ATTR_GW_SEL_CLASS] = { .type = NLA_U32 }, [BATADV_ATTR_HOP_PENALTY] = { .type = NLA_U8 }, + [BATADV_ATTR_LOG_LEVEL] = { .type = NLA_U32 }, }; /** @@ -334,6 +336,12 @@ static int batadv_netlink_mesh_put(struct sk_buff *msg, atomic_read(&bat_priv->hop_penalty))) goto nla_put_failure; +#ifdef CONFIG_BATMAN_ADV_DEBUG + if (nla_put_u32(msg, BATADV_ATTR_LOG_LEVEL, + atomic_read(&bat_priv->log_level))) + goto nla_put_failure; +#endif /* CONFIG_BATMAN_ADV_DEBUG */ + batadv_hardif_put(primary_if); genlmsg_end(msg, hdr); @@ -545,6 +553,15 @@ static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info) atomic_set(&bat_priv->hop_penalty, nla_get_u8(attr)); } +#ifdef CONFIG_BATMAN_ADV_DEBUG + if (info->attrs[BATADV_ATTR_LOG_LEVEL]) { + attr = info->attrs[BATADV_ATTR_LOG_LEVEL]; + + atomic_set(&bat_priv->log_level, + nla_get_u32(attr) & BATADV_DBG_ALL); + } +#endif /* CONFIG_BATMAN_ADV_DEBUG */ + batadv_netlink_notify_mesh(bat_priv); return 0; -- 2.19.2 From sven at narfation.org Fri Dec 7 14:58:41 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 14:58:41 +0100 Subject: [B.A.T.M.A.N.] [RFC v3 14/19] batman-adv: Add multicast_mode mesh genl configuration In-Reply-To: <20181207135846.6152-1-sven@narfation.org> References: <20181207135846.6152-1-sven@narfation.org> Message-ID: <20181207135846.6152-15-sven@narfation.org> The mesh interface can optimize the flooding of multicast packets based on the content of the global translation tables. The BATADV_CMD_SET_MESH/BATADV_CMD_GET_MESH commands allow to set/get the configuration of this feature using the BATADV_ATTR_MULTICAST_MODE attribute. Setting the u8 to zero will disable this feature and setting it to something else is enabling this feature. Signed-off-by: Sven Eckelmann --- Cc: Linus Lüssing --- include/uapi/linux/batman_adv.h | 8 ++++++++ net/batman-adv/netlink.c | 15 +++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h index efc06449..514acc06 100644 --- a/include/uapi/linux/batman_adv.h +++ b/include/uapi/linux/batman_adv.h @@ -454,6 +454,14 @@ enum batadv_nl_attrs { */ BATADV_ATTR_LOG_LEVEL, + /** + * @BATADV_ATTR_MULTICAST_MODE: whether multicast optimizations are + * enabled or disabled. If set to zero then all nodes in the mesh are + * going to use classic flooding for any multicast packet with no + * optimizations. + */ + BATADV_ATTR_MULTICAST_MODE, + /* add attributes above here, update the policy in netlink.c */ /** diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index 8e3a1b6e..32762003 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -155,6 +155,7 @@ static const struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = { [BATADV_ATTR_GW_SEL_CLASS] = { .type = NLA_U32 }, [BATADV_ATTR_HOP_PENALTY] = { .type = NLA_U8 }, [BATADV_ATTR_LOG_LEVEL] = { .type = NLA_U32 }, + [BATADV_ATTR_MULTICAST_MODE] = { .type = NLA_U8 }, }; /** @@ -342,6 +343,12 @@ static int batadv_netlink_mesh_put(struct sk_buff *msg, goto nla_put_failure; #endif /* CONFIG_BATMAN_ADV_DEBUG */ +#ifdef CONFIG_BATMAN_ADV_MCAST + if (nla_put_u8(msg, BATADV_ATTR_MULTICAST_MODE, + !!atomic_read(&bat_priv->multicast_mode))) + goto nla_put_failure; +#endif /* CONFIG_BATMAN_ADV_MCAST */ + batadv_hardif_put(primary_if); genlmsg_end(msg, hdr); @@ -562,6 +569,14 @@ static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info) } #endif /* CONFIG_BATMAN_ADV_DEBUG */ +#ifdef CONFIG_BATMAN_ADV_MCAST + if (info->attrs[BATADV_ATTR_MULTICAST_MODE]) { + attr = info->attrs[BATADV_ATTR_MULTICAST_MODE]; + + atomic_set(&bat_priv->multicast_mode, !!nla_get_u8(attr)); + } +#endif /* CONFIG_BATMAN_ADV_MCAST */ + batadv_netlink_notify_mesh(bat_priv); return 0; -- 2.19.2 From sven at narfation.org Fri Dec 7 14:58:42 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 14:58:42 +0100 Subject: [B.A.T.M.A.N.] [RFC v3 15/19] batman-adv: Add network_coding mesh genl configuration In-Reply-To: <20181207135846.6152-1-sven@narfation.org> References: <20181207135846.6152-1-sven@narfation.org> Message-ID: <20181207135846.6152-16-sven@narfation.org> The mesh interface can use (in an homogeneous mesh) network coding, a mechanism that aims to increase the overall network throughput by fusing multiple packets in one transmission. The BATADV_CMD_SET_MESH/BATADV_CMD_GET_MESH commands allow to set/get the configuration of this feature using the BATADV_ATTR_NETWORK_CODING attribute. Setting the u8 to zero will disable this feature and setting it to something else is enabling this feature. Signed-off-by: Sven Eckelmann --- Cc: Martin Hundeboll Cc: Marek Lindner --- include/uapi/linux/batman_adv.h | 7 +++++++ net/batman-adv/netlink.c | 17 +++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h index 514acc06..7e8a086f 100644 --- a/include/uapi/linux/batman_adv.h +++ b/include/uapi/linux/batman_adv.h @@ -462,6 +462,13 @@ enum batadv_nl_attrs { */ BATADV_ATTR_MULTICAST_MODE, + /** + * @BATADV_ATTR_NETWORK_CODING: whether Network Coding (using some magic + * to send fewer wifi packets but still the same content) is enabled or + * not. + */ + BATADV_ATTR_NETWORK_CODING, + /* add attributes above here, update the policy in netlink.c */ /** diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index 32762003..bdfea982 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -55,6 +55,7 @@ #include "hard-interface.h" #include "log.h" #include "multicast.h" +#include "network-coding.h" #include "originator.h" #include "soft-interface.h" #include "tp_meter.h" @@ -156,6 +157,7 @@ static const struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = { [BATADV_ATTR_HOP_PENALTY] = { .type = NLA_U8 }, [BATADV_ATTR_LOG_LEVEL] = { .type = NLA_U32 }, [BATADV_ATTR_MULTICAST_MODE] = { .type = NLA_U8 }, + [BATADV_ATTR_NETWORK_CODING] = { .type = NLA_U8 }, }; /** @@ -349,6 +351,12 @@ static int batadv_netlink_mesh_put(struct sk_buff *msg, goto nla_put_failure; #endif /* CONFIG_BATMAN_ADV_MCAST */ +#ifdef CONFIG_BATMAN_ADV_NC + if (nla_put_u8(msg, BATADV_ATTR_NETWORK_CODING, + !!atomic_read(&bat_priv->network_coding))) + goto nla_put_failure; +#endif /* CONFIG_BATMAN_ADV_NC */ + batadv_hardif_put(primary_if); genlmsg_end(msg, hdr); @@ -577,6 +585,15 @@ static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info) } #endif /* CONFIG_BATMAN_ADV_MCAST */ +#ifdef CONFIG_BATMAN_ADV_NC + if (info->attrs[BATADV_ATTR_NETWORK_CODING]) { + attr = info->attrs[BATADV_ATTR_NETWORK_CODING]; + + atomic_set(&bat_priv->network_coding, !!nla_get_u8(attr)); + batadv_nc_status_update(bat_priv->soft_iface); + } +#endif /* CONFIG_BATMAN_ADV_NC */ + batadv_netlink_notify_mesh(bat_priv); return 0; -- 2.19.2 From sven at narfation.org Fri Dec 7 14:58:43 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 14:58:43 +0100 Subject: [B.A.T.M.A.N.] [RFC v3 16/19] batman-adv: Add orig_interval mesh genl configuration In-Reply-To: <20181207135846.6152-1-sven@narfation.org> References: <20181207135846.6152-1-sven@narfation.org> Message-ID: <20181207135846.6152-17-sven@narfation.org> The OGM packets are transmitted every orig_interval milliseconds. This value can be changed using the configuration interface. The BATADV_CMD_SET_MESH/BATADV_CMD_GET_MESH commands allow to set/get the configuration of this feature using the u32 BATADV_ATTR_ORIG_INTERVAL attribute. Signed-off-by: Sven Eckelmann --- Cc: Marek Lindner --- include/uapi/linux/batman_adv.h | 6 ++++++ net/batman-adv/netlink.c | 17 +++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h index 7e8a086f..b8cb26d2 100644 --- a/include/uapi/linux/batman_adv.h +++ b/include/uapi/linux/batman_adv.h @@ -469,6 +469,12 @@ enum batadv_nl_attrs { */ BATADV_ATTR_NETWORK_CODING, + /** + * @BATADV_ATTR_ORIG_INTERVAL: defines the interval in milliseconds in + * which batman sends its protocol messages. + */ + BATADV_ATTR_ORIG_INTERVAL, + /* add attributes above here, update the policy in netlink.c */ /** diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index bdfea982..831678fd 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -158,6 +158,7 @@ static const struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = { [BATADV_ATTR_LOG_LEVEL] = { .type = NLA_U32 }, [BATADV_ATTR_MULTICAST_MODE] = { .type = NLA_U8 }, [BATADV_ATTR_NETWORK_CODING] = { .type = NLA_U8 }, + [BATADV_ATTR_ORIG_INTERVAL] = { .type = NLA_U32 }, }; /** @@ -357,6 +358,10 @@ static int batadv_netlink_mesh_put(struct sk_buff *msg, goto nla_put_failure; #endif /* CONFIG_BATMAN_ADV_NC */ + if (nla_put_u32(msg, BATADV_ATTR_ORIG_INTERVAL, + atomic_read(&bat_priv->orig_interval))) + goto nla_put_failure; + batadv_hardif_put(primary_if); genlmsg_end(msg, hdr); @@ -594,6 +599,18 @@ static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info) } #endif /* CONFIG_BATMAN_ADV_NC */ + if (info->attrs[BATADV_ATTR_ORIG_INTERVAL]) { + u32 orig_interval; + + attr = info->attrs[BATADV_ATTR_ORIG_INTERVAL]; + orig_interval = nla_get_u32(attr); + + orig_interval = min_t(u32, orig_interval, INT_MAX); + orig_interval = max_t(u32, orig_interval, 2 * BATADV_JITTER); + + atomic_set(&bat_priv->orig_interval, orig_interval); + } + batadv_netlink_notify_mesh(bat_priv); return 0; -- 2.19.2 From sven at narfation.org Fri Dec 7 14:58:44 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 14:58:44 +0100 Subject: [B.A.T.M.A.N.] [RFC v3 17/19] batman-adv: Add elp_interval hardif genl configuration In-Reply-To: <20181207135846.6152-1-sven@narfation.org> References: <20181207135846.6152-1-sven@narfation.org> Message-ID: <20181207135846.6152-18-sven@narfation.org> The ELP packets are transmitted every elp_interval milliseconds on an slave/hard-interface. This value can be changed using the configuration interface. The BATADV_CMD_SET_HARDIF/BATADV_CMD_GET_HARDIF commands allow to set/get the configuration of this feature using the u32 BATADV_ATTR_ELP_INTERVAL attribute. Signed-off-by: Sven Eckelmann --- Cc: Linus Lüssing --- include/uapi/linux/batman_adv.h | 6 ++++++ net/batman-adv/netlink.c | 17 +++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h index b8cb26d2..716471df 100644 --- a/include/uapi/linux/batman_adv.h +++ b/include/uapi/linux/batman_adv.h @@ -475,6 +475,12 @@ enum batadv_nl_attrs { */ BATADV_ATTR_ORIG_INTERVAL, + /** + * @BATADV_ATTR_ELP_INTERVAL: defines the interval in milliseconds in + * which batman emits probing packets for neighbor sensing (ELP). + */ + BATADV_ATTR_ELP_INTERVAL, + /* add attributes above here, update the policy in netlink.c */ /** diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index 831678fd..5144c350 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -159,6 +159,7 @@ static const struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = { [BATADV_ATTR_MULTICAST_MODE] = { .type = NLA_U8 }, [BATADV_ATTR_NETWORK_CODING] = { .type = NLA_U8 }, [BATADV_ATTR_ORIG_INTERVAL] = { .type = NLA_U32 }, + [BATADV_ATTR_ELP_INTERVAL] = { .type = NLA_U32 }, }; /** @@ -823,6 +824,12 @@ static int batadv_netlink_hardif_put(struct sk_buff *msg, goto nla_put_failure; } +#ifdef CONFIG_BATMAN_ADV_BATMAN_V + if (nla_put_u32(msg, BATADV_ATTR_ELP_INTERVAL, + atomic_read(&hard_iface->bat_v.elp_interval))) + goto nla_put_failure; +#endif /* CONFIG_BATMAN_ADV_BATMAN_V */ + genlmsg_end(msg, hdr); return 0; @@ -908,6 +915,16 @@ static int batadv_netlink_set_hardif(struct sk_buff *skb, struct batadv_hard_iface *hard_iface = info->user_ptr[1]; struct batadv_priv *bat_priv = info->user_ptr[0]; +#ifdef CONFIG_BATMAN_ADV_BATMAN_V + struct nlattr *attr; + + if (info->attrs[BATADV_ATTR_ELP_INTERVAL]) { + attr = info->attrs[BATADV_ATTR_ELP_INTERVAL]; + + atomic_set(&hard_iface->bat_v.elp_interval, nla_get_u32(attr)); + } +#endif /* CONFIG_BATMAN_ADV_BATMAN_V */ + batadv_netlink_notify_hardif(bat_priv, hard_iface); return 0; -- 2.19.2 From sven at narfation.org Fri Dec 7 14:58:45 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 14:58:45 +0100 Subject: [B.A.T.M.A.N.] [RFC v3 18/19] batman-adv: Add throughput_override hardif genl configuration In-Reply-To: <20181207135846.6152-1-sven@narfation.org> References: <20181207135846.6152-1-sven@narfation.org> Message-ID: <20181207135846.6152-19-sven@narfation.org> The B.A.T.M.A.N. V implementation tries to estimate the link throughput of an interface to an originator using different automatic methods. It is still possible to overwrite it the link throughput for all reachable originators via this interface. The BATADV_CMD_SET_HARDIF/BATADV_CMD_GET_HARDIF commands allow to set/get the configuration of this feature using the u32 BATADV_ATTR_THROUGHPUT_OVERRIDE attribute. The used unit is in 100 Kbit/s. If the value is set to 0 then batman-adv will try to estimate the throughput by itself. Signed-off-by: Sven Eckelmann --- Cc: Antonio Quartulli --- include/uapi/linux/batman_adv.h | 8 ++++++++ net/batman-adv/netlink.c | 12 ++++++++++++ 2 files changed, 20 insertions(+) diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h index 716471df..b5a245ef 100644 --- a/include/uapi/linux/batman_adv.h +++ b/include/uapi/linux/batman_adv.h @@ -481,6 +481,14 @@ enum batadv_nl_attrs { */ BATADV_ATTR_ELP_INTERVAL, + /** + * @BATADV_ATTR_THROUGHPUT_OVERRIDE: defines the throughput value to be + * used by B.A.T.M.A.N. V when estimating the link throughput using + * this interface. If the value is set to 0 then batman-adv will try to + * estimate the throughput by itself. + */ + BATADV_ATTR_THROUGHPUT_OVERRIDE, + /* add attributes above here, update the policy in netlink.c */ /** diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index 5144c350..4065d871 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -160,6 +160,7 @@ static const struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = { [BATADV_ATTR_NETWORK_CODING] = { .type = NLA_U8 }, [BATADV_ATTR_ORIG_INTERVAL] = { .type = NLA_U32 }, [BATADV_ATTR_ELP_INTERVAL] = { .type = NLA_U32 }, + [BATADV_ATTR_THROUGHPUT_OVERRIDE] = { .type = NLA_U32 }, }; /** @@ -828,6 +829,10 @@ static int batadv_netlink_hardif_put(struct sk_buff *msg, if (nla_put_u32(msg, BATADV_ATTR_ELP_INTERVAL, atomic_read(&hard_iface->bat_v.elp_interval))) goto nla_put_failure; + + if (nla_put_u32(msg, BATADV_ATTR_THROUGHPUT_OVERRIDE, + atomic_read(&hard_iface->bat_v.throughput_override))) + goto nla_put_failure; #endif /* CONFIG_BATMAN_ADV_BATMAN_V */ genlmsg_end(msg, hdr); @@ -923,6 +928,13 @@ static int batadv_netlink_set_hardif(struct sk_buff *skb, atomic_set(&hard_iface->bat_v.elp_interval, nla_get_u32(attr)); } + + if (info->attrs[BATADV_ATTR_THROUGHPUT_OVERRIDE]) { + attr = info->attrs[BATADV_ATTR_THROUGHPUT_OVERRIDE]; + + atomic_set(&hard_iface->bat_v.throughput_override, + nla_get_u32(attr)); + } #endif /* CONFIG_BATMAN_ADV_BATMAN_V */ batadv_netlink_notify_hardif(bat_priv, hard_iface); -- 2.19.2 From sven at narfation.org Fri Dec 7 14:58:46 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 14:58:46 +0100 Subject: [B.A.T.M.A.N.] [RFC v3 19/19] batman-adv: Trigger genl notification on sysfs config change In-Reply-To: <20181207135846.6152-1-sven@narfation.org> References: <20181207135846.6152-1-sven@narfation.org> Message-ID: <20181207135846.6152-20-sven@narfation.org> The generic netlink code is expected to trigger notification messages when configuration might have been changed. But the configuration of batman-adv is most of the time still done using sysfs. So the sysfs interface should also trigger the corresponding netlink messages via the "config" multicast group. Signed-off-by: Sven Eckelmann --- net/batman-adv/netlink.c | 10 +++---- net/batman-adv/netlink.h | 6 ++++ net/batman-adv/sysfs.c | 63 +++++++++++++++++++++++++++++++++------- 3 files changed, 63 insertions(+), 16 deletions(-) diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index 4065d871..37552736 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -383,7 +383,7 @@ static int batadv_netlink_mesh_put(struct sk_buff *msg, * * Return: 0 on success, < 0 on error */ -static int batadv_netlink_notify_mesh(struct batadv_priv *bat_priv) +int batadv_netlink_notify_mesh(struct batadv_priv *bat_priv) { struct sk_buff *msg; int ret; @@ -850,8 +850,8 @@ static int batadv_netlink_hardif_put(struct sk_buff *msg, * * Return: 0 on success, < 0 on error */ -static int batadv_netlink_notify_hardif(struct batadv_priv *bat_priv, - struct batadv_hard_iface *hard_iface) +int batadv_netlink_notify_hardif(struct batadv_priv *bat_priv, + struct batadv_hard_iface *hard_iface) { struct sk_buff *msg; int ret; @@ -1055,8 +1055,8 @@ static int batadv_netlink_vlan_put(struct sk_buff *msg, * * Return: 0 on success, < 0 on error */ -static int batadv_netlink_notify_vlan(struct batadv_priv *bat_priv, - struct batadv_softif_vlan *vlan) +int batadv_netlink_notify_vlan(struct batadv_priv *bat_priv, + struct batadv_softif_vlan *vlan) { struct sk_buff *msg; int ret; diff --git a/net/batman-adv/netlink.h b/net/batman-adv/netlink.h index 571d9a5a..8d17ce0e 100644 --- a/net/batman-adv/netlink.h +++ b/net/batman-adv/netlink.h @@ -34,6 +34,12 @@ int batadv_netlink_tpmeter_notify(struct batadv_priv *bat_priv, const u8 *dst, u8 result, u32 test_time, u64 total_bytes, u32 cookie); +int batadv_netlink_notify_mesh(struct batadv_priv *bat_priv); +int batadv_netlink_notify_hardif(struct batadv_priv *bat_priv, + struct batadv_hard_iface *hard_iface); +int batadv_netlink_notify_vlan(struct batadv_priv *bat_priv, + struct batadv_softif_vlan *vlan); + extern struct genl_family batadv_netlink_family; #endif /* _NET_BATMAN_ADV_NETLINK_H_ */ diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c index 344e5787..7c67fe29 100644 --- a/net/batman-adv/sysfs.c +++ b/net/batman-adv/sysfs.c @@ -48,6 +48,7 @@ #include "gateway_common.h" #include "hard-interface.h" #include "log.h" +#include "netlink.h" #include "network-coding.h" #include "soft-interface.h" @@ -154,9 +155,14 @@ ssize_t batadv_store_##_name(struct kobject *kobj, \ { \ struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \ struct batadv_priv *bat_priv = netdev_priv(net_dev); \ + ssize_t length; \ + \ + length = __batadv_store_bool_attr(buff, count, _post_func, attr,\ + &bat_priv->_name, net_dev); \ \ - return __batadv_store_bool_attr(buff, count, _post_func, attr, \ - &bat_priv->_name, net_dev); \ + batadv_netlink_notify_mesh(bat_priv); \ + \ + return length; \ } #define BATADV_ATTR_SIF_SHOW_BOOL(_name) \ @@ -186,11 +192,16 @@ ssize_t batadv_store_##_name(struct kobject *kobj, \ { \ struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \ struct batadv_priv *bat_priv = netdev_priv(net_dev); \ + ssize_t length; \ \ - return __batadv_store_uint_attr(buff, count, _min, _max, \ - _post_func, attr, \ - &bat_priv->_var, net_dev, \ - NULL); \ + length = __batadv_store_uint_attr(buff, count, _min, _max, \ + _post_func, attr, \ + &bat_priv->_var, net_dev, \ + NULL); \ + \ + batadv_netlink_notify_mesh(bat_priv); \ + \ + return length; \ } #define BATADV_ATTR_SIF_SHOW_UINT(_name, _var) \ @@ -223,6 +234,11 @@ ssize_t batadv_store_vlan_##_name(struct kobject *kobj, \ attr, &vlan->_name, \ bat_priv->soft_iface); \ \ + if (vlan->vid) \ + batadv_netlink_notify_vlan(bat_priv, vlan); \ + else \ + batadv_netlink_notify_mesh(bat_priv); \ + \ batadv_softif_vlan_put(vlan); \ return res; \ } @@ -256,6 +272,7 @@ ssize_t batadv_store_##_name(struct kobject *kobj, \ { \ struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \ struct batadv_hard_iface *hard_iface; \ + struct batadv_priv *bat_priv; \ ssize_t length; \ \ hard_iface = batadv_hardif_get_by_netdev(net_dev); \ @@ -268,6 +285,11 @@ ssize_t batadv_store_##_name(struct kobject *kobj, \ hard_iface->soft_iface, \ net_dev); \ \ + if (hard_iface->soft_iface) { \ + bat_priv = netdev_priv(hard_iface->soft_iface); \ + batadv_netlink_notify_hardif(bat_priv, hard_iface); \ + } \ + \ batadv_hardif_put(hard_iface); \ return length; \ } @@ -537,6 +559,9 @@ static ssize_t batadv_store_gw_mode(struct kobject *kobj, batadv_gw_check_client_stop(bat_priv); atomic_set(&bat_priv->gw.mode, (unsigned int)gw_mode_tmp); batadv_gw_tvlv_container_update(bat_priv); + + batadv_netlink_notify_mesh(bat_priv); + return count; } @@ -563,6 +588,7 @@ static ssize_t batadv_store_gw_sel_class(struct kobject *kobj, size_t count) { struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); + ssize_t length; /* setting the GW selection class is allowed only if the routing * algorithm in use implements the GW API @@ -578,10 +604,14 @@ static ssize_t batadv_store_gw_sel_class(struct kobject *kobj, return bat_priv->algo_ops->gw.store_sel_class(bat_priv, buff, count); - return __batadv_store_uint_attr(buff, count, 1, BATADV_TQ_MAX_VALUE, - batadv_post_gw_reselect, attr, - &bat_priv->gw.sel_class, - bat_priv->soft_iface, NULL); + length = __batadv_store_uint_attr(buff, count, 1, BATADV_TQ_MAX_VALUE, + batadv_post_gw_reselect, attr, + &bat_priv->gw.sel_class, + bat_priv->soft_iface, NULL); + + batadv_netlink_notify_mesh(bat_priv); + + return length; } static ssize_t batadv_show_gw_bwidth(struct kobject *kobj, @@ -601,12 +631,18 @@ static ssize_t batadv_store_gw_bwidth(struct kobject *kobj, struct attribute *attr, char *buff, size_t count) { + struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); struct net_device *net_dev = batadv_kobj_to_netdev(kobj); + ssize_t length; if (buff[count - 1] == '\n') buff[count - 1] = '\0'; - return batadv_gw_bandwidth_set(net_dev, buff, count); + length = batadv_gw_bandwidth_set(net_dev, buff, count); + + batadv_netlink_notify_mesh(bat_priv); + + return length; } /** @@ -674,6 +710,8 @@ static ssize_t batadv_store_isolation_mark(struct kobject *kobj, "New skb mark for extended isolation: %#.8x/%#.8x\n", bat_priv->isolation_mark, bat_priv->isolation_mark_mask); + batadv_netlink_notify_mesh(bat_priv); + return count; } @@ -1078,6 +1116,7 @@ static ssize_t batadv_store_throughput_override(struct kobject *kobj, struct attribute *attr, char *buff, size_t count) { + struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); struct net_device *net_dev = batadv_kobj_to_netdev(kobj); struct batadv_hard_iface *hard_iface; u32 tp_override; @@ -1108,6 +1147,8 @@ static ssize_t batadv_store_throughput_override(struct kobject *kobj, atomic_set(&hard_iface->bat_v.throughput_override, tp_override); + batadv_netlink_notify_hardif(bat_priv, hard_iface); + out: batadv_hardif_put(hard_iface); return count; -- 2.19.2 From sven at narfation.org Fri Dec 7 21:31:49 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 21:31:49 +0100 Subject: [B.A.T.M.A.N.] [RFC v4 00/20] batctl: netlink restructuring, part 3 Message-ID: <20181207203209.22633-1-sven@narfation.org> As mentioned earlier, the netlink config restructuring in batctl will be splitted in multiple steps. The first step was already merged and the RFC changes for the netlink interface in batman-adv were just posted. The batman-adv weren't directly rejected by Jiro and thus I've started to convert all settings to netlink while still allowing sysfs as fallback. v4: * last patch (which adds the netlink implementation of the settings commands) was splitted in 16 separate patches * Cc the (most likely) responsible developers for each setting to more directly ask them for feedback v3: * fix kernel-doc in batman_adv.h * add three patches to use the netlink interface with the already existing setting commands v2: * drop of generic config command * reimplementation of the event command Kind regards, Sven Sven Eckelmann (20): batctl: Add support for config mcast group in event monitor batctl: Don't allocate new buffer for vlan parent device batctl: Automatically translate vlan to mesh_iface batctl: Add settings_data hooks for netlink integration batctl: Parse the arguments for gw_mode batctl: Add netlink simple query helper batctl: Support generic netlink for gw_mode command batctl: Support generic netlink for loglevel command batctl: Support generic netlink for isolation_mark command batctl: Support generic netlink for orig_interval command batctl: Add helper to read/write boolean configuration values batctl: Support generic netlink for aggregation command batctl: Support generic netlink for ap_isolation command batctl: Support generic netlink for bonding command batctl: Support generic netlink for bridge_loop_avoidance command batctl: Support generic netlink for distributed_arp_table command batctl: Support generic netlink for fragmentation command batctl: Support generic netlink for multicast_mode command batctl: Support generic netlink for network_coding command batctl: Drop settings_date param lists aggregation.c | 45 ++++- ap_isolation.c | 67 ++++++- batman_adv.h | 188 +++++++++++++++++- bonding.c | 45 ++++- bridge_loop_avoidance.c | 46 ++++- distributed_arp_table.c | 46 ++++- event.c | 234 ++++++++++++++++++++++ fragmentation.c | 45 ++++- functions.c | 160 +++++++++++++--- functions.h | 23 ++- gateways.c | 10 +- gw_mode.c | 416 +++++++++++++++++++++++++++++++--------- isolation_mark.c | 123 +++++++++++- loglevel.c | 138 ++++++++++--- main.c | 10 +- main.h | 6 +- mcast_flags.c | 10 +- multicast_mode.c | 45 ++++- netlink.c | 108 ++++++++++- netlink.h | 2 + network_coding.c | 45 ++++- orig_interval.c | 84 +++++++- originators.c | 10 +- routing_algo.c | 1 - sys.c | 219 ++++++++++++++++----- sys.h | 25 ++- 26 files changed, 1895 insertions(+), 256 deletions(-) -- 2.19.2 From sven at narfation.org Fri Dec 7 21:31:50 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 21:31:50 +0100 Subject: [B.A.T.M.A.N.] [RFC v4 01/20] batctl: Add support for config mcast group in event monitor In-Reply-To: <20181207203209.22633-1-sven@narfation.org> References: <20181207203209.22633-1-sven@narfation.org> Message-ID: <20181207203209.22633-2-sven@narfation.org> The netlink set netlink messages issued by the config subcommands get as reply a multicast message with the new value. The event monitor should show these messages similar to the tp_meter results. Signed-off-by: Sven Eckelmann --- batman_adv.h | 188 +++++++++++++++++++++++++++++++++++++++-- event.c | 234 +++++++++++++++++++++++++++++++++++++++++++++++++++ netlink.c | 20 +++++ 3 files changed, 437 insertions(+), 5 deletions(-) diff --git a/batman_adv.h b/batman_adv.h index 324a0e1..b5a245e 100644 --- a/batman_adv.h +++ b/batman_adv.h @@ -27,6 +27,7 @@ #define BATADV_NL_NAME "batadv" +#define BATADV_NL_MCAST_GROUP_CONFIG "config" #define BATADV_NL_MCAST_GROUP_TPMETER "tpmeter" /** @@ -138,6 +139,20 @@ enum batadv_mcast_flags_priv { BATADV_MCAST_FLAGS_QUERIER_IPV6_SHADOWING = (1 << 4), }; +/** + * enum batadv_gw_modes - gateway mode of node + */ +enum batadv_gw_modes { + /** @BATADV_GW_MODE_OFF: gw mode disabled */ + BATADV_GW_MODE_OFF, + + /** @BATADV_GW_MODE_CLIENT: send DHCP requests to gw servers */ + BATADV_GW_MODE_CLIENT, + + /** @BATADV_GW_MODE_SERVER: announce itself as gatway server */ + BATADV_GW_MODE_SERVER, +}; + /** * enum batadv_nl_attrs - batman-adv netlink attributes */ @@ -344,6 +359,136 @@ enum batadv_nl_attrs { */ BATADV_ATTR_MCAST_FLAGS_PRIV, + /** + * @BATADV_ATTR_VLANID: VLAN id on top of soft interface + */ + BATADV_ATTR_VLANID, + + /** + * @BATADV_ATTR_AGGREGATED_OGMS: whether the batman protocol messages + * of the mesh mesh interface shall be aggregated or not. + */ + BATADV_ATTR_AGGREGATED_OGMS, + + /** + * @BATADV_ATTR_AP_ISOLATION: whether the data traffic going from a + * wireless client to another wireless client will be silently dropped. + */ + BATADV_ATTR_AP_ISOLATION, + + /** + * @BATADV_ATTR_ISOLATION_MARK: the isolation mark which is used to + * classify clients as "isolated" by the Extended Isolation feature. + */ + BATADV_ATTR_ISOLATION_MARK, + + /** + * @BATADV_ATTR_ISOLATION_MASK: the isolation (bit)mask which is used to + * classify clients as "isolated" by the Extended Isolation feature. + */ + BATADV_ATTR_ISOLATION_MASK, + + /** + * @BATADV_ATTR_BONDING: whether the data traffic going through the + * mesh will be sent using multiple interfaces at the same time. + */ + BATADV_ATTR_BONDING, + + /** + * @BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE: whether the bridge loop avoidance + * feature is enabled. This feature detects and avoids loops between + * the mesh and devices bridged with the soft interface + */ + BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE, + + /** + * @BATADV_ATTR_DISTRIBUTED_ARP_TABLE: whether the distributed arp table + * feature is enabled. This feature uses a distributed hash table to + * answer ARP requests without flooding the request through the whole + * mesh. + */ + BATADV_ATTR_DISTRIBUTED_ARP_TABLE, + + /** + * @BATADV_ATTR_FRAGMENTATION: whether the data traffic going through + * the mesh will be fragmented or silently discarded if the packet size + * exceeds the outgoing interface MTU. + */ + BATADV_ATTR_FRAGMENTATION, + + /** + * @BATADV_ATTR_GW_BANDWIDTH_DOWN: defines the download bandwidth which + * is propagated by this node if %BATADV_ATTR_GW_BANDWIDTH_MODE was set + * to 'server'. + */ + BATADV_ATTR_GW_BANDWIDTH_DOWN, + + /** + * @BATADV_ATTR_GW_BANDWIDTH_UP: defines the upload bandwidth which + * is propagated by this node if %BATADV_ATTR_GW_BANDWIDTH_MODE was set + * to 'server'. + */ + BATADV_ATTR_GW_BANDWIDTH_UP, + + /** + * @BATADV_ATTR_GW_MODE: defines the state of the gateway features. + * Possible values are specified in enum batadv_gw_modes + */ + BATADV_ATTR_GW_MODE, + + /** + * @BATADV_ATTR_GW_SEL_CLASS: defines the selection criteria this node + * will use to choose a gateway if gw_mode was set to 'client'. + */ + BATADV_ATTR_GW_SEL_CLASS, + + /** + * @BATADV_ATTR_HOP_PENALTY: defines the penalty which will be applied + * to an originator message's tq-field on every hop. + */ + BATADV_ATTR_HOP_PENALTY, + + /** + * @BATADV_ATTR_LOG_LEVEL: bitmask with to define which debug messages + * should be send to the debug log/trace ring buffer + */ + BATADV_ATTR_LOG_LEVEL, + + /** + * @BATADV_ATTR_MULTICAST_MODE: whether multicast optimizations are + * enabled or disabled. If set to zero then all nodes in the mesh are + * going to use classic flooding for any multicast packet with no + * optimizations. + */ + BATADV_ATTR_MULTICAST_MODE, + + /** + * @BATADV_ATTR_NETWORK_CODING: whether Network Coding (using some magic + * to send fewer wifi packets but still the same content) is enabled or + * not. + */ + BATADV_ATTR_NETWORK_CODING, + + /** + * @BATADV_ATTR_ORIG_INTERVAL: defines the interval in milliseconds in + * which batman sends its protocol messages. + */ + BATADV_ATTR_ORIG_INTERVAL, + + /** + * @BATADV_ATTR_ELP_INTERVAL: defines the interval in milliseconds in + * which batman emits probing packets for neighbor sensing (ELP). + */ + BATADV_ATTR_ELP_INTERVAL, + + /** + * @BATADV_ATTR_THROUGHPUT_OVERRIDE: defines the throughput value to be + * used by B.A.T.M.A.N. V when estimating the link throughput using + * this interface. If the value is set to 0 then batman-adv will try to + * estimate the throughput by itself. + */ + BATADV_ATTR_THROUGHPUT_OVERRIDE, + /* add attributes above here, update the policy in netlink.c */ /** @@ -372,10 +517,14 @@ enum batadv_nl_commands { BATADV_CMD_UNSPEC, /** - * @BATADV_CMD_GET_MESH_INFO: Query basic information about batman-adv - * device + * @BATADV_CMD_GET_MESH: Get attributes from softif/mesh + */ + BATADV_CMD_GET_MESH, + + /** + * @BATADV_CMD_GET_MESH_INFO: Alias for @BATADV_CMD_GET_MESH */ - BATADV_CMD_GET_MESH_INFO, + BATADV_CMD_GET_MESH_INFO = BATADV_CMD_GET_MESH, /** * @BATADV_CMD_TP_METER: Start a tp meter session @@ -393,9 +542,15 @@ enum batadv_nl_commands { BATADV_CMD_GET_ROUTING_ALGOS, /** - * @BATADV_CMD_GET_HARDIFS: Query list of hard interfaces + * @BATADV_CMD_GET_HARDIF: Get attributes from a hardif of the + * current softif */ - BATADV_CMD_GET_HARDIFS, + BATADV_CMD_GET_HARDIF, + + /** + * @BATADV_CMD_GET_HARDIFS: Alias for @BATADV_CMD_GET_HARDIF + */ + BATADV_CMD_GET_HARDIFS = BATADV_CMD_GET_HARDIF, /** * @BATADV_CMD_GET_TRANSTABLE_LOCAL: Query list of local translations @@ -443,6 +598,29 @@ enum batadv_nl_commands { */ BATADV_CMD_GET_MCAST_FLAGS, + /** + * @BATADV_CMD_SET_MESH: Set attributes for softif/mesh + */ + BATADV_CMD_SET_MESH, + + /** + * @BATADV_CMD_SET_HARDIF: Set attributes for hardif of the + * current softif + */ + BATADV_CMD_SET_HARDIF, + + /** + * @BATADV_CMD_GET_VLAN: Get attributes from a VLAN of the + * current softif + */ + BATADV_CMD_GET_VLAN, + + /** + * @BATADV_CMD_SET_VLAN: Set attributes for VLAN of the + * current softif + */ + BATADV_CMD_SET_VLAN, + /* add new commands above here */ /** diff --git a/event.c b/event.c index 8eda269..28a5205 100644 --- a/event.c +++ b/event.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -51,6 +52,14 @@ struct event_args { struct timeval tv; }; +static const char *u8_to_boolstr(struct nlattr *attrs) +{ + if (nla_get_u8(attrs)) + return "true"; + else + return "false"; +} + static void event_usage(void) { fprintf(stderr, "Usage: batctl [options] event [parameters]\n"); @@ -87,6 +96,25 @@ static int event_prepare(struct state *state) skip_tp_meter: + mcid = nl_get_multicast_id(state->sock, BATADV_NL_NAME, + BATADV_NL_MCAST_GROUP_CONFIG); + if (mcid < 0) { + fprintf(stderr, "Failed to resolve batadv config multicast group: %d\n", + mcid); + /* ignore error for now */ + goto skip_config; + } + + ret = nl_socket_add_membership(state->sock, mcid); + if (ret) { + fprintf(stderr, "Failed to join batadv config multicast group: %d\n", + ret); + /* ignore error for now */ + goto skip_config; + } + +skip_config: + return 0; } @@ -145,6 +173,203 @@ static void event_parse_tp_meter(struct nlattr **attrs) printf("tp_meter 0x%08x: %s\n", cookie, result_str); } +static void event_parse_set_mesh(struct nlattr **attrs) +{ + static const int mesh_mandatory[] = { + BATADV_ATTR_MESH_IFINDEX, + BATADV_ATTR_ALGO_NAME, + }; + char meshif_buf[IF_NAMESIZE]; + char *meshif_name; + uint32_t mesh_ifindex; + + /* ignore entry when attributes are missing */ + if (missing_mandatory_attrs(attrs, mesh_mandatory, + ARRAY_SIZE(mesh_mandatory))) + return; + + mesh_ifindex = nla_get_u32(attrs[BATADV_ATTR_MESH_IFINDEX]); + meshif_name = if_indextoname(mesh_ifindex, meshif_buf); + if (!meshif_name) + return; + + printf("%s: set mesh:\n", meshif_name); + + if (attrs[BATADV_ATTR_AGGREGATED_OGMS]) + printf("* aggregated_ogms %s\n", + u8_to_boolstr(attrs[BATADV_ATTR_AGGREGATED_OGMS])); + + if (attrs[BATADV_ATTR_AP_ISOLATION]) + printf("* ap_isolation %s\n", + u8_to_boolstr(attrs[BATADV_ATTR_AP_ISOLATION])); + + if (attrs[BATADV_ATTR_ISOLATION_MARK]) + printf("* isolation_mark 0x%08x\n", + nla_get_u32(attrs[BATADV_ATTR_ISOLATION_MARK])); + + if (attrs[BATADV_ATTR_ISOLATION_MASK]) + printf("* isolation_mask 0x%08x\n", + nla_get_u32(attrs[BATADV_ATTR_ISOLATION_MASK])); + + if (attrs[BATADV_ATTR_BONDING]) + printf("* bonding %s\n", + u8_to_boolstr(attrs[BATADV_ATTR_BONDING])); + + if (attrs[BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE]) + printf("* bridge_loop_avoidance %s\n", + u8_to_boolstr(attrs[BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE])); + + if (attrs[BATADV_ATTR_DISTRIBUTED_ARP_TABLE]) + printf("* distributed_arp_table %s\n", + u8_to_boolstr(attrs[BATADV_ATTR_DISTRIBUTED_ARP_TABLE])); + + if (attrs[BATADV_ATTR_FRAGMENTATION]) + printf("* fragmentation %s\n", + u8_to_boolstr(attrs[BATADV_ATTR_FRAGMENTATION])); + + if (attrs[BATADV_ATTR_GW_BANDWIDTH_DOWN]) { + uint32_t val; + + val = nla_get_u32(attrs[BATADV_ATTR_GW_BANDWIDTH_DOWN]); + printf("* gw_bandwidth_down %u.%01u MBit/s\n", val / 10, + val % 10); + } + + if (attrs[BATADV_ATTR_GW_BANDWIDTH_UP]) { + uint32_t val; + + val = nla_get_u32(attrs[BATADV_ATTR_GW_BANDWIDTH_UP]); + printf("* gw_bandwidth_up %u.%01u MBit/s\n", val / 10, + val % 10); + } + + if (attrs[BATADV_ATTR_GW_MODE]) { + uint8_t val = nla_get_u8(attrs[BATADV_ATTR_GW_MODE]); + const char *valstr; + + switch (val) { + case BATADV_GW_MODE_OFF: + valstr = "off"; + break; + case BATADV_GW_MODE_CLIENT: + valstr = "client"; + break; + case BATADV_GW_MODE_SERVER: + valstr = "server"; + break; + default: + valstr = "unknown"; + break; + } + + printf("* gw_mode %s\n", valstr); + } + + if (attrs[BATADV_ATTR_GW_SEL_CLASS]) { + uint32_t val = nla_get_u32(attrs[BATADV_ATTR_GW_SEL_CLASS]); + const char *algo = nla_data(attrs[BATADV_ATTR_ALGO_NAME]); + + if (strcmp(algo, "BATMAN_V") == 0) + printf("* gw_sel_class %u.%01u MBit/s\n", val / 10, + val % 10); + else + printf("* gw_sel_class %u\n", val); + } + + if (attrs[BATADV_ATTR_HOP_PENALTY]) + printf("* hop_penalty %u\n", + nla_get_u8(attrs[BATADV_ATTR_HOP_PENALTY])); + + if (attrs[BATADV_ATTR_LOG_LEVEL]) + printf("* log_level 0x%08x\n", + nla_get_u32(attrs[BATADV_ATTR_LOG_LEVEL])); + + if (attrs[BATADV_ATTR_MULTICAST_MODE]) + printf("* multicast_mode %s\n", + u8_to_boolstr(attrs[BATADV_ATTR_MULTICAST_MODE])); + + if (attrs[BATADV_ATTR_NETWORK_CODING]) + printf("* network_coding %s\n", + u8_to_boolstr(attrs[BATADV_ATTR_NETWORK_CODING])); + + if (attrs[BATADV_ATTR_ORIG_INTERVAL]) + printf("* orig_interval %u ms\n", + nla_get_u32(attrs[BATADV_ATTR_ORIG_INTERVAL])); +} + +static void event_parse_set_hardif(struct nlattr **attrs) +{ + static const int hardif_mandatory[] = { + BATADV_ATTR_MESH_IFINDEX, + BATADV_ATTR_HARD_IFINDEX, + }; + char meshif_buf[IF_NAMESIZE]; + char hardif_buf[IF_NAMESIZE]; + char *meshif_name; + char *hardif_name; + uint32_t hardif_ifindex; + uint32_t mesh_ifindex; + + /* ignore entry when attributes are missing */ + if (missing_mandatory_attrs(attrs, hardif_mandatory, + ARRAY_SIZE(hardif_mandatory))) + return; + + mesh_ifindex = nla_get_u32(attrs[BATADV_ATTR_MESH_IFINDEX]); + meshif_name = if_indextoname(mesh_ifindex, meshif_buf); + if (!meshif_name) + return; + + hardif_ifindex = nla_get_u32(attrs[BATADV_ATTR_HARD_IFINDEX]); + hardif_name = if_indextoname(hardif_ifindex, hardif_buf); + if (!hardif_name) + return; + + printf("%s (%s): set hardif:\n", meshif_name, hardif_name); + + if (attrs[BATADV_ATTR_ELP_INTERVAL]) + printf("* elp_interval %u ms\n", + nla_get_u32(attrs[BATADV_ATTR_ELP_INTERVAL])); + + if (attrs[BATADV_ATTR_THROUGHPUT_OVERRIDE]) { + uint32_t val; + + val = nla_get_u32(attrs[BATADV_ATTR_THROUGHPUT_OVERRIDE]); + printf("* throughput_override %u.%01u MBit/s\n", val / 10, + val % 10); + } +} + +static void event_parse_set_vlan(struct nlattr **attrs) +{ + static const int vlan_mandatory[] = { + BATADV_ATTR_MESH_IFINDEX, + BATADV_ATTR_VLANID, + }; + char meshif_buf[IF_NAMESIZE]; + char *meshif_name; + uint32_t mesh_ifindex; + uint16_t vid; + + /* ignore entry when attributes are missing */ + if (missing_mandatory_attrs(attrs, vlan_mandatory, + ARRAY_SIZE(vlan_mandatory))) + return; + + mesh_ifindex = nla_get_u32(attrs[BATADV_ATTR_MESH_IFINDEX]); + meshif_name = if_indextoname(mesh_ifindex, meshif_buf); + if (!meshif_name) + return; + + vid = nla_get_u16(attrs[BATADV_ATTR_VLANID]); + + printf("%s (vid %u): set vlan:\n", meshif_name, vid); + + if (attrs[BATADV_ATTR_AP_ISOLATION]) + printf("* ap_isolation %s\n", + u8_to_boolstr(attrs[BATADV_ATTR_AP_ISOLATION])); +} + static unsigned long long get_timestamp(struct event_args *event_args) { unsigned long long prevtime = 0; @@ -190,6 +415,15 @@ static int event_parse(struct nl_msg *msg, void *arg) case BATADV_CMD_TP_METER: event_parse_tp_meter(attrs); break; + case BATADV_CMD_SET_MESH: + event_parse_set_mesh(attrs); + break; + case BATADV_CMD_SET_HARDIF: + event_parse_set_hardif(attrs); + break; + case BATADV_CMD_SET_VLAN: + event_parse_set_vlan(attrs); + break; default: printf("Received unknown event %u\n", ghdr->cmd); break; diff --git a/netlink.c b/netlink.c index 5285759..1829544 100644 --- a/netlink.c +++ b/netlink.c @@ -107,6 +107,26 @@ struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = { [BATADV_ATTR_DAT_CACHE_VID] = { .type = NLA_U16 }, [BATADV_ATTR_MCAST_FLAGS] = { .type = NLA_U32 }, [BATADV_ATTR_MCAST_FLAGS_PRIV] = { .type = NLA_U32 }, + [BATADV_ATTR_VLANID] = { .type = NLA_U16 }, + [BATADV_ATTR_AGGREGATED_OGMS] = { .type = NLA_U8 }, + [BATADV_ATTR_AP_ISOLATION] = { .type = NLA_U8 }, + [BATADV_ATTR_ISOLATION_MARK] = { .type = NLA_U32 }, + [BATADV_ATTR_ISOLATION_MASK] = { .type = NLA_U32 }, + [BATADV_ATTR_BONDING] = { .type = NLA_U8 }, + [BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE] = { .type = NLA_U8 }, + [BATADV_ATTR_DISTRIBUTED_ARP_TABLE] = { .type = NLA_U8 }, + [BATADV_ATTR_FRAGMENTATION] = { .type = NLA_U8 }, + [BATADV_ATTR_GW_BANDWIDTH_DOWN] = { .type = NLA_U32 }, + [BATADV_ATTR_GW_BANDWIDTH_UP] = { .type = NLA_U32 }, + [BATADV_ATTR_GW_MODE] = { .type = NLA_U8 }, + [BATADV_ATTR_GW_SEL_CLASS] = { .type = NLA_U32 }, + [BATADV_ATTR_HOP_PENALTY] = { .type = NLA_U8 }, + [BATADV_ATTR_LOG_LEVEL] = { .type = NLA_U32 }, + [BATADV_ATTR_MULTICAST_MODE] = { .type = NLA_U8 }, + [BATADV_ATTR_NETWORK_CODING] = { .type = NLA_U8 }, + [BATADV_ATTR_ORIG_INTERVAL] = { .type = NLA_U32 }, + [BATADV_ATTR_ELP_INTERVAL] = { .type = NLA_U32 }, + [BATADV_ATTR_THROUGHPUT_OVERRIDE] = { .type = NLA_U32 }, }; int netlink_create(struct state *state) -- 2.19.2 From sven at narfation.org Fri Dec 7 21:31:51 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 21:31:51 +0100 Subject: [B.A.T.M.A.N.] [RFC v4 02/20] batctl: Don't allocate new buffer for vlan parent device In-Reply-To: <20181207203209.22633-1-sven@narfation.org> References: <20181207203209.22633-1-sven@narfation.org> Message-ID: <20181207203209.22633-3-sven@narfation.org> The buffer size is limited by IF_NAMESIZE and can easily be stored on the stack. This will also make it easier to store this as part of the the state of batctl. Signed-off-by: Sven Eckelmann --- functions.c | 23 ++++++----------------- functions.h | 2 +- sys.c | 6 +++--- 3 files changed, 10 insertions(+), 21 deletions(-) diff --git a/functions.c b/functions.c index bdede8b..ecfd202 100644 --- a/functions.c +++ b/functions.c @@ -830,10 +830,6 @@ static int vlan_get_link_parse(struct nl_msg *msg, void *arg) /* get parent link name */ idx = *(int *)nla_data(tb[IFLA_LINK]); - free(nl_arg->iface); - nl_arg->iface = malloc(IFNAMSIZ + 1); - if (!nl_arg->iface) - goto err; if (!if_indextoname(idx, nl_arg->iface)) goto err; @@ -851,12 +847,12 @@ static int vlan_get_link_parse(struct nl_msg *msg, void *arg) /** * vlan_get_link - convert a VLAN interface into its parent one * @ifname: the interface to convert - * @parent: buffer where the parent interface name will be written (allocated by - * this function) + * @parent: buffer where the parent interface name will be written + * (minimum IF_NAMESIZE) * * Returns the vlan identifier on success or -1 on error */ -int vlan_get_link(const char *ifname, char **parent) +int vlan_get_link(const char *ifname, char *parent) { struct nl_sock *sock; int ret; @@ -866,12 +862,10 @@ int vlan_get_link(const char *ifname, char **parent) }; struct nl_cb *cb = NULL; struct vlan_get_link_nl_arg arg = { - .iface = NULL, + .iface = parent, .vid = -1, }; - *parent = NULL; - sock = nl_socket_alloc(); if (!sock) goto err; @@ -894,8 +888,6 @@ int vlan_get_link(const char *ifname, char **parent) if (ret < 0) goto err; - *parent = arg.iface; - err: if (cb) nl_cb_put(cb); @@ -1029,13 +1021,13 @@ int netlink_simple_request(struct nl_msg *msg) int check_mesh_iface(char *mesh_iface) { - char *base_dev = NULL; char path_buff[PATH_BUFF_LEN]; + char base_dev[IF_NAMESIZE]; int ret = -1, vid; DIR *dir; /* use the parent interface if this is a VLAN */ - vid = vlan_get_link(mesh_iface, &base_dev); + vid = vlan_get_link(mesh_iface, base_dev); if (vid >= 0) snprintf(path_buff, PATH_BUFF_LEN, SYS_VLAN_PATH, base_dev, vid); else @@ -1050,9 +1042,6 @@ int check_mesh_iface(char *mesh_iface) ret = 0; out: - if (base_dev) - free(base_dev); - return ret; } diff --git a/functions.h b/functions.h index c16ba2e..2680e6d 100644 --- a/functions.h +++ b/functions.h @@ -48,7 +48,7 @@ int write_file(const char *dir, const char *fname, const char *arg1, struct ether_addr *translate_mac(const char *mesh_iface, const struct ether_addr *mac); struct ether_addr *resolve_mac(const char *asc); -int vlan_get_link(const char *ifname, char **parent);\ +int vlan_get_link(const char *ifname, char *parent); int query_rtnl_link(int ifindex, nl_recvmsg_msg_cb_t func, void *arg); int netlink_simple_request(struct nl_msg *msg); int check_mesh_iface(char *mesh_iface); diff --git a/sys.c b/sys.c index 6b98ac4..5c54f08 100644 --- a/sys.c +++ b/sys.c @@ -67,7 +67,8 @@ int handle_sys_setting(struct state *state, int argc, char **argv) { struct settings_data *settings = state->cmd->arg; int vid, optchar, res = EXIT_FAILURE; - char *path_buff, *base_dev = NULL; + char base_dev[IF_NAMESIZE]; + char *path_buff; const char **ptr; while ((optchar = getopt(argc, argv, "h")) != -1) { @@ -93,7 +94,7 @@ int handle_sys_setting(struct state *state, int argc, char **argv) /* if the specified interface is a VLAN then change the path to point * to the proper "vlan%{vid}" subfolder in the sysfs tree. */ - vid = vlan_get_link(state->mesh_iface, &base_dev); + vid = vlan_get_link(state->mesh_iface, base_dev); if (vid >= 0) snprintf(path_buff, PATH_BUFF_LEN, SYS_VLAN_PATH, base_dev, vid); @@ -133,6 +134,5 @@ int handle_sys_setting(struct state *state, int argc, char **argv) out: free(path_buff); - free(base_dev); return res; } -- 2.19.2 From sven at narfation.org Fri Dec 7 21:31:52 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 21:31:52 +0100 Subject: [B.A.T.M.A.N.] [RFC v4 03/20] batctl: Automatically translate vlan to mesh_iface In-Reply-To: <20181207203209.22633-1-sven@narfation.org> References: <20181207203209.22633-1-sven@narfation.org> Message-ID: <20181207203209.22633-4-sven@narfation.org> The way batctl is implementing support for VLANs is rather suboptimal. The program has to guess whether it is started with an batadv or vlan interface as argument. Instead of distributing this over the whole program, do it on startup and already retrieve the required mesh interface index and vid before the rest of the program runs. Signed-off-by: Sven Eckelmann --- functions.c | 34 ++++++++++++++++++++++++++-------- functions.h | 6 ++++-- gateways.c | 10 ++-------- main.c | 10 ++++++---- main.h | 6 +++++- mcast_flags.c | 10 ++-------- netlink.c | 12 ++---------- originators.c | 10 ++-------- sys.c | 14 +++++++------- 9 files changed, 56 insertions(+), 56 deletions(-) diff --git a/functions.c b/functions.c index ecfd202..600c29a 100644 --- a/functions.c +++ b/functions.c @@ -852,7 +852,7 @@ static int vlan_get_link_parse(struct nl_msg *msg, void *arg) * * Returns the vlan identifier on success or -1 on error */ -int vlan_get_link(const char *ifname, char *parent) +static int vlan_get_link(const char *ifname, char *parent) { struct nl_sock *sock; int ret; @@ -1019,19 +1019,33 @@ int netlink_simple_request(struct nl_msg *msg) return err; } -int check_mesh_iface(char *mesh_iface) +int translate_mesh_iface(struct state *state) +{ + state->vid = vlan_get_link(state->arg_iface, state->mesh_iface); + if (state->vid < 0) { + /* if there is no iface then the argument must be the + * mesh interface + */ + snprintf(state->mesh_iface, sizeof(state->mesh_iface), "%s", + state->arg_iface); + } + + return 0; +} + +int check_mesh_iface(struct state *state) { char path_buff[PATH_BUFF_LEN]; - char base_dev[IF_NAMESIZE]; - int ret = -1, vid; + int ret = -1; DIR *dir; /* use the parent interface if this is a VLAN */ - vid = vlan_get_link(mesh_iface, base_dev); - if (vid >= 0) - snprintf(path_buff, PATH_BUFF_LEN, SYS_VLAN_PATH, base_dev, vid); + if (state->vid >= 0) + snprintf(path_buff, PATH_BUFF_LEN, SYS_VLAN_PATH, + state->mesh_iface, state->vid); else - snprintf(path_buff, PATH_BUFF_LEN, SYS_BATIF_PATH_FMT, mesh_iface); + snprintf(path_buff, PATH_BUFF_LEN, SYS_BATIF_PATH_FMT, + state->mesh_iface); /* try to open the mesh sys directory */ dir = opendir(path_buff); @@ -1040,6 +1054,10 @@ int check_mesh_iface(char *mesh_iface) closedir(dir); + state->mesh_ifindex = if_nametoindex(state->mesh_iface); + if (state->mesh_ifindex == 0) + goto out; + ret = 0; out: return ret; diff --git a/functions.h b/functions.h index 2680e6d..ea3c307 100644 --- a/functions.h +++ b/functions.h @@ -34,6 +34,8 @@ #define PATH_BUFF_LEN 400 +struct state; + /* return time delta from start to end in milliseconds */ void start_timer(void); double end_timer(void); @@ -48,10 +50,10 @@ int write_file(const char *dir, const char *fname, const char *arg1, struct ether_addr *translate_mac(const char *mesh_iface, const struct ether_addr *mac); struct ether_addr *resolve_mac(const char *asc); -int vlan_get_link(const char *ifname, char *parent); int query_rtnl_link(int ifindex, nl_recvmsg_msg_cb_t func, void *arg); int netlink_simple_request(struct nl_msg *msg); -int check_mesh_iface(char *mesh_iface); +int translate_mesh_iface(struct state *state); +int check_mesh_iface(struct state *state); int check_mesh_iface_ownership(char *mesh_iface, char *hard_iface); void get_random_bytes(void *buf, size_t buflen); diff --git a/gateways.c b/gateways.c index ff7693f..5beddc7 100644 --- a/gateways.c +++ b/gateways.c @@ -133,17 +133,11 @@ static int netlink_print_gateways(struct state *state, char *orig_iface, { char *header = NULL; char *info_header; - int ifindex; - - ifindex = if_nametoindex(state->mesh_iface); - if (!ifindex) { - fprintf(stderr, "Interface %s is unknown\n", state->mesh_iface); - return -ENODEV; - } /* only parse routing algorithm name */ last_err = -EINVAL; - info_header = netlink_get_info(ifindex, BATADV_CMD_GET_ORIGINATORS, NULL); + info_header = netlink_get_info(state->mesh_ifindex, + BATADV_CMD_GET_ORIGINATORS, NULL); free(info_header); if (strlen(algo_name_buf) == 0) diff --git a/main.c b/main.c index ab7da45..37a2b5a 100644 --- a/main.c +++ b/main.c @@ -125,7 +125,7 @@ int main(int argc, char **argv) { const struct command *cmd; struct state state = { - .mesh_iface = mesh_dfl_iface, + .arg_iface = mesh_dfl_iface, .cmd = NULL, }; int opt; @@ -138,13 +138,13 @@ int main(int argc, char **argv) exit(EXIT_SUCCESS); break; case 'm': - if (state.mesh_iface != mesh_dfl_iface) { + if (state.arg_iface != mesh_dfl_iface) { fprintf(stderr, "Error - multiple mesh interfaces specified\n"); goto err; } - state.mesh_iface = argv[2]; + state.arg_iface = argv[2]; break; case 'v': version(); @@ -173,8 +173,10 @@ int main(int argc, char **argv) state.cmd = cmd; + translate_mesh_iface(&state); + if (cmd->flags & COMMAND_FLAG_MESH_IFACE && - check_mesh_iface(state.mesh_iface) < 0) { + check_mesh_iface(&state) < 0) { fprintf(stderr, "Error - interface %s is not present or not a batman-adv interface\n", state.mesh_iface); diff --git a/main.h b/main.h index 276a018..274fae5 100644 --- a/main.h +++ b/main.h @@ -25,6 +25,7 @@ #include +#include #include #include #include @@ -74,7 +75,10 @@ enum command_type { }; struct state { - char *mesh_iface; + char *arg_iface; + char mesh_iface[IF_NAMESIZE]; + unsigned int mesh_ifindex; + int vid; const struct command *cmd; struct nl_sock *sock; diff --git a/mcast_flags.c b/mcast_flags.c index 0dc4227..eb9734e 100644 --- a/mcast_flags.c +++ b/mcast_flags.c @@ -113,17 +113,11 @@ static int netlink_print_mcast_flags(struct state *state, char *orig_iface, char *info_header; char *header; bool bridged; - int ifindex; int ret; - ifindex = if_nametoindex(state->mesh_iface); - if (!ifindex) { - fprintf(stderr, "Interface %s is unknown\n", state->mesh_iface); - return -ENODEV; - } - /* only parse own multicast flags */ - info_header = netlink_get_info(ifindex, BATADV_CMD_GET_MCAST_FLAGS, NULL); + info_header = netlink_get_info(state->mesh_ifindex, + BATADV_CMD_GET_MCAST_FLAGS, NULL); free(info_header); if (mcast_flags == -EOPNOTSUPP || mcast_flags_priv == -EOPNOTSUPP) diff --git a/netlink.c b/netlink.c index 1829544..b0d57b1 100644 --- a/netlink.c +++ b/netlink.c @@ -443,20 +443,12 @@ int netlink_print_common(struct state *state, char *orig_iface, int read_opt, }; int hardifindex = 0; struct nl_msg *msg; - int ifindex; if (!state->sock) { last_err = -EOPNOTSUPP; return last_err; } - ifindex = if_nametoindex(state->mesh_iface); - if (!ifindex) { - fprintf(stderr, "Interface %s is unknown\n", state->mesh_iface); - last_err = -ENODEV; - return last_err; - } - if (orig_iface) { hardifindex = if_nametoindex(orig_iface); if (!hardifindex) { @@ -479,7 +471,7 @@ int netlink_print_common(struct state *state, char *orig_iface, int read_opt, printf("\033[2J\033[0;0f"); if (!(read_opt & SKIP_HEADER)) - opts.remaining_header = netlink_get_info(ifindex, + opts.remaining_header = netlink_get_info(state->mesh_ifindex, nl_cmd, header); @@ -490,7 +482,7 @@ int netlink_print_common(struct state *state, char *orig_iface, int read_opt, genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, state->batadv_family, 0, NLM_F_DUMP, nl_cmd, 1); - nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, ifindex); + nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, state->mesh_ifindex); if (hardifindex) nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, hardifindex); diff --git a/originators.c b/originators.c index c29300a..3c13c66 100644 --- a/originators.c +++ b/originators.c @@ -185,17 +185,11 @@ static int netlink_print_originators(struct state *state, char *orig_iface, { char *header = NULL; char *info_header; - int ifindex; - - ifindex = if_nametoindex(state->mesh_iface); - if (!ifindex) { - fprintf(stderr, "Interface %s is unknown\n", state->mesh_iface); - return -ENODEV; - } /* only parse routing algorithm name */ last_err = -EINVAL; - info_header = netlink_get_info(ifindex, BATADV_CMD_GET_ORIGINATORS, NULL); + info_header = netlink_get_info(state->mesh_ifindex, + BATADV_CMD_GET_ORIGINATORS, NULL); free(info_header); if (strlen(algo_name_buf) == 0) diff --git a/sys.c b/sys.c index 5c54f08..be20be7 100644 --- a/sys.c +++ b/sys.c @@ -66,8 +66,7 @@ static void settings_usage(struct state *state) int handle_sys_setting(struct state *state, int argc, char **argv) { struct settings_data *settings = state->cmd->arg; - int vid, optchar, res = EXIT_FAILURE; - char base_dev[IF_NAMESIZE]; + int optchar, res = EXIT_FAILURE; char *path_buff; const char **ptr; @@ -89,14 +88,15 @@ int handle_sys_setting(struct state *state, int argc, char **argv) return EXIT_FAILURE; } - snprintf(path_buff, PATH_BUFF_LEN, SYS_BATIF_PATH_FMT, state->mesh_iface); - /* if the specified interface is a VLAN then change the path to point * to the proper "vlan%{vid}" subfolder in the sysfs tree. */ - vid = vlan_get_link(state->mesh_iface, base_dev); - if (vid >= 0) - snprintf(path_buff, PATH_BUFF_LEN, SYS_VLAN_PATH, base_dev, vid); + if (state->vid >= 0) + snprintf(path_buff, PATH_BUFF_LEN, SYS_VLAN_PATH, + state->mesh_iface, state->vid); + else + snprintf(path_buff, PATH_BUFF_LEN, SYS_BATIF_PATH_FMT, + state->mesh_iface); if (argc == 1) { res = read_file(path_buff, settings->sysfs_name, -- 2.19.2 From sven at narfation.org Fri Dec 7 21:31:53 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 21:31:53 +0100 Subject: [B.A.T.M.A.N.] [RFC v4 04/20] batctl: Add settings_data hooks for netlink integration In-Reply-To: <20181207203209.22633-1-sven@narfation.org> References: <20181207203209.22633-1-sven@narfation.org> Message-ID: <20181207203209.22633-5-sven@narfation.org> The generic netlink infrastructure will be used in the future to replace sysfs for manipulating the runtime configuation of batman-adv meshifs, hardifs and vlans. These will not use the raw strings when communicating with the kernel interface but a well defined binary message format. This means that the read function for settings must parse the binary format and convert it to a textual representation for the user. The netlink_get hook of struct settings_data will be used for that. A similar problem is the setting of configuration entries. The textual representation of the user input has to be parsed and validated. And the resulting attributes have to be put in a message which the kernel can interpret. The parsing is done in the parse hook which can use the data pointer to store the results. The netlink_set hook has to prepare the generic netlink message and send it to the kernel. Signed-off-by: Sven Eckelmann --- sys.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- sys.h | 4 ++++ 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/sys.c b/sys.c index be20be7..e883369 100644 --- a/sys.c +++ b/sys.c @@ -63,6 +63,47 @@ static void settings_usage(struct state *state) fprintf(stderr, " \t -h print this help\n"); } +static int sys_read_setting(struct state *state, const char *path_buff, + const char *sysfs_name) +{ + struct settings_data *settings = state->cmd->arg; + int res = EXIT_FAILURE; + + if (settings->netlink_get) { + res = settings->netlink_get(state); + if (res < 0 && res != -EOPNOTSUPP) + return EXIT_FAILURE; + if (res >= 0) + return EXIT_SUCCESS; + } + + if (sysfs_name) + res = read_file(path_buff, sysfs_name, NO_FLAGS, 0, 0, 0); + + return res; +} + +static int sys_write_setting(struct state *state, const char *path_buff, + const char *sysfs_name, int argc, char **argv) +{ + struct settings_data *settings = state->cmd->arg; + int res = EXIT_FAILURE; + + if (settings->netlink_set) { + res = settings->netlink_set(state); + if (res < 0 && res != -EOPNOTSUPP) + return EXIT_FAILURE; + if (res >= 0) + return EXIT_SUCCESS; + } + + if (sysfs_name) + res = write_file(path_buff, sysfs_name, + argv[1], argc > 2 ? argv[2] : NULL); + + return res; +} + int handle_sys_setting(struct state *state, int argc, char **argv) { struct settings_data *settings = state->cmd->arg; @@ -99,13 +140,20 @@ int handle_sys_setting(struct state *state, int argc, char **argv) state->mesh_iface); if (argc == 1) { - res = read_file(path_buff, settings->sysfs_name, - NO_FLAGS, 0, 0, 0); + res = sys_read_setting(state, path_buff, settings->sysfs_name); goto out; } check_root_or_die("batctl"); + if (settings->parse) { + res = settings->parse(state, argc, argv); + if (res < 0) { + res = EXIT_FAILURE; + goto out; + } + } + if (!settings->params) goto write_file; @@ -129,8 +177,8 @@ int handle_sys_setting(struct state *state, int argc, char **argv) goto out; write_file: - res = write_file(path_buff, settings->sysfs_name, - argv[1], argc > 2 ? argv[2] : NULL); + res = sys_write_setting(state, path_buff, settings->sysfs_name, argc, + argv); out: free(path_buff); diff --git a/sys.h b/sys.h index 20e1934..cac2c53 100644 --- a/sys.h +++ b/sys.h @@ -42,6 +42,10 @@ struct settings_data { const char *sysfs_name; const char **params; + void *data; + int (*parse)(struct state *state, int argc, char *argv[]); + int (*netlink_get)(struct state *state); + int (*netlink_set)(struct state *state); }; extern const char *sysfs_param_enable[]; -- 2.19.2 From sven at narfation.org Fri Dec 7 21:31:54 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 21:31:54 +0100 Subject: [B.A.T.M.A.N.] [RFC v4 05/20] batctl: Parse the arguments for gw_mode In-Reply-To: <20181207203209.22633-1-sven@narfation.org> References: <20181207203209.22633-1-sven@narfation.org> Message-ID: <20181207203209.22633-6-sven@narfation.org> The generic netlink interface requires that the configuration settings are parsed in userspace. But it can also be used to do a more fine grained validation of the input data before it is written to the sysfs files. Signed-off-by: Sven Eckelmann --- Cc: Marek Lindner Cc: Antonio Quartulli --- functions.c | 92 ++++++++++++++++++++++++++ functions.h | 16 +++++ gw_mode.c | 171 +++++++++++++++++++++++++++++++++++++++---------- netlink.c | 76 ++++++++++++++++++++++ netlink.h | 2 + routing_algo.c | 1 - sys.c | 7 -- sys.h | 2 +- 8 files changed, 324 insertions(+), 43 deletions(-) diff --git a/functions.c b/functions.c index 600c29a..ead7e97 100644 --- a/functions.c +++ b/functions.c @@ -499,6 +499,44 @@ struct ether_addr *translate_mac(const char *mesh_iface, return mac_result; } +int get_algoname(const char *mesh_iface, char *algoname, size_t algoname_len) +{ + char *path_buff; + int ret; + + ret = get_algoname_netlink(mesh_iface, algoname, algoname_len); + if (ret != -EOPNOTSUPP) + return ret; + + path_buff = malloc(PATH_BUFF_LEN); + if (!path_buff) { + fprintf(stderr, "Error - could not allocate path buffer: out of memory ?\n"); + return -ENOMEM; + } + + snprintf(path_buff, PATH_BUFF_LEN, SYS_ROUTING_ALGO_FMT, mesh_iface); + ret = read_file("", path_buff, USE_READ_BUFF | SILENCE_ERRORS, 0, 0, 0); + if (ret != EXIT_SUCCESS) { + ret = -ENOENT; + goto free_path_buf; + } + + if (line_ptr[strlen(line_ptr) - 1] == '\n') + line_ptr[strlen(line_ptr) - 1] = '\0'; + + strncpy(algoname, line_ptr, algoname_len); + if (algoname_len > 0) + algoname[algoname_len - 1] = '\0'; + +free_path_buf: + free(path_buff); + + free(line_ptr); + line_ptr = NULL; + + return ret; +} + static int resolve_l3addr(int ai_family, const char *asc, void *l3addr) { int ret; @@ -1162,3 +1200,57 @@ void check_root_or_die(const char *cmd) exit(EXIT_FAILURE); } } + +bool parse_throughput(char *buff, const char *description, uint32_t *throughput) +{ + enum batadv_bandwidth_units bw_unit_type = BATADV_BW_UNIT_KBIT; + uint64_t lthroughput; + char *tmp_ptr; + char *endptr; + + if (strlen(buff) > 4) { + tmp_ptr = buff + strlen(buff) - 4; + + if (strncasecmp(tmp_ptr, "mbit", 4) == 0) + bw_unit_type = BATADV_BW_UNIT_MBIT; + + if (strncasecmp(tmp_ptr, "kbit", 4) == 0 || + bw_unit_type == BATADV_BW_UNIT_MBIT) + *tmp_ptr = '\0'; + } + + lthroughput = strtoull(buff, &endptr, 10); + if (!endptr || *endptr != '\0') { + fprintf(stderr, "Invalid throughput speed for %s: %s\n", + description, buff); + return false; + } + + switch (bw_unit_type) { + case BATADV_BW_UNIT_MBIT: + /* prevent overflow */ + if (UINT64_MAX / 10 < lthroughput) { + fprintf(stderr, + "Throughput speed for %s too large: %s\n", + description, buff); + return false; + } + + lthroughput *= 10; + break; + case BATADV_BW_UNIT_KBIT: + default: + lthroughput = lthroughput / 100; + break; + } + + if (lthroughput > UINT32_MAX) { + fprintf(stderr, "Throughput speed for %s too large: %s\n", + description, buff); + return false; + } + + *throughput = lthroughput; + + return true; +} diff --git a/functions.h b/functions.h index ea3c307..4a6ab61 100644 --- a/functions.h +++ b/functions.h @@ -26,8 +26,20 @@ #include #include #include +#include #include +#include +/** + * enum batadv_bandwidth_units - bandwidth unit types + */ +enum batadv_bandwidth_units { + /** @BATADV_BW_UNIT_KBIT: unit type kbit */ + BATADV_BW_UNIT_KBIT, + + /** @BATADV_BW_UNIT_MBIT: unit type mbit */ + BATADV_BW_UNIT_MBIT, +}; #define ETH_STR_LEN 17 #define BATMAN_ADV_TAG "batman-adv:" @@ -53,12 +65,16 @@ struct ether_addr *resolve_mac(const char *asc); int query_rtnl_link(int ifindex, nl_recvmsg_msg_cb_t func, void *arg); int netlink_simple_request(struct nl_msg *msg); int translate_mesh_iface(struct state *state); +int get_algoname(const char *mesh_iface, char *algoname, size_t algoname_len); int check_mesh_iface(struct state *state); int check_mesh_iface_ownership(char *mesh_iface, char *hard_iface); void get_random_bytes(void *buf, size_t buflen); void check_root_or_die(const char *cmd); +bool parse_throughput(char *buff, const char *description, + uint32_t *throughput); + extern char *line_ptr; enum { diff --git a/gw_mode.c b/gw_mode.c index 4093f89..167b777 100644 --- a/gw_mode.c +++ b/gw_mode.c @@ -20,23 +20,33 @@ * License-Filename: LICENSES/preferred/GPL-2.0 */ +#include #include +#include +#include #include #include #include +#include "batman_adv.h" #include "functions.h" +#include "main.h" +#include "netlink.h" #include "sys.h" #define SYS_GW_MODE "gw_mode" #define SYS_GW_SEL "gw_sel_class" #define SYS_GW_BW "gw_bandwidth" -enum gw_modes { - GW_MODE_OFF, - GW_MODE_CLIENT, - GW_MODE_SERVER, -}; +static struct gw_data { + uint8_t bandwidth_down_found:1; + uint8_t bandwidth_up_found:1; + uint8_t sel_class_found:1; + uint8_t mode; + uint32_t bandwidth_down; + uint32_t bandwidth_up; + uint32_t sel_class; +} gw_globals; static void gw_mode_usage(void) { @@ -45,11 +55,117 @@ static void gw_mode_usage(void) fprintf(stderr, " \t -h print this help\n"); } +static bool is_throughput_select_class(struct state *state) +{ + char algoname[32]; + int ret; + + ret = get_algoname(state->mesh_iface, algoname, sizeof(algoname)); + + /* no algo name -> assume that it is a pre-B.A.T.M.A.N. V version */ + if (ret < 0) + return false; + + if (strcmp(algoname, "BATMAN_V") == 0) + return true; + + return false; +} +static int parse_gw_limit(char *buff) +{ + char *slash_ptr; + bool ret; + + slash_ptr = strchr(buff, '/'); + if (slash_ptr) + *slash_ptr = 0; + + ret = parse_throughput(buff, "download gateway speed", + &gw_globals.bandwidth_down); + if (!ret) + return -EINVAL; + + gw_globals.bandwidth_down_found = 1; + + /* we also got some upload info */ + if (slash_ptr) { + ret = parse_throughput(slash_ptr + 1, "upload gateway speed", + &gw_globals.bandwidth_up); + if (!ret) + return -EINVAL; + + gw_globals.bandwidth_up_found = 1; + } + + return 0; +} + +static int parse_gw(struct state *state, int argc, char *argv[]) +{ + char buff[256]; + char *endptr; + int ret; + + if (argc != 2 && argc != 3) { + fprintf(stderr, "Error - incorrect number of arguments (expected 1/2)\n"); + return -EINVAL; + } + + if (strcmp(argv[1], "client") == 0) { + gw_globals.mode = BATADV_GW_MODE_CLIENT; + } else if (strcmp(argv[1], "server") == 0) { + gw_globals.mode = BATADV_GW_MODE_SERVER; + } else if (strcmp(argv[1], "off") == 0) { + gw_globals.mode = BATADV_GW_MODE_OFF; + } else { + fprintf(stderr, "Error - the supplied argument is invalid: %s\n", argv[1]); + fprintf(stderr, "The following values are allowed:\n"); + fprintf(stderr, " * off\n"); + fprintf(stderr, " * client\n"); + fprintf(stderr, " * server\n"); + + return -EINVAL; + } + + if (argc <= 2) + return 0; + + strncpy(buff, argv[2], sizeof(buff)); + buff[sizeof(buff) - 1] = '\0'; + + switch (gw_globals.mode) { + case BATADV_GW_MODE_OFF: + fprintf(stderr, "Error - unexpected argument for mode \"off\": %s\n", argv[2]); + return -EINVAL; + case BATADV_GW_MODE_CLIENT: + if (is_throughput_select_class(state)) { + if (!parse_throughput(buff, "sel_class", + &gw_globals.sel_class)) + return -EINVAL; + } else { + gw_globals.sel_class = strtoul(buff, &endptr, 0); + if (!endptr || *endptr != '\0') { + fprintf(stderr, "Error - unexpected argument for mode \"client\": %s\n", buff); + return -EINVAL; + } + } + + gw_globals.sel_class_found = 1; + break; + case BATADV_GW_MODE_SERVER: + ret = parse_gw_limit(buff); + if (ret < 0) + return ret; + break; + } + + return 0; +} + static int gw_mode(struct state *state, int argc, char **argv) { int optchar, res = EXIT_FAILURE; char *path_buff, gw_mode; - const char **ptr; while ((optchar = getopt(argc, argv, "h")) != -1) { switch (optchar) { @@ -80,20 +196,20 @@ static int gw_mode(struct state *state, int argc, char **argv) line_ptr[strlen(line_ptr) - 1] = '\0'; if (strcmp(line_ptr, "client") == 0) - gw_mode = GW_MODE_CLIENT; + gw_mode = BATADV_GW_MODE_CLIENT; else if (strcmp(line_ptr, "server") == 0) - gw_mode = GW_MODE_SERVER; + gw_mode = BATADV_GW_MODE_SERVER; else - gw_mode = GW_MODE_OFF; + gw_mode = BATADV_GW_MODE_OFF; free(line_ptr); line_ptr = NULL; switch (gw_mode) { - case GW_MODE_CLIENT: + case BATADV_GW_MODE_CLIENT: res = read_file(path_buff, SYS_GW_SEL, USE_READ_BUFF, 0, 0, 0); break; - case GW_MODE_SERVER: + case BATADV_GW_MODE_SERVER: res = read_file(path_buff, SYS_GW_BW, USE_READ_BUFF, 0, 0, 0); break; default: @@ -108,10 +224,10 @@ static int gw_mode(struct state *state, int argc, char **argv) line_ptr[strlen(line_ptr) - 1] = '\0'; switch (gw_mode) { - case GW_MODE_CLIENT: + case BATADV_GW_MODE_CLIENT: printf("client (selection class: %s)\n", line_ptr); break; - case GW_MODE_SERVER: + case BATADV_GW_MODE_SERVER: printf("server (announced bw: %s)\n", line_ptr); break; default: @@ -125,14 +241,11 @@ static int gw_mode(struct state *state, int argc, char **argv) check_root_or_die("batctl gw_mode"); - if (strcmp(argv[1], "client") == 0) - gw_mode = GW_MODE_CLIENT; - else if (strcmp(argv[1], "server") == 0) - gw_mode = GW_MODE_SERVER; - else if (strcmp(argv[1], "off") == 0) - gw_mode = GW_MODE_OFF; - else - goto opt_err; + res = parse_gw(state, argc, argv); + if (res < 0) { + res = EXIT_FAILURE; + goto out; + } res = write_file(path_buff, SYS_GW_MODE, argv[1], NULL); if (res != EXIT_SUCCESS) @@ -141,27 +254,17 @@ static int gw_mode(struct state *state, int argc, char **argv) if (argc == 2) goto out; - switch (gw_mode) { - case GW_MODE_CLIENT: + switch (gw_globals.mode) { + case BATADV_GW_MODE_CLIENT: res = write_file(path_buff, SYS_GW_SEL, argv[2], NULL); break; - case GW_MODE_SERVER: + case BATADV_GW_MODE_SERVER: res = write_file(path_buff, SYS_GW_BW, argv[2], NULL); break; } goto out; -opt_err: - fprintf(stderr, "Error - the supplied argument is invalid: %s\n", argv[1]); - fprintf(stderr, "The following values are allowed:\n"); - - ptr = sysfs_param_server; - while (*ptr) { - fprintf(stderr, " * %s\n", *ptr); - ptr++; - } - out: free(path_buff); return res; diff --git a/netlink.c b/netlink.c index b0d57b1..9c29774 100644 --- a/netlink.c +++ b/netlink.c @@ -853,3 +853,79 @@ int get_primarymac_netlink(const char *mesh_iface, uint8_t *primarymac) return 0; } + +struct get_algoname_netlink_opts { + char *algoname; + size_t algoname_len; + bool found; + struct nlquery_opts query_opts; +}; + +static int get_algoname_netlink_cb(struct nl_msg *msg, void *arg) +{ + static const int mandatory[] = { + BATADV_ATTR_ALGO_NAME, + }; + struct nlattr *attrs[BATADV_ATTR_MAX + 1]; + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct nlquery_opts *query_opts = arg; + struct get_algoname_netlink_opts *opts; + struct genlmsghdr *ghdr; + const char *algoname; + + opts = container_of(query_opts, struct get_algoname_netlink_opts, + query_opts); + + if (!genlmsg_valid_hdr(nlh, 0)) + return NL_OK; + + ghdr = nlmsg_data(nlh); + + if (ghdr->cmd != BATADV_CMD_GET_MESH) + return NL_OK; + + if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), + genlmsg_len(ghdr), batadv_netlink_policy)) { + return NL_OK; + } + + if (missing_mandatory_attrs(attrs, mandatory, ARRAY_SIZE(mandatory))) + return NL_OK; + + algoname = nla_data(attrs[BATADV_ATTR_ALGO_NAME]); + + /* save result */ + strncpy(opts->algoname, algoname, opts->algoname_len); + if (opts->algoname_len > 0) + opts->algoname[opts->algoname_len - 1] = '\0'; + + opts->found = true; + opts->query_opts.err = 0; + + return NL_STOP; +} + +int get_algoname_netlink(const char *mesh_iface, char *algoname, + size_t algoname_len) +{ + struct get_algoname_netlink_opts opts = { + .algoname = algoname, + .algoname_len = algoname_len, + .found = false, + .query_opts = { + .err = 0, + }, + }; + int ret; + + ret = netlink_query_common(mesh_iface, BATADV_CMD_GET_MESH, + get_algoname_netlink_cb, 0, + &opts.query_opts); + if (ret < 0) + return ret; + + if (!opts.found) + return -EOPNOTSUPP; + + return 0; +} diff --git a/netlink.h b/netlink.h index b91ca10..9be49cd 100644 --- a/netlink.h +++ b/netlink.h @@ -50,6 +50,8 @@ int translate_mac_netlink(const char *mesh_iface, const struct ether_addr *mac, int get_nexthop_netlink(const char *mesh_iface, const struct ether_addr *mac, uint8_t *nexthop, char *ifname); int get_primarymac_netlink(const char *mesh_iface, uint8_t *primarymac); +int get_algoname_netlink(const char *mesh_iface, char *algoname, + size_t algoname_len); extern struct nla_policy batadv_netlink_policy[]; diff --git a/routing_algo.c b/routing_algo.c index 18d9ef7..69eac34 100644 --- a/routing_algo.c +++ b/routing_algo.c @@ -41,7 +41,6 @@ #include "sys.h" #define SYS_SELECTED_RA_PATH "/sys/module/batman_adv/parameters/routing_algo" -#define SYS_ROUTING_ALGO_FMT SYS_IFACE_PATH"/%s/mesh/routing_algo" static void ra_mode_usage(void) { diff --git a/sys.c b/sys.c index e883369..482daed 100644 --- a/sys.c +++ b/sys.c @@ -47,13 +47,6 @@ const char *sysfs_param_enable[] = { NULL, }; -const char *sysfs_param_server[] = { - "off", - "client", - "server", - NULL, -}; - static void settings_usage(struct state *state) { fprintf(stderr, "Usage: batctl [options] %s|%s [parameters] %s\n", diff --git a/sys.h b/sys.h index cac2c53..1c8f23d 100644 --- a/sys.h +++ b/sys.h @@ -37,6 +37,7 @@ #define SYS_MESH_IFACE_FMT SYS_IFACE_PATH"/%s/batman_adv/mesh_iface" #define SYS_IFACE_STATUS_FMT SYS_IFACE_PATH"/%s/batman_adv/iface_status" #define SYS_VLAN_PATH SYS_IFACE_PATH"/%s/mesh/vlan%d/" +#define SYS_ROUTING_ALGO_FMT SYS_IFACE_PATH"/%s/mesh/routing_algo" #define VLAN_ID_MAX_LEN 4 struct settings_data { @@ -49,7 +50,6 @@ struct settings_data { }; extern const char *sysfs_param_enable[]; -extern const char *sysfs_param_server[]; int handle_sys_setting(struct state *state, int argc, char **argv); -- 2.19.2 From sven at narfation.org Fri Dec 7 21:31:55 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 21:31:55 +0100 Subject: [B.A.T.M.A.N.] [RFC v4 06/20] batctl: Add netlink simple query helper In-Reply-To: <20181207203209.22633-1-sven@narfation.org> References: <20181207203209.22633-1-sven@narfation.org> Message-ID: <20181207203209.22633-7-sven@narfation.org> All functions which will use the new configuration interface for meshifs, hardifs and vlans require a simple method to send messages and have one or multiple extra functionality: * add special attributes (attribute_cb) * return errors which happened during communication via netlink * parse the reply message (callback) The sys_simple_nlquery provides this but requires that the netlink socket and the single use nl_cb was allocated by the initialization helper via COMMAND_FLAG_MESH_IFACE. Signed-off-by: Sven Eckelmann --- sys.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ sys.h | 10 ++++++++++ 2 files changed, 69 insertions(+) diff --git a/sys.c b/sys.c index 482daed..a44502c 100644 --- a/sys.c +++ b/sys.c @@ -47,6 +47,65 @@ const char *sysfs_param_enable[] = { NULL, }; +static int sys_simple_nlerror(struct sockaddr_nl *nla __maybe_unused, + struct nlmsgerr *nlerr, void *arg) +{ + int *result = arg; + + if (nlerr->error != -EOPNOTSUPP) + fprintf(stderr, "Error received: %s\n", + strerror(-nlerr->error)); + + *result = nlerr->error; + + return NL_STOP; +} + +int sys_simple_nlquery(struct state *state, enum batadv_nl_commands nl_cmd, + nl_recvmsg_msg_cb_t attribute_cb, + nl_recvmsg_msg_cb_t callback) +{ + int result; + struct nl_msg *msg; + int ret; + + if (!state->sock) + return -EOPNOTSUPP; + + if (callback) { + result = -EOPNOTSUPP; + nl_cb_set(state->cb, NL_CB_VALID, NL_CB_CUSTOM, callback, + &result); + } else { + result = 0; + } + + nl_cb_err(state->cb, NL_CB_CUSTOM, sys_simple_nlerror, &result); + + msg = nlmsg_alloc(); + if (!msg) + return -ENOMEM; + + genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, state->batadv_family, 0, 0, + nl_cmd, 1); + nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, state->mesh_ifindex); + + if (attribute_cb) { + ret = attribute_cb(msg, state); + if (ret < 0) { + nlmsg_free(msg); + return -ENOMEM; + } + } + + nl_send_auto_complete(state->sock, msg); + nlmsg_free(msg); + + nl_recvmsgs(state->sock, state->cb); + + return result; +} + static void settings_usage(struct state *state) { fprintf(stderr, "Usage: batctl [options] %s|%s [parameters] %s\n", diff --git a/sys.h b/sys.h index 1c8f23d..57224d5 100644 --- a/sys.h +++ b/sys.h @@ -25,6 +25,12 @@ #include "main.h" +#include +#include + +#include "batman_adv.h" +#include "netlink.h" + #define SYS_BATIF_PATH_FMT "/sys/class/net/%s/mesh/" #define SYS_LOG_LEVEL "log_level" #define SYS_LOG "log" @@ -53,4 +59,8 @@ extern const char *sysfs_param_enable[]; int handle_sys_setting(struct state *state, int argc, char **argv); +int sys_simple_nlquery(struct state *state, enum batadv_nl_commands nl_cmd, + nl_recvmsg_msg_cb_t attribute_cb, + nl_recvmsg_msg_cb_t callback); + #endif -- 2.19.2 From sven at narfation.org Fri Dec 7 21:31:56 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 21:31:56 +0100 Subject: [B.A.T.M.A.N.] [RFC v4 07/20] batctl: Support generic netlink for gw_mode command In-Reply-To: <20181207203209.22633-1-sven@narfation.org> References: <20181207203209.22633-1-sven@narfation.org> Message-ID: <20181207203209.22633-8-sven@narfation.org> sysfs should be avoided for new settings of network interfaces. To still provide a common configuration infrastructure, all the existing settings subcommands also have to be reimplemented via generic netlink while still using sysfs as fallback. The gw_mode implementation is using the commands BATADV_CMD_SET_MESH/BATADV_CMD_GET_MESH to set/get the configuration of this feature using the attributes: * u8 BATADV_ATTR_GW_MODE (0 == off, 1 == client, 2 == server) * u32 BATADV_ATTR_GW_BANDWIDTH_DOWN (in 100 kbit/s steps) * u32 BATADV_ATTR_GW_BANDWIDTH_UP (in 100 kbit/s steps) * u32 BATADV_ATTR_GW_SEL_CLASS - 1-255 for BATMAN_IV - 1-UINT32_MAX for BATMAN_V Signed-off-by: Sven Eckelmann --- Cc: Marek Lindner Cc: Antonio Quartulli --- gw_mode.c | 275 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 206 insertions(+), 69 deletions(-) diff --git a/gw_mode.c b/gw_mode.c index 167b777..477a1ff 100644 --- a/gw_mode.c +++ b/gw_mode.c @@ -162,80 +162,233 @@ static int parse_gw(struct state *state, int argc, char *argv[]) return 0; } -static int gw_mode(struct state *state, int argc, char **argv) +static int print_gw(struct nl_msg *msg, void *arg) { - int optchar, res = EXIT_FAILURE; - char *path_buff, gw_mode; + static const int mandatory[] = { + BATADV_ATTR_GW_MODE, + }; + static const int mandatory_client[] = { + BATADV_ATTR_ALGO_NAME, + BATADV_ATTR_GW_SEL_CLASS, + }; + static const int mandatory_server[] = { + BATADV_ATTR_GW_BANDWIDTH_DOWN, + BATADV_ATTR_GW_BANDWIDTH_UP, + }; + struct nlattr *attrs[BATADV_ATTR_MAX + 1]; + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct genlmsghdr *ghdr; + int *result = arg; + const char *algo; + uint8_t gw_mode; + uint32_t val; + uint32_t down; + uint32_t up; + + if (!genlmsg_valid_hdr(nlh, 0)) + return NL_OK; + + ghdr = nlmsg_data(nlh); + + if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), + genlmsg_len(ghdr), batadv_netlink_policy)) { + return NL_OK; + } - while ((optchar = getopt(argc, argv, "h")) != -1) { - switch (optchar) { - case 'h': - gw_mode_usage(); - return EXIT_SUCCESS; - default: - gw_mode_usage(); - return EXIT_FAILURE; - } + /* ignore entry when attributes are missing */ + if (missing_mandatory_attrs(attrs, mandatory, ARRAY_SIZE(mandatory))) + return NL_OK; + + gw_mode = nla_get_u8(attrs[BATADV_ATTR_GW_MODE]); + switch (gw_mode) { + case BATADV_GW_MODE_OFF: + printf("off\n"); + break; + case BATADV_GW_MODE_CLIENT: + if (missing_mandatory_attrs(attrs, mandatory_client, + ARRAY_SIZE(mandatory_client))) + return NL_OK; + + algo = nla_data(attrs[BATADV_ATTR_ALGO_NAME]); + val = nla_get_u32(attrs[BATADV_ATTR_GW_SEL_CLASS]); + + if (strcmp(algo, "BATMAN_V") == 0) + printf("client (selection class: %u.%01u MBit)\n", + val / 10, val % 10); + else + printf("client (selection class: %u)\n", val); + break; + case BATADV_GW_MODE_SERVER: + if (missing_mandatory_attrs(attrs, mandatory_server, + ARRAY_SIZE(mandatory_server))) + return NL_OK; + + down = nla_get_u32(attrs[BATADV_ATTR_GW_BANDWIDTH_DOWN]); + up = nla_get_u32(attrs[BATADV_ATTR_GW_BANDWIDTH_UP]); + + printf("server (announced bw: %u.%01u/%u.%01u MBit)\n", + down / 10, down % 10, up / 10, up % 10); + break; + default: + printf("unknown\n"); + break; } - path_buff = malloc(PATH_BUFF_LEN); - if (!path_buff) { - fprintf(stderr, "Error - could not allocate path buffer: out of memory ?\n"); + *result = 0; + return NL_STOP; +} + +static int get_gw(struct state *state) +{ + return sys_simple_nlquery(state, BATADV_CMD_GET_MESH, NULL, print_gw); +} + +static int set_attrs_gw(struct nl_msg *msg, void *arg __maybe_unused) +{ + nla_put_u8(msg, BATADV_ATTR_GW_MODE, gw_globals.mode); + + if (gw_globals.bandwidth_down_found) + nla_put_u32(msg, BATADV_ATTR_GW_BANDWIDTH_DOWN, + gw_globals.bandwidth_down); + + if (gw_globals.bandwidth_up_found) + nla_put_u32(msg, BATADV_ATTR_GW_BANDWIDTH_UP, + gw_globals.bandwidth_up); + + if (gw_globals.sel_class_found) + nla_put_u32(msg, BATADV_ATTR_GW_SEL_CLASS, + gw_globals.sel_class); + + return 0; +} + +static int set_gw(struct state *state) +{ + return sys_simple_nlquery(state, BATADV_CMD_SET_MESH, set_attrs_gw, + NULL); +} + +static int gw_read_setting(struct state *state, const char *path_buff) +{ + enum batadv_gw_modes gw_mode; + int res; + + res = get_gw(state); + if (res < 0 && res != -EOPNOTSUPP) return EXIT_FAILURE; + if (res >= 0) + return EXIT_SUCCESS; + + /* fallback to sysfs */ + res = read_file(path_buff, SYS_GW_MODE, USE_READ_BUFF, 0, 0, 0); + if (res != EXIT_SUCCESS) + goto out; + + if (line_ptr[strlen(line_ptr) - 1] == '\n') + line_ptr[strlen(line_ptr) - 1] = '\0'; + + if (strcmp(line_ptr, "client") == 0) + gw_mode = BATADV_GW_MODE_CLIENT; + else if (strcmp(line_ptr, "server") == 0) + gw_mode = BATADV_GW_MODE_SERVER; + else + gw_mode = BATADV_GW_MODE_OFF; + + free(line_ptr); + line_ptr = NULL; + + switch (gw_mode) { + case BATADV_GW_MODE_CLIENT: + res = read_file(path_buff, SYS_GW_SEL, USE_READ_BUFF, 0, 0, 0); + break; + case BATADV_GW_MODE_SERVER: + res = read_file(path_buff, SYS_GW_BW, USE_READ_BUFF, 0, 0, 0); + break; + default: + printf("off\n"); + goto out; } - snprintf(path_buff, PATH_BUFF_LEN, SYS_BATIF_PATH_FMT, state->mesh_iface); + if (res != EXIT_SUCCESS) + goto out; - if (argc == 1) { - res = read_file(path_buff, SYS_GW_MODE, USE_READ_BUFF, 0, 0, 0); + if (line_ptr[strlen(line_ptr) - 1] == '\n') + line_ptr[strlen(line_ptr) - 1] = '\0'; - if (res != EXIT_SUCCESS) - goto out; + switch (gw_mode) { + case BATADV_GW_MODE_CLIENT: + printf("client (selection class: %s)\n", line_ptr); + break; + case BATADV_GW_MODE_SERVER: + printf("server (announced bw: %s)\n", line_ptr); + break; + default: + goto out; + } - if (line_ptr[strlen(line_ptr) - 1] == '\n') - line_ptr[strlen(line_ptr) - 1] = '\0'; +out: + free(line_ptr); + line_ptr = NULL; - if (strcmp(line_ptr, "client") == 0) - gw_mode = BATADV_GW_MODE_CLIENT; - else if (strcmp(line_ptr, "server") == 0) - gw_mode = BATADV_GW_MODE_SERVER; - else - gw_mode = BATADV_GW_MODE_OFF; + return res; +} + +static int gw_write_setting(struct state *state, const char *path_buff, + int argc, char *argv[]) +{ + int res = EXIT_FAILURE; + + res = set_gw(state); + if (res < 0 && res != -EOPNOTSUPP) + return EXIT_FAILURE; + if (res >= 0) + return EXIT_SUCCESS; - free(line_ptr); - line_ptr = NULL; + /* sysfs fallback */ + res = write_file(path_buff, SYS_GW_MODE, argv[1], NULL); + if (res != EXIT_SUCCESS) + return res; - switch (gw_mode) { + if (argc > 2) { + switch (gw_globals.mode) { case BATADV_GW_MODE_CLIENT: - res = read_file(path_buff, SYS_GW_SEL, USE_READ_BUFF, 0, 0, 0); + res = write_file(path_buff, SYS_GW_SEL, argv[2], NULL); break; case BATADV_GW_MODE_SERVER: - res = read_file(path_buff, SYS_GW_BW, USE_READ_BUFF, 0, 0, 0); + res = write_file(path_buff, SYS_GW_BW, argv[2], NULL); break; - default: - printf("off\n"); - goto out; } + } - if (res != EXIT_SUCCESS) - goto out; + return res; +} - if (line_ptr[strlen(line_ptr) - 1] == '\n') - line_ptr[strlen(line_ptr) - 1] = '\0'; +static int gw_mode(struct state *state, int argc, char **argv) +{ + int optchar, res = EXIT_FAILURE; + char *path_buff; - switch (gw_mode) { - case BATADV_GW_MODE_CLIENT: - printf("client (selection class: %s)\n", line_ptr); - break; - case BATADV_GW_MODE_SERVER: - printf("server (announced bw: %s)\n", line_ptr); - break; + while ((optchar = getopt(argc, argv, "h")) != -1) { + switch (optchar) { + case 'h': + gw_mode_usage(); + return EXIT_SUCCESS; default: - goto out; + gw_mode_usage(); + return EXIT_FAILURE; } + } - free(line_ptr); - line_ptr = NULL; + path_buff = malloc(PATH_BUFF_LEN); + if (!path_buff) { + fprintf(stderr, "Error - could not allocate path buffer: out of memory ?\n"); + return EXIT_FAILURE; + } + + snprintf(path_buff, PATH_BUFF_LEN, SYS_BATIF_PATH_FMT, state->mesh_iface); + + if (argc == 1) { + res = gw_read_setting(state, path_buff); goto out; } @@ -247,28 +400,12 @@ static int gw_mode(struct state *state, int argc, char **argv) goto out; } - res = write_file(path_buff, SYS_GW_MODE, argv[1], NULL); - if (res != EXIT_SUCCESS) - goto out; - - if (argc == 2) - goto out; - - switch (gw_globals.mode) { - case BATADV_GW_MODE_CLIENT: - res = write_file(path_buff, SYS_GW_SEL, argv[2], NULL); - break; - case BATADV_GW_MODE_SERVER: - res = write_file(path_buff, SYS_GW_BW, argv[2], NULL); - break; - } - - goto out; - + res = gw_write_setting(state, path_buff, argc, argv); out: free(path_buff); return res; } -COMMAND(SUBCOMMAND, gw_mode, "gw", COMMAND_FLAG_MESH_IFACE, NULL, +COMMAND(SUBCOMMAND, gw_mode, "gw", + COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK, NULL, "[mode] \tdisplay or modify the gateway mode"); -- 2.19.2 From sven at narfation.org Fri Dec 7 21:31:57 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 21:31:57 +0100 Subject: [B.A.T.M.A.N.] [RFC v4 08/20] batctl: Support generic netlink for loglevel command In-Reply-To: <20181207203209.22633-1-sven@narfation.org> References: <20181207203209.22633-1-sven@narfation.org> Message-ID: <20181207203209.22633-9-sven@narfation.org> sysfs should be avoided for new settings of network interfaces. To still provide a common configuration infrastructure, all the existing settings subcommands also have to be reimplemented via generic netlink while still using sysfs as fallback. The loglevel implementation is using the commands BATADV_CMD_SET_MESH/BATADV_CMD_GET_MESH to set/get the configuration of this feature using the u32 (bitmask) BATADV_ATTR_LOG_LEVEL attribute. Signed-off-by: Sven Eckelmann --- Cc: Marek Lindner --- loglevel.c | 138 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 110 insertions(+), 28 deletions(-) diff --git a/loglevel.c b/loglevel.c index fed70c8..72e16e0 100644 --- a/loglevel.c +++ b/loglevel.c @@ -20,7 +20,9 @@ * License-Filename: LICENSES/preferred/GPL-2.0 */ +#include #include +#include #include #include #include @@ -29,6 +31,10 @@ #include "main.h" #include "sys.h" +static struct log_level_data { + uint32_t log_level; +} log_level_globals; + static void log_level_usage(void) { fprintf(stderr, "Usage: batctl [options] loglevel [parameters] [level[ level[ level]]...]\n"); @@ -47,14 +53,93 @@ static void log_level_usage(void) fprintf(stderr, " \t tp Messages related to throughput meter\n"); } +static int extract_log_level(struct nl_msg *msg, void *arg) +{ + struct nlattr *attrs[BATADV_ATTR_MAX + 1]; + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct genlmsghdr *ghdr; + int *result = arg; + + if (!genlmsg_valid_hdr(nlh, 0)) + return NL_OK; + + ghdr = nlmsg_data(nlh); + + if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), + genlmsg_len(ghdr), batadv_netlink_policy)) { + return NL_OK; + } + + if (!attrs[BATADV_ATTR_LOG_LEVEL]) + return NL_OK; + + log_level_globals.log_level = nla_get_u32(attrs[BATADV_ATTR_LOG_LEVEL]); + + *result = 0; + return NL_STOP; +} + +static int get_log_level(struct state *state) +{ + return sys_simple_nlquery(state, BATADV_CMD_GET_MESH, + NULL, extract_log_level); +} + +static int set_attrs_log_level(struct nl_msg *msg, void *arg __maybe_unused) +{ + nla_put_u32(msg, BATADV_ATTR_LOG_LEVEL, log_level_globals.log_level); + + return 0; +} + +static int set_log_level(struct state *state) +{ + return sys_simple_nlquery(state, BATADV_CMD_SET_MESH, + set_attrs_log_level, NULL); +} + +static int log_level_read_setting(struct state *state, const char *path_buff) +{ + int res; + + res = get_log_level(state); + if (res < 0 && res != -EOPNOTSUPP) + return EXIT_FAILURE; + if (res >= 0) + return EXIT_SUCCESS; + + res = read_file(path_buff, SYS_LOG_LEVEL, USE_READ_BUFF, 0, 0, 0); + if (res != EXIT_SUCCESS) + return res; + + log_level_globals.log_level = strtol(line_ptr, (char **) NULL, 10); + + return res; +} + +static int log_level_write_setting(struct state *state, const char *path_buff) +{ + int res; + char str[4]; + + res = set_log_level(state); + if (res < 0 && res != -EOPNOTSUPP) + return EXIT_FAILURE; + if (res >= 0) + return EXIT_SUCCESS; + + snprintf(str, sizeof(str), "%i", log_level_globals.log_level); + return write_file(path_buff, SYS_LOG_LEVEL, str, NULL); +} + static int loglevel(struct state *state, int argc, char **argv) { int optchar, res = EXIT_FAILURE; - int log_level = 0; char *path_buff; - char str[4]; int i; + log_level_globals.log_level = 0; + while ((optchar = getopt(argc, argv, "h")) != -1) { switch (optchar) { case 'h': @@ -79,63 +164,59 @@ static int loglevel(struct state *state, int argc, char **argv) for (i = 1; i < argc; i++) { if (strcmp(argv[i], "none") == 0) { - log_level = 0; + log_level_globals.log_level = 0; break; } else if (strcmp(argv[i], "all") == 0) { - log_level = 255; + log_level_globals.log_level = 255; break; } else if (strcmp(argv[i], "batman") == 0) - log_level |= BIT(0); + log_level_globals.log_level |= BIT(0); else if (strcmp(argv[i], "routes") == 0) - log_level |= BIT(1); + log_level_globals.log_level |= BIT(1); else if (strcmp(argv[i], "tt") == 0) - log_level |= BIT(2); + log_level_globals.log_level |= BIT(2); else if (strcmp(argv[i], "bla") == 0) - log_level |= BIT(3); + log_level_globals.log_level |= BIT(3); else if (strcmp(argv[i], "dat") == 0) - log_level |= BIT(4); + log_level_globals.log_level |= BIT(4); else if (strcmp(argv[i], "nc") == 0) - log_level |= BIT(5); + log_level_globals.log_level |= BIT(5); else if (strcmp(argv[i], "mcast") == 0) - log_level |= BIT(6); + log_level_globals.log_level |= BIT(6); else if (strcmp(argv[i], "tp") == 0) - log_level |= BIT(7); + log_level_globals.log_level |= BIT(7); else { log_level_usage(); goto out; } } - snprintf(str, sizeof(str), "%i", log_level); - res = write_file(path_buff, SYS_LOG_LEVEL, str, NULL); + log_level_write_setting(state, path_buff); goto out; } - res = read_file(path_buff, SYS_LOG_LEVEL, USE_READ_BUFF, 0, 0, 0); - + res = log_level_read_setting(state, path_buff); if (res != EXIT_SUCCESS) goto out; - log_level = strtol(line_ptr, (char **) NULL, 10); - - printf("[%c] %s (%s)\n", (!log_level) ? 'x' : ' ', + printf("[%c] %s (%s)\n", (!log_level_globals.log_level) ? 'x' : ' ', "all debug output disabled", "none"); - printf("[%c] %s (%s)\n", (log_level & BIT(0)) ? 'x' : ' ', + printf("[%c] %s (%s)\n", (log_level_globals.log_level & BIT(0)) ? 'x' : ' ', "messages related to routing / flooding / broadcasting", "batman"); - printf("[%c] %s (%s)\n", (log_level & BIT(1)) ? 'x' : ' ', + printf("[%c] %s (%s)\n", (log_level_globals.log_level & BIT(1)) ? 'x' : ' ', "messages related to route added / changed / deleted", "routes"); - printf("[%c] %s (%s)\n", (log_level & BIT(2)) ? 'x' : ' ', + printf("[%c] %s (%s)\n", (log_level_globals.log_level & BIT(2)) ? 'x' : ' ', "messages related to translation table operations", "tt"); - printf("[%c] %s (%s)\n", (log_level & BIT(3)) ? 'x' : ' ', + printf("[%c] %s (%s)\n", (log_level_globals.log_level & BIT(3)) ? 'x' : ' ', "messages related to bridge loop avoidance", "bla"); - printf("[%c] %s (%s)\n", (log_level & BIT(4)) ? 'x' : ' ', + printf("[%c] %s (%s)\n", (log_level_globals.log_level & BIT(4)) ? 'x' : ' ', "messages related to arp snooping and distributed arp table", "dat"); - printf("[%c] %s (%s)\n", (log_level & BIT(5)) ? 'x' : ' ', + printf("[%c] %s (%s)\n", (log_level_globals.log_level & BIT(5)) ? 'x' : ' ', "messages related to network coding", "nc"); - printf("[%c] %s (%s)\n", (log_level & BIT(6)) ? 'x' : ' ', + printf("[%c] %s (%s)\n", (log_level_globals.log_level & BIT(6)) ? 'x' : ' ', "messages related to multicast", "mcast"); - printf("[%c] %s (%s)\n", (log_level & BIT(7)) ? 'x' : ' ', + printf("[%c] %s (%s)\n", (log_level_globals.log_level & BIT(7)) ? 'x' : ' ', "messages related to throughput meter", "tp"); out: @@ -143,5 +224,6 @@ static int loglevel(struct state *state, int argc, char **argv) return res; } -COMMAND(SUBCOMMAND, loglevel, "ll", COMMAND_FLAG_MESH_IFACE, NULL, +COMMAND(SUBCOMMAND, loglevel, "ll", + COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK, NULL, "[level] \tdisplay or modify the log level"); -- 2.19.2 From sven at narfation.org Fri Dec 7 21:31:58 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 21:31:58 +0100 Subject: [B.A.T.M.A.N.] [RFC v4 09/20] batctl: Support generic netlink for isolation_mark command In-Reply-To: <20181207203209.22633-1-sven@narfation.org> References: <20181207203209.22633-1-sven@narfation.org> Message-ID: <20181207203209.22633-10-sven@narfation.org> sysfs should be avoided for new settings of network interfaces. To still provide a common configuration infrastructure, all the existing settings subcommands also have to be reimplemented via generic netlink while still using sysfs as fallback. The isolation_mark implementation is using the commands BATADV_CMD_SET_MESH/BATADV_CMD_GET_MESH to set/get the configuration of the mark/mask using the u32 attributes BATADV_ATTR_ISOLATION_MARK and BATADV_ATTR_ISOLATION_MASK. Signed-off-by: Sven Eckelmann --- Cc: Antonio Quartulli --- isolation_mark.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 121 insertions(+), 2 deletions(-) diff --git a/isolation_mark.c b/isolation_mark.c index 13ba869..461053f 100644 --- a/isolation_mark.c +++ b/isolation_mark.c @@ -20,16 +20,135 @@ * License-Filename: LICENSES/preferred/GPL-2.0 */ +#include #include +#include +#include #include "main.h" #include "sys.h" +static struct isolation_mark_data { + uint32_t isolation_mark; + uint32_t isolation_mask; +} isolation_mark; + +static int parse_isolation_mark(struct state *state, int argc, char *argv[]) +{ + struct settings_data *settings = state->cmd->arg; + struct isolation_mark_data *data = settings->data; + char *mask_ptr; + char buff[256]; + uint32_t mark; + uint32_t mask; + char *endptr; + + if (argc != 2) { + fprintf(stderr, "Error - incorrect number of arguments (expected 1)\n"); + return -EINVAL; + } + + strncpy(buff, argv[1], sizeof(buff)); + buff[sizeof(buff) - 1] = '\0'; + + /* parse the mask if it has been specified, otherwise assume the mask is + * the biggest possible + */ + mask = 0xFFFFFFFF; + mask_ptr = strchr(buff, '/'); + if (mask_ptr) { + *mask_ptr = '\0'; + mask_ptr++; + + /* the mask must be entered in hex base as it is going to be a + * bitmask and not a prefix length + */ + mask = strtoul(mask_ptr, &endptr, 16); + if (!endptr || *endptr != '\0') + goto inval_format; + } + + /* the mark can be entered in any base */ + mark = strtoul(buff, &endptr, 0); + if (!endptr || *endptr != '\0') + goto inval_format; + + data->isolation_mask = mask; + /* erase bits not covered by the mask */ + data->isolation_mark = mark & mask; + + return 0; + +inval_format: + fprintf(stderr, "Error - incorrect number of arguments (expected 1)\n"); + fprintf(stderr, "The following formats for mark(/mask) are allowed:\n"); + fprintf(stderr, " * 0x12345678\n"); + fprintf(stderr, " * 0x12345678/0xabcdef09\n"); + return -EINVAL; +} + +static int print_isolation_mark(struct nl_msg *msg, void *arg) +{ + struct nlattr *attrs[BATADV_ATTR_MAX + 1]; + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct genlmsghdr *ghdr; + int *result = arg; + + if (!genlmsg_valid_hdr(nlh, 0)) + return NL_OK; + + ghdr = nlmsg_data(nlh); + + if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), + genlmsg_len(ghdr), batadv_netlink_policy)) { + return NL_OK; + } + + if (!attrs[BATADV_ATTR_ISOLATION_MARK] || + !attrs[BATADV_ATTR_ISOLATION_MASK]) + return NL_OK; + + printf("0x%08x/0x%08x\n", + nla_get_u32(attrs[BATADV_ATTR_ISOLATION_MARK]), + nla_get_u32(attrs[BATADV_ATTR_ISOLATION_MASK])); + + *result = 0; + return NL_STOP; +} + +static int get_isolation_mark(struct state *state) +{ + return sys_simple_nlquery(state, BATADV_CMD_GET_MESH, + NULL, print_isolation_mark); +} + +static int set_attrs_isolation_mark(struct nl_msg *msg, void *arg) +{ + struct state *state = arg; + struct settings_data *settings = state->cmd->arg; + struct isolation_mark_data *data = settings->data; + + nla_put_u32(msg, BATADV_ATTR_ISOLATION_MARK, data->isolation_mark); + nla_put_u32(msg, BATADV_ATTR_ISOLATION_MASK, data->isolation_mask); + + return 0; +} + +static int set_isolation_mark(struct state *state) +{ + return sys_simple_nlquery(state, BATADV_CMD_SET_MESH, + set_attrs_isolation_mark, NULL); +} + static struct settings_data batctl_settings_isolation_mark = { .sysfs_name = "isolation_mark", - .params = NULL, + .data = &isolation_mark, + .parse = parse_isolation_mark, + .netlink_get = get_isolation_mark, + .netlink_set = set_isolation_mark, }; COMMAND_NAMED(SUBCOMMAND, isolation_mark, "mark", handle_sys_setting, - COMMAND_FLAG_MESH_IFACE, &batctl_settings_isolation_mark, + COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK, + &batctl_settings_isolation_mark, "[mark] \tdisplay or modify isolation_mark setting"); -- 2.19.2 From sven at narfation.org Fri Dec 7 21:31:59 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 21:31:59 +0100 Subject: [B.A.T.M.A.N.] [RFC v4 10/20] batctl: Support generic netlink for orig_interval command In-Reply-To: <20181207203209.22633-1-sven@narfation.org> References: <20181207203209.22633-1-sven@narfation.org> Message-ID: <20181207203209.22633-11-sven@narfation.org> sysfs should be avoided for new settings of network interfaces. To still provide a common configuration infrastructure, all the existing settings subcommands also have to be reimplemented via generic netlink while still using sysfs as fallback. The orig_interval implementation is using the commands BATADV_CMD_SET_MESH/BATADV_CMD_GET_MESH to set/get the configuration of the u32 BATADV_ATTR_ORIG_INTERVAL attribute. Signed-off-by: Sven Eckelmann --- Cc: Marek Lindner --- orig_interval.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/orig_interval.c b/orig_interval.c index d308ea2..6dd0039 100644 --- a/orig_interval.c +++ b/orig_interval.c @@ -20,16 +20,96 @@ * License-Filename: LICENSES/preferred/GPL-2.0 */ +#include #include +#include +#include #include "main.h" #include "sys.h" +static struct orig_interval_data { + uint32_t orig_interval; +} orig_interval; + +static int parse_orig_interval(struct state *state, int argc, char *argv[]) +{ + struct settings_data *settings = state->cmd->arg; + struct orig_interval_data *data = settings->data; + char *endptr; + + if (argc != 2) { + fprintf(stderr, "Error - incorrect number of arguments (expected 1)\n"); + return -EINVAL; + } + + data->orig_interval = strtoul(argv[1], &endptr, 0); + if (!endptr || *endptr != '\0') { + fprintf(stderr, "Error - the supplied argument is invalid: %s\n", argv[1]); + return -EINVAL; + } + + return 0; +} + +static int print_orig_interval(struct nl_msg *msg, void *arg) +{ + struct nlattr *attrs[BATADV_ATTR_MAX + 1]; + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct genlmsghdr *ghdr; + int *result = arg; + + if (!genlmsg_valid_hdr(nlh, 0)) + return NL_OK; + + ghdr = nlmsg_data(nlh); + + if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), + genlmsg_len(ghdr), batadv_netlink_policy)) { + return NL_OK; + } + + if (!attrs[BATADV_ATTR_ORIG_INTERVAL]) + return NL_OK; + + printf("%u\n", nla_get_u32(attrs[BATADV_ATTR_ORIG_INTERVAL])); + + *result = 0; + return NL_STOP; +} + +static int get_orig_interval(struct state *state) +{ + return sys_simple_nlquery(state, BATADV_CMD_GET_MESH, + NULL, print_orig_interval); +} + +static int set_attrs_orig_interval(struct nl_msg *msg, void *arg) +{ + struct state *state = arg; + struct settings_data *settings = state->cmd->arg; + struct orig_interval_data *data = settings->data; + + nla_put_u32(msg, BATADV_ATTR_ORIG_INTERVAL, data->orig_interval); + + return 0; +} + +static int set_orig_interval(struct state *state) +{ + return sys_simple_nlquery(state, BATADV_CMD_SET_MESH, + set_attrs_orig_interval, NULL); +} + static struct settings_data batctl_settings_orig_interval = { .sysfs_name = "orig_interval", - .params = NULL, + .data = &orig_interval, + .parse = parse_orig_interval, + .netlink_get = get_orig_interval, + .netlink_set = set_orig_interval, }; COMMAND_NAMED(SUBCOMMAND, orig_interval, "it", handle_sys_setting, - COMMAND_FLAG_MESH_IFACE, &batctl_settings_orig_interval, + COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK, + &batctl_settings_orig_interval, "[interval] \tdisplay or modify orig_interval setting"); -- 2.19.2 From sven at narfation.org Fri Dec 7 21:32:00 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 21:32:00 +0100 Subject: [B.A.T.M.A.N.] [RFC v4 11/20] batctl: Add helper to read/write boolean configuration values In-Reply-To: <20181207203209.22633-1-sven@narfation.org> References: <20181207203209.22633-1-sven@narfation.org> Message-ID: <20181207203209.22633-12-sven@narfation.org> Most of the available settings commands in batctl only operate on a single boolean value. Both the reading, parsing and writing of these values can mostly be handled by the same set of helper functions. Only the actual setting/getting of the correct attribute has to be handled by the actual settings command implementation. Signed-off-by: Sven Eckelmann --- functions.c | 17 +++++++++++++++++ functions.h | 1 + sys.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++ sys.h | 8 ++++++++ 4 files changed, 81 insertions(+) diff --git a/functions.c b/functions.c index ead7e97..bb6dc31 100644 --- a/functions.c +++ b/functions.c @@ -1201,6 +1201,23 @@ void check_root_or_die(const char *cmd) } } +int parse_bool(const char *val, bool *res) +{ + if (strcasecmp(val, "0") == 0 || + strcasecmp(val, "disable") == 0 || + strcasecmp(val, "disabled") == 0) { + *res = false; + return 0; + } else if (strcasecmp(val, "1") == 0 || + strcasecmp(val, "enable") == 0 || + strcasecmp(val, "enabled") == 0) { + *res = true; + return 0; + } + + return -EINVAL; +} + bool parse_throughput(char *buff, const char *description, uint32_t *throughput) { enum batadv_bandwidth_units bw_unit_type = BATADV_BW_UNIT_KBIT; diff --git a/functions.h b/functions.h index 4a6ab61..5f39104 100644 --- a/functions.h +++ b/functions.h @@ -72,6 +72,7 @@ int check_mesh_iface_ownership(char *mesh_iface, char *hard_iface); void get_random_bytes(void *buf, size_t buflen); void check_root_or_die(const char *cmd); +int parse_bool(const char *val, bool *res); bool parse_throughput(char *buff, const char *description, uint32_t *throughput); diff --git a/sys.c b/sys.c index a44502c..ede8b09 100644 --- a/sys.c +++ b/sys.c @@ -47,6 +47,34 @@ const char *sysfs_param_enable[] = { NULL, }; +int parse_simple_boolean(struct state *state, int argc, char *argv[]) +{ + struct settings_data *settings = state->cmd->arg; + struct simple_boolean_data *data = settings->data; + int ret; + + if (argc != 2) { + fprintf(stderr, "Error - incorrect number of arguments (expected 1)\n"); + return -EINVAL; + } + + ret = parse_bool(argv[1], &data->val); + if (ret < 0) { + fprintf(stderr, "Error - the supplied argument is invalid: %s\n", argv[1]); + fprintf(stderr, "The following values are allowed:\n"); + fprintf(stderr, " * 0\n"); + fprintf(stderr, " * disable\n"); + fprintf(stderr, " * disabled\n"); + fprintf(stderr, " * 1\n"); + fprintf(stderr, " * enable\n"); + fprintf(stderr, " * enabled\n"); + + return ret; + } + + return 0; +} + static int sys_simple_nlerror(struct sockaddr_nl *nla __maybe_unused, struct nlmsgerr *nlerr, void *arg) { @@ -106,6 +134,33 @@ int sys_simple_nlquery(struct state *state, enum batadv_nl_commands nl_cmd, return result; } +int sys_simple_print_boolean(struct nl_msg *msg, void *arg, + enum batadv_nl_attrs attr) +{ + struct nlattr *attrs[BATADV_ATTR_MAX + 1]; + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct genlmsghdr *ghdr; + int *result = arg; + + if (!genlmsg_valid_hdr(nlh, 0)) + return NL_OK; + + ghdr = nlmsg_data(nlh); + + if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), + genlmsg_len(ghdr), batadv_netlink_policy)) { + return NL_OK; + } + + if (!attrs[attr]) + return NL_OK; + + printf("%s\n", nla_get_u8(attrs[attr]) ? "enabled" : "disabled"); + + *result = 0; + return NL_STOP; +} + static void settings_usage(struct state *state) { fprintf(stderr, "Usage: batctl [options] %s|%s [parameters] %s\n", diff --git a/sys.h b/sys.h index 57224d5..f32f134 100644 --- a/sys.h +++ b/sys.h @@ -27,6 +27,7 @@ #include #include +#include #include "batman_adv.h" #include "netlink.h" @@ -57,10 +58,17 @@ struct settings_data { extern const char *sysfs_param_enable[]; +struct simple_boolean_data { + bool val; +}; + int handle_sys_setting(struct state *state, int argc, char **argv); +int parse_simple_boolean(struct state *state, int argc, char *argv[]); int sys_simple_nlquery(struct state *state, enum batadv_nl_commands nl_cmd, nl_recvmsg_msg_cb_t attribute_cb, nl_recvmsg_msg_cb_t callback); +int sys_simple_print_boolean(struct nl_msg *msg, void *arg, + enum batadv_nl_attrs attr); #endif -- 2.19.2 From sven at narfation.org Fri Dec 7 21:32:01 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 21:32:01 +0100 Subject: [B.A.T.M.A.N.] [RFC v4 12/20] batctl: Support generic netlink for aggregation command In-Reply-To: <20181207203209.22633-1-sven@narfation.org> References: <20181207203209.22633-1-sven@narfation.org> Message-ID: <20181207203209.22633-13-sven@narfation.org> sysfs should be avoided for new settings of network interfaces. To still provide a common configuration infrastructure, all the existing settings subcommands also have to be reimplemented via generic netlink while still using sysfs as fallback. The aggregation implementation is using the commands BATADV_CMD_SET_MESH/BATADV_CMD_GET_MESH to set/get the configuration of the u8 (boolean) BATADV_ATTR_AGGREGATED_OGMS attribute. Signed-off-by: Sven Eckelmann --- Cc: Marek Lindner --- aggregation.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/aggregation.c b/aggregation.c index 57c1dbb..fa6610c 100644 --- a/aggregation.c +++ b/aggregation.c @@ -21,13 +21,54 @@ */ #include "main.h" + +#include +#include +#include + +#include "batman_adv.h" +#include "netlink.h" #include "sys.h" +static struct simple_boolean_data aggregated_ogms; + +static int print_aggregated_ogms(struct nl_msg *msg, void *arg) +{ + return sys_simple_print_boolean(msg, arg, BATADV_ATTR_AGGREGATED_OGMS); +} + +static int get_aggregated_ogms(struct state *state) +{ + return sys_simple_nlquery(state, BATADV_CMD_GET_MESH, + NULL, print_aggregated_ogms); +} + +static int set_attrs_aggregated_ogms(struct nl_msg *msg, void *arg) +{ + struct state *state = arg; + struct settings_data *settings = state->cmd->arg; + struct simple_boolean_data *data = settings->data; + + nla_put_u8(msg, BATADV_ATTR_AGGREGATED_OGMS, data->val); + + return 0; +} + +static int set_aggregated_ogms(struct state *state) +{ + return sys_simple_nlquery(state, BATADV_CMD_SET_MESH, + set_attrs_aggregated_ogms, NULL); +} + static struct settings_data batctl_settings_aggregation = { .sysfs_name = "aggregated_ogms", - .params = sysfs_param_enable, + .data = &aggregated_ogms, + .parse = parse_simple_boolean, + .netlink_get = get_aggregated_ogms, + .netlink_set = set_aggregated_ogms, }; COMMAND_NAMED(SUBCOMMAND, aggregation, "ag", handle_sys_setting, - COMMAND_FLAG_MESH_IFACE, &batctl_settings_aggregation, + COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK, + &batctl_settings_aggregation, "[0|1] \tdisplay or modify aggregation setting"); -- 2.19.2 From sven at narfation.org Fri Dec 7 21:32:02 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 21:32:02 +0100 Subject: [B.A.T.M.A.N.] [RFC v4 13/20] batctl: Support generic netlink for ap_isolation command In-Reply-To: <20181207203209.22633-1-sven@narfation.org> References: <20181207203209.22633-1-sven@narfation.org> Message-ID: <20181207203209.22633-14-sven@narfation.org> sysfs should be avoided for new settings of network interfaces. To still provide a common configuration infrastructure, all the existing settings subcommands also have to be reimplemented via generic netlink while still using sysfs as fallback. The ap_isolation implementation is using the commands BATADV_CMD_SET_MESH/BATADV_CMD_GET_MESH and BATADV_CMD_SET_VLAN/BATADV_CMD_GET_VLAN to set/get the configuration of the u8 (boolean) BATADV_ATTR_AP_ISOLATION attribute. Signed-off-by: Sven Eckelmann --- Cc: Antonio Quartulli --- ap_isolation.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/ap_isolation.c b/ap_isolation.c index 2d16c68..c9fd336 100644 --- a/ap_isolation.c +++ b/ap_isolation.c @@ -21,13 +21,76 @@ */ #include "main.h" + +#include +#include +#include + +#include "batman_adv.h" +#include "netlink.h" #include "sys.h" +static struct simple_boolean_data ap_isolation; + +static int print_ap_isolation(struct nl_msg *msg, void *arg) +{ + return sys_simple_print_boolean(msg, arg, BATADV_ATTR_AP_ISOLATION); +} + +static int get_attrs_ap_isolation(struct nl_msg *msg, void *arg) +{ + struct state *state = arg; + + if (state->vid >= 0) + nla_put_u16(msg, BATADV_ATTR_VLANID, state->vid); + + return 0; +} + +static int get_ap_isolation(struct state *state) +{ + enum batadv_nl_commands nl_cmd = BATADV_CMD_SET_MESH; + + if (state->vid >= 0) + nl_cmd = BATADV_CMD_GET_VLAN; + + return sys_simple_nlquery(state, nl_cmd, get_attrs_ap_isolation, + print_ap_isolation); +} + +static int set_attrs_ap_isolation(struct nl_msg *msg, void *arg) +{ + struct state *state = arg; + struct settings_data *settings = state->cmd->arg; + struct simple_boolean_data *data = settings->data; + + nla_put_u8(msg, BATADV_ATTR_AP_ISOLATION, data->val); + + if (state->vid >= 0) + nla_put_u16(msg, BATADV_ATTR_VLANID, state->vid); + + return 0; +} + +static int set_ap_isolation(struct state *state) +{ + enum batadv_nl_commands nl_cmd = BATADV_CMD_SET_MESH; + + if (state->vid >= 0) + nl_cmd = BATADV_CMD_SET_VLAN; + + return sys_simple_nlquery(state, nl_cmd, set_attrs_ap_isolation, NULL); +} + static struct settings_data batctl_settings_ap_isolation = { .sysfs_name = "ap_isolation", - .params = sysfs_param_enable, + .data = &ap_isolation, + .parse = parse_simple_boolean, + .netlink_get = get_ap_isolation, + .netlink_set = set_ap_isolation, }; COMMAND_NAMED(SUBCOMMAND, ap_isolation, "ap", handle_sys_setting, - COMMAND_FLAG_MESH_IFACE, &batctl_settings_ap_isolation, + COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK, + &batctl_settings_ap_isolation, "[0|1] \tdisplay or modify ap_isolation setting"); -- 2.19.2 From sven at narfation.org Fri Dec 7 21:32:03 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 21:32:03 +0100 Subject: [B.A.T.M.A.N.] [RFC v4 14/20] batctl: Support generic netlink for bonding command In-Reply-To: <20181207203209.22633-1-sven@narfation.org> References: <20181207203209.22633-1-sven@narfation.org> Message-ID: <20181207203209.22633-15-sven@narfation.org> sysfs should be avoided for new settings of network interfaces. To still provide a common configuration infrastructure, all the existing settings subcommands also have to be reimplemented via generic netlink while still using sysfs as fallback. The bonding implementation is using the commands BATADV_CMD_SET_MESH/BATADV_CMD_GET_MESH to set/get the configuration of the u8 (boolean) BATADV_ATTR_BONDING attribute. Signed-off-by: Sven Eckelmann --- Cc: Simon Wunderlich --- bonding.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/bonding.c b/bonding.c index f7105c9..3b8b11b 100644 --- a/bonding.c +++ b/bonding.c @@ -21,13 +21,54 @@ */ #include "main.h" + +#include +#include +#include + +#include "batman_adv.h" +#include "netlink.h" #include "sys.h" +static struct simple_boolean_data bonding; + +static int print_bonding(struct nl_msg *msg, void *arg) +{ + return sys_simple_print_boolean(msg, arg, BATADV_ATTR_BONDING); +} + +static int get_bonding(struct state *state) +{ + return sys_simple_nlquery(state, BATADV_CMD_GET_MESH, + NULL, print_bonding); +} + +static int set_attrs_bonding(struct nl_msg *msg, void *arg) +{ + struct state *state = arg; + struct settings_data *settings = state->cmd->arg; + struct simple_boolean_data *data = settings->data; + + nla_put_u8(msg, BATADV_ATTR_BONDING, data->val); + + return 0; +} + +static int set_bonding(struct state *state) +{ + return sys_simple_nlquery(state, BATADV_CMD_SET_MESH, + set_attrs_bonding, NULL); +} + static struct settings_data batctl_settings_bonding = { .sysfs_name = "bonding", - .params = sysfs_param_enable, + .data = &bonding, + .parse = parse_simple_boolean, + .netlink_get = get_bonding, + .netlink_set = set_bonding, }; COMMAND_NAMED(SUBCOMMAND, bonding, "b", handle_sys_setting, - COMMAND_FLAG_MESH_IFACE, &batctl_settings_bonding, + COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK, + &batctl_settings_bonding, "[0|1] \tdisplay or modify bonding setting"); -- 2.19.2 From sven at narfation.org Fri Dec 7 21:32:04 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 21:32:04 +0100 Subject: [B.A.T.M.A.N.] [RFC v4 15/20] batctl: Support generic netlink for bridge_loop_avoidance command In-Reply-To: <20181207203209.22633-1-sven@narfation.org> References: <20181207203209.22633-1-sven@narfation.org> Message-ID: <20181207203209.22633-16-sven@narfation.org> sysfs should be avoided for new settings of network interfaces. To still provide a common configuration infrastructure, all the existing settings subcommands also have to be reimplemented via generic netlink while still using sysfs as fallback. The bridge_loop_avoidance implementation is using the commands BATADV_CMD_SET_MESH/BATADV_CMD_GET_MESH to set/get the configuration of the u8 (boolean) BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE attribute. Signed-off-by: Sven Eckelmann --- Cc: Simon Wunderlich --- bridge_loop_avoidance.c | 46 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/bridge_loop_avoidance.c b/bridge_loop_avoidance.c index 0db49f2..7831a19 100644 --- a/bridge_loop_avoidance.c +++ b/bridge_loop_avoidance.c @@ -21,13 +21,55 @@ */ #include "main.h" + +#include +#include +#include + +#include "batman_adv.h" +#include "netlink.h" #include "sys.h" +static struct simple_boolean_data bridge_loop_avoidance; + +static int print_bridge_loop_avoidance(struct nl_msg *msg, void *arg) +{ + return sys_simple_print_boolean(msg, arg, + BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE); +} + +static int get_bridge_loop_avoidance(struct state *state) +{ + return sys_simple_nlquery(state, BATADV_CMD_GET_MESH, + NULL, print_bridge_loop_avoidance); +} + +static int set_attrs_bridge_loop_avoidance(struct nl_msg *msg, void *arg) +{ + struct state *state = arg; + struct settings_data *settings = state->cmd->arg; + struct simple_boolean_data *data = settings->data; + + nla_put_u8(msg, BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE, data->val); + + return 0; +} + +static int set_bridge_loop_avoidance(struct state *state) +{ + return sys_simple_nlquery(state, BATADV_CMD_SET_MESH, + set_attrs_bridge_loop_avoidance, NULL); +} + static struct settings_data batctl_settings_bridge_loop_avoidance = { .sysfs_name = SYS_BLA, - .params = sysfs_param_enable, + .data = &bridge_loop_avoidance, + .parse = parse_simple_boolean, + .netlink_get = get_bridge_loop_avoidance, + .netlink_set = set_bridge_loop_avoidance, }; COMMAND_NAMED(SUBCOMMAND, bridge_loop_avoidance, "bl", handle_sys_setting, - COMMAND_FLAG_MESH_IFACE, &batctl_settings_bridge_loop_avoidance, + COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK, + &batctl_settings_bridge_loop_avoidance, "[0|1] \tdisplay or modify bridge_loop_avoidance setting"); -- 2.19.2 From sven at narfation.org Fri Dec 7 21:32:05 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 21:32:05 +0100 Subject: [B.A.T.M.A.N.] [RFC v4 16/20] batctl: Support generic netlink for distributed_arp_table command In-Reply-To: <20181207203209.22633-1-sven@narfation.org> References: <20181207203209.22633-1-sven@narfation.org> Message-ID: <20181207203209.22633-17-sven@narfation.org> sysfs should be avoided for new settings of network interfaces. To still provide a common configuration infrastructure, all the existing settings subcommands also have to be reimplemented via generic netlink while still using sysfs as fallback. The distributed_arp_table implementation is using the commands BATADV_CMD_SET_MESH/BATADV_CMD_GET_MESH to set/get the configuration of the u8 (boolean) BATADV_ATTR_DISTRIBUTED_ARP_TABLE attribute. Signed-off-by: Sven Eckelmann --- Cc: Antonio Quartulli --- distributed_arp_table.c | 46 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/distributed_arp_table.c b/distributed_arp_table.c index ba6e5b7..ab3da32 100644 --- a/distributed_arp_table.c +++ b/distributed_arp_table.c @@ -21,13 +21,55 @@ */ #include "main.h" + +#include +#include +#include + +#include "batman_adv.h" +#include "netlink.h" #include "sys.h" +static struct simple_boolean_data distributed_arp_table; + +static int print_distributed_arp_table(struct nl_msg *msg, void *arg) +{ + return sys_simple_print_boolean(msg, arg, + BATADV_ATTR_DISTRIBUTED_ARP_TABLE); +} + +static int get_distributed_arp_table(struct state *state) +{ + return sys_simple_nlquery(state, BATADV_CMD_GET_MESH, + NULL, print_distributed_arp_table); +} + +static int set_attrs_distributed_arp_table(struct nl_msg *msg, void *arg) +{ + struct state *state = arg; + struct settings_data *settings = state->cmd->arg; + struct simple_boolean_data *data = settings->data; + + nla_put_u8(msg, BATADV_ATTR_DISTRIBUTED_ARP_TABLE, data->val); + + return 0; +} + +static int set_distributed_arp_table(struct state *state) +{ + return sys_simple_nlquery(state, BATADV_CMD_SET_MESH, + set_attrs_distributed_arp_table, NULL); +} + static struct settings_data batctl_settings_distributed_arp_table = { .sysfs_name = SYS_DAT, - .params = sysfs_param_enable, + .data = &distributed_arp_table, + .parse = parse_simple_boolean, + .netlink_get = get_distributed_arp_table, + .netlink_set = set_distributed_arp_table, }; COMMAND_NAMED(SUBCOMMAND, distributed_arp_table, "dat", handle_sys_setting, - COMMAND_FLAG_MESH_IFACE, &batctl_settings_distributed_arp_table, + COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK, + &batctl_settings_distributed_arp_table, "[0|1] \tdisplay or modify distributed_arp_table setting"); -- 2.19.2 From sven at narfation.org Fri Dec 7 21:32:08 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 21:32:08 +0100 Subject: [B.A.T.M.A.N.] [RFC v4 19/20] batctl: Support generic netlink for network_coding command In-Reply-To: <20181207203209.22633-1-sven@narfation.org> References: <20181207203209.22633-1-sven@narfation.org> Message-ID: <20181207203209.22633-20-sven@narfation.org> sysfs should be avoided for new settings of network interfaces. To still provide a common configuration infrastructure, all the existing settings subcommands also have to be reimplemented via generic netlink while still using sysfs as fallback. The network_coding implementation is using the commands BATADV_CMD_SET_MESH/BATADV_CMD_GET_MESH to set/get the configuration of the u8 (boolean) BATADV_ATTR_NETWORK_CODING attribute. Signed-off-by: Sven Eckelmann --- Cc: Martin Hundeboll Cc: Marek Lindner --- network_coding.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/network_coding.c b/network_coding.c index a4c4296..1dc23ef 100644 --- a/network_coding.c +++ b/network_coding.c @@ -21,13 +21,54 @@ */ #include "main.h" + +#include +#include +#include + +#include "batman_adv.h" +#include "netlink.h" #include "sys.h" +static struct simple_boolean_data network_coding; + +static int print_network_coding(struct nl_msg *msg, void *arg) +{ + return sys_simple_print_boolean(msg, arg, BATADV_ATTR_NETWORK_CODING); +} + +static int get_network_coding(struct state *state) +{ + return sys_simple_nlquery(state, BATADV_CMD_GET_MESH, + NULL, print_network_coding); +} + +static int set_attrs_network_coding(struct nl_msg *msg, void *arg) +{ + struct state *state = arg; + struct settings_data *settings = state->cmd->arg; + struct simple_boolean_data *data = settings->data; + + nla_put_u8(msg, BATADV_ATTR_NETWORK_CODING, data->val); + + return 0; +} + +static int set_network_coding(struct state *state) +{ + return sys_simple_nlquery(state, BATADV_CMD_SET_MESH, + set_attrs_network_coding, NULL); +} + static struct settings_data batctl_settings_network_coding = { .sysfs_name = SYS_NETWORK_CODING, - .params = sysfs_param_enable, + .data = &network_coding, + .parse = parse_simple_boolean, + .netlink_get = get_network_coding, + .netlink_set = set_network_coding, }; COMMAND_NAMED(SUBCOMMAND, network_coding, "nc", handle_sys_setting, - COMMAND_FLAG_MESH_IFACE, &batctl_settings_network_coding, + COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK, + &batctl_settings_network_coding, "[0|1] \tdisplay or modify network_coding setting"); -- 2.19.2 From sven at narfation.org Fri Dec 7 21:32:07 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 21:32:07 +0100 Subject: [B.A.T.M.A.N.] [RFC v4 18/20] batctl: Support generic netlink for multicast_mode command In-Reply-To: <20181207203209.22633-1-sven@narfation.org> References: <20181207203209.22633-1-sven@narfation.org> Message-ID: <20181207203209.22633-19-sven@narfation.org> sysfs should be avoided for new settings of network interfaces. To still provide a common configuration infrastructure, all the existing settings subcommands also have to be reimplemented via generic netlink while still using sysfs as fallback. The multicast_mode implementation is using the commands BATADV_CMD_SET_MESH/BATADV_CMD_GET_MESH to set/get the configuration of the u8 (boolean) BATADV_ATTR_MULTICAST_MODE attribute. Signed-off-by: Sven Eckelmann --- Cc: Linus Lüssing --- multicast_mode.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/multicast_mode.c b/multicast_mode.c index 8542928..381b8a6 100644 --- a/multicast_mode.c +++ b/multicast_mode.c @@ -21,13 +21,54 @@ */ #include "main.h" + +#include +#include +#include + +#include "batman_adv.h" +#include "netlink.h" #include "sys.h" +static struct simple_boolean_data multicast_mode; + +static int print_multicast_mode(struct nl_msg *msg, void *arg) +{ + return sys_simple_print_boolean(msg, arg, BATADV_ATTR_MULTICAST_MODE); +} + +static int get_multicast_mode(struct state *state) +{ + return sys_simple_nlquery(state, BATADV_CMD_GET_MESH, + NULL, print_multicast_mode); +} + +static int set_attrs_multicast_mode(struct nl_msg *msg, void *arg) +{ + struct state *state = arg; + struct settings_data *settings = state->cmd->arg; + struct simple_boolean_data *data = settings->data; + + nla_put_u8(msg, BATADV_ATTR_MULTICAST_MODE, data->val); + + return 0; +} + +static int set_multicast_mode(struct state *state) +{ + return sys_simple_nlquery(state, BATADV_CMD_SET_MESH, + set_attrs_multicast_mode, NULL); +} + static struct settings_data batctl_settings_multicast_mode = { .sysfs_name = SYS_MULTICAST_MODE, - .params = sysfs_param_enable, + .data = &multicast_mode, + .parse = parse_simple_boolean, + .netlink_get = get_multicast_mode, + .netlink_set = set_multicast_mode, }; COMMAND_NAMED(SUBCOMMAND, multicast_mode, "mm", handle_sys_setting, - COMMAND_FLAG_MESH_IFACE, &batctl_settings_multicast_mode, + COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK, + &batctl_settings_multicast_mode, "[0|1] \tdisplay or modify multicast_mode setting"); -- 2.19.2 From sven at narfation.org Fri Dec 7 21:32:09 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 21:32:09 +0100 Subject: [B.A.T.M.A.N.] [RFC v4 20/20] batctl: Drop settings_date param lists In-Reply-To: <20181207203209.22633-1-sven@narfation.org> References: <20181207203209.22633-1-sven@narfation.org> Message-ID: <20181207203209.22633-21-sven@narfation.org> The parsing and validation of the settings command parameters is handled by the parse function. The params struct member is therefore no longer used and can just be dropped. Signed-off-by: Sven Eckelmann --- sys.c | 32 -------------------------------- sys.h | 3 --- 2 files changed, 35 deletions(-) diff --git a/sys.c b/sys.c index ede8b09..a53b419 100644 --- a/sys.c +++ b/sys.c @@ -39,14 +39,6 @@ #include "functions.h" #include "debug.h" -const char *sysfs_param_enable[] = { - "enable", - "disable", - "1", - "0", - NULL, -}; - int parse_simple_boolean(struct state *state, int argc, char *argv[]) { struct settings_data *settings = state->cmd->arg; @@ -216,7 +208,6 @@ int handle_sys_setting(struct state *state, int argc, char **argv) struct settings_data *settings = state->cmd->arg; int optchar, res = EXIT_FAILURE; char *path_buff; - const char **ptr; while ((optchar = getopt(argc, argv, "h")) != -1) { switch (optchar) { @@ -261,29 +252,6 @@ int handle_sys_setting(struct state *state, int argc, char **argv) } } - if (!settings->params) - goto write_file; - - ptr = settings->params; - while (*ptr) { - if (strcmp(*ptr, argv[1]) == 0) - goto write_file; - - ptr++; - } - - fprintf(stderr, "Error - the supplied argument is invalid: %s\n", argv[1]); - fprintf(stderr, "The following values are allowed:\n"); - - ptr = settings->params; - while (*ptr) { - fprintf(stderr, " * %s\n", *ptr); - ptr++; - } - - goto out; - -write_file: res = sys_write_setting(state, path_buff, settings->sysfs_name, argc, argv); diff --git a/sys.h b/sys.h index f32f134..e7d227d 100644 --- a/sys.h +++ b/sys.h @@ -49,15 +49,12 @@ struct settings_data { const char *sysfs_name; - const char **params; void *data; int (*parse)(struct state *state, int argc, char *argv[]); int (*netlink_get)(struct state *state); int (*netlink_set)(struct state *state); }; -extern const char *sysfs_param_enable[]; - struct simple_boolean_data { bool val; }; -- 2.19.2 From sven at narfation.org Fri Dec 7 21:32:06 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 21:32:06 +0100 Subject: [B.A.T.M.A.N.] [RFC v4 17/20] batctl: Support generic netlink for fragmentation command In-Reply-To: <20181207203209.22633-1-sven@narfation.org> References: <20181207203209.22633-1-sven@narfation.org> Message-ID: <20181207203209.22633-18-sven@narfation.org> sysfs should be avoided for new settings of network interfaces. To still provide a common configuration infrastructure, all the existing settings subcommands also have to be reimplemented via generic netlink while still using sysfs as fallback. The fragmentation implementation is using the commands BATADV_CMD_SET_MESH/BATADV_CMD_GET_MESH to set/get the configuration of the u8 (boolean) BATADV_ATTR_FRAGMENTATION attribute. Signed-off-by: Sven Eckelmann --- Cc: Andreas Langer Cc: Martin Hundeboll Cc: Marek Lindner --- fragmentation.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/fragmentation.c b/fragmentation.c index e159bdd..7f5f488 100644 --- a/fragmentation.c +++ b/fragmentation.c @@ -21,13 +21,54 @@ */ #include "main.h" + +#include +#include +#include + +#include "batman_adv.h" +#include "netlink.h" #include "sys.h" +static struct simple_boolean_data fragmentation; + +static int print_fragmentation(struct nl_msg *msg, void *arg) +{ + return sys_simple_print_boolean(msg, arg, BATADV_ATTR_FRAGMENTATION); +} + +static int get_fragmentation(struct state *state) +{ + return sys_simple_nlquery(state, BATADV_CMD_GET_MESH, + NULL, print_fragmentation); +} + +static int set_attrs_fragmentation(struct nl_msg *msg, void *arg) +{ + struct state *state = arg; + struct settings_data *settings = state->cmd->arg; + struct simple_boolean_data *data = settings->data; + + nla_put_u8(msg, BATADV_ATTR_FRAGMENTATION, data->val); + + return 0; +} + +static int set_fragmentation(struct state *state) +{ + return sys_simple_nlquery(state, BATADV_CMD_SET_MESH, + set_attrs_fragmentation, NULL); +} + static struct settings_data batctl_settings_fragmentation = { .sysfs_name = "fragmentation", - .params = sysfs_param_enable, + .data = &fragmentation, + .parse = parse_simple_boolean, + .netlink_get = get_fragmentation, + .netlink_set = set_fragmentation, }; COMMAND_NAMED(SUBCOMMAND, fragmentation, "f", handle_sys_setting, - COMMAND_FLAG_MESH_IFACE, &batctl_settings_fragmentation, + COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK, + &batctl_settings_fragmentation, "[0|1] \tdisplay or modify fragmentation setting"); -- 2.19.2 From sven at narfation.org Fri Dec 7 21:50:13 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 21:50:13 +0100 Subject: [B.A.T.M.A.N.] [PATCH] batctl: Rename option_watch_interval to option_timeout_interval Message-ID: <20181207205013.25105-1-sven@narfation.org> The watch interval is actually a different option for debug tables which uses the parameter '-w'. The configuration to enable/disable the parameter to set the timeout for not displaying not seen originators should therefore use a different name. Signed-off-by: Sven Eckelmann --- debug.c | 4 ++-- debug.h | 2 +- originators.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/debug.c b/debug.c index 316312f..182877a 100644 --- a/debug.c +++ b/debug.c @@ -44,7 +44,7 @@ static void debug_table_usage(struct state *state) fprintf(stderr, " \t -H don't show the header\n"); fprintf(stderr, " \t -w [interval] watch mode - refresh the table continuously\n"); - if (debug_table->option_watch_interval) + if (debug_table->option_timeout_interval) fprintf(stderr, " \t -t timeout interval - don't print originators not seen for x.y seconds \n"); if (debug_table->option_orig_iface) @@ -89,7 +89,7 @@ int handle_debug_table(struct state *state, int argc, char **argv) } break; case 't': - if (!debug_table->option_watch_interval) { + if (!debug_table->option_timeout_interval) { fprintf(stderr, "Error - unrecognised option '-%c'\n", optchar); debug_table_usage(state); return EXIT_FAILURE; diff --git a/debug.h b/debug.h index 2dac1b7..f1a3fd4 100644 --- a/debug.h +++ b/debug.h @@ -43,7 +43,7 @@ struct debug_table_data { float orig_timeout, float watch_interval); unsigned int option_unicast_only:1; unsigned int option_multicast_only:1; - unsigned int option_watch_interval:1; + unsigned int option_timeout_interval:1; unsigned int option_orig_iface:1; }; diff --git a/originators.c b/originators.c index c29300a..7dc9b4c 100644 --- a/originators.c +++ b/originators.c @@ -219,7 +219,7 @@ static struct debug_table_data batctl_debug_table_originators = { .debugfs_name = "originators", .header_lines = 2, .netlink_fn = netlink_print_originators, - .option_watch_interval = 1, + .option_timeout_interval = 1, .option_orig_iface = 1, }; -- 2.19.2 From sven at narfation.org Fri Dec 7 22:46:28 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 22:46:28 +0100 Subject: [B.A.T.M.A.N.] [PATCH 1/2] batctl: Remove check of compiled_out files Message-ID: <20181207214629.30307-1-sven@narfation.org> Many files in the sysfs and debugfs of batman-adv can be compiled out. The debugfs support of batman-adv can currently be disabled completely and something similar may happen in the future for sysfs. Printing the information that a file cannot be opened because the feature was disabled should therefore be printed for read/writes from/to all files when the caller didn't ask to disable error messages. Signed-off-by: Sven Eckelmann --- bridge_loop_avoidance.c | 2 +- distributed_arp_table.c | 2 +- functions.c | 36 +++++------------------------------- loglevel.c | 2 ++ multicast_mode.c | 2 +- network_coding.c | 2 +- sys.h | 6 ------ 7 files changed, 11 insertions(+), 41 deletions(-) diff --git a/bridge_loop_avoidance.c b/bridge_loop_avoidance.c index 0db49f2..04b41e0 100644 --- a/bridge_loop_avoidance.c +++ b/bridge_loop_avoidance.c @@ -24,7 +24,7 @@ #include "sys.h" static struct settings_data batctl_settings_bridge_loop_avoidance = { - .sysfs_name = SYS_BLA, + .sysfs_name = "bridge_loop_avoidance", .params = sysfs_param_enable, }; diff --git a/distributed_arp_table.c b/distributed_arp_table.c index ba6e5b7..c3595fc 100644 --- a/distributed_arp_table.c +++ b/distributed_arp_table.c @@ -24,7 +24,7 @@ #include "sys.h" static struct settings_data batctl_settings_distributed_arp_table = { - .sysfs_name = SYS_DAT, + .sysfs_name = "distributed_arp_table", .params = sysfs_param_enable, }; diff --git a/functions.c b/functions.c index bdede8b..9a130e1 100644 --- a/functions.c +++ b/functions.c @@ -66,21 +66,6 @@ static struct timespec start_time; static char *host_name; char *line_ptr = NULL; -const char *fs_compile_out_param[] = { - SYS_LOG, - SYS_LOG_LEVEL, - SYS_BLA, - SYS_DAT, - SYS_NETWORK_CODING, - SYS_MULTICAST_MODE, - DEBUG_DAT_CACHE, - DEBUG_BACKBONETABLE, - DEBUG_DAT_CACHE, - DEBUG_NC_NODES, - DEBUG_MCAST_FLAGS, - NULL, -}; - void start_timer(void) { clock_gettime(CLOCK_MONOTONIC, &start_time); @@ -147,10 +132,8 @@ int file_exists(const char *fpath) return stat(fpath, &st) == 0; } -static void file_open_problem_dbg(const char *dir, const char *fname, - const char *full_path) +static void file_open_problem_dbg(const char *dir, const char *full_path) { - const char **ptr; struct stat st; if (strstr(dir, "/sys/")) { @@ -172,18 +155,9 @@ static void file_open_problem_dbg(const char *dir, const char *fname, return; } - for (ptr = fs_compile_out_param; *ptr; ptr++) { - if (strcmp(*ptr, fname) != 0) - continue; - - break; - } - fprintf(stderr, "Error - can't open file '%s': %s\n", full_path, strerror(errno)); - if (*ptr) { - fprintf(stderr, "The option you called seems not to be compiled into your batman-adv kernel module.\n"); - fprintf(stderr, "Consult the README if you wish to learn more about compiling options into batman-adv.\n"); - } + fprintf(stderr, "The option you called seems not to be compiled into your batman-adv kernel module.\n"); + fprintf(stderr, "Consult the README if you wish to learn more about compiling options into batman-adv.\n"); } static int str_is_mcast_addr(char *addr) @@ -230,7 +204,7 @@ int read_file(const char *dir, const char *fname, int read_opt, if (!fp) { if (!(read_opt & SILENCE_ERRORS)) - file_open_problem_dbg(dir, fname, full_path); + file_open_problem_dbg(dir, full_path); goto out; } @@ -366,7 +340,7 @@ int write_file(const char *dir, const char *fname, const char *arg1, fd = open(full_path, O_WRONLY); if (fd < 0) { - file_open_problem_dbg(dir, fname, full_path); + file_open_problem_dbg(dir, full_path); goto out; } diff --git a/loglevel.c b/loglevel.c index fed70c8..b5bbd0d 100644 --- a/loglevel.c +++ b/loglevel.c @@ -29,6 +29,8 @@ #include "main.h" #include "sys.h" +#define SYS_LOG_LEVEL "log_level" + static void log_level_usage(void) { fprintf(stderr, "Usage: batctl [options] loglevel [parameters] [level[ level[ level]]...]\n"); diff --git a/multicast_mode.c b/multicast_mode.c index 8542928..b65732d 100644 --- a/multicast_mode.c +++ b/multicast_mode.c @@ -24,7 +24,7 @@ #include "sys.h" static struct settings_data batctl_settings_multicast_mode = { - .sysfs_name = SYS_MULTICAST_MODE, + .sysfs_name = "multicast_mode", .params = sysfs_param_enable, }; diff --git a/network_coding.c b/network_coding.c index a4c4296..076f4cf 100644 --- a/network_coding.c +++ b/network_coding.c @@ -24,7 +24,7 @@ #include "sys.h" static struct settings_data batctl_settings_network_coding = { - .sysfs_name = SYS_NETWORK_CODING, + .sysfs_name = "network_coding", .params = sysfs_param_enable, }; diff --git a/sys.h b/sys.h index 20e1934..b493219 100644 --- a/sys.h +++ b/sys.h @@ -26,12 +26,6 @@ #include "main.h" #define SYS_BATIF_PATH_FMT "/sys/class/net/%s/mesh/" -#define SYS_LOG_LEVEL "log_level" -#define SYS_LOG "log" -#define SYS_BLA "bridge_loop_avoidance" -#define SYS_DAT "distributed_arp_table" -#define SYS_NETWORK_CODING "network_coding" -#define SYS_MULTICAST_MODE "multicast_mode" #define SYS_IFACE_PATH "/sys/class/net" #define SYS_IFACE_DIR SYS_IFACE_PATH"/%s/" #define SYS_MESH_IFACE_FMT SYS_IFACE_PATH"/%s/batman_adv/mesh_iface" -- 2.19.2 From sven at narfation.org Fri Dec 7 22:46:29 2018 From: sven at narfation.org (Sven Eckelmann) Date: Fri, 7 Dec 2018 22:46:29 +0100 Subject: [B.A.T.M.A.N.] [PATCH 2/2] batctl: Drop incorrect check for existing meshif directory In-Reply-To: <20181207214629.30307-1-sven@narfation.org> References: <20181207214629.30307-1-sven@narfation.org> Message-ID: <20181207214629.30307-2-sven@narfation.org> The (not silenced) read_file/write_file functions will check whether the directory of a file exists. This is used to determine whether the mesh interface was created. In that case, it will print: Error - mesh has not been enabled yet Activate your mesh by adding interfaces to batman-adv This is most of the time wrong because only a limited number of commands will call these function: * gw_mode * log * loglevel * routing_algo * backbonetable * claimtable * dat_cache * gateways * mcast_flags * nc_nodes * neighbors * originators * transglobal * translocal Beside routing_algo, every command is marked as COMMAND_FLAG_MESH_IFACE and therefore already requested a check to make sure that the specified meshif existed at some point. This message is especially confusing because debugfs can be disabled in batman-adv. If it was compiled without debugfs and the user tries to still use `batctl log`, the log command will fail with an incorrect error message instead of showing a more detailed (and more correct): Error - can't open file '/sys/kernel/debug//batman_adv/bat0/log': No such file or directory The option you called seems not to be compiled into your batman-adv kernel module. Consult the README if you wish to learn more about compiling options into batman-adv. And for routing_algo, the problem of the missing batman-adv module should already be catched when the batman-adv module version path is checked. Reported-by: Andre Kasper Signed-off-by: Sven Eckelmann --- functions.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/functions.c b/functions.c index 9a130e1..9d64c62 100644 --- a/functions.c +++ b/functions.c @@ -149,12 +149,6 @@ static void file_open_problem_dbg(const char *dir, const char *full_path) return; } - if (!file_exists(dir)) { - fprintf(stderr, "Error - mesh has not been enabled yet\n"); - fprintf(stderr, "Activate your mesh by adding interfaces to batman-adv\n"); - return; - } - fprintf(stderr, "Error - can't open file '%s': %s\n", full_path, strerror(errno)); fprintf(stderr, "The option you called seems not to be compiled into your batman-adv kernel module.\n"); fprintf(stderr, "Consult the README if you wish to learn more about compiling options into batman-adv.\n"); -- 2.19.2 From sprudent at osmozis.com Thu Dec 20 11:07:24 2018 From: sprudent at osmozis.com (Sylvain PRUDENT) Date: Thu, 20 Dec 2018 11:07:24 +0100 Subject: [B.A.T.M.A.N.] short introduction Message-ID: <19d2838a-524f-27a9-84a3-05842c049df2@osmozis.com> Hello everyone, as it is my first mail to the mailing list I thought I had to introduce myself a bit. I work in a French company providing WiFi mesh networks to campsites. Our WiFi spots are based on OpenWRT and we use a lot batman-adv to build our mesh networks. Batman is a great and powerful tool and I look forward to contribute to the different exchanges on the mailing list. Best regards, sprudent From sprudent at osmozis.com Thu Dec 20 11:09:01 2018 From: sprudent at osmozis.com (Sylvain PRUDENT) Date: Thu, 20 Dec 2018 11:09:01 +0100 Subject: [B.A.T.M.A.N.] gw_mode & vlan Message-ID: <06c85527-ec8d-bead-ca65-2736cba8507f@osmozis.com> Hello again, I am using batman to set up a big lan network that allows clients to roam between the different APs. The mesh network is also carrying private vlan that have dedicated dhcp servers outside of the mesh network. A lot of clients may connect to the lan so I would like to use gateway mode (client/server) feature to avoid dhcp broadcast storms. Is it possible to use gw_mode for the main lan network without affecting dhcp traffic on the private vlan networks ? I already checked that the setting is not usable in the vlan scope. Right now, my test setup is composed of qemu vm bridged together running vanilla openwrt-18.06.1-x86-64-combined-ext4.img (batman-adv: 2018.1). regards, sprudent From sven at narfation.org Thu Dec 20 13:19:19 2018 From: sven at narfation.org (Sven Eckelmann) Date: Thu, 20 Dec 2018 13:19:19 +0100 Subject: [B.A.T.M.A.N.] gw_mode & vlan In-Reply-To: <06c85527-ec8d-bead-ca65-2736cba8507f@osmozis.com> References: <06c85527-ec8d-bead-ca65-2736cba8507f@osmozis.com> Message-ID: <5663464.jlV71abGFt@sven-edge> On Thursday, 20 December 2018 11.09.01 CET Sylvain PRUDENT wrote: > A lot of clients may connect to the lan so I would like to use gateway > mode (client/server) feature to avoid dhcp broadcast storms. > Is it possible to use gw_mode for the main lan network without affecting > dhcp traffic on the private vlan networks ? No Kind regards, Sven -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: This is a digitally signed message part. URL: From linus.luessing at c0d3.blue Fri Dec 21 16:15:07 2018 From: linus.luessing at c0d3.blue (=?UTF-8?q?Linus=20L=C3=BCssing?=) Date: Fri, 21 Dec 2018 16:15:07 +0100 Subject: [B.A.T.M.A.N.] [PATCH net-next 0/4] bridge: implement Multicast Router Discovery (RFC4286) Message-ID: <20181221151511.14923-1-linus.luessing@c0d3.blue> Hi, This patchset adds initial Multicast Router Discovery support to the Linux bridge (RFC4286). With MRD it is possible to detect multicast routers and mark bridge ports and forward multicast packets to such routers accordingly. So far, multicast routers are detected via IGMP/MLD queries and PIM messages in the Linux bridge. As there is only one active, selected querier at a time RFC4541 ("Considerations for Internet Group Management Protocol (IGMP) and Multicast Listener Discovery (MLD) Snooping Switches") section 2.1.1.a) recommends snooping Multicast Router Advertisements as provided by MRD (RFC4286). The first two patches are refactoring some existing code which is reused for parsing the Multicast Router Advertisements later in the fourth patch. The third patch lets the bridge join the all-snoopers multicast address to be able to reliably receive the Multicast Router Advertisements. What is not implemented yet from RFC4286 yet: * Sending Multicast Router Solicitations: -> RFC4286: "[...] may be sent when [...] an interface is (re-)initialized [or] MRD is enabled" * Snooping Multicast Router Terminations: -> currently this only relies on our own timeouts * Adjusting timeouts with the values provided in the announcements Regards, Linus From davem at davemloft.net Fri Dec 21 18:06:51 2018 From: davem at davemloft.net (David Miller) Date: Fri, 21 Dec 2018 09:06:51 -0800 (PST) Subject: [B.A.T.M.A.N.] [PATCH net-next 0/4] bridge: implement Multicast Router Discovery (RFC4286) In-Reply-To: <20181221151511.14923-1-linus.luessing@c0d3.blue> References: <20181221151511.14923-1-linus.luessing@c0d3.blue> Message-ID: <20181221.090651.1241372602429144964.davem@davemloft.net> From: Linus Lüssing Date: Fri, 21 Dec 2018 16:15:07 +0100 > This patchset adds initial Multicast Router Discovery support to > the Linux bridge (RFC4286). With MRD it is possible to detect multicast > routers and mark bridge ports and forward multicast packets to such routers > accordingly. ... The net-next tree is currently closed, please resubmit this when it opens back up again. Thank you. From linus.luessing at c0d3.blue Fri Dec 21 16:15:11 2018 From: linus.luessing at c0d3.blue (=?UTF-8?q?Linus=20L=C3=BCssing?=) Date: Fri, 21 Dec 2018 16:15:11 +0100 Subject: [B.A.T.M.A.N.] [PATCH net-next 4/4] bridge: Snoop Multicast Router Advertisements In-Reply-To: <20181221151511.14923-1-linus.luessing@c0d3.blue> References: <20181221151511.14923-1-linus.luessing@c0d3.blue> Message-ID: <20181221151511.14923-5-linus.luessing@c0d3.blue> When multiple multicast routers are present in a broadcast domain then only one of them will be detectable via IGMP/MLD query snooping. The multicast router with the lowest IP address will become the selected and active querier while all other multicast routers will then refrain from sending queries. To detect such rather silent multicast routers, too, RFC4286 ("Multicast Router Discovery") provides a standardized protocol to detect multicast routers for multicast snooping switches. This patch implements the necessary MRD Advertisement message parsing and after successful processing adds such routers to the internal multicast router list. Signed-off-by: Linus Lüssing --- include/linux/in.h | 5 +++++ include/net/addrconf.h | 15 +++++++++++++ include/uapi/linux/icmpv6.h | 2 ++ include/uapi/linux/igmp.h | 1 + net/bridge/br_multicast.c | 55 +++++++++++++++++++++++++++++++++++++++++++++ net/ipv6/mcast_snoop.c | 5 ++++- 6 files changed, 82 insertions(+), 1 deletion(-) diff --git a/include/linux/in.h b/include/linux/in.h index 31b493734763..435e7f2a513a 100644 --- a/include/linux/in.h +++ b/include/linux/in.h @@ -60,6 +60,11 @@ static inline bool ipv4_is_lbcast(__be32 addr) return addr == htonl(INADDR_BROADCAST); } +static inline bool ipv4_is_all_snoopers(__be32 addr) +{ + return addr == htonl(INADDR_ALLSNOOPERS_GROUP); +} + static inline bool ipv4_is_zeronet(__be32 addr) { return (addr & htonl(0xff000000)) == htonl(0x00000000); diff --git a/include/net/addrconf.h b/include/net/addrconf.h index daf11dcb0f70..20d523ee2fec 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -229,6 +229,7 @@ void ipv6_mc_unmap(struct inet6_dev *idev); void ipv6_mc_remap(struct inet6_dev *idev); void ipv6_mc_init_dev(struct inet6_dev *idev); void ipv6_mc_destroy_dev(struct inet6_dev *idev); +int ipv6_mc_check_icmpv6(struct sk_buff *skb); int ipv6_mc_check_mld(struct sk_buff *skb); void addrconf_dad_failure(struct sk_buff *skb, struct inet6_ifaddr *ifp); @@ -499,6 +500,20 @@ static inline bool ipv6_addr_is_solict_mult(const struct in6_addr *addr) #endif } +static inline bool ipv6_addr_is_all_snoopers(const struct in6_addr *addr) +{ +#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 + __be64 *p = (__be64 *)addr; + + return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) | + (p[1] ^ cpu_to_be64(0x6a))) == 0UL; +#else + return ((addr->s6_addr32[0] ^ htonl(0xff020000)) | + addr->s6_addr32[1] | addr->s6_addr32[2] | + (addr->s6_addr32[3] ^ htonl(0x0000006a))) == 0; +#endif +} + #ifdef CONFIG_PROC_FS int if6_proc_init(void); void if6_proc_exit(void); diff --git a/include/uapi/linux/icmpv6.h b/include/uapi/linux/icmpv6.h index caf8dc019250..325395f56bfa 100644 --- a/include/uapi/linux/icmpv6.h +++ b/include/uapi/linux/icmpv6.h @@ -108,6 +108,8 @@ struct icmp6hdr { #define ICMPV6_MOBILE_PREFIX_SOL 146 #define ICMPV6_MOBILE_PREFIX_ADV 147 +#define ICMPV6_MRDISC_ADV 151 + /* * Codes for Destination Unreachable */ diff --git a/include/uapi/linux/igmp.h b/include/uapi/linux/igmp.h index 7e44ac02ca18..90c28bc466c6 100644 --- a/include/uapi/linux/igmp.h +++ b/include/uapi/linux/igmp.h @@ -93,6 +93,7 @@ struct igmpv3_query { #define IGMP_MTRACE_RESP 0x1e #define IGMP_MTRACE 0x1f +#define IGMP_MRDISC_ADV 0x30 /* From RFC4286 */ /* * Use the BSD names for these for compatibility diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 2366f4a2780e..2c46c7aca571 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -29,10 +30,12 @@ #include #include #if IS_ENABLED(CONFIG_IPV6) +#include #include #include #include #include +#include #endif #include "br_private.h" @@ -1583,6 +1586,19 @@ static void br_multicast_pim(struct net_bridge *br, br_multicast_mark_router(br, port); } +static int br_ip4_multicast_mrd_rcv(struct net_bridge *br, + struct net_bridge_port *port, + struct sk_buff *skb) +{ + if (ip_hdr(skb)->protocol != IPPROTO_IGMP || + igmp_hdr(skb)->type != IGMP_MRDISC_ADV) + return -ENOMSG; + + br_multicast_mark_router(br, port); + + return 0; +} + static int br_multicast_ipv4_rcv(struct net_bridge *br, struct net_bridge_port *port, struct sk_buff *skb, @@ -1600,7 +1616,15 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, } else if (pim_ipv4_all_pim_routers(ip_hdr(skb)->daddr)) { if (ip_hdr(skb)->protocol == IPPROTO_PIM) br_multicast_pim(br, port, skb); + } else if (ipv4_is_all_snoopers(ip_hdr(skb)->daddr)) { + err = br_ip4_multicast_mrd_rcv(br, port, skb); + + if (err < 0 && err != -ENOMSG) { + br_multicast_err_count(br, port, skb->protocol); + return err; + } } + return 0; } else if (err < 0) { br_multicast_err_count(br, port, skb->protocol); @@ -1635,6 +1659,27 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, } #if IS_ENABLED(CONFIG_IPV6) +static int br_ip6_multicast_mrd_rcv(struct net_bridge *br, + struct net_bridge_port *port, + struct sk_buff *skb) +{ + int ret; + + if (ipv6_hdr(skb)->nexthdr != IPPROTO_ICMPV6) + return -ENOMSG; + + ret = ipv6_mc_check_icmpv6(skb); + if (ret < 0) + return ret; + + if (icmp6_hdr(skb)->icmp6_type != ICMPV6_MRDISC_ADV) + return -ENOMSG; + + br_multicast_mark_router(br, port); + + return 0; +} + static int br_multicast_ipv6_rcv(struct net_bridge *br, struct net_bridge_port *port, struct sk_buff *skb, @@ -1649,6 +1694,16 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, if (err == -ENOMSG) { if (!ipv6_addr_is_ll_all_nodes(&ipv6_hdr(skb)->daddr)) BR_INPUT_SKB_CB(skb)->mrouters_only = 1; + + if (ipv6_addr_is_all_snoopers(&ipv6_hdr(skb)->daddr)) { + err = br_ip6_multicast_mrd_rcv(br, port, skb); + + if (err < 0 && err != -ENOMSG) { + br_multicast_err_count(br, port, skb->protocol); + return err; + } + } + return 0; } else if (err < 0) { br_multicast_err_count(br, port, skb->protocol); diff --git a/net/ipv6/mcast_snoop.c b/net/ipv6/mcast_snoop.c index a72ddfc40eb3..55e2ac179f28 100644 --- a/net/ipv6/mcast_snoop.c +++ b/net/ipv6/mcast_snoop.c @@ -41,6 +41,8 @@ static int ipv6_mc_check_ip6hdr(struct sk_buff *skb) if (skb->len < len || len <= offset) return -EINVAL; + skb_set_transport_header(skb, offset); + return 0; } @@ -142,7 +144,7 @@ static inline __sum16 ipv6_mc_validate_checksum(struct sk_buff *skb) return skb_checksum_validate(skb, IPPROTO_ICMPV6, ip6_compute_pseudo); } -static int ipv6_mc_check_icmpv6(struct sk_buff *skb) +int ipv6_mc_check_icmpv6(struct sk_buff *skb) { unsigned int len = skb_transport_offset(skb) + sizeof(struct icmp6hdr); unsigned int transport_len = ipv6_transport_len(skb); @@ -161,6 +163,7 @@ static int ipv6_mc_check_icmpv6(struct sk_buff *skb) return 0; } +EXPORT_SYMBOL(ipv6_mc_check_icmpv6); /** * ipv6_mc_check_mld - checks whether this is a sane MLD packet -- 2.11.0 From linus.luessing at c0d3.blue Fri Dec 21 16:15:10 2018 From: linus.luessing at c0d3.blue (=?UTF-8?q?Linus=20L=C3=BCssing?=) Date: Fri, 21 Dec 2018 16:15:10 +0100 Subject: [B.A.T.M.A.N.] [PATCH net-next 3/4] bridge: join all-snoopers multicast address In-Reply-To: <20181221151511.14923-1-linus.luessing@c0d3.blue> References: <20181221151511.14923-1-linus.luessing@c0d3.blue> Message-ID: <20181221151511.14923-4-linus.luessing@c0d3.blue> Next to snooping IGMP/MLD queries RFC4541, section 2.1.1.a) recommends to snoop multicast router advertisements to detect multicast routers. Multicast router advertisements are sent to an "all-snoopers" multicast address. To be able to receive them reliably, we need to join this group. Otherwise other snooping switches might refrain from forwarding these advertisements to us. Signed-off-by: Linus Lüssing --- include/uapi/linux/in.h | 9 +++--- net/bridge/br_multicast.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++- net/ipv6/mcast.c | 2 ++ 3 files changed, 78 insertions(+), 5 deletions(-) diff --git a/include/uapi/linux/in.h b/include/uapi/linux/in.h index f6052e70bf40..7ab685cacb8f 100644 --- a/include/uapi/linux/in.h +++ b/include/uapi/linux/in.h @@ -292,10 +292,11 @@ struct sockaddr_in { #define IN_LOOPBACK(a) ((((long int) (a)) & 0xff000000) == 0x7f000000) /* Defines for Multicast INADDR */ -#define INADDR_UNSPEC_GROUP 0xe0000000U /* 224.0.0.0 */ -#define INADDR_ALLHOSTS_GROUP 0xe0000001U /* 224.0.0.1 */ -#define INADDR_ALLRTRS_GROUP 0xe0000002U /* 224.0.0.2 */ -#define INADDR_MAX_LOCAL_GROUP 0xe00000ffU /* 224.0.0.255 */ +#define INADDR_UNSPEC_GROUP 0xe0000000U /* 224.0.0.0 */ +#define INADDR_ALLHOSTS_GROUP 0xe0000001U /* 224.0.0.1 */ +#define INADDR_ALLRTRS_GROUP 0xe0000002U /* 224.0.0.2 */ +#define INADDR_ALLSNOOPERS_GROUP 0xe000006aU /* 224.0.0.106 */ +#define INADDR_MAX_LOCAL_GROUP 0xe00000ffU /* 224.0.0.255 */ #endif /* contains the htonl type stuff.. */ diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 156c4905639e..2366f4a2780e 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1780,6 +1780,68 @@ void br_multicast_init(struct net_bridge *br) INIT_HLIST_HEAD(&br->mdb_list); } +static void br_ip4_multicast_join_snoopers(struct net_bridge *br) +{ + struct in_device *in_dev = in_dev_get(br->dev); + + if (!in_dev) + return; + + ip_mc_inc_group(in_dev, htonl(INADDR_ALLSNOOPERS_GROUP)); + in_dev_put(in_dev); +} + +#if IS_ENABLED(CONFIG_IPV6) +static void br_ip6_multicast_join_snoopers(struct net_bridge *br) +{ + struct in6_addr addr; + + ipv6_addr_set(&addr, htonl(0xff020000), 0, 0, htonl(0x6a)); + ipv6_dev_mc_inc(br->dev, &addr); +} +#else +static inline void br_ip6_multicast_join_snoopers(struct net_bridge *br) +{ +} +#endif + +static void br_multicast_join_snoopers(struct net_bridge *br) +{ + br_ip4_multicast_join_snoopers(br); + br_ip6_multicast_join_snoopers(br); +} + +static void br_ip4_multicast_leave_snoopers(struct net_bridge *br) +{ + struct in_device *in_dev = in_dev_get(br->dev); + + if (WARN_ON(!in_dev)) + return; + + ip_mc_dec_group(in_dev, htonl(INADDR_ALLSNOOPERS_GROUP)); + in_dev_put(in_dev); +} + +#if IS_ENABLED(CONFIG_IPV6) +static void br_ip6_multicast_leave_snoopers(struct net_bridge *br) +{ + struct in6_addr addr; + + ipv6_addr_set(&addr, htonl(0xff020000), 0, 0, htonl(0x6a)); + ipv6_dev_mc_dec(br->dev, &addr); +} +#else +static inline void br_ip6_multicast_leave_snoopers(struct net_bridge *br) +{ +} +#endif + +static void br_multicast_leave_snoopers(struct net_bridge *br) +{ + br_ip4_multicast_leave_snoopers(br); + br_ip6_multicast_leave_snoopers(br); +} + static void __br_multicast_open(struct net_bridge *br, struct bridge_mcast_own_query *query) { @@ -1793,6 +1855,9 @@ static void __br_multicast_open(struct net_bridge *br, void br_multicast_open(struct net_bridge *br) { + if (br_opt_get(br, BROPT_MULTICAST_ENABLED)) + br_multicast_join_snoopers(br); + __br_multicast_open(br, &br->ip4_own_query); #if IS_ENABLED(CONFIG_IPV6) __br_multicast_open(br, &br->ip6_own_query); @@ -1808,6 +1873,9 @@ void br_multicast_stop(struct net_bridge *br) del_timer_sync(&br->ip6_other_query.timer); del_timer_sync(&br->ip6_own_query.timer); #endif + + if (br_opt_get(br, BROPT_MULTICAST_ENABLED)) + br_multicast_leave_snoopers(br); } void br_multicast_dev_del(struct net_bridge *br) @@ -1943,8 +2011,10 @@ int br_multicast_toggle(struct net_bridge *br, unsigned long val) br_mc_disabled_update(br->dev, val); br_opt_toggle(br, BROPT_MULTICAST_ENABLED, !!val); - if (!br_opt_get(br, BROPT_MULTICAST_ENABLED)) + if (!br_opt_get(br, BROPT_MULTICAST_ENABLED)) { + br_multicast_leave_snoopers(br); goto unlock; + } if (!netif_running(br->dev)) goto unlock; diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 21f6deb2aec9..42f3f5cd349f 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -940,6 +940,7 @@ int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr) { return __ipv6_dev_mc_inc(dev, addr, MCAST_EXCLUDE); } +EXPORT_SYMBOL(ipv6_dev_mc_inc); /* * device multicast group del @@ -987,6 +988,7 @@ int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr) return err; } +EXPORT_SYMBOL(ipv6_dev_mc_dec); /* * check if the interface/address pair is valid -- 2.11.0 From linus.luessing at c0d3.blue Fri Dec 21 16:15:09 2018 From: linus.luessing at c0d3.blue (=?UTF-8?q?Linus=20L=C3=BCssing?=) Date: Fri, 21 Dec 2018 16:15:09 +0100 Subject: [B.A.T.M.A.N.] [PATCH net-next 2/4] bridge: simplify ip_mc_check_igmp() and ipv6_mc_check_mld() internals In-Reply-To: <20181221151511.14923-1-linus.luessing@c0d3.blue> References: <20181221151511.14923-1-linus.luessing@c0d3.blue> Message-ID: <20181221151511.14923-3-linus.luessing@c0d3.blue> With this patch the internal use of the skb_trimmed is reduced to the ICMPv6/IGMP checksum verification. And for the length checks the newly introduced helper functions are used instead of calculating and checking with skb->len directly. These changes should hopefully make it easier to verify that length checks are performed properly. Signed-off-by: Linus Lüssing --- net/ipv4/igmp.c | 51 ++++++++++++++++++----------------------- net/ipv6/mcast_snoop.c | 62 ++++++++++++++++++++++++-------------------------- 2 files changed, 52 insertions(+), 61 deletions(-) diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index b1f6d93282d7..a40e48ded10d 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -1493,22 +1493,22 @@ static int ip_mc_check_igmp_reportv3(struct sk_buff *skb) len += sizeof(struct igmpv3_report); - return pskb_may_pull(skb, len) ? 0 : -EINVAL; + return ip_mc_may_pull(skb, len) ? 0 : -EINVAL; } static int ip_mc_check_igmp_query(struct sk_buff *skb) { - unsigned int len = skb_transport_offset(skb); - - len += sizeof(struct igmphdr); - if (skb->len < len) - return -EINVAL; + unsigned int transport_len = ip_transport_len(skb); + unsigned int len; /* IGMPv{1,2}? */ - if (skb->len != len) { + if (transport_len != sizeof(struct igmphdr)) { /* or IGMPv3? */ - len += sizeof(struct igmpv3_query) - sizeof(struct igmphdr); - if (skb->len < len || !pskb_may_pull(skb, len)) + if (transport_len < sizeof(struct igmpv3_query)) + return -EINVAL; + + len = skb_transport_offset(skb) + sizeof(struct igmpv3_query); + if (!ip_mc_may_pull(skb, len)) return -EINVAL; } @@ -1544,35 +1544,24 @@ static inline __sum16 ip_mc_validate_checksum(struct sk_buff *skb) return skb_checksum_simple_validate(skb); } -static int __ip_mc_check_igmp(struct sk_buff *skb) - +static int ip_mc_check_igmp_csum(struct sk_buff *skb) { - struct sk_buff *skb_chk; - unsigned int transport_len; unsigned int len = skb_transport_offset(skb) + sizeof(struct igmphdr); - int ret = -EINVAL; + unsigned int transport_len = ip_transport_len(skb); + struct sk_buff *skb_chk; - transport_len = ntohs(ip_hdr(skb)->tot_len) - ip_hdrlen(skb); + if (!ip_mc_may_pull(skb, len)) + return -EINVAL; skb_chk = skb_checksum_trimmed(skb, transport_len, ip_mc_validate_checksum); if (!skb_chk) - goto err; + return -EINVAL; - if (!pskb_may_pull(skb_chk, len)) - goto err; - - ret = ip_mc_check_igmp_msg(skb_chk); - if (ret) - goto err; - - ret = 0; - -err: - if (skb_chk && skb_chk != skb) + if (skb_chk != skb) kfree_skb(skb_chk); - return ret; + return 0; } /** @@ -1600,7 +1589,11 @@ int ip_mc_check_igmp(struct sk_buff *skb) if (ip_hdr(skb)->protocol != IPPROTO_IGMP) return -ENOMSG; - return __ip_mc_check_igmp(skb); + ret = ip_mc_check_igmp_csum(skb); + if (ret < 0) + return ret; + + return ip_mc_check_igmp_msg(skb); } EXPORT_SYMBOL(ip_mc_check_igmp); diff --git a/net/ipv6/mcast_snoop.c b/net/ipv6/mcast_snoop.c index 1a917dc80d5e..a72ddfc40eb3 100644 --- a/net/ipv6/mcast_snoop.c +++ b/net/ipv6/mcast_snoop.c @@ -77,27 +77,27 @@ static int ipv6_mc_check_mld_reportv2(struct sk_buff *skb) len += sizeof(struct mld2_report); - return pskb_may_pull(skb, len) ? 0 : -EINVAL; + return ipv6_mc_may_pull(skb, len) ? 0 : -EINVAL; } static int ipv6_mc_check_mld_query(struct sk_buff *skb) { + unsigned int transport_len = ipv6_transport_len(skb); struct mld_msg *mld; - unsigned int len = skb_transport_offset(skb); + unsigned int len; /* RFC2710+RFC3810 (MLDv1+MLDv2) require link-local source addresses */ if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) return -EINVAL; - len += sizeof(struct mld_msg); - if (skb->len < len) - return -EINVAL; - /* MLDv1? */ - if (skb->len != len) { + if (transport_len != sizeof(struct mld_msg)) { /* or MLDv2? */ - len += sizeof(struct mld2_query) - sizeof(struct mld_msg); - if (skb->len < len || !pskb_may_pull(skb, len)) + if (transport_len < sizeof(struct mld2_query)) + return -EINVAL; + + len = skb_transport_offset(skb) + sizeof(struct mld2_query); + if (!ipv6_mc_may_pull(skb, len)) return -EINVAL; } @@ -115,7 +115,13 @@ static int ipv6_mc_check_mld_query(struct sk_buff *skb) static int ipv6_mc_check_mld_msg(struct sk_buff *skb) { - struct mld_msg *mld = (struct mld_msg *)skb_transport_header(skb); + unsigned int len = skb_transport_offset(skb) + sizeof(struct mld_msg); + struct mld_msg *mld; + + if (!ipv6_mc_may_pull(skb, len)) + return -EINVAL; + + mld = (struct mld_msg *)skb_transport_header(skb); switch (mld->mld_type) { case ICMPV6_MGM_REDUCTION: @@ -136,36 +142,24 @@ static inline __sum16 ipv6_mc_validate_checksum(struct sk_buff *skb) return skb_checksum_validate(skb, IPPROTO_ICMPV6, ip6_compute_pseudo); } -static int __ipv6_mc_check_mld(struct sk_buff *skb) - +static int ipv6_mc_check_icmpv6(struct sk_buff *skb) { - struct sk_buff *skb_chk = NULL; - unsigned int transport_len; - unsigned int len = skb_transport_offset(skb) + sizeof(struct mld_msg); - int ret = -EINVAL; + unsigned int len = skb_transport_offset(skb) + sizeof(struct icmp6hdr); + unsigned int transport_len = ipv6_transport_len(skb); + struct sk_buff *skb_chk; - transport_len = ntohs(ipv6_hdr(skb)->payload_len); - transport_len -= skb_transport_offset(skb) - sizeof(struct ipv6hdr); + if (!ipv6_mc_may_pull(skb, len)) + return -EINVAL; skb_chk = skb_checksum_trimmed(skb, transport_len, ipv6_mc_validate_checksum); if (!skb_chk) - goto err; + return -EINVAL; - if (!pskb_may_pull(skb_chk, len)) - goto err; - - ret = ipv6_mc_check_mld_msg(skb_chk); - if (ret) - goto err; - - ret = 0; - -err: - if (skb_chk && skb_chk != skb) + if (skb_chk != skb) kfree_skb(skb_chk); - return ret; + return 0; } /** @@ -195,6 +189,10 @@ int ipv6_mc_check_mld(struct sk_buff *skb) if (ret < 0) return ret; - return __ipv6_mc_check_mld(skb); + ret = ipv6_mc_check_icmpv6(skb); + if (ret < 0) + return ret; + + return ipv6_mc_check_mld_msg(skb); } EXPORT_SYMBOL(ipv6_mc_check_mld); -- 2.11.0 From linus.luessing at c0d3.blue Fri Dec 21 16:15:08 2018 From: linus.luessing at c0d3.blue (=?UTF-8?q?Linus=20L=C3=BCssing?=) Date: Fri, 21 Dec 2018 16:15:08 +0100 Subject: [B.A.T.M.A.N.] [PATCH net-next 1/4] bridge: simplify ip_mc_check_igmp() and ipv6_mc_check_mld() calls In-Reply-To: <20181221151511.14923-1-linus.luessing@c0d3.blue> References: <20181221151511.14923-1-linus.luessing@c0d3.blue> Message-ID: <20181221151511.14923-2-linus.luessing@c0d3.blue> This patch refactors ip_mc_check_igmp(), ipv6_mc_check_mld() and their callers (more precisely, the Linux bridge) to not rely on the skb_trimmed parameter anymore. An skb with its tail trimmed to the IP packet length was initially introduced for the following three reasons: 1) To be able to verify the ICMPv6 checksum. 2) To be able to distinguish the version of an IGMP or MLD query. They are distinguishable only by their size. 3) To avoid parsing data for an IGMPv3 or MLDv2 report that is beyond the IP packet but still within the skb. The first case still uses a cloned and potentially trimmed skb to verfiy. However, there is no need to propagate it to the caller. For the second and third case explicit IP packet length checks were added. This hopefully makes ip_mc_check_igmp() and ipv6_mc_check_mld() easier to read and verfiy, as well as easier to use. Signed-off-by: Linus Lüssing --- include/linux/igmp.h | 11 ++++++++- include/linux/ip.h | 5 ++++ include/linux/ipv6.h | 6 +++++ include/net/addrconf.h | 12 +++++++++- net/batman-adv/multicast.c | 4 ++-- net/bridge/br_multicast.c | 57 +++++++++++++++++++++++----------------------- net/ipv4/igmp.c | 23 ++++--------------- net/ipv6/mcast_snoop.c | 24 ++++--------------- 8 files changed, 70 insertions(+), 72 deletions(-) diff --git a/include/linux/igmp.h b/include/linux/igmp.h index 119f53941c12..8b4348f69bc5 100644 --- a/include/linux/igmp.h +++ b/include/linux/igmp.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -106,6 +107,14 @@ struct ip_mc_list { #define IGMPV3_QQIC(value) IGMPV3_EXP(0x80, 4, 3, value) #define IGMPV3_MRC(value) IGMPV3_EXP(0x80, 4, 3, value) +static inline int ip_mc_may_pull(struct sk_buff *skb, unsigned int len) +{ + if (skb_transport_offset(skb) + ip_transport_len(skb) < len) + return -EINVAL; + + return pskb_may_pull(skb, len); +} + extern int ip_check_mc_rcu(struct in_device *dev, __be32 mc_addr, __be32 src_addr, u8 proto); extern int igmp_rcv(struct sk_buff *); extern int ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr); @@ -130,6 +139,6 @@ extern void ip_mc_unmap(struct in_device *); extern void ip_mc_remap(struct in_device *); extern void ip_mc_dec_group(struct in_device *in_dev, __be32 addr); extern void ip_mc_inc_group(struct in_device *in_dev, __be32 addr); -int ip_mc_check_igmp(struct sk_buff *skb, struct sk_buff **skb_trimmed); +int ip_mc_check_igmp(struct sk_buff *skb); #endif diff --git a/include/linux/ip.h b/include/linux/ip.h index 492bc6513533..482b7b7c9f30 100644 --- a/include/linux/ip.h +++ b/include/linux/ip.h @@ -34,4 +34,9 @@ static inline struct iphdr *ipip_hdr(const struct sk_buff *skb) { return (struct iphdr *)skb_transport_header(skb); } + +static inline unsigned int ip_transport_len(const struct sk_buff *skb) +{ + return ntohs(ip_hdr(skb)->tot_len) - skb_network_header_len(skb); +} #endif /* _LINUX_IP_H */ diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index 495e834c1367..6d45ce784bea 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -104,6 +104,12 @@ static inline struct ipv6hdr *ipipv6_hdr(const struct sk_buff *skb) return (struct ipv6hdr *)skb_transport_header(skb); } +static inline unsigned int ipv6_transport_len(const struct sk_buff *skb) +{ + return ntohs(ipv6_hdr(skb)->payload_len) + sizeof(struct ipv6hdr) - + skb_network_header_len(skb); +} + /* This structure contains results of exthdrs parsing as offsets from skb->nh. diff --git a/include/net/addrconf.h b/include/net/addrconf.h index 1656c5978498..daf11dcb0f70 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -49,6 +49,7 @@ struct prefix_info { struct in6_addr prefix; }; +#include #include #include #include @@ -201,6 +202,15 @@ u32 ipv6_addr_label(struct net *net, const struct in6_addr *addr, /* * multicast prototypes (mcast.c) */ +static inline int ipv6_mc_may_pull(struct sk_buff *skb, + unsigned int len) +{ + if (skb_transport_offset(skb) + ipv6_transport_len(skb) < len) + return -EINVAL; + + return pskb_may_pull(skb, len); +} + int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr); int ipv6_sock_mc_drop(struct sock *sk, int ifindex, @@ -219,7 +229,7 @@ void ipv6_mc_unmap(struct inet6_dev *idev); void ipv6_mc_remap(struct inet6_dev *idev); void ipv6_mc_init_dev(struct inet6_dev *idev); void ipv6_mc_destroy_dev(struct inet6_dev *idev); -int ipv6_mc_check_mld(struct sk_buff *skb, struct sk_buff **skb_trimmed); +int ipv6_mc_check_mld(struct sk_buff *skb); void addrconf_dad_failure(struct sk_buff *skb, struct inet6_ifaddr *ifp); bool ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group, diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c index 69244e4598f5..1dd70f048e7b 100644 --- a/net/batman-adv/multicast.c +++ b/net/batman-adv/multicast.c @@ -674,7 +674,7 @@ static void batadv_mcast_mla_update(struct work_struct *work) */ static bool batadv_mcast_is_report_ipv4(struct sk_buff *skb) { - if (ip_mc_check_igmp(skb, NULL) < 0) + if (ip_mc_check_igmp(skb) < 0) return false; switch (igmp_hdr(skb)->type) { @@ -741,7 +741,7 @@ static int batadv_mcast_forw_mode_check_ipv4(struct batadv_priv *bat_priv, */ static bool batadv_mcast_is_report_ipv6(struct sk_buff *skb) { - if (ipv6_mc_check_mld(skb, NULL) < 0) + if (ipv6_mc_check_mld(skb) < 0) return false; switch (icmp6_hdr(skb)->icmp6_type) { diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 3aeff0895669..156c4905639e 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -938,7 +938,7 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br, for (i = 0; i < num; i++) { len += sizeof(*grec); - if (!pskb_may_pull(skb, len)) + if (!ip_mc_may_pull(skb, len)) return -EINVAL; grec = (void *)(skb->data + len - sizeof(*grec)); @@ -946,7 +946,7 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br, type = grec->grec_type; len += ntohs(grec->grec_nsrcs) * 4; - if (!pskb_may_pull(skb, len)) + if (!ip_mc_may_pull(skb, len)) return -EINVAL; /* We treat this as an IGMPv2 report for now. */ @@ -985,15 +985,17 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br, struct sk_buff *skb, u16 vid) { + unsigned int nsrcs_offset; const unsigned char *src; struct icmp6hdr *icmp6h; struct mld2_grec *grec; + unsigned int grec_len; int i; int len; int num; int err = 0; - if (!pskb_may_pull(skb, sizeof(*icmp6h))) + if (!ipv6_mc_may_pull(skb, sizeof(*icmp6h))) return -EINVAL; icmp6h = icmp6_hdr(skb); @@ -1003,21 +1005,25 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br, for (i = 0; i < num; i++) { __be16 *nsrcs, _nsrcs; - nsrcs = skb_header_pointer(skb, - len + offsetof(struct mld2_grec, - grec_nsrcs), + nsrcs_offset = len + offsetof(struct mld2_grec, grec_nsrcs); + + if (skb_transport_offset(skb) + ipv6_transport_len(skb) < + nsrcs_offset + sizeof(_nsrcs)) + return -EINVAL; + + nsrcs = skb_header_pointer(skb, nsrcs_offset, sizeof(_nsrcs), &_nsrcs); if (!nsrcs) return -EINVAL; - if (!pskb_may_pull(skb, - len + sizeof(*grec) + - sizeof(struct in6_addr) * ntohs(*nsrcs))) + grec_len = sizeof(*grec) + + sizeof(struct in6_addr) * ntohs(*nsrcs); + + if (!ipv6_mc_may_pull(skb, len + grec_len)) return -EINVAL; grec = (struct mld2_grec *)(skb->data + len); - len += sizeof(*grec) + - sizeof(struct in6_addr) * ntohs(*nsrcs); + len += grec_len; /* We treat these as MLDv1 reports for now. */ switch (grec->grec_type) { @@ -1219,6 +1225,7 @@ static void br_ip4_multicast_query(struct net_bridge *br, struct sk_buff *skb, u16 vid) { + unsigned int transport_len = ip_transport_len(skb); const struct iphdr *iph = ip_hdr(skb); struct igmphdr *ih = igmp_hdr(skb); struct net_bridge_mdb_entry *mp; @@ -1228,7 +1235,6 @@ static void br_ip4_multicast_query(struct net_bridge *br, struct br_ip saddr; unsigned long max_delay; unsigned long now = jiffies; - unsigned int offset = skb_transport_offset(skb); __be32 group; spin_lock(&br->multicast_lock); @@ -1238,14 +1244,14 @@ static void br_ip4_multicast_query(struct net_bridge *br, group = ih->group; - if (skb->len == offset + sizeof(*ih)) { + if (transport_len == sizeof(*ih)) { max_delay = ih->code * (HZ / IGMP_TIMER_SCALE); if (!max_delay) { max_delay = 10 * HZ; group = 0; } - } else if (skb->len >= offset + sizeof(*ih3)) { + } else if (transport_len >= sizeof(*ih3)) { ih3 = igmpv3_query_hdr(skb); if (ih3->nsrcs) goto out; @@ -1296,6 +1302,7 @@ static int br_ip6_multicast_query(struct net_bridge *br, struct sk_buff *skb, u16 vid) { + unsigned int transport_len = ipv6_transport_len(skb); const struct ipv6hdr *ip6h = ipv6_hdr(skb); struct mld_msg *mld; struct net_bridge_mdb_entry *mp; @@ -1315,7 +1322,7 @@ static int br_ip6_multicast_query(struct net_bridge *br, (port && port->state == BR_STATE_DISABLED)) goto out; - if (skb->len == offset + sizeof(*mld)) { + if (transport_len == sizeof(*mld)) { if (!pskb_may_pull(skb, offset + sizeof(*mld))) { err = -EINVAL; goto out; @@ -1581,12 +1588,11 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, struct sk_buff *skb, u16 vid) { - struct sk_buff *skb_trimmed = NULL; const unsigned char *src; struct igmphdr *ih; int err; - err = ip_mc_check_igmp(skb, &skb_trimmed); + err = ip_mc_check_igmp(skb); if (err == -ENOMSG) { if (!ipv4_is_local_multicast(ip_hdr(skb)->daddr)) { @@ -1612,19 +1618,16 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, err = br_ip4_multicast_add_group(br, port, ih->group, vid, src); break; case IGMPV3_HOST_MEMBERSHIP_REPORT: - err = br_ip4_multicast_igmp3_report(br, port, skb_trimmed, vid); + err = br_ip4_multicast_igmp3_report(br, port, skb, vid); break; case IGMP_HOST_MEMBERSHIP_QUERY: - br_ip4_multicast_query(br, port, skb_trimmed, vid); + br_ip4_multicast_query(br, port, skb, vid); break; case IGMP_HOST_LEAVE_MESSAGE: br_ip4_multicast_leave_group(br, port, ih->group, vid, src); break; } - if (skb_trimmed && skb_trimmed != skb) - kfree_skb(skb_trimmed); - br_multicast_count(br, port, skb, BR_INPUT_SKB_CB(skb)->igmp, BR_MCAST_DIR_RX); @@ -1637,12 +1640,11 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, struct sk_buff *skb, u16 vid) { - struct sk_buff *skb_trimmed = NULL; const unsigned char *src; struct mld_msg *mld; int err; - err = ipv6_mc_check_mld(skb, &skb_trimmed); + err = ipv6_mc_check_mld(skb); if (err == -ENOMSG) { if (!ipv6_addr_is_ll_all_nodes(&ipv6_hdr(skb)->daddr)) @@ -1664,10 +1666,10 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, src); break; case ICMPV6_MLD2_REPORT: - err = br_ip6_multicast_mld2_report(br, port, skb_trimmed, vid); + err = br_ip6_multicast_mld2_report(br, port, skb, vid); break; case ICMPV6_MGM_QUERY: - err = br_ip6_multicast_query(br, port, skb_trimmed, vid); + err = br_ip6_multicast_query(br, port, skb, vid); break; case ICMPV6_MGM_REDUCTION: src = eth_hdr(skb)->h_source; @@ -1675,9 +1677,6 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, break; } - if (skb_trimmed && skb_trimmed != skb) - kfree_skb(skb_trimmed); - br_multicast_count(br, port, skb, BR_INPUT_SKB_CB(skb)->igmp, BR_MCAST_DIR_RX); diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 765b2b32c4a4..b1f6d93282d7 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -1544,7 +1544,7 @@ static inline __sum16 ip_mc_validate_checksum(struct sk_buff *skb) return skb_checksum_simple_validate(skb); } -static int __ip_mc_check_igmp(struct sk_buff *skb, struct sk_buff **skb_trimmed) +static int __ip_mc_check_igmp(struct sk_buff *skb) { struct sk_buff *skb_chk; @@ -1566,16 +1566,10 @@ static int __ip_mc_check_igmp(struct sk_buff *skb, struct sk_buff **skb_trimmed) if (ret) goto err; - if (skb_trimmed) - *skb_trimmed = skb_chk; - /* free now unneeded clone */ - else if (skb_chk != skb) - kfree_skb(skb_chk); - ret = 0; err: - if (ret && skb_chk && skb_chk != skb) + if (skb_chk && skb_chk != skb) kfree_skb(skb_chk); return ret; @@ -1584,7 +1578,6 @@ static int __ip_mc_check_igmp(struct sk_buff *skb, struct sk_buff **skb_trimmed) /** * ip_mc_check_igmp - checks whether this is a sane IGMP packet * @skb: the skb to validate - * @skb_trimmed: to store an skb pointer trimmed to IPv4 packet tail (optional) * * Checks whether an IPv4 packet is a valid IGMP packet. If so sets * skb transport header accordingly and returns zero. @@ -1594,18 +1587,10 @@ static int __ip_mc_check_igmp(struct sk_buff *skb, struct sk_buff **skb_trimmed) * -ENOMSG: IP header validation succeeded but it is not an IGMP packet. * -ENOMEM: A memory allocation failure happened. * - * Optionally, an skb pointer might be provided via skb_trimmed (or set it - * to NULL): After parsing an IGMP packet successfully it will point to - * an skb which has its tail aligned to the IP packet end. This might - * either be the originally provided skb or a trimmed, cloned version if - * the skb frame had data beyond the IP packet. A cloned skb allows us - * to leave the original skb and its full frame unchanged (which might be - * desirable for layer 2 frame jugglers). - * * Caller needs to set the skb network header and free any returned skb if it * differs from the provided skb. */ -int ip_mc_check_igmp(struct sk_buff *skb, struct sk_buff **skb_trimmed) +int ip_mc_check_igmp(struct sk_buff *skb) { int ret = ip_mc_check_iphdr(skb); @@ -1615,7 +1600,7 @@ int ip_mc_check_igmp(struct sk_buff *skb, struct sk_buff **skb_trimmed) if (ip_hdr(skb)->protocol != IPPROTO_IGMP) return -ENOMSG; - return __ip_mc_check_igmp(skb, skb_trimmed); + return __ip_mc_check_igmp(skb); } EXPORT_SYMBOL(ip_mc_check_igmp); diff --git a/net/ipv6/mcast_snoop.c b/net/ipv6/mcast_snoop.c index 9405b04eecc6..1a917dc80d5e 100644 --- a/net/ipv6/mcast_snoop.c +++ b/net/ipv6/mcast_snoop.c @@ -136,8 +136,7 @@ static inline __sum16 ipv6_mc_validate_checksum(struct sk_buff *skb) return skb_checksum_validate(skb, IPPROTO_ICMPV6, ip6_compute_pseudo); } -static int __ipv6_mc_check_mld(struct sk_buff *skb, - struct sk_buff **skb_trimmed) +static int __ipv6_mc_check_mld(struct sk_buff *skb) { struct sk_buff *skb_chk = NULL; @@ -160,16 +159,10 @@ static int __ipv6_mc_check_mld(struct sk_buff *skb, if (ret) goto err; - if (skb_trimmed) - *skb_trimmed = skb_chk; - /* free now unneeded clone */ - else if (skb_chk != skb) - kfree_skb(skb_chk); - ret = 0; err: - if (ret && skb_chk && skb_chk != skb) + if (skb_chk && skb_chk != skb) kfree_skb(skb_chk); return ret; @@ -178,7 +171,6 @@ static int __ipv6_mc_check_mld(struct sk_buff *skb, /** * ipv6_mc_check_mld - checks whether this is a sane MLD packet * @skb: the skb to validate - * @skb_trimmed: to store an skb pointer trimmed to IPv6 packet tail (optional) * * Checks whether an IPv6 packet is a valid MLD packet. If so sets * skb transport header accordingly and returns zero. @@ -188,18 +180,10 @@ static int __ipv6_mc_check_mld(struct sk_buff *skb, * -ENOMSG: IP header validation succeeded but it is not an MLD packet. * -ENOMEM: A memory allocation failure happened. * - * Optionally, an skb pointer might be provided via skb_trimmed (or set it - * to NULL): After parsing an MLD packet successfully it will point to - * an skb which has its tail aligned to the IP packet end. This might - * either be the originally provided skb or a trimmed, cloned version if - * the skb frame had data beyond the IP packet. A cloned skb allows us - * to leave the original skb and its full frame unchanged (which might be - * desirable for layer 2 frame jugglers). - * * Caller needs to set the skb network header and free any returned skb if it * differs from the provided skb. */ -int ipv6_mc_check_mld(struct sk_buff *skb, struct sk_buff **skb_trimmed) +int ipv6_mc_check_mld(struct sk_buff *skb) { int ret; @@ -211,6 +195,6 @@ int ipv6_mc_check_mld(struct sk_buff *skb, struct sk_buff **skb_trimmed) if (ret < 0) return ret; - return __ipv6_mc_check_mld(skb, skb_trimmed); + return __ipv6_mc_check_mld(skb); } EXPORT_SYMBOL(ipv6_mc_check_mld); -- 2.11.0 From nikolay at cumulusnetworks.com Fri Dec 21 16:37:32 2018 From: nikolay at cumulusnetworks.com (Nikolay Aleksandrov) Date: Fri, 21 Dec 2018 17:37:32 +0200 Subject: [B.A.T.M.A.N.] [PATCH net-next 0/4] bridge: implement Multicast Router Discovery (RFC4286) In-Reply-To: <20181221151511.14923-1-linus.luessing@c0d3.blue> References: <20181221151511.14923-1-linus.luessing@c0d3.blue> Message-ID: On 12/21/18 5:15 PM, Linus Lüssing wrote: > Hi, > > This patchset adds initial Multicast Router Discovery support to > the Linux bridge (RFC4286). With MRD it is possible to detect multicast > routers and mark bridge ports and forward multicast packets to such routers > accordingly. > > So far, multicast routers are detected via IGMP/MLD queries and PIM > messages in the Linux bridge. As there is only one active, selected > querier at a time RFC4541 ("Considerations for Internet Group Management > Protocol (IGMP) and Multicast Listener Discovery (MLD) Snooping > Switches") section 2.1.1.a) recommends snooping Multicast Router > Advertisements as provided by MRD (RFC4286). > > > The first two patches are refactoring some existing code which is reused > for parsing the Multicast Router Advertisements later in the fourth > patch. The third patch lets the bridge join the all-snoopers multicast > address to be able to reliably receive the Multicast Router > Advertisements. > > > What is not implemented yet from RFC4286 yet: > > * Sending Multicast Router Solicitations: > -> RFC4286: "[...] may be sent when [...] an interface is > (re-)initialized [or] MRD is enabled" > * Snooping Multicast Router Terminations: > -> currently this only relies on our own timeouts > * Adjusting timeouts with the values provided in the announcements > > > Regards, Linus > > > Hi Linus, Nice work, unfortunately net-next is currenty closed. Anyway I'll review the patches in detail after the holidays so if there's anything it can be adjusted for when net-next opens up. Thanks, Nik From pakki001 at umn.edu Mon Dec 24 18:49:26 2018 From: pakki001 at umn.edu (Aditya Pakki) Date: Mon, 24 Dec 2018 11:49:26 -0600 Subject: [B.A.T.M.A.N.] [PATCH] batman-adv/main: Fix check on return value of rtnl_link_register Message-ID: <20181224174926.20321-1-pakki001@umn.edu> rtnl_link_register() may fail and can impact registering the device. The fix checks the return value and pushes the error upstream. Signed-off-by: Aditya Pakki --- net/batman-adv/main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 69c0d85bceb3..e0007f242823 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c @@ -109,7 +109,10 @@ static int __init batadv_init(void) batadv_debugfs_init(); register_netdevice_notifier(&batadv_hard_if_notifier); - rtnl_link_register(&batadv_link_ops); + ret = rtnl_link_register(&batadv_link_ops); + if (ret < 0) + return ret; + batadv_netlink_register(); pr_info("B.A.T.M.A.N. advanced %s (compatibility version %i) loaded\n", -- 2.17.1 From sven at narfation.org Mon Dec 24 19:43:07 2018 From: sven at narfation.org (Sven Eckelmann) Date: Mon, 24 Dec 2018 19:43:07 +0100 Subject: [B.A.T.M.A.N.] [PATCH] batman-adv/main: Fix check on return value of rtnl_link_register In-Reply-To: <20181224174926.20321-1-pakki001@umn.edu> References: <20181224174926.20321-1-pakki001@umn.edu> Message-ID: <4059540.uxCivL65nk@sven-edge> On Monday, 24 December 2018 18.49.26 CET Aditya Pakki wrote: [...] > diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c > index 69c0d85bceb3..e0007f242823 100644 > --- a/net/batman-adv/main.c > +++ b/net/batman-adv/main.c > @@ -109,7 +109,10 @@ static int __init batadv_init(void) > batadv_debugfs_init(); > > register_netdevice_notifier(&batadv_hard_if_notifier); > - rtnl_link_register(&batadv_link_ops); > + ret = rtnl_link_register(&batadv_link_ops); > + if (ret < 0) > + return ret; > + > batadv_netlink_register(); Uhm, but shouldn't the already initialized parts be unregistered/uninitialized in this case? Rejecting this patch because this could cause a new bug. Also "Fixes: " line is missing Kind regards, Sven -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: This is a digitally signed message part. URL: From sven at narfation.org Mon Dec 24 19:46:32 2018 From: sven at narfation.org (Sven Eckelmann) Date: Mon, 24 Dec 2018 19:46:32 +0100 Subject: [B.A.T.M.A.N.] [PATCH] batman-adv/main: Fix check on return value of rtnl_link_register In-Reply-To: <20181224174926.20321-1-pakki001@umn.edu> References: <20181224174926.20321-1-pakki001@umn.edu> Message-ID: <3515548.IyJqbIalli@sven-edge> On Monday, 24 December 2018 18.49.26 CET Aditya Pakki wrote: > rtnl_link_register() may fail and can impact registering the device. > The fix checks the return value and pushes the error upstream. Regarding the commit message - what is "batman-adv/main"? Shouldn't this be "batman-adv: "? And the device can still be registered without batadv_link_ops - just not using rtnl. Kind regards, Sven -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: This is a digitally signed message part. URL: From linus.luessing at c0d3.blue Sat Dec 29 04:10:40 2018 From: linus.luessing at c0d3.blue (=?UTF-8?q?Linus=20L=C3=BCssing?=) Date: Sat, 29 Dec 2018 04:10:40 +0100 Subject: [B.A.T.M.A.N.] [PATCH v7] batman-adv: Snoop DHCPACKs for DAT Message-ID: <20181229031040.7207-1-linus.luessing@c0d3.blue> In a 1000 nodes mesh network (Freifunk Hamburg) we can still see 30KBit/s of ARP traffic (equalling about 25% of all layer two specific overhead, remaining after some filtering) flooded through the mesh. These 30KBit/s are mainly ARP Requests from the gateways / DHCP servers. By snooping DHCPACKs we can learn about MAC/IP address pairs in the DHCP range without relying on ARP. This patch is in preparation to eliminate the need for mesh wide message flooding for IPv4 address resolution. Also this allows to quickly update a MAC/IP pair at least in the DHT when DHCP reassigns an IP address to a new host. Signed-off-by: Linus Lüssing --- Changen in v7: * fixed a memory access bug in batadv_dat_snoop_outgoing_dhcp_ack(): ip_hdr(skb)->saddr is unsafe because we never ensured linear skb data; -> refactored functions to take an ip_src paramter instead * fixed a memory access bug in batadv_dat_check_dhcp_ipudp(): ip_hdrlen(skb) is unsafe on potentially non-linear skb data * fixed a memory access bug in batadv_dat_get_dhcp_chaddr(): the len parameter provided to skb_header_pointer() is 16 bytes long but we only reserved 6 bytes (ETH_ALEN) in batadv_dat_snoop_outgoing_dhcp_ack() -> increased the buffer length to the full DHCP chaddr size * renamed batadv_dat_put_pairs() to batadv_dat_put_dhcp(), renamed its parameters and moved the batadv_dbg() functions into it, to make the naming and the function's purpose a bit more specific and meaningful * added parsing of DHCPACKs on the mesh-ingress side, too, and if successful adding retrieved values to the local DAT cache; similar to what is done for incoming ARP replies, too * removed unnecessary and unused hdr_size calculation in former batadv_dat_put_pairs() * batadv_dat_dhcp_get_yiaddr() and batadv_dat_get_dhcp_chaddr() now always return a copy of the yiaddr chaddr so that callers have one less pointer to play with and do not need to worry about memory alignment anymore themselves * rebased to master * sorted variables to reverse Christmas tree Changes in v6: * moved dhcp packet definition from batadv_packet.h to distributed-arp-table.c Changes in v5: * fixed unaligned access issues (that is, enforce a two step load via "get_unaligned") for DHCP magic and yiaddr fields * simplified batadv_dat_put_pairs(): there is no need to check that arp_create() set the ARP type correctly. It always does or returns NULL otherwise. (this also fixes another unaligned access) Changes in v4: * Removed @proto from kerneldoc * Less enum values in batadv_packet.h * Moved skb_set_network_header() call * Updated commit message Changes in v3: * Rebase to master * Shortened commit message Changes in v2: * Rebase to master * Fix compilation with CONFIG_BATMAN_ADV=n (added stubs) Changes in RFC -> non-RFC * Added kerneldoc * Added Signed-off-by * More IP Header checks (iph->hlen considered, ip version checked, ...) * Parsing & checking DHCP Message Type Option, only snooping DHCPACKs now * Moved ethernet protocol check from batadv_dat_check_dhcp to batadv_dat_check_dhcp_ipudp * Removed buffer-length parameter from batadv_dat_dhcp_get_{yiaddr,chaddr}() * Renamed batadv_dat_put() to batadv_dat_put_pairs() fixup DAT DHCP snooping --- net/batman-adv/distributed-arp-table.c | 410 +++++++++++++++++++++++++++++++++ net/batman-adv/distributed-arp-table.h | 13 ++ net/batman-adv/routing.c | 4 + net/batman-adv/soft-interface.c | 11 +- 4 files changed, 436 insertions(+), 2 deletions(-) diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index b9ffe182..d03184ec 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -42,9 +43,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -60,6 +63,49 @@ #include "translation-table.h" #include "tvlv.h" +enum batadv_bootpop { + BATADV_BOOTREPLY = 2, +}; + +enum batadv_boothtype { + BATADV_HTYPE_ETHERNET = 1, +}; + +enum batadv_dhcpoptioncode { + BATADV_DHCP_OPT_PAD = 0, + BATADV_DHCP_OPT_MSG_TYPE = 53, + BATADV_DHCP_OPT_END = 255, +}; + +enum batadv_dhcptype { + BATADV_DHCPACK = 5, +}; + +/* { 99, 130, 83, 99 } */ +#define BATADV_DHCP_MAGIC 1669485411 + +struct batadv_dhcp_packet { + __u8 op; + __u8 htype; + __u8 hlen; + __u8 hops; + __be32 xid; + __be16 secs; + __be16 flags; + __be32 ciaddr; + __be32 yiaddr; + __be32 siaddr; + __be32 giaddr; + __u8 chaddr[16]; + __u8 sname[64]; + __u8 file[128]; + __be32 magic; + __u8 options[0]; +}; + +#define BATADV_DHCP_YIADDR_LEN sizeof(((struct batadv_dhcp_packet *)0)->chaddr) +#define BATADV_DHCP_CHADDR_LEN sizeof(((struct batadv_dhcp_packet *)0)->chaddr) + static void batadv_dat_purge(struct work_struct *work); /** @@ -1440,6 +1486,370 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, } /** + * batadv_dat_check_dhcp_ipudp() - check skb for IP+UDP headers valid for DHCP + * @skb: the packet to check + * @ip_src: a buffer to store the IPv4 source address in + * + * Checks whether the given skb has an IP and UDP header valid for a DHCP + * message from a DHCP server. And if so, stores the IPv4 source address in + * the provided buffer. + * + * Return: True if valid, false otherwise. + */ +static bool +batadv_dat_check_dhcp_ipudp(struct sk_buff *skb, __be32 *ip_src) +{ + unsigned int offset = skb_network_offset(skb); + struct udphdr *udphdr, _udphdr; + struct iphdr *iphdr, _iphdr; + + iphdr = skb_header_pointer(skb, offset, sizeof(_iphdr), &_iphdr); + if (!iphdr || iphdr->version != 4 || iphdr->ihl * 4 < sizeof(_iphdr)) + return false; + + if (iphdr->protocol != IPPROTO_UDP) + return false; + + offset += iphdr->ihl * 4; + skb_set_transport_header(skb, offset); + + udphdr = skb_header_pointer(skb, offset, sizeof(_udphdr), &_udphdr); + if (!udphdr || udphdr->source != htons(67)) + return false; + + *ip_src = get_unaligned(&iphdr->saddr); + + return true; +} + +/** + * batadv_dat_check_dhcp() - examine packet for valid DHCP message + * @skb: the packet to check + * @proto: ethernet protocol hint (behind a potential vlan) + * @ip_src: a buffer to store the IPv4 source address in + * + * Checks whether the given skb is a valid DHCP packet. And if so, stores the + * IPv4 source address in the provided buffer. + * + * Caller needs to ensure that the skb network header is set correctly. + * + * Return: If skb is a valid DHCP packet, then returns its op code + * (e.g. BOOTREPLY vs. BOOTREQUEST). Otherwise returns -EINVAL. + */ +static int +batadv_dat_check_dhcp(struct sk_buff *skb, __be16 proto, __be32 *ip_src) +{ + unsigned int dhcp_offset; + __be32 *magic, _magic; + unsigned int offset; + u8 *htype, _htype; + u8 *hlen, _hlen; + u8 *op, _op; + + if (proto != htons(ETH_P_IP)) + return -EINVAL; + + if (!batadv_dat_check_dhcp_ipudp(skb, ip_src)) + return -EINVAL; + + dhcp_offset = skb_transport_offset(skb) + sizeof(struct udphdr); + if (skb->len < dhcp_offset + sizeof(struct batadv_dhcp_packet)) + return -EINVAL; + + offset = dhcp_offset + offsetof(struct batadv_dhcp_packet, op); + + op = skb_header_pointer(skb, offset, sizeof(_op), &_op); + if (!op) + return -EINVAL; + + offset = dhcp_offset + offsetof(struct batadv_dhcp_packet, htype); + + htype = skb_header_pointer(skb, offset, sizeof(_htype), &_htype); + if (!htype || *htype != BATADV_HTYPE_ETHERNET) + return -EINVAL; + + offset = dhcp_offset + offsetof(struct batadv_dhcp_packet, hlen); + + hlen = skb_header_pointer(skb, offset, sizeof(_hlen), &_hlen); + if (!hlen || *hlen != ETH_ALEN) + return -EINVAL; + + offset = dhcp_offset + offsetof(struct batadv_dhcp_packet, magic); + + magic = skb_header_pointer(skb, offset, sizeof(_magic), &_magic); + if (!magic || get_unaligned(magic) != htonl(BATADV_DHCP_MAGIC)) + return -EINVAL; + + return *op; +} + +/** + * batadv_dat_get_dhcp_message_type() - get message type of a DHCP packet + * @skb: the DHCP packet to parse + * + * Iterates over the DHCP options of the given DHCP packet to find a + * DHCP Message Type option and parse it. + * + * Caller needs to ensure that the given skb is a valid DHCP packet and + * that the skb transport header is set correctly. + * + * Return: The found DHCP message type value, if found. -EINVAL otherwise. + */ +static int batadv_dat_get_dhcp_message_type(struct sk_buff *skb) +{ + unsigned int offset = skb_transport_offset(skb) + sizeof(struct udphdr); + u8 *type, _type; + struct { + u8 type; + u8 len; + } *tl, _tl; + + offset += sizeof(struct batadv_dhcp_packet); + + while ((tl = skb_header_pointer(skb, offset, sizeof(_tl), &_tl))) { + if (tl->type == BATADV_DHCP_OPT_MSG_TYPE) + break; + + if (tl->type == BATADV_DHCP_OPT_END) + break; + + if (tl->type == BATADV_DHCP_OPT_PAD) + offset++; + else + offset += tl->len + sizeof(_tl); + } + + /* Option Overload Code not supported */ + if (!tl || tl->type != BATADV_DHCP_OPT_MSG_TYPE || + tl->len != sizeof(_type)) + return -EINVAL; + + offset += sizeof(_tl); + + type = skb_header_pointer(skb, offset, sizeof(_type), &_type); + if (!type) + return -EINVAL; + + return *type; +} + +/** + * batadv_dat_get_dhcp_yiaddr() - get yiaddr from a DHCP packet + * @skb: the DHCP packet to parse + * @buf: a buffer to store the yiaddr in + * + * Caller needs to ensure that the given skb is a valid DHCP packet and + * that the skb transport header is set correctly. + * + * Return: True on success, false otherwise. + */ +static bool batadv_dat_dhcp_get_yiaddr(struct sk_buff *skb, __be32 *buf) +{ + unsigned int offset = skb_transport_offset(skb) + sizeof(struct udphdr); + __be32 *yiaddr; + + offset += offsetof(struct batadv_dhcp_packet, yiaddr); + yiaddr = skb_header_pointer(skb, offset, BATADV_DHCP_YIADDR_LEN, buf); + + if (!yiaddr) + return false; + + if (yiaddr != buf) + *buf = get_unaligned(yiaddr); + + return true; +} + +/** + * batadv_dat_get_dhcp_chaddr() - get chaddr from a DHCP packet + * @skb: the DHCP packet to parse + * @buf: a buffer to store the chaddr in + * + * Caller needs to ensure that the given skb is a valid DHCP packet and + * that the skb transport header is set correctly. + * + * Return: True on success, false otherwise + */ +static bool batadv_dat_get_dhcp_chaddr(struct sk_buff *skb, u8 *buf) +{ + unsigned int offset = skb_transport_offset(skb) + sizeof(struct udphdr); + u8 *chaddr; + + offset += offsetof(struct batadv_dhcp_packet, chaddr); + chaddr = skb_header_pointer(skb, offset, BATADV_DHCP_CHADDR_LEN, buf); + + if (!chaddr) + return false; + + if (chaddr != buf) + memcpy(buf, chaddr, BATADV_DHCP_CHADDR_LEN); + + return true; +} + +/** + * batadv_dat_put_dhcp() - puts addresses from a DHCP packet into the DHT and + * DAT cache + * @bat_priv: the bat priv with all the soft interface information + * @chaddr: the DHCP client MAC address + * @yiaddr: the DHCP client IP address + * @hw_dst: the DHCP server MAC address + * @ip_dst: the DHCP server IP address + * @vid: VLAN identifier + * + * Adds given MAC/IP pairs to the local DAT cache and propagates them further + * into the DHT. + * + * For the DHT propagation, client MAC + IP will appear as the ARP Reply + * transmitter (and hw_dst/ip_dst as the target). + */ +static void batadv_dat_put_dhcp(struct batadv_priv *bat_priv, u8 *chaddr, + __be32 yiaddr, u8 *hw_dst, __be32 ip_dst, + unsigned short vid) +{ + struct sk_buff *skb; + + skb = batadv_dat_arp_create_reply(bat_priv, yiaddr, ip_dst, chaddr, + hw_dst, vid); + if (!skb) + return; + + skb_set_network_header(skb, ETH_HLEN); + + batadv_dat_entry_add(bat_priv, yiaddr, chaddr, vid); + batadv_dat_entry_add(bat_priv, ip_dst, hw_dst, vid); + + batadv_dat_send_data(bat_priv, skb, yiaddr, vid, BATADV_P_DAT_DHT_PUT); + batadv_dat_send_data(bat_priv, skb, ip_dst, vid, BATADV_P_DAT_DHT_PUT); + + batadv_dbg(BATADV_DBG_DAT, bat_priv, + "Snooped from outgoing DHCPACK (server address): %pI4, %pM (vid: %i)\n", + &ip_dst, hw_dst, batadv_print_vid(vid)); + batadv_dbg(BATADV_DBG_DAT, bat_priv, + "Snooped from outgoing DHCPACK (client address): %pI4, %pM (vid: %i)\n", + &yiaddr, chaddr, batadv_print_vid(vid)); +} + +/** + * batadv_dat_check_dhcp_ack() - examine packet for valid DHCP message + * @skb: the packet to check + * @proto: ethernet protocol hint (behind a potential vlan) + * @ip_src: a buffer to store the IPv4 source address in + * @chaddr: a buffer to store the DHCP Client Hardware Address in + * @yiaddr: a buffer to store the DHCP Your IP Address in + * + * Checks whether the given skb is a valid DHCPACK. And if so, stores the + * IPv4 server source address (ip_src), client MAC address (chaddr) and client + * IPv4 address (yiaddr) in the provided buffers. + + * Caller needs to ensure that the skb network header is set correctly. + * + * Return: True if the skb is a valid DHCPACK. False otherwise. + */ +static bool +batadv_dat_check_dhcp_ack(struct sk_buff *skb, __be16 proto, __be32 *ip_src, + u8 *chaddr, __be32 *yiaddr) +{ + int type; + + type = batadv_dat_check_dhcp(skb, proto, ip_src); + if (type != BATADV_BOOTREPLY) + return false; + + type = batadv_dat_get_dhcp_message_type(skb); + if (type != BATADV_DHCPACK) + return false; + + if (!batadv_dat_dhcp_get_yiaddr(skb, yiaddr)) + return false; + + if (!batadv_dat_get_dhcp_chaddr(skb, chaddr)) + return false; + + return true; +} + +/** + * batadv_dat_snoop_outgoing_dhcp_ack() - snoop DHCPACK and fill DAT with it + * @bat_priv: the bat priv with all the soft interface information + * @skb: the packet to snoop + * @proto: ethernet protocol hint (behind a potential vlan) + * @vid: VLAN identifier + * + * This function first checks whether the given skb is a valid DHCPACK. If + * so then its source MAC and IP as well as its DHCP Client Hardware Address + * field and DHCP Your IP Address field are added to the local DAT cache and + * propagated into the DHT. + * + * Caller needs to ensure that the skb mac and network headers are set + * correctly. + */ +void batadv_dat_snoop_outgoing_dhcp_ack(struct batadv_priv *bat_priv, + struct sk_buff *skb, + __be16 proto, + unsigned short vid) +{ + u8 chaddr[BATADV_DHCP_CHADDR_LEN]; + __be32 ip_src, yiaddr; + + if (!atomic_read(&bat_priv->distributed_arp_table)) + return; + + if (!batadv_dat_check_dhcp_ack(skb, proto, &ip_src, chaddr, &yiaddr)) + return; + + batadv_dat_put_dhcp(bat_priv, chaddr, yiaddr, eth_hdr(skb)->h_source, + ip_src, vid); +} + +/** + * batadv_dat_snoop_incoming_dhcp_ack() - snoop DHCPACK and fill DAT cache + * @bat_priv: the bat priv with all the soft interface information + * @skb: the packet to snoop + * @hdr_size: header size, up to the tail of the batman-adv header + * + * This function first checks whether the given skb is a valid DHCPACK. If + * so then its source MAC and IP as well as its DHCP Client Hardware Address + * field and DHCP Your IP Address field are added to the local DAT cache. + */ +void batadv_dat_snoop_incoming_dhcp_ack(struct batadv_priv *bat_priv, + struct sk_buff *skb, int hdr_size) +{ + u8 chaddr[BATADV_DHCP_CHADDR_LEN]; + struct ethhdr *ethhdr; + __be32 ip_src, yiaddr; + unsigned short vid; + __be16 proto; + u8 *hw_src; + + if (!atomic_read(&bat_priv->distributed_arp_table)) + return; + + if (unlikely(!pskb_may_pull(skb, hdr_size + ETH_HLEN))) + return; + + ethhdr = (struct ethhdr *)(skb->data + hdr_size); + skb_set_network_header(skb, hdr_size + ETH_HLEN); + proto = ethhdr->h_proto; + + if (!batadv_dat_check_dhcp_ack(skb, proto, &ip_src, chaddr, &yiaddr)) + return; + + hw_src = ethhdr->h_source; + vid = batadv_dat_get_vid(skb, &hdr_size); + + batadv_dat_entry_add(bat_priv, yiaddr, chaddr, vid); + batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid); + + batadv_dbg(BATADV_DBG_DAT, bat_priv, + "Snooped from incoming DHCPACK (server address): %pI4, %pM (vid: %i)\n", + &ip_src, hw_src, batadv_print_vid(vid)); + batadv_dbg(BATADV_DBG_DAT, bat_priv, + "Snooped from incoming DHCPACK (client address): %pI4, %pM (vid: %i)\n", + &yiaddr, chaddr, batadv_print_vid(vid)); +} + +/** * batadv_dat_drop_broadcast_packet() - check if an ARP request has to be * dropped (because the node has already obtained the reply via DAT) or not * @bat_priv: the bat priv with all the soft interface information diff --git a/net/batman-adv/distributed-arp-table.h b/net/batman-adv/distributed-arp-table.h index a0459602..6c2c87d7 100644 --- a/net/batman-adv/distributed-arp-table.h +++ b/net/batman-adv/distributed-arp-table.h @@ -46,6 +46,12 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv, struct sk_buff *skb); bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, struct sk_buff *skb, int hdr_size); +void batadv_dat_snoop_outgoing_dhcp_ack(struct batadv_priv *bat_priv, + struct sk_buff *skb, + __be16 proto, + unsigned short vid); +void batadv_dat_snoop_incoming_dhcp_ack(struct batadv_priv *bat_priv, + struct sk_buff *skb, int hdr_size); bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv, struct batadv_forw_packet *forw_packet); @@ -140,6 +146,13 @@ batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, return false; } +static inline void +batadv_dat_snoop_outgoing_dhcp_ack(struct batadv_priv *bat_priv, + struct sk_buff *skb, __be16 proto, + unsigned short vid) +{ +} + static inline bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv, struct batadv_forw_packet *forw_packet) diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index cc3ed93a..469fa97d 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -1043,6 +1043,8 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, hdr_size)) goto rx_success; + batadv_dat_snoop_incoming_dhcp_ack(bat_priv, skb, hdr_size); + batadv_interface_rx(recv_if->soft_iface, skb, hdr_size, orig_node); @@ -1278,6 +1280,8 @@ int batadv_recv_bcast_packet(struct sk_buff *skb, if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb, hdr_size)) goto rx_success; + batadv_dat_snoop_incoming_dhcp_ack(bat_priv, skb, hdr_size); + /* broadcast for me */ batadv_interface_rx(recv_if->soft_iface, skb, hdr_size, orig_node); diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 5db5a0a4..94307100 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -212,6 +212,7 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb, enum batadv_forw_mode forw_mode; struct batadv_orig_node *mcast_single_orig = NULL; int network_offset = ETH_HLEN; + __be16 proto; if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) goto dropped; @@ -223,12 +224,15 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb, vid = batadv_get_vid(skb, 0); ethhdr = eth_hdr(skb); - switch (ntohs(ethhdr->h_proto)) { + proto = ethhdr->h_proto; + + switch (ntohs(proto)) { case ETH_P_8021Q: vhdr = vlan_eth_hdr(skb); + proto = vhdr->h_vlan_encapsulated_proto; /* drop batman-in-batman packets to prevent loops */ - if (vhdr->h_vlan_encapsulated_proto != htons(ETH_P_BATMAN)) { + if (proto != htons(ETH_P_BATMAN)) { network_offset += VLAN_HLEN; break; } @@ -256,6 +260,9 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb, goto dropped; } + /* Snoop address candidates from DHCPACKs for early DAT filling */ + batadv_dat_snoop_outgoing_dhcp_ack(bat_priv, skb, proto, vid); + /* don't accept stp packets. STP does not help in meshes. * better use the bridge loop avoidance ... * -- 2.11.0 From syzbot+c764de0fcfadca9a8595 at syzkaller.appspotmail.com Sun Dec 30 11:41:03 2018 From: syzbot+c764de0fcfadca9a8595 at syzkaller.appspotmail.com (syzbot) Date: Sun, 30 Dec 2018 02:41:03 -0800 Subject: [B.A.T.M.A.N.] WARNING in batadv_is_on_batman_iface Message-ID: <000000000000d89413057e3aeec2@google.com> Hello, syzbot found the following crash on: HEAD commit: d8924c0d76aa Merge tag 'devprop-4.21-rc1' of git://git.ker.. git tree: upstream console output: https://syzkaller.appspot.com/x/log.txt?x=122a373f400000 kernel config: https://syzkaller.appspot.com/x/.config?x=91a256823ef17263 dashboard link: https://syzkaller.appspot.com/bug?extid=c764de0fcfadca9a8595 compiler: gcc (GCC) 8.0.1 20180413 (experimental) syz repro: https://syzkaller.appspot.com/x/repro.syz?x=16fd1d67400000 IMPORTANT: if you fix the bug, please add the following tag to the commit: Reported-by: syzbot+c764de0fcfadca9a8595 at syzkaller.appspotmail.com 8021q: adding VLAN 0 to HW filter on device team0 8021q: adding VLAN 0 to HW filter on device team0 8021q: adding VLAN 0 to HW filter on device team0 ------------[ cut here ]------------ Cannot find parent device WARNING: CPU: 1 PID: 9391 at net/batman-adv/hard-interface.c:182 batadv_is_on_batman_iface+0x3ef/0x460 net/batman-adv/hard-interface.c:182 Kernel panic - not syncing: panic_on_warn set ... CPU: 1 PID: 9391 Comm: syz-executor2 Not tainted 4.20.0+ #388 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x1d3/0x2c6 lib/dump_stack.c:113 panic+0x2ad/0x55c kernel/panic.c:188 __warn.cold.8+0x20/0x45 kernel/panic.c:540 report_bug+0x254/0x2d0 lib/bug.c:186 fixup_bug arch/x86/kernel/traps.c:178 [inline] do_error_trap+0x11b/0x200 arch/x86/kernel/traps.c:271 do_invalid_op+0x36/0x40 arch/x86/kernel/traps.c:290 invalid_op+0x14/0x20 arch/x86/entry/entry_64.S:973 RIP: 0010:batadv_is_on_batman_iface+0x3ef/0x460 net/batman-adv/hard-interface.c:182 Code: 8b 45 d0 48 89 45 c0 e9 f5 fe ff ff 4c 89 ff e8 67 f7 03 fa e9 f4 fc ff ff e8 2d ec c0 f9 48 c7 c7 00 16 d6 88 e8 b1 9f 8a f9 <0f> 0b eb b7 e8 68 f7 03 fa e9 3e fc ff ff 48 8b 7d c0 e8 5a f7 03 RSP: 0018:ffff8881d31e68b8 EFLAGS: 00010282 RAX: 0000000000000000 RBX: ffff8881d78d0ec0 RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffffffff8164e075 RDI: 0000000000000006 RBP: ffff8881d31e6900 R08: ffff8881b0d9c040 R09: 0000000000000006 R10: 0000000000000000 R11: ffff8881b0d9c040 R12: 0000000000000000 R13: ffff8881bd630140 R14: 00000000447eea95 R15: ffff8881d78d0fc8 batadv_is_valid_iface net/batman-adv/hard-interface.c:205 [inline] batadv_hardif_add_interface net/batman-adv/hard-interface.c:917 [inline] batadv_hard_if_event+0x944/0x11e0 net/batman-adv/hard-interface.c:1041 notifier_call_chain+0x17e/0x380 kernel/notifier.c:93 __raw_notifier_call_chain kernel/notifier.c:394 [inline] raw_notifier_call_chain+0x2d/0x40 kernel/notifier.c:401 call_netdevice_notifiers_info+0x3f/0x90 net/core/dev.c:1733 call_netdevice_notifiers net/core/dev.c:1751 [inline] register_netdevice+0xb98/0x10f0 net/core/dev.c:8570 ip6gre_newlink_common.isra.29+0x165/0x3c0 net/ipv6/ip6_gre.c:1948 ip6gre_newlink+0x353/0x9b0 net/ipv6/ip6_gre.c:1981 rtnl_newlink+0xf08/0x1da0 net/core/rtnetlink.c:3175 rtnetlink_rcv_msg+0x46a/0xc20 net/core/rtnetlink.c:4950 netlink_rcv_skb+0x172/0x440 net/netlink/af_netlink.c:2477 rtnetlink_rcv+0x1c/0x20 net/core/rtnetlink.c:4968 netlink_unicast_kernel net/netlink/af_netlink.c:1310 [inline] netlink_unicast+0x5a5/0x760 net/netlink/af_netlink.c:1336 netlink_sendmsg+0xa18/0xfc0 net/netlink/af_netlink.c:1917 sock_sendmsg_nosec net/socket.c:621 [inline] sock_sendmsg+0xd5/0x120 net/socket.c:631 ___sys_sendmsg+0x7fd/0x930 net/socket.c:2116 __sys_sendmsg+0x11d/0x280 net/socket.c:2154 __do_sys_sendmsg net/socket.c:2163 [inline] __se_sys_sendmsg net/socket.c:2161 [inline] __x64_sys_sendmsg+0x78/0xb0 net/socket.c:2161 do_syscall_64+0x1b9/0x820 arch/x86/entry/common.c:290 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x457759 Code: fd b3 fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 cb b3 fb ff c3 66 2e 0f 1f 84 00 00 00 00 RSP: 002b:00007fd848638c78 EFLAGS: 00000246 ORIG_RAX: 000000000000002e RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 0000000000457759 RDX: 0000000000000000 RSI: 00000000200005c0 RDI: 0000000000000003 RBP: 000000000073bf00 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 00007fd8486396d4 R13: 00000000004c49f1 R14: 00000000004d80d0 R15: 00000000ffffffff Kernel Offset: disabled Rebooting in 86400 seconds.. --- This bug is generated by a bot. It may contain errors. See https://goo.gl/tpsmEJ for more information about syzbot. syzbot engineers can be reached at syzkaller at googlegroups.com. syzbot will keep track of this bug report. See: https://goo.gl/tpsmEJ#bug-status-tracking for how to communicate with syzbot. syzbot can test patches for this bug, for details see: https://goo.gl/tpsmEJ#testing-patches From sven at narfation.org Sun Dec 30 12:00:12 2018 From: sven at narfation.org (Sven Eckelmann) Date: Sun, 30 Dec 2018 12:00:12 +0100 Subject: [B.A.T.M.A.N.] WARNING in batadv_is_on_batman_iface In-Reply-To: <000000000000d89413057e3aeec2@google.com> References: <000000000000d89413057e3aeec2@google.com> Message-ID: <3100603.HWLWhOUWpG@sven-edge> On Sunday, 30 December 2018 11.41.03 CET syzbot wrote: [...] > HEAD commit: d8924c0d76aa Merge tag 'devprop-4.21-rc1' of git://git.ker.. > git tree: upstream > console output: https://syzkaller.appspot.com/x/log.txt?x=122a373f400000 > kernel config: https://syzkaller.appspot.com/x/.config?x=91a256823ef17263 > dashboard link: https://syzkaller.appspot.com/bug?extid=c764de0fcfadca9a8595 > compiler: gcc (GCC) 8.0.1 20180413 (experimental) > syz repro: https://syzkaller.appspot.com/x/repro.syz?x=16fd1d67400000 > > IMPORTANT: if you fix the bug, please add the following tag to the commit: > Reported-by: syzbot+c764de0fcfadca9a8595 at syzkaller.appspotmail.com What is the bug here? The kernel module showed a warning because the parent device cannot be found in the same netns using __dev_get_by_index. The test system was just configured to panic on warnings. So are we now expected to show warnings or what is the expected behavior? This behavior was added with commit b7eddd0b3950 ("batman-adv: prevent using any virtual device created on batman-adv as hard-interface") - 3d48811b27f5 in the out-of-tree module. Kind regards, Sven [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b7eddd0b3950ea9dc863f1cbfa30d172dbf772f4 -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: This is a digitally signed message part. URL: From dvyukov at google.com Sun Dec 30 12:08:53 2018 From: dvyukov at google.com (Dmitry Vyukov) Date: Sun, 30 Dec 2018 12:08:53 +0100 Subject: WARNING in batadv_is_on_batman_iface In-Reply-To: <3100603.HWLWhOUWpG@sven-edge> References: <000000000000d89413057e3aeec2@google.com> <3100603.HWLWhOUWpG@sven-edge> Message-ID: On Sun, Dec 30, 2018 at 12:00 PM Sven Eckelmann wrote: > > On Sunday, 30 December 2018 11.41.03 CET syzbot wrote: > [...] > > HEAD commit: d8924c0d76aa Merge tag 'devprop-4.21-rc1' of git://git.ker.. > > git tree: upstream > > console output: https://syzkaller.appspot.com/x/log.txt?x=122a373f400000 > > kernel config: https://syzkaller.appspot.com/x/.config?x=91a256823ef17263 > > dashboard link: https://syzkaller.appspot.com/bug?extid=c764de0fcfadca9a8595 > > compiler: gcc (GCC) 8.0.1 20180413 (experimental) > > syz repro: https://syzkaller.appspot.com/x/repro.syz?x=16fd1d67400000 > > > > IMPORTANT: if you fix the bug, please add the following tag to the commit: > > Reported-by: syzbot+c764de0fcfadca9a8595 at syzkaller.appspotmail.com > > What is the bug here? The kernel module showed a warning because the parent > device cannot be found in the same netns using __dev_get_by_index. > > The test system was just configured to panic on warnings. So are we now > expected to show warnings or what is the expected behavior? > > This behavior was added with commit b7eddd0b3950 ("batman-adv: prevent using > any virtual device created on batman-adv as hard-interface") - 3d48811b27f5 in > the out-of-tree module. Hi Sven, The problem is that kernel code uses WARNING when it should not. For WARN guidelines please see this: https://elixir.bootlin.com/linux/v4.20/source/include/asm-generic/bug.h#L81 and this (search for WARN_ON_ONCE): https://lwn.net/Articles/769365/ > Kind regards, > Sven > > [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b7eddd0b3950ea9dc863f1cbfa30d172dbf772f4 From sven at narfation.org Sun Dec 30 12:46:01 2018 From: sven at narfation.org (Sven Eckelmann) Date: Sun, 30 Dec 2018 12:46:01 +0100 Subject: [B.A.T.M.A.N.] [PATCH maint] batman-adv: Avoid WARN on net_device without parent in netns Message-ID: <20181230114601.3546-1-sven@narfation.org> It is not allowed to use WARN* helpers on potential incorrect input from the user or transient problems because systems configured as panic_on_warn will reboot due to such a problem. A NULL return value of __dev_get_by_index can be caused by various problems which can either be related to the system configuration or problems (incorrectly returned network namespaces) in other (virtual) net_device drivers. batman-adv should not cause a (harmful) WARN in this situation and instead only report it via a simple message. Fixes: 3d48811b27f5 ("batman-adv: prevent using any virtual device created on batman-adv as hard-interface") Reported-by: syzbot+c764de0fcfadca9a8595 at syzkaller.appspotmail.com Reported-by: Dmitry Vyukov Signed-off-by: Sven Eckelmann --- Cc: syzbot Cc: Dmitry Vyukov Cc: syzkaller-bugs at googlegroups.com --- net/batman-adv/hard-interface.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 508f4416..5b7632cf 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -20,7 +20,6 @@ #include "main.h" #include -#include #include #include #include @@ -179,8 +178,10 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev) parent_dev = __dev_get_by_index((struct net *)parent_net, dev_get_iflink(net_dev)); /* if we got a NULL parent_dev there is something broken.. */ - if (WARN(!parent_dev, "Cannot find parent device")) + if (!parent_dev) { + pr_err("Cannot find parent device\n"); return false; + } if (batadv_mutual_parents(net_dev, net, parent_dev, parent_net)) return false; -- 2.19.2 From sven at narfation.org Sun Dec 30 14:51:12 2018 From: sven at narfation.org (Sven Eckelmann) Date: Sun, 30 Dec 2018 14:51:12 +0100 Subject: [B.A.T.M.A.N.] [PATCH v7] batman-adv: Snoop DHCPACKs for DAT In-Reply-To: <20181229031040.7207-1-linus.luessing@c0d3.blue> References: <20181229031040.7207-1-linus.luessing@c0d3.blue> Message-ID: <1976755.cJCZaRukfj@sven-edge> On Saturday, 29 December 2018 04.10.40 CET Linus Lüssing wrote: > +#define BATADV_DHCP_YIADDR_LEN sizeof(((struct batadv_dhcp_packet *)0)->chaddr) > +#define BATADV_DHCP_CHADDR_LEN sizeof(((struct batadv_dhcp_packet *)0)->chaddr) Why do you use chaddr to calculate the size of yiaddr? yiaddr is only 4 byte and chaddr is 16 byte. Looks to me like you have a potential stack overflow in batadv_dat_dhcp_get_yiaddr because of that. And you have a lot of code which calls skb_header_pointer again and again + a lot of offset calculations. So it has to potentially traverse all the fragments again and again. I have seen: * op * htype * hlen * magic * TLV options parts * yiaddr * chaddr Do you see any potential in combining some of them in batadv_dat_check_dhcp (e.g. op, htype, hlen)? > +/** > + * batadv_dat_check_dhcp_ack() - examine packet for valid DHCP message > > + * @skb: the packet to check > + * @proto: ethernet protocol hint (behind a potential vlan) > + * @ip_src: a buffer to store the IPv4 source address in > + * @chaddr: a buffer to store the DHCP Client Hardware Address in > + * @yiaddr: a buffer to store the DHCP Your IP Address in > + * > + * Checks whether the given skb is a valid DHCPACK. And if so, stores the > + * IPv4 server source address (ip_src), client MAC address (chaddr) and client > + * IPv4 address (yiaddr) in the provided buffers. > + > + * Caller needs to ensure that the skb network header is set correctly. > + * > + * Return: True if the skb is a valid DHCPACK. False otherwise. > + */ There seems to be a missing "*" in the line before the line "Caller needs to ensure that the skb network header" Missing header in distributed-arp-table.c: * asm/unaligned.h > --- a/net/batman-adv/distributed-arp-table.c > +++ b/net/batman-adv/distributed-arp-table.c [...] > @@ -42,9 +43,11 @@ > #include > #include > #include > +#include > #include > #include > #include > +#include > #include > #include > #include And "net/ip.h" also doesn't seem to be used in distributed-arp-table.c But the biggest problem is that it doesn't build: /usr/bin/make -C /home/build_test/build_env/linux-build/linux-4.9.148 M=/home/build_test/build_env/tmp.9CjwRXIj4f PWD=/home/build_test/build_env/tmp.9CjwRXIj4f REVISION= CONFIG_BATMAN_ADV=m CONFIG_BATMAN_ADV_DEBUG=n CONFIG_BATMAN_ADV_DEBUGFS=y CONFIG_BATMAN_ADV_BLA=n CONFIG_BATMAN_ADV_DAT=n CONFIG_BATMAN_ADV_NC=y CONFIG_BATMAN_ADV_MCAST=y CONFIG_BATMAN_ADV_TRACING=y CONFIG_BATMAN_ADV_BATMAN_V=y INSTALL_MOD_DIR=updates/ modules [...] /home/build_test/build_env/tmp.9CjwRXIj4f/net/batman-adv/routing.c:1046:17: error: undefined identifier 'batadv_dat_snoop_incoming_dhcp_ack' /home/build_test/build_env/tmp.9CjwRXIj4f/net/batman-adv/routing.c:1283:9: error: undefined identifier 'batadv_dat_snoop_incoming_dhcp_ack' /home/build_test/build_env/tmp.9CjwRXIj4f/net/batman-adv/routing.c: In function ‘batadv_recv_unicast_packet’: /home/build_test/build_env/tmp.9CjwRXIj4f/net/batman-adv/routing.c:1046:3: error: implicit declaration of function ‘batadv_dat_snoop_incoming_dhcp_ack’ [-Werror=implicit-function-declaration] batadv_dat_snoop_incoming_dhcp_ack(bat_priv, skb, hdr_size); Looks like distributed-arp-table.h is missing a stub function for batadv_dat_snoop_incoming_dhcp_ack when CONFIG_BATMAN_ADV_DAT is not set. Kind regards, Sven -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: This is a digitally signed message part. URL: From linus.luessing at c0d3.blue Sun Dec 30 15:51:33 2018 From: linus.luessing at c0d3.blue (Linus =?utf-8?Q?L=C3=BCssing?=) Date: Sun, 30 Dec 2018 15:51:33 +0100 Subject: [B.A.T.M.A.N.] [PATCH v7] batman-adv: Snoop DHCPACKs for DAT In-Reply-To: <1976755.cJCZaRukfj@sven-edge> References: <20181229031040.7207-1-linus.luessing@c0d3.blue> <1976755.cJCZaRukfj@sven-edge> Message-ID: <20181230145133.GA4150@otheros> On Sun, Dec 30, 2018 at 02:51:12PM +0100, Sven Eckelmann wrote: > On Saturday, 29 December 2018 04.10.40 CET Linus Lüssing wrote: > > +#define BATADV_DHCP_YIADDR_LEN sizeof(((struct batadv_dhcp_packet *)0)->chaddr) > > +#define BATADV_DHCP_CHADDR_LEN sizeof(((struct batadv_dhcp_packet *)0)->chaddr) > > Why do you use chaddr to calculate the size of yiaddr? yiaddr is only 4 byte > and chaddr is 16 byte. Looks to me like you have a potential stack overflow in > batadv_dat_dhcp_get_yiaddr because of that. Urgh... three memory issues fixed, one new one introduced, yaiy... thanks! > And you have a lot of code which calls skb_header_pointer again and again + a > lot of offset calculations. So it has to potentially traverse all the > fragments again and again. I have seen: > > * op > * htype > * hlen > * magic > * TLV options parts > * yiaddr > * chaddr > > Do you see any potential in combining some of them in batadv_dat_check_dhcp > (e.g. op, htype, hlen)? Good question. The advantage of the current approach is that the extra buffers _op, _htype and _hlen actually would not be used because a single byte itself has no fragmentation or alignment issues. So no copying needed, we should always get a pointer right into the skb data/fragments. On the other hand, a few copying instructions is probably less overhead than traversing fragments multiple times. I'll change that. [...] > There seems to be a missing "*" in the line before the line "Caller needs to > ensure that the skb network header" ok > > > Missing header in distributed-arp-table.c: > > * asm/unaligned.h ok > > > --- a/net/batman-adv/distributed-arp-table.c > > +++ b/net/batman-adv/distributed-arp-table.c > [...] > > @@ -42,9 +43,11 @@ > > #include > > #include > > #include > > +#include > > #include > > #include > > #include > > +#include > > #include > > #include > > #include > > And "net/ip.h" also doesn't seem to be used in distributed-arp-table.c Right, not needed anymore after replacing ip_hdrlen(skb) with iphdr->ihl * 4 in v7. > > > > But the biggest problem is that it doesn't build: > > /usr/bin/make -C /home/build_test/build_env/linux-build/linux-4.9.148 M=/home/build_test/build_env/tmp.9CjwRXIj4f PWD=/home/build_test/build_env/tmp.9CjwRXIj4f REVISION= CONFIG_BATMAN_ADV=m CONFIG_BATMAN_ADV_DEBUG=n CONFIG_BATMAN_ADV_DEBUGFS=y CONFIG_BATMAN_ADV_BLA=n CONFIG_BATMAN_ADV_DAT=n CONFIG_BATMAN_ADV_NC=y CONFIG_BATMAN_ADV_MCAST=y CONFIG_BATMAN_ADV_TRACING=y CONFIG_BATMAN_ADV_BATMAN_V=y INSTALL_MOD_DIR=updates/ modules > [...] > /home/build_test/build_env/tmp.9CjwRXIj4f/net/batman-adv/routing.c:1046:17: error: undefined identifier 'batadv_dat_snoop_incoming_dhcp_ack' > /home/build_test/build_env/tmp.9CjwRXIj4f/net/batman-adv/routing.c:1283:9: error: undefined identifier 'batadv_dat_snoop_incoming_dhcp_ack' > /home/build_test/build_env/tmp.9CjwRXIj4f/net/batman-adv/routing.c: In function ‘batadv_recv_unicast_packet’: > /home/build_test/build_env/tmp.9CjwRXIj4f/net/batman-adv/routing.c:1046:3: error: implicit declaration of function ‘batadv_dat_snoop_incoming_dhcp_ack’ [-Werror=implicit-function-declaration] > batadv_dat_snoop_incoming_dhcp_ack(bat_priv, skb, hdr_size); > > Looks like distributed-arp-table.h is missing a stub function for > batadv_dat_snoop_incoming_dhcp_ack when CONFIG_BATMAN_ADV_DAT is not set. ok From linus.luessing at c0d3.blue Sun Dec 30 16:52:53 2018 From: linus.luessing at c0d3.blue (=?UTF-8?q?Linus=20L=C3=BCssing?=) Date: Sun, 30 Dec 2018 16:52:53 +0100 Subject: [B.A.T.M.A.N.] [PATCH v8] batman-adv: Snoop DHCPACKs for DAT Message-ID: <20181230155253.16465-1-linus.luessing@c0d3.blue> In a 1000 nodes mesh network (Freifunk Hamburg) we can still see 30KBit/s of ARP traffic (equalling about 25% of all layer two specific overhead, remaining after some filtering) flooded through the mesh. These 30KBit/s are mainly ARP Requests from the gateways / DHCP servers. By snooping DHCPACKs we can learn about MAC/IP address pairs in the DHCP range without relying on ARP. This patch is in preparation to eliminate the need for mesh wide message flooding for IPv4 address resolution. Also this allows to quickly update a MAC/IP pair at least in the DHT when DHCP reassigns an IP address to a new host. Signed-off-by: Linus Lüssing --- Changes in v8: * fixed a potential stackoverflow with BATADV_DHCP_YIADDR_LEN: -> wrongly had the size of chaddr instead of yiaddr * added missing include for asm/unaligned.h * removed unncessary include for net/ip.h: -> got unncessary with v7 due to ip_hdrlen() removal * fixed build error with disabled DAT: -> missing stub for batadv_dat_snoop_incoming_dhcp_ack() * grouped DHCP packet op, htype and hlen field fetch into a single skb_header_pointer() call * added missing "*" in batadv_dat_put_dhcp() kerneldoc Changes in v7: * fixed a memory access bug in batadv_dat_snoop_outgoing_dhcp_ack(): ip_hdr(skb)->saddr is unsafe because we never ensured linear skb data; -> refactored functions to take an ip_src paramter instead * fixed a memory access bug in batadv_dat_check_dhcp_ipudp(): ip_hdrlen(skb) is unsafe on potentially non-linear skb data * fixed a memory access bug in batadv_dat_get_dhcp_chaddr(): the len parameter provided to skb_header_pointer() is 16 bytes long but we only reserved 6 bytes (ETH_ALEN) in batadv_dat_snoop_outgoing_dhcp_ack() -> increased the buffer length to the full DHCP chaddr size * renamed batadv_dat_put_pairs() to batadv_dat_put_dhcp(), renamed its parameters and moved the batadv_dbg() functions into it, to make the naming and the function's purpose a bit more specific and meaningful * added parsing of DHCPACKs on the mesh-ingress side, too, and if successful adding retrieved values to the local DAT cache; similar to what is done for incoming ARP replies, too * removed unnecessary and unused hdr_size calculation in former batadv_dat_put_pairs() * batadv_dat_dhcp_get_yiaddr() and batadv_dat_get_dhcp_chaddr() now always return a copy of the yiaddr chaddr so that callers have one less pointer to play with and do not need to worry about memory alignment anymore themselves * rebased to master * sorted variables to reverse Christmas tree Changes in v6: * moved dhcp packet definition from batadv_packet.h to distributed-arp-table.c Changes in v5: * fixed unaligned access issues (that is, enforce a two step load via "get_unaligned") for DHCP magic and yiaddr fields * simplified batadv_dat_put_pairs(): there is no need to check that arp_create() set the ARP type correctly. It always does or returns NULL otherwise. (this also fixes another unaligned access) Changes in v4: * Removed @proto from kerneldoc * Less enum values in batadv_packet.h * Moved skb_set_network_header() call * Updated commit message Changes in v3: * Rebase to master * Shortened commit message Changes in v2: * Rebase to master * Fix compilation with CONFIG_BATMAN_ADV=n (added stubs) Changes in RFC -> non-RFC * Added kerneldoc * Added Signed-off-by * More IP Header checks (iph->hlen considered, ip version checked, ...) * Parsing & checking DHCP Message Type Option, only snooping DHCPACKs now * Moved ethernet protocol check from batadv_dat_check_dhcp to batadv_dat_check_dhcp_ipudp * Removed buffer-length parameter from batadv_dat_dhcp_get_{yiaddr,chaddr}() * Renamed batadv_dat_put() to batadv_dat_put_pairs() fixup DAT DHCP snooping --- net/batman-adv/distributed-arp-table.c | 399 +++++++++++++++++++++++++++++++++ net/batman-adv/distributed-arp-table.h | 19 ++ net/batman-adv/routing.c | 4 + net/batman-adv/soft-interface.c | 11 +- 4 files changed, 431 insertions(+), 2 deletions(-) diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index b9ffe182..c7f3e223 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@ -19,6 +19,7 @@ #include "distributed-arp-table.h" #include "main.h" +#include #include #include #include @@ -29,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -42,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -60,6 +63,49 @@ #include "translation-table.h" #include "tvlv.h" +enum batadv_bootpop { + BATADV_BOOTREPLY = 2, +}; + +enum batadv_boothtype { + BATADV_HTYPE_ETHERNET = 1, +}; + +enum batadv_dhcpoptioncode { + BATADV_DHCP_OPT_PAD = 0, + BATADV_DHCP_OPT_MSG_TYPE = 53, + BATADV_DHCP_OPT_END = 255, +}; + +enum batadv_dhcptype { + BATADV_DHCPACK = 5, +}; + +/* { 99, 130, 83, 99 } */ +#define BATADV_DHCP_MAGIC 1669485411 + +struct batadv_dhcp_packet { + __u8 op; + __u8 htype; + __u8 hlen; + __u8 hops; + __be32 xid; + __be16 secs; + __be16 flags; + __be32 ciaddr; + __be32 yiaddr; + __be32 siaddr; + __be32 giaddr; + __u8 chaddr[16]; + __u8 sname[64]; + __u8 file[128]; + __be32 magic; + __u8 options[0]; +}; + +#define BATADV_DHCP_YIADDR_LEN sizeof(((struct batadv_dhcp_packet *)0)->yiaddr) +#define BATADV_DHCP_CHADDR_LEN sizeof(((struct batadv_dhcp_packet *)0)->chaddr) + static void batadv_dat_purge(struct work_struct *work); /** @@ -1440,6 +1486,359 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, } /** + * batadv_dat_check_dhcp_ipudp() - check skb for IP+UDP headers valid for DHCP + * @skb: the packet to check + * @ip_src: a buffer to store the IPv4 source address in + * + * Checks whether the given skb has an IP and UDP header valid for a DHCP + * message from a DHCP server. And if so, stores the IPv4 source address in + * the provided buffer. + * + * Return: True if valid, false otherwise. + */ +static bool +batadv_dat_check_dhcp_ipudp(struct sk_buff *skb, __be32 *ip_src) +{ + unsigned int offset = skb_network_offset(skb); + struct udphdr *udphdr, _udphdr; + struct iphdr *iphdr, _iphdr; + + iphdr = skb_header_pointer(skb, offset, sizeof(_iphdr), &_iphdr); + if (!iphdr || iphdr->version != 4 || iphdr->ihl * 4 < sizeof(_iphdr)) + return false; + + if (iphdr->protocol != IPPROTO_UDP) + return false; + + offset += iphdr->ihl * 4; + skb_set_transport_header(skb, offset); + + udphdr = skb_header_pointer(skb, offset, sizeof(_udphdr), &_udphdr); + if (!udphdr || udphdr->source != htons(67)) + return false; + + *ip_src = get_unaligned(&iphdr->saddr); + + return true; +} + +/** + * batadv_dat_check_dhcp() - examine packet for valid DHCP message + * @skb: the packet to check + * @proto: ethernet protocol hint (behind a potential vlan) + * @ip_src: a buffer to store the IPv4 source address in + * + * Checks whether the given skb is a valid DHCP packet. And if so, stores the + * IPv4 source address in the provided buffer. + * + * Caller needs to ensure that the skb network header is set correctly. + * + * Return: If skb is a valid DHCP packet, then returns its op code + * (e.g. BOOTREPLY vs. BOOTREQUEST). Otherwise returns -EINVAL. + */ +static int +batadv_dat_check_dhcp(struct sk_buff *skb, __be16 proto, __be32 *ip_src) +{ + __be32 *magic, _magic; + unsigned int offset; + struct { + __u8 op; + __u8 htype; + __u8 hlen; + __u8 hops; + } *dhcp_h, _dhcp_h; + + if (proto != htons(ETH_P_IP)) + return -EINVAL; + + if (!batadv_dat_check_dhcp_ipudp(skb, ip_src)) + return -EINVAL; + + offset = skb_transport_offset(skb) + sizeof(struct udphdr); + if (skb->len < offset + sizeof(struct batadv_dhcp_packet)) + return -EINVAL; + + dhcp_h = skb_header_pointer(skb, offset, sizeof(_dhcp_h), &_dhcp_h); + if (!dhcp_h || dhcp_h->htype != BATADV_HTYPE_ETHERNET || + dhcp_h->hlen != ETH_ALEN) + return -EINVAL; + + offset += offsetof(struct batadv_dhcp_packet, magic); + + magic = skb_header_pointer(skb, offset, sizeof(_magic), &_magic); + if (!magic || get_unaligned(magic) != htonl(BATADV_DHCP_MAGIC)) + return -EINVAL; + + return dhcp_h->op; +} + +/** + * batadv_dat_get_dhcp_message_type() - get message type of a DHCP packet + * @skb: the DHCP packet to parse + * + * Iterates over the DHCP options of the given DHCP packet to find a + * DHCP Message Type option and parse it. + * + * Caller needs to ensure that the given skb is a valid DHCP packet and + * that the skb transport header is set correctly. + * + * Return: The found DHCP message type value, if found. -EINVAL otherwise. + */ +static int batadv_dat_get_dhcp_message_type(struct sk_buff *skb) +{ + unsigned int offset = skb_transport_offset(skb) + sizeof(struct udphdr); + u8 *type, _type; + struct { + u8 type; + u8 len; + } *tl, _tl; + + offset += sizeof(struct batadv_dhcp_packet); + + while ((tl = skb_header_pointer(skb, offset, sizeof(_tl), &_tl))) { + if (tl->type == BATADV_DHCP_OPT_MSG_TYPE) + break; + + if (tl->type == BATADV_DHCP_OPT_END) + break; + + if (tl->type == BATADV_DHCP_OPT_PAD) + offset++; + else + offset += tl->len + sizeof(_tl); + } + + /* Option Overload Code not supported */ + if (!tl || tl->type != BATADV_DHCP_OPT_MSG_TYPE || + tl->len != sizeof(_type)) + return -EINVAL; + + offset += sizeof(_tl); + + type = skb_header_pointer(skb, offset, sizeof(_type), &_type); + if (!type) + return -EINVAL; + + return *type; +} + +/** + * batadv_dat_get_dhcp_yiaddr() - get yiaddr from a DHCP packet + * @skb: the DHCP packet to parse + * @buf: a buffer to store the yiaddr in + * + * Caller needs to ensure that the given skb is a valid DHCP packet and + * that the skb transport header is set correctly. + * + * Return: True on success, false otherwise. + */ +static bool batadv_dat_dhcp_get_yiaddr(struct sk_buff *skb, __be32 *buf) +{ + unsigned int offset = skb_transport_offset(skb) + sizeof(struct udphdr); + __be32 *yiaddr; + + offset += offsetof(struct batadv_dhcp_packet, yiaddr); + yiaddr = skb_header_pointer(skb, offset, BATADV_DHCP_YIADDR_LEN, buf); + + if (!yiaddr) + return false; + + if (yiaddr != buf) + *buf = get_unaligned(yiaddr); + + return true; +} + +/** + * batadv_dat_get_dhcp_chaddr() - get chaddr from a DHCP packet + * @skb: the DHCP packet to parse + * @buf: a buffer to store the chaddr in + * + * Caller needs to ensure that the given skb is a valid DHCP packet and + * that the skb transport header is set correctly. + * + * Return: True on success, false otherwise + */ +static bool batadv_dat_get_dhcp_chaddr(struct sk_buff *skb, u8 *buf) +{ + unsigned int offset = skb_transport_offset(skb) + sizeof(struct udphdr); + u8 *chaddr; + + offset += offsetof(struct batadv_dhcp_packet, chaddr); + chaddr = skb_header_pointer(skb, offset, BATADV_DHCP_CHADDR_LEN, buf); + + if (!chaddr) + return false; + + if (chaddr != buf) + memcpy(buf, chaddr, BATADV_DHCP_CHADDR_LEN); + + return true; +} + +/** + * batadv_dat_put_dhcp() - puts addresses from a DHCP packet into the DHT and + * DAT cache + * @bat_priv: the bat priv with all the soft interface information + * @chaddr: the DHCP client MAC address + * @yiaddr: the DHCP client IP address + * @hw_dst: the DHCP server MAC address + * @ip_dst: the DHCP server IP address + * @vid: VLAN identifier + * + * Adds given MAC/IP pairs to the local DAT cache and propagates them further + * into the DHT. + * + * For the DHT propagation, client MAC + IP will appear as the ARP Reply + * transmitter (and hw_dst/ip_dst as the target). + */ +static void batadv_dat_put_dhcp(struct batadv_priv *bat_priv, u8 *chaddr, + __be32 yiaddr, u8 *hw_dst, __be32 ip_dst, + unsigned short vid) +{ + struct sk_buff *skb; + + skb = batadv_dat_arp_create_reply(bat_priv, yiaddr, ip_dst, chaddr, + hw_dst, vid); + if (!skb) + return; + + skb_set_network_header(skb, ETH_HLEN); + + batadv_dat_entry_add(bat_priv, yiaddr, chaddr, vid); + batadv_dat_entry_add(bat_priv, ip_dst, hw_dst, vid); + + batadv_dat_send_data(bat_priv, skb, yiaddr, vid, BATADV_P_DAT_DHT_PUT); + batadv_dat_send_data(bat_priv, skb, ip_dst, vid, BATADV_P_DAT_DHT_PUT); + + batadv_dbg(BATADV_DBG_DAT, bat_priv, + "Snooped from outgoing DHCPACK (server address): %pI4, %pM (vid: %i)\n", + &ip_dst, hw_dst, batadv_print_vid(vid)); + batadv_dbg(BATADV_DBG_DAT, bat_priv, + "Snooped from outgoing DHCPACK (client address): %pI4, %pM (vid: %i)\n", + &yiaddr, chaddr, batadv_print_vid(vid)); +} + +/** + * batadv_dat_check_dhcp_ack() - examine packet for valid DHCP message + * @skb: the packet to check + * @proto: ethernet protocol hint (behind a potential vlan) + * @ip_src: a buffer to store the IPv4 source address in + * @chaddr: a buffer to store the DHCP Client Hardware Address in + * @yiaddr: a buffer to store the DHCP Your IP Address in + * + * Checks whether the given skb is a valid DHCPACK. And if so, stores the + * IPv4 server source address (ip_src), client MAC address (chaddr) and client + * IPv4 address (yiaddr) in the provided buffers. + * + * Caller needs to ensure that the skb network header is set correctly. + * + * Return: True if the skb is a valid DHCPACK. False otherwise. + */ +static bool +batadv_dat_check_dhcp_ack(struct sk_buff *skb, __be16 proto, __be32 *ip_src, + u8 *chaddr, __be32 *yiaddr) +{ + int type; + + type = batadv_dat_check_dhcp(skb, proto, ip_src); + if (type != BATADV_BOOTREPLY) + return false; + + type = batadv_dat_get_dhcp_message_type(skb); + if (type != BATADV_DHCPACK) + return false; + + if (!batadv_dat_dhcp_get_yiaddr(skb, yiaddr)) + return false; + + if (!batadv_dat_get_dhcp_chaddr(skb, chaddr)) + return false; + + return true; +} + +/** + * batadv_dat_snoop_outgoing_dhcp_ack() - snoop DHCPACK and fill DAT with it + * @bat_priv: the bat priv with all the soft interface information + * @skb: the packet to snoop + * @proto: ethernet protocol hint (behind a potential vlan) + * @vid: VLAN identifier + * + * This function first checks whether the given skb is a valid DHCPACK. If + * so then its source MAC and IP as well as its DHCP Client Hardware Address + * field and DHCP Your IP Address field are added to the local DAT cache and + * propagated into the DHT. + * + * Caller needs to ensure that the skb mac and network headers are set + * correctly. + */ +void batadv_dat_snoop_outgoing_dhcp_ack(struct batadv_priv *bat_priv, + struct sk_buff *skb, + __be16 proto, + unsigned short vid) +{ + u8 chaddr[BATADV_DHCP_CHADDR_LEN]; + __be32 ip_src, yiaddr; + + if (!atomic_read(&bat_priv->distributed_arp_table)) + return; + + if (!batadv_dat_check_dhcp_ack(skb, proto, &ip_src, chaddr, &yiaddr)) + return; + + batadv_dat_put_dhcp(bat_priv, chaddr, yiaddr, eth_hdr(skb)->h_source, + ip_src, vid); +} + +/** + * batadv_dat_snoop_incoming_dhcp_ack() - snoop DHCPACK and fill DAT cache + * @bat_priv: the bat priv with all the soft interface information + * @skb: the packet to snoop + * @hdr_size: header size, up to the tail of the batman-adv header + * + * This function first checks whether the given skb is a valid DHCPACK. If + * so then its source MAC and IP as well as its DHCP Client Hardware Address + * field and DHCP Your IP Address field are added to the local DAT cache. + */ +void batadv_dat_snoop_incoming_dhcp_ack(struct batadv_priv *bat_priv, + struct sk_buff *skb, int hdr_size) +{ + u8 chaddr[BATADV_DHCP_CHADDR_LEN]; + struct ethhdr *ethhdr; + __be32 ip_src, yiaddr; + unsigned short vid; + __be16 proto; + u8 *hw_src; + + if (!atomic_read(&bat_priv->distributed_arp_table)) + return; + + if (unlikely(!pskb_may_pull(skb, hdr_size + ETH_HLEN))) + return; + + ethhdr = (struct ethhdr *)(skb->data + hdr_size); + skb_set_network_header(skb, hdr_size + ETH_HLEN); + proto = ethhdr->h_proto; + + if (!batadv_dat_check_dhcp_ack(skb, proto, &ip_src, chaddr, &yiaddr)) + return; + + hw_src = ethhdr->h_source; + vid = batadv_dat_get_vid(skb, &hdr_size); + + batadv_dat_entry_add(bat_priv, yiaddr, chaddr, vid); + batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid); + + batadv_dbg(BATADV_DBG_DAT, bat_priv, + "Snooped from incoming DHCPACK (server address): %pI4, %pM (vid: %i)\n", + &ip_src, hw_src, batadv_print_vid(vid)); + batadv_dbg(BATADV_DBG_DAT, bat_priv, + "Snooped from incoming DHCPACK (client address): %pI4, %pM (vid: %i)\n", + &yiaddr, chaddr, batadv_print_vid(vid)); +} + +/** * batadv_dat_drop_broadcast_packet() - check if an ARP request has to be * dropped (because the node has already obtained the reply via DAT) or not * @bat_priv: the bat priv with all the soft interface information diff --git a/net/batman-adv/distributed-arp-table.h b/net/batman-adv/distributed-arp-table.h index a0459602..e58d7a9b 100644 --- a/net/batman-adv/distributed-arp-table.h +++ b/net/batman-adv/distributed-arp-table.h @@ -46,6 +46,12 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv, struct sk_buff *skb); bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, struct sk_buff *skb, int hdr_size); +void batadv_dat_snoop_outgoing_dhcp_ack(struct batadv_priv *bat_priv, + struct sk_buff *skb, + __be16 proto, + unsigned short vid); +void batadv_dat_snoop_incoming_dhcp_ack(struct batadv_priv *bat_priv, + struct sk_buff *skb, int hdr_size); bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv, struct batadv_forw_packet *forw_packet); @@ -140,6 +146,19 @@ batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, return false; } +static inline void +batadv_dat_snoop_outgoing_dhcp_ack(struct batadv_priv *bat_priv, + struct sk_buff *skb, __be16 proto, + unsigned short vid) +{ +} + +static inline void +batadv_dat_snoop_incoming_dhcp_ack(struct batadv_priv *bat_priv, + struct sk_buff *skb, int hdr_size) +{ +} + static inline bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv, struct batadv_forw_packet *forw_packet) diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index cc3ed93a..469fa97d 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -1043,6 +1043,8 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, hdr_size)) goto rx_success; + batadv_dat_snoop_incoming_dhcp_ack(bat_priv, skb, hdr_size); + batadv_interface_rx(recv_if->soft_iface, skb, hdr_size, orig_node); @@ -1278,6 +1280,8 @@ int batadv_recv_bcast_packet(struct sk_buff *skb, if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb, hdr_size)) goto rx_success; + batadv_dat_snoop_incoming_dhcp_ack(bat_priv, skb, hdr_size); + /* broadcast for me */ batadv_interface_rx(recv_if->soft_iface, skb, hdr_size, orig_node); diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 5db5a0a4..94307100 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -212,6 +212,7 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb, enum batadv_forw_mode forw_mode; struct batadv_orig_node *mcast_single_orig = NULL; int network_offset = ETH_HLEN; + __be16 proto; if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) goto dropped; @@ -223,12 +224,15 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb, vid = batadv_get_vid(skb, 0); ethhdr = eth_hdr(skb); - switch (ntohs(ethhdr->h_proto)) { + proto = ethhdr->h_proto; + + switch (ntohs(proto)) { case ETH_P_8021Q: vhdr = vlan_eth_hdr(skb); + proto = vhdr->h_vlan_encapsulated_proto; /* drop batman-in-batman packets to prevent loops */ - if (vhdr->h_vlan_encapsulated_proto != htons(ETH_P_BATMAN)) { + if (proto != htons(ETH_P_BATMAN)) { network_offset += VLAN_HLEN; break; } @@ -256,6 +260,9 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb, goto dropped; } + /* Snoop address candidates from DHCPACKs for early DAT filling */ + batadv_dat_snoop_outgoing_dhcp_ack(bat_priv, skb, proto, vid); + /* don't accept stp packets. STP does not help in meshes. * better use the bridge loop avoidance ... * -- 2.11.0 From linus.luessing at c0d3.blue Sun Dec 30 17:57:54 2018 From: linus.luessing at c0d3.blue (Linus =?utf-8?Q?L=C3=BCssing?=) Date: Sun, 30 Dec 2018 17:57:54 +0100 Subject: [B.A.T.M.A.N.] [RFC v3 01/19] batman-adv: Move common genl doit code pre/post hooks In-Reply-To: <20181207135846.6152-2-sven@narfation.org> References: <20181207135846.6152-1-sven@narfation.org> <20181207135846.6152-2-sven@narfation.org> Message-ID: <20181230165754.GC4150@otheros> On Fri, Dec 07, 2018 at 02:58:28PM +0100, Sven Eckelmann wrote: > +/** > + * batadv_get_softif_from_info() - Retrieve soft interface from genl attributes > + * @net: the applicable net namespace > + * @info: receiver information > + * > + * Return: Pointer to soft interface on success, error pointer on error > + */ > +static struct batadv_priv * > +batadv_get_softif_from_info(struct net *net, struct genl_info *info) Since this returns a batadv_priv, shouldn't it better be called batadv_get_batpriv_from_info() or batadv_get_bat_priv_from_info() maybe? > +{ > + struct net_device *soft_iface; > + int ifindex; > + > + if (!info->attrs[BATADV_ATTR_MESH_IFINDEX]) > + return ERR_PTR(-EINVAL); > + > + ifindex = nla_get_u32(info->attrs[BATADV_ATTR_MESH_IFINDEX]); > + > + soft_iface = dev_get_by_index(net, ifindex); > + if (!soft_iface) > + return ERR_PTR(-ENODEV); > + > + if (!batadv_softif_is_valid(soft_iface)) > + goto err_put_softif; > + > + return netdev_priv(soft_iface); > + > +err_put_softif: > + dev_put(soft_iface); > + > + return ERR_PTR(-EINVAL); > +} Is holding a reference to bat_priv->soft_iface really necessary (and releasing it in batadv_post_doit() )? If we are able to retrieve a valid bat_priv then this bat_priv itself should hold a reference to to soft_iface, shouldn't it? > + > +/** > + * batadv_pre_doit() - Prepare batman-adv genl doit request > + * @ops: requested netlink operation > + * @skb: Netlink message with request data > + * @info: receiver information > + * > + * Return: 0 on success or negative error number in case of failure > + */ > +static int batadv_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, > + struct genl_info *info) > +{ > + struct batadv_priv *bat_priv; > + > + if (ops->internal_flags & BATADV_FLAG_NEED_MESH) { > + bat_priv = batadv_get_softif_from_info(genl_info_net(info), > + info); Would it look nicer to store genl_info_net(info) in a temporary variable so that its shorter and the newline for the second parameter could be avoided? > + if (IS_ERR(bat_priv)) > + return PTR_ERR(bat_priv); > + > + info->user_ptr[0] = bat_priv; Would it make sense to wrap this private data access into something somehow? Conceptually similar to what we do not with skb private data already for instance. There we use BATADV_SKB_CB() for instance. > + } > + > + return 0; > +} From linus.luessing at c0d3.blue Mon Dec 31 12:09:50 2018 From: linus.luessing at c0d3.blue (Linus =?utf-8?Q?L=C3=BCssing?=) Date: Mon, 31 Dec 2018 12:09:50 +0100 Subject: [B.A.T.M.A.N.] [RFC v3 02/19] batman-adv: Prepare framework for mesh genl config In-Reply-To: <20181207135846.6152-3-sven@narfation.org> References: <20181207135846.6152-1-sven@narfation.org> <20181207135846.6152-3-sven@narfation.org> Message-ID: <20181231110950.GD4150@otheros> On Fri, Dec 07, 2018 at 02:58:29PM +0100, Sven Eckelmann wrote: > The batman-adv configuration interface was implemented solely using sysfs. > This approach was condemned by non-batadv developers as "huge mistake". > Instead a netlink/genl based implementation was suggested. > > The main objects for this configuration is the mesh/soft-interface object. > Its actual object in memory already contains most of the available > configuration settings. The genl interface reflects this by allowing to > get/set it using the mesh specific commands. > > The BATADV_CMD_GET_MESH_INFO (or short version BATADV_CMD_GET_MESH) is > reused as get command because it already provides the content of other > information from the mesh/soft-interface which are not yet configuration > specific. > > The set command BATADV_CMD_SET_MESH will also notify interested userspace > listeners of the "config" mcast group using the BATADV_CMD_SET_MESH command > message type that settings might have been changed and what the current > values are. > > Signed-off-by: Sven Eckelmann > --- > include/uapi/linux/batman_adv.h | 16 +++- > net/batman-adv/netlink.c | 159 +++++++++++++++++++------------- > 2 files changed, 110 insertions(+), 65 deletions(-) > > diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h > index 324a0e11..2d6a175e 100644 > --- a/include/uapi/linux/batman_adv.h > +++ b/include/uapi/linux/batman_adv.h > @@ -27,6 +27,7 @@ > > #define BATADV_NL_NAME "batadv" > > +#define BATADV_NL_MCAST_GROUP_CONFIG "config" > #define BATADV_NL_MCAST_GROUP_TPMETER "tpmeter" > > /** > @@ -372,10 +373,14 @@ enum batadv_nl_commands { > BATADV_CMD_UNSPEC, > > /** > - * @BATADV_CMD_GET_MESH_INFO: Query basic information about batman-adv > - * device > + * @BATADV_CMD_GET_MESH: Get attributes from softif/mesh > */ > - BATADV_CMD_GET_MESH_INFO, > + BATADV_CMD_GET_MESH, > + > + /** > + * @BATADV_CMD_GET_MESH_INFO: Alias for @BATADV_CMD_GET_MESH > + */ > + BATADV_CMD_GET_MESH_INFO = BATADV_CMD_GET_MESH, > > /** > * @BATADV_CMD_TP_METER: Start a tp meter session > @@ -443,6 +448,11 @@ enum batadv_nl_commands { > */ > BATADV_CMD_GET_MCAST_FLAGS, > > + /** > + * @BATADV_CMD_SET_MESH: Set attributes for softif/mesh > + */ > + BATADV_CMD_SET_MESH, > + > /* add new commands above here */ > > /** > diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c > index b20801a3..d89761f8 100644 > --- a/net/batman-adv/netlink.c > +++ b/net/batman-adv/netlink.c > @@ -62,6 +62,7 @@ struct genl_family batadv_netlink_family; > > /* multicast groups */ > enum batadv_netlink_multicast_groups { > + BATADV_NL_MCGRP_CONFIG, > BATADV_NL_MCGRP_TPMETER, > }; > > @@ -78,6 +79,7 @@ enum batadv_genl_ops_flags { > }; > > static const struct genl_multicast_group batadv_netlink_mcgrps[] = { > + [BATADV_NL_MCGRP_CONFIG] = { .name = BATADV_NL_MCAST_GROUP_CONFIG }, > [BATADV_NL_MCGRP_TPMETER] = { .name = BATADV_NL_MCAST_GROUP_TPMETER }, > }; > > @@ -138,20 +140,29 @@ batadv_netlink_get_ifindex(const struct nlmsghdr *nlh, int attrtype) > } > > /** > - * batadv_netlink_mesh_info_put() - fill in generic information about mesh > - * interface > - * @msg: netlink message to be sent back > - * @soft_iface: interface for which the data should be taken > + * batadv_netlink_mesh_put() - Fill message with mesh attributes > + * @msg: Netlink message to dump into > + * @bat_priv: the bat priv with all the soft interface information > + * @cmd: type of message to generate > + * @portid: Port making netlink request > + * @seq: sequence number for message > + * @flags: Additional flags for message > * > - * Return: 0 on success, < 0 on error > + * Return: 0 on success or negative error number in case of failure > */ > -static int > -batadv_netlink_mesh_info_put(struct sk_buff *msg, struct net_device *soft_iface) > +static int batadv_netlink_mesh_put(struct sk_buff *msg, > + struct batadv_priv *bat_priv, > + enum batadv_nl_commands cmd, > + u32 portid, u32 seq, int flags) > { [...] > #ifdef CONFIG_BATMAN_ADV_BLA > if (nla_put_u16(msg, BATADV_ATTR_BLA_CRC, > ntohs(bat_priv->bla.claim_dest.group))) > - goto out; > + goto nla_put_failure; > #endif > > if (batadv_mcast_mesh_info_put(msg, bat_priv)) > - goto out; > + goto nla_put_failure; With the rename of "batadv_netlink_mesh_info_put" to "batadv_netlink_mesh_put", I'm wondering whether batadv_mcast_mesh_info_put() should be renamed, too. batadv_mcast_mesh_put() would probably be a bit too generic. But maybe something like batadv_mcast_nl_mesh_put()? > +/** > + * batadv_netlink_get_mesh() - Get softif attributes > + * @skb: Netlink message with request data > + * @info: receiver information > + * > + * Return: 0 on success or negative error number in case of failure > + */ > +static int batadv_netlink_get_mesh(struct sk_buff *skb, struct genl_info *info) > +{ > + struct batadv_priv *bat_priv = info->user_ptr[0]; > + struct sk_buff *msg; > + int ret; Same question here for info->user_ptr[0], would a wrapper make sense? From linus.luessing at c0d3.blue Mon Dec 31 12:59:36 2018 From: linus.luessing at c0d3.blue (Linus =?utf-8?Q?L=C3=BCssing?=) Date: Mon, 31 Dec 2018 12:59:36 +0100 Subject: [B.A.T.M.A.N.] [RFC v3 03/19] batman-adv: Prepare framework for hardif genl config In-Reply-To: <20181207135846.6152-4-sven@narfation.org> References: <20181207135846.6152-1-sven@narfation.org> <20181207135846.6152-4-sven@narfation.org> Message-ID: <20181231115936.GE4150@otheros> On Fri, Dec 07, 2018 at 02:58:30PM +0100, Sven Eckelmann wrote: [...] > The BATADV_CMD_GET_HARDIFS (or short version BATADV_CMD_GET_HARDIF) is > reused as get command because it already allow to dump the content of other > information from the slave/hard-interface which are not yet configuration > specific. "already allow" -> "already allows" [...] > @@ -76,6 +77,13 @@ enum batadv_genl_ops_flags { > * safed in info->user_ptr[0] > */ > BATADV_FLAG_NEED_MESH = BIT(0), > + > + /** > + * @BATADV_FLAG_NEED_HARDIF: request requires valid hard interface in > + * attribute BATADV_ATTR_HARD_IFINDEX and expects a pointer to it to be > + * safed in info->user_ptr[1] > + */ > + BATADV_FLAG_NEED_HARDIF = BIT(1), safed -> saved (and same in the previous patch) [...] > /** > * batadv_pre_doit() - Prepare batman-adv genl doit request > * @ops: requested netlink operation > @@ -592,7 +738,16 @@ batadv_get_softif_from_info(struct net *net, struct genl_info *info) > static int batadv_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, > struct genl_info *info) > { > - struct batadv_priv *bat_priv; > + struct batadv_hard_iface *hard_iface; > + struct batadv_priv *bat_priv = NULL; > + int ret; > + > + if (WARN_ON(ops->internal_flags & BATADV_FLAG_NEED_HARDIF)) > + return -EINVAL; > + > + if (WARN_ON((ops->internal_flags & BATADV_FLAG_NEED_HARDIF) && > + (~ops->internal_flags & BATADV_FLAG_NEED_MESH))) > + return -EINVAL; Seems like the second part is unreachable code. If BATADV_FLAG_NEED_HARDIF is set then the function returns with the first if-clause already. From syzbot+83f2d54ec6b7e417e13f at syzkaller.appspotmail.com Mon Dec 31 05:11:04 2018 From: syzbot+83f2d54ec6b7e417e13f at syzkaller.appspotmail.com (syzbot) Date: Sun, 30 Dec 2018 20:11:04 -0800 Subject: [B.A.T.M.A.N.] WARNING in batadv_mcast_mla_tt_retract Message-ID: <000000000000fa4f60057e499989@google.com> Hello, syzbot found the following crash on: HEAD commit: eed9688f8513 Merge branch 'ras-core-for-linus' of git://gi.. git tree: upstream console output: https://syzkaller.appspot.com/x/log.txt?x=103bffaf400000 kernel config: https://syzkaller.appspot.com/x/.config?x=fa5c63e12fd85b25 dashboard link: https://syzkaller.appspot.com/bug?extid=83f2d54ec6b7e417e13f compiler: gcc (GCC) 8.0.1 20180413 (experimental) Unfortunately, I don't have any reproducer for this crash yet. IMPORTANT: if you fix the bug, please add the following tag to the commit: Reported-by: syzbot+83f2d54ec6b7e417e13f at syzkaller.appspotmail.com bond0 (unregistering): Releasing backup interface bond_slave_0 bond0 (unregistering): Released all slaves WARNING: CPU: 1 PID: 7 at net/batman-adv/multicast.c:337 batadv_mcast_mla_tt_retract+0x476/0x590 net/batman-adv/multicast.c:337 Kernel panic - not syncing: panic_on_warn set ... CPU: 1 PID: 7 Comm: kworker/u4:0 Not tainted 4.20.0+ #169 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Workqueue: bat_events batadv_mcast_mla_update Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x1d3/0x2c6 lib/dump_stack.c:113 panic+0x2ad/0x55c kernel/panic.c:188 __warn.cold.8+0x20/0x45 kernel/panic.c:540 report_bug+0x254/0x2d0 lib/bug.c:186 fixup_bug arch/x86/kernel/traps.c:178 [inline] do_error_trap+0x11b/0x200 arch/x86/kernel/traps.c:271 do_invalid_op+0x36/0x40 arch/x86/kernel/traps.c:290 invalid_op+0x14/0x20 arch/x86/entry/entry_64.S:973 RIP: 0010:batadv_mcast_mla_tt_retract+0x476/0x590 net/batman-adv/multicast.c:337 Code: 00 00 ad de 4c 89 ff 49 89 47 08 e8 b4 0f 03 fa e9 b6 fe ff ff 49 8d 47 10 48 89 85 60 ff ff ff e9 05 ff ff ff e8 4a 30 c0 f9 <0f> 0b e9 3f fc ff ff e8 6e 3b 03 fa e9 44 fe ff ff 4c 89 f7 e8 81 RSP: 0018:ffff8880a9e1f260 EFLAGS: 00010293 RAX: ffff8880a9e041c0 RBX: 0000000000000001 RCX: ffffffff87bedca3 RDX: 0000000000000000 RSI: ffffffff87bee066 RDI: 0000000000000007 RBP: ffff8880a9e1f328 R08: ffff8880a9e041c0 R09: ffffed1015ce5b8f R10: 0000000000000003 R11: ffff8880ae72dc7b R12: ffff8880a9e1f490 R13: 0000000000000000 R14: ffff888055b95fc0 R15: ffff8880a9e1f710 __batadv_mcast_mla_update net/batman-adv/multicast.c:635 [inline] batadv_mcast_mla_update+0x819/0x2da0 net/batman-adv/multicast.c:661 process_one_work+0xc90/0x1c40 kernel/workqueue.c:2153 worker_thread+0x17f/0x1390 kernel/workqueue.c:2296 kthread+0x35a/0x440 kernel/kthread.c:246 ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:352 Kernel Offset: disabled Rebooting in 86400 seconds.. --- This bug is generated by a bot. It may contain errors. See https://goo.gl/tpsmEJ for more information about syzbot. syzbot engineers can be reached at syzkaller at googlegroups.com. syzbot will keep track of this bug report. See: https://goo.gl/tpsmEJ#bug-status-tracking for how to communicate with syzbot. From syzbot+050927a651272b145a5d at syzkaller.appspotmail.com Mon Dec 31 05:17:03 2018 From: syzbot+050927a651272b145a5d at syzkaller.appspotmail.com (syzbot) Date: Sun, 30 Dec 2018 20:17:03 -0800 Subject: [B.A.T.M.A.N.] WARNING in batadv_mcast_mla_update Message-ID: <0000000000005c2068057e49afcf@google.com> Hello, syzbot found the following crash on: HEAD commit: eed9688f8513 Merge branch 'ras-core-for-linus' of git://gi.. git tree: upstream console output: https://syzkaller.appspot.com/x/log.txt?x=10785d57400000 kernel config: https://syzkaller.appspot.com/x/.config?x=fa5c63e12fd85b25 dashboard link: https://syzkaller.appspot.com/bug?extid=050927a651272b145a5d compiler: gcc (GCC) 8.0.1 20180413 (experimental) Unfortunately, I don't have any reproducer for this crash yet. IMPORTANT: if you fix the bug, please add the following tag to the commit: Reported-by: syzbot+050927a651272b145a5d at syzkaller.appspotmail.com QAT: Invalid ioctl bond0 (unregistering): Releasing backup interface bond_slave_0 bond0 (unregistering): Released all slaves WARNING: CPU: 0 PID: 28 at net/batman-adv/multicast.c:371 batadv_mcast_mla_tt_add net/batman-adv/multicast.c:371 [inline] WARNING: CPU: 0 PID: 28 at net/batman-adv/multicast.c:371 __batadv_mcast_mla_update net/batman-adv/multicast.c:636 [inline] WARNING: CPU: 0 PID: 28 at net/batman-adv/multicast.c:371 batadv_mcast_mla_update+0x248f/0x2da0 net/batman-adv/multicast.c:661 Kernel panic - not syncing: panic_on_warn set ... CPU: 0 PID: 28 Comm: kworker/u4:2 Not tainted 4.20.0+ #390 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Workqueue: bat_events batadv_mcast_mla_update Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x1d3/0x2c6 lib/dump_stack.c:113 panic+0x2ad/0x55c kernel/panic.c:188 __warn.cold.8+0x20/0x45 kernel/panic.c:540 report_bug+0x254/0x2d0 lib/bug.c:186 fixup_bug arch/x86/kernel/traps.c:178 [inline] do_error_trap+0x11b/0x200 arch/x86/kernel/traps.c:271 do_invalid_op+0x36/0x40 arch/x86/kernel/traps.c:290 invalid_op+0x14/0x20 arch/x86/entry/entry_64.S:973 RIP: 0010:batadv_mcast_mla_tt_add net/batman-adv/multicast.c:371 [inline] RIP: 0010:__batadv_mcast_mla_update net/batman-adv/multicast.c:636 [inline] RIP: 0010:batadv_mcast_mla_update+0x248f/0x2da0 net/batman-adv/multicast.c:661 Code: 49 c1 ee 03 48 b8 00 00 00 00 00 fc ff df be f8 f8 ff ff 66 41 89 34 06 48 c1 ea 03 c6 04 02 f8 e9 f7 e7 ff ff e8 41 f3 bf f9 <0f> 0b e9 b8 e3 ff ff 48 8b bd 48 fc ff ff e8 1e fe 02 fa e9 99 df RSP: 0018:ffff8880a9fe7338 EFLAGS: 00010293 RAX: ffff8880a9422000 RBX: 0000000000000001 RCX: ffffffff87bf0125 RDX: 0000000000000000 RSI: ffffffff87bf1d6f RDI: 0000000000000007 RBP: ffff8880a9fe7738 R08: ffff8880a9422000 R09: 0000000000000006 R10: 0000000000000000 R11: ffff8880a9422000 R12: ffff8880a9fe7490 R13: 0000000000000000 R14: 1ffff110153fce92 R15: ffff8880a9fe7710 process_one_work+0xc90/0x1c40 kernel/workqueue.c:2153 worker_thread+0x17f/0x1390 kernel/workqueue.c:2296 kthread+0x35a/0x440 kernel/kthread.c:246 ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:352 Kernel Offset: disabled Rebooting in 86400 seconds.. --- This bug is generated by a bot. It may contain errors. See https://goo.gl/tpsmEJ for more information about syzbot. syzbot engineers can be reached at syzkaller at googlegroups.com. syzbot will keep track of this bug report. See: https://goo.gl/tpsmEJ#bug-status-tracking for how to communicate with syzbot. From syzbot+7d20bc3f1ddddc0f9079 at syzkaller.appspotmail.com Mon Dec 31 06:51:03 2018 From: syzbot+7d20bc3f1ddddc0f9079 at syzkaller.appspotmail.com (syzbot) Date: Sun, 30 Dec 2018 21:51:03 -0800 Subject: [B.A.T.M.A.N.] KASAN: use-after-free Read in batadv_interface_tx Message-ID: <0000000000008d3a7f057e4aff68@google.com> Hello, syzbot found the following crash on: HEAD commit: 903b77c63167 Merge tag 'linux-kselftest-4.21-rc1' of git:/.. git tree: upstream console output: https://syzkaller.appspot.com/x/log.txt?x=168acbdd400000 kernel config: https://syzkaller.appspot.com/x/.config?x=53a2f2aa0b1f7606 dashboard link: https://syzkaller.appspot.com/bug?extid=7d20bc3f1ddddc0f9079 compiler: gcc (GCC) 8.0.1 20180413 (experimental) syz repro: https://syzkaller.appspot.com/x/repro.syz?x=11aa3b57400000 C reproducer: https://syzkaller.appspot.com/x/repro.c?x=12c907ed400000 IMPORTANT: if you fix the bug, please add the following tag to the commit: Reported-by: syzbot+7d20bc3f1ddddc0f9079 at syzkaller.appspotmail.com IPv6: ADDRCONF(NETDEV_UP): vxcan1: link is not ready 8021q: adding VLAN 0 to HW filter on device batadv0 ================================================================== BUG: KASAN: use-after-free in batadv_interface_tx+0x160a/0x18b0 net/batman-adv/soft-interface.c:226 Read of size 2 at addr ffff88809f96aa4b by task syz-executor871/8379 CPU: 1 PID: 8379 Comm: syz-executor871 Not tainted 4.20.0+ #395 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x1d3/0x2c6 lib/dump_stack.c:113 print_address_description.cold.5+0x9/0x1ff mm/kasan/report.c:187 kasan_report.cold.6+0x1b/0x39 mm/kasan/report.c:317 __asan_report_load_n_noabort+0xf/0x20 mm/kasan/generic_report.c:145 batadv_interface_tx+0x160a/0x18b0 net/batman-adv/soft-interface.c:226 __netdev_start_xmit include/linux/netdevice.h:4382 [inline] netdev_start_xmit include/linux/netdevice.h:4391 [inline] dev_direct_xmit+0x36c/0x6a0 net/core/dev.c:3930 packet_direct_xmit+0xfb/0x170 net/packet/af_packet.c:246 packet_snd net/packet/af_packet.c:2932 [inline] packet_sendmsg+0x298a/0x6ad0 net/packet/af_packet.c:2957 sock_sendmsg_nosec net/socket.c:621 [inline] sock_sendmsg+0xd5/0x120 net/socket.c:631 __sys_sendto+0x3d7/0x670 net/socket.c:1788 __do_sys_sendto net/socket.c:1800 [inline] __se_sys_sendto net/socket.c:1796 [inline] __x64_sys_sendto+0xe1/0x1a0 net/socket.c:1796 do_syscall_64+0x1b9/0x820 arch/x86/entry/common.c:290 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x441eb9 Code: e8 4c ad 02 00 48 83 c4 18 c3 0f 1f 80 00 00 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 fb 04 fc ff c3 66 2e 0f 1f 84 00 00 00 00 RSP: 002b:00007ffee312ce58 EFLAGS: 00000212 ORIG_RAX: 000000000000002c RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 0000000000441eb9 RDX: 000000000000000e RSI: 0000000020000180 RDI: 0000000000000003 RBP: 0000000000000001 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000212 R12: 0000000000000000 R13: 00000000004028d0 R14: 0000000000000000 R15: 0000000000000000 Allocated by task 8368: save_stack+0x43/0xd0 mm/kasan/common.c:73 set_track mm/kasan/common.c:85 [inline] kasan_kmalloc+0xcb/0xd0 mm/kasan/common.c:482 kasan_slab_alloc+0x12/0x20 mm/kasan/common.c:397 kmem_cache_alloc+0x130/0x730 mm/slab.c:3541 getname_flags+0xd0/0x590 fs/namei.c:140 user_path_at_empty+0x2d/0x50 fs/namei.c:2608 user_path_at include/linux/namei.h:57 [inline] do_faccessat+0x254/0x800 fs/open.c:378 __do_sys_access fs/open.c:430 [inline] __se_sys_access fs/open.c:428 [inline] __x64_sys_access+0x59/0x80 fs/open.c:428 do_syscall_64+0x1b9/0x820 arch/x86/entry/common.c:290 entry_SYSCALL_64_after_hwframe+0x49/0xbe Freed by task 8368: save_stack+0x43/0xd0 mm/kasan/common.c:73 set_track mm/kasan/common.c:85 [inline] __kasan_slab_free+0x102/0x150 mm/kasan/common.c:444 kasan_slab_free+0xe/0x10 mm/kasan/common.c:452 __cache_free mm/slab.c:3485 [inline] kmem_cache_free+0x83/0x290 mm/slab.c:3747 putname+0xf2/0x130 fs/namei.c:261 filename_lookup+0x39a/0x520 fs/namei.c:2357 user_path_at_empty+0x40/0x50 fs/namei.c:2608 user_path_at include/linux/namei.h:57 [inline] do_faccessat+0x254/0x800 fs/open.c:378 __do_sys_access fs/open.c:430 [inline] __se_sys_access fs/open.c:428 [inline] __x64_sys_access+0x59/0x80 fs/open.c:428 do_syscall_64+0x1b9/0x820 arch/x86/entry/common.c:290 entry_SYSCALL_64_after_hwframe+0x49/0xbe The buggy address belongs to the object at ffff88809f96a2c0 which belongs to the cache names_cache of size 4096 The buggy address is located 1931 bytes inside of 4096-byte region [ffff88809f96a2c0, ffff88809f96b2c0) The buggy address belongs to the page: page:ffffea00027e5a80 count:1 mapcount:0 mapping:ffff88821bc49080 index:0x0 compound_mapcount: 0 flags: 0x1fffc0000010200(slab|head) raw: 01fffc0000010200 ffffea0002810f08 ffffea00027d0388 ffff88821bc49080 raw: 0000000000000000 ffff88809f96a2c0 0000000100000001 0000000000000000 page dumped because: kasan: bad access detected Memory state around the buggy address: ffff88809f96a900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ffff88809f96a980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb > ffff88809f96aa00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ^ ffff88809f96aa80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ffff88809f96ab00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ================================================================== --- This bug is generated by a bot. It may contain errors. See https://goo.gl/tpsmEJ for more information about syzbot. syzbot engineers can be reached at syzkaller at googlegroups.com. syzbot will keep track of this bug report. See: https://goo.gl/tpsmEJ#bug-status-tracking for how to communicate with syzbot. syzbot can test patches for this bug, for details see: https://goo.gl/tpsmEJ#testing-patches From syzbot+9d7405c7faa390e60b4e at syzkaller.appspotmail.com Mon Dec 31 10:41:03 2018 From: syzbot+9d7405c7faa390e60b4e at syzkaller.appspotmail.com (syzbot) Date: Mon, 31 Dec 2018 01:41:03 -0800 Subject: [B.A.T.M.A.N.] KASAN: slab-out-of-bounds Read in batadv_interface_tx Message-ID: <0000000000000f098d057e4e3662@google.com> Hello, syzbot found the following crash on: HEAD commit: f346b0becb1b Merge branch 'akpm' (patches from Andrew) git tree: upstream console output: https://syzkaller.appspot.com/x/log.txt?x=10f0bbdd400000 kernel config: https://syzkaller.appspot.com/x/.config?x=c255c77ba370fe7c dashboard link: https://syzkaller.appspot.com/bug?extid=9d7405c7faa390e60b4e compiler: gcc (GCC) 8.0.1 20180413 (experimental) syz repro: https://syzkaller.appspot.com/x/repro.syz?x=14c3eabf400000 C reproducer: https://syzkaller.appspot.com/x/repro.c?x=164bfbfb400000 IMPORTANT: if you fix the bug, please add the following tag to the commit: Reported-by: syzbot+9d7405c7faa390e60b4e at syzkaller.appspotmail.com IPv6: ADDRCONF(NETDEV_UP): vxcan1: link is not ready 8021q: adding VLAN 0 to HW filter on device batadv0 ================================================================== BUG: KASAN: slab-out-of-bounds in batadv_interface_tx+0x160a/0x18b0 net/batman-adv/soft-interface.c:226 Read of size 2 at addr ffff8880a662f5cb by task syz-executor922/8142 CPU: 0 PID: 8142 Comm: syz-executor922 Not tainted 4.20.0+ #173 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x1d3/0x2c6 lib/dump_stack.c:113 print_address_description.cold.5+0x9/0x1ff mm/kasan/report.c:187 kasan_report.cold.6+0x1b/0x39 mm/kasan/report.c:317 __asan_report_load_n_noabort+0xf/0x20 mm/kasan/generic_report.c:145 batadv_interface_tx+0x160a/0x18b0 net/batman-adv/soft-interface.c:226 __netdev_start_xmit include/linux/netdevice.h:4382 [inline] netdev_start_xmit include/linux/netdevice.h:4391 [inline] dev_direct_xmit+0x36c/0x6a0 net/core/dev.c:3930 packet_direct_xmit+0xfb/0x170 net/packet/af_packet.c:246 packet_snd net/packet/af_packet.c:2932 [inline] packet_sendmsg+0x298a/0x6ad0 net/packet/af_packet.c:2957 sock_sendmsg_nosec net/socket.c:621 [inline] sock_sendmsg+0xd5/0x120 net/socket.c:631 __sys_sendto+0x3d7/0x670 net/socket.c:1788 __do_sys_sendto net/socket.c:1800 [inline] __se_sys_sendto net/socket.c:1796 [inline] __x64_sys_sendto+0xe1/0x1a0 net/socket.c:1796 do_syscall_64+0x1b9/0x820 arch/x86/entry/common.c:290 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x441619 Code: 18 89 d0 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 3b 0b fc ff c3 66 2e 0f 1f 84 00 00 00 00 RSP: 002b:00007ffd5c9334f8 EFLAGS: 00000212 ORIG_RAX: 000000000000002c RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 0000000000441619 RDX: 000000000000000e RSI: 0000000020000180 RDI: 0000000000000003 RBP: 0000000000000001 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000212 R12: 00000000004025e0 R13: 0000000000402670 R14: 0000000000000000 R15: 0000000000000000 Allocated by task 8184: save_stack+0x43/0xd0 mm/kasan/common.c:73 set_track mm/kasan/common.c:85 [inline] kasan_kmalloc+0xcb/0xd0 mm/kasan/common.c:482 kasan_slab_alloc+0x12/0x20 mm/kasan/common.c:397 kmem_cache_alloc+0x130/0x730 mm/slab.c:3541 getname_flags+0xd0/0x590 fs/namei.c:140 getname+0x19/0x20 fs/namei.c:211 do_sys_open+0x383/0x780 fs/open.c:1057 __do_sys_open fs/open.c:1081 [inline] __se_sys_open fs/open.c:1076 [inline] __x64_sys_open+0x7e/0xc0 fs/open.c:1076 do_syscall_64+0x1b9/0x820 arch/x86/entry/common.c:290 entry_SYSCALL_64_after_hwframe+0x49/0xbe Freed by task 8184: save_stack+0x43/0xd0 mm/kasan/common.c:73 set_track mm/kasan/common.c:85 [inline] __kasan_slab_free+0x102/0x150 mm/kasan/common.c:444 kasan_slab_free+0xe/0x10 mm/kasan/common.c:452 __cache_free mm/slab.c:3485 [inline] kmem_cache_free+0x83/0x290 mm/slab.c:3747 putname+0xf2/0x130 fs/namei.c:261 do_sys_open+0x54d/0x780 fs/open.c:1072 __do_sys_open fs/open.c:1081 [inline] __se_sys_open fs/open.c:1076 [inline] __x64_sys_open+0x7e/0xc0 fs/open.c:1076 do_syscall_64+0x1b9/0x820 arch/x86/entry/common.c:290 entry_SYSCALL_64_after_hwframe+0x49/0xbe The buggy address belongs to the object at ffff8880a662e5c0 which belongs to the cache names_cache of size 4096 The buggy address is located 11 bytes to the right of 4096-byte region [ffff8880a662e5c0, ffff8880a662f5c0) The buggy address belongs to the page: page:ffffea0002998b80 count:1 mapcount:0 mapping:ffff88821bc48200 index:0x0 compound_mapcount: 0 flags: 0x1fffc0000010200(slab|head) raw: 01fffc0000010200 ffffea00029fa208 ffffea00022fd188 ffff88821bc48200 raw: 0000000000000000 ffff8880a662e5c0 0000000100000001 0000000000000000 page dumped because: kasan: bad access detected Memory state around the buggy address: ffff8880a662f480: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ffff8880a662f500: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb > ffff8880a662f580: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc ^ ffff8880a662f600: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc ffff8880a662f680: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc ================================================================== --- This bug is generated by a bot. It may contain errors. See https://goo.gl/tpsmEJ for more information about syzbot. syzbot engineers can be reached at syzkaller at googlegroups.com. syzbot will keep track of this bug report. See: https://goo.gl/tpsmEJ#bug-status-tracking for how to communicate with syzbot. syzbot can test patches for this bug, for details see: https://goo.gl/tpsmEJ#testing-patches From sven at narfation.org Mon Dec 31 20:08:19 2018 From: sven at narfation.org (Sven Eckelmann) Date: Mon, 31 Dec 2018 20:08:19 +0100 Subject: [B.A.T.M.A.N.] [RFC v3 01/19] batman-adv: Move common genl doit code pre/post hooks In-Reply-To: <20181230165754.GC4150@otheros> References: <20181207135846.6152-1-sven@narfation.org> <20181207135846.6152-2-sven@narfation.org> <20181230165754.GC4150@otheros> Message-ID: <1842705.uoa0R6XjVQ@sven-edge> On Sunday, 30 December 2018 17.57.54 CET Linus Lüssing wrote: > On Fri, Dec 07, 2018 at 02:58:28PM +0100, Sven Eckelmann wrote: > > +/** > > + * batadv_get_softif_from_info() - Retrieve soft interface from genl attributes > > + * @net: the applicable net namespace > > + * @info: receiver information > > + * > > + * Return: Pointer to soft interface on success, error pointer on error > > + */ > > +static struct batadv_priv * > > +batadv_get_softif_from_info(struct net *net, struct genl_info *info) > > Since this returns a batadv_priv, shouldn't it better be called > batadv_get_batpriv_from_info() or batadv_get_bat_priv_from_info() maybe? OK > > > +{ > > + struct net_device *soft_iface; > > + int ifindex; > > + > > + if (!info->attrs[BATADV_ATTR_MESH_IFINDEX]) > > + return ERR_PTR(-EINVAL); > > + > > + ifindex = nla_get_u32(info->attrs[BATADV_ATTR_MESH_IFINDEX]); > > + > > + soft_iface = dev_get_by_index(net, ifindex); > > + if (!soft_iface) > > + return ERR_PTR(-ENODEV); > > + > > + if (!batadv_softif_is_valid(soft_iface)) > > + goto err_put_softif; > > + > > + return netdev_priv(soft_iface); > > + > > +err_put_softif: > > + dev_put(soft_iface); > > + > > + return ERR_PTR(-EINVAL); > > +} > > Is holding a reference to bat_priv->soft_iface really > necessary (and releasing it in batadv_post_doit() )? > If we are able to retrieve a valid bat_priv then this bat_priv > itself should hold a reference to to soft_iface, shouldn't it? No, we don't hold any explicit reference to bat_priv itself. The bat_priv is a part of the memory of the soft_iface. So we most hold a reference for soft_iface because we don't prevent that it is removed in the meantime (the netlink interface is registered per module and not per meshif/softif). [...] > > + if (ops->internal_flags & BATADV_FLAG_NEED_MESH) { > > + bat_priv = batadv_get_softif_from_info(genl_info_net(info), > > + info); > > Would it look nicer to store genl_info_net(info) in a temporary variable > so that its shorter and the newline for the second parameter could > be avoided? Ok > > + if (IS_ERR(bat_priv)) > > + return PTR_ERR(bat_priv); > > + > > + info->user_ptr[0] = bat_priv; > > Would it make sense to wrap this private data access into > something somehow? Conceptually similar to what we do not with skb private > data already for instance. There we use BATADV_SKB_CB() for instance. Please not, we only have two pointers and I definitely don't want to force specific positions (we need three at the moment - but max two per command). You should compare it with the nl80211 code. Kind regards, Sven -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: This is a digitally signed message part. URL: From sven at narfation.org Mon Dec 31 20:11:18 2018 From: sven at narfation.org (Sven Eckelmann) Date: Mon, 31 Dec 2018 20:11:18 +0100 Subject: [B.A.T.M.A.N.] [RFC v3 02/19] batman-adv: Prepare framework for mesh genl config In-Reply-To: <20181231110950.GD4150@otheros> References: <20181207135846.6152-1-sven@narfation.org> <20181207135846.6152-3-sven@narfation.org> <20181231110950.GD4150@otheros> Message-ID: <5881296.i1tslI3xJu@sven-edge> On Monday, 31 December 2018 12.09.50 CET Linus Lüssing wrote: [...] > [...] > > > #ifdef CONFIG_BATMAN_ADV_BLA > > if (nla_put_u16(msg, BATADV_ATTR_BLA_CRC, > > ntohs(bat_priv->bla.claim_dest.group))) > > - goto out; > > + goto nla_put_failure; > > #endif > > > > if (batadv_mcast_mesh_info_put(msg, bat_priv)) > > - goto out; > > + goto nla_put_failure; > > With the rename of "batadv_netlink_mesh_info_put" to > "batadv_netlink_mesh_put", I'm wondering whether > batadv_mcast_mesh_info_put() should be renamed, too. > batadv_mcast_mesh_put() would probably be a bit too generic. > But maybe something like batadv_mcast_nl_mesh_put()? Not relevant for this patch. But feel free to check what we can do to make it more consistent. We can then do it after having the rest in place. Kind regards, Sven -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: This is a digitally signed message part. URL: From sven at narfation.org Mon Dec 31 20:17:58 2018 From: sven at narfation.org (Sven Eckelmann) Date: Mon, 31 Dec 2018 20:17:58 +0100 Subject: [B.A.T.M.A.N.] [RFC v3 03/19] batman-adv: Prepare framework for hardif genl config In-Reply-To: <20181231115936.GE4150@otheros> References: <20181207135846.6152-1-sven@narfation.org> <20181207135846.6152-4-sven@narfation.org> <20181231115936.GE4150@otheros> Message-ID: <2071883.YQQqAYjll7@sven-edge> On Monday, 31 December 2018 12.59.36 CET Linus Lüssing wrote: [...] > > static int batadv_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, > > struct genl_info *info) > > { > > - struct batadv_priv *bat_priv; > > + struct batadv_hard_iface *hard_iface; > > + struct batadv_priv *bat_priv = NULL; > > + int ret; > > + > > + if (WARN_ON(ops->internal_flags & BATADV_FLAG_NEED_HARDIF)) > > + return -EINVAL; > > + > > + if (WARN_ON((ops->internal_flags & BATADV_FLAG_NEED_HARDIF) && > > + (~ops->internal_flags & BATADV_FLAG_NEED_MESH))) > > + return -EINVAL; > > Seems like the second part is unreachable code. If > BATADV_FLAG_NEED_HARDIF is set then the function returns with the first > if-clause already. Looks like I've incorrectly splitted the patch at this position. Makes more sense when you check the next patch. So the first check should be removed from this patch to make it less confusing. Btw. thanks for the spelling/grammar fixes. Kind regards, Sven -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: This is a digitally signed message part. URL: From sven at narfation.org Mon Dec 31 22:46:09 2018 From: sven at narfation.org (Sven Eckelmann) Date: Mon, 31 Dec 2018 22:46:09 +0100 Subject: [B.A.T.M.A.N.] [PATCH maint] batman-adv: Force mac header to start of data on xmit Message-ID: <20181231214609.22378-1-sven@narfation.org> The caller of ndo_start_xmit may not already have called skb_reset_mac_header. The returned value of skb_mac_header/eth_hdr therefore can be in the wrong position and even outside the current skbuff. This for example happens when the user binds to the device using a PF_PACKET-SOCK_RAW with enabled qdisc-bypass: int opt = 4; setsockopt(sock, SOL_PACKET, PACKET_QDISC_BYPASS, &opt, sizeof(opt)); Since eth_hdr is used all over the codebase, the batadv_interface_tx function must always take care of resetting it. Fixes: fe28a94c01e1 ("batman-adv: receive packets directly using skbs") Reported-by: syzbot+9d7405c7faa390e60b4e at syzkaller.appspotmail.com Reported-by: syzbot+7d20bc3f1ddddc0f9079 at syzkaller.appspotmail.com Signed-off-by: Sven Eckelmann --- Cc: syzkaller-bugs at googlegroups.com --- net/batman-adv/soft-interface.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 5db5a0a4..b85ca809 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -221,6 +221,8 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb, netif_trans_update(soft_iface); vid = batadv_get_vid(skb, 0); + + skb_reset_mac_header(skb); ethhdr = eth_hdr(skb); switch (ntohs(ethhdr->h_proto)) { -- 2.19.2 From sven at narfation.org Mon Dec 31 23:59:59 2018 From: sven at narfation.org (Sven Eckelmann) Date: Mon, 31 Dec 2018 23:59:59 +0100 Subject: [B.A.T.M.A.N.] [PATCH 1/3] batman-adv: Update copyright years for 2019 In-Reply-To: <20181231230001.17417-1-sven@narfation.org> References: <20181231230001.17417-1-sven@narfation.org> Message-ID: <20181231230001.17417-2-sven@narfation.org> Signed-off-by: Sven Eckelmann --- Makefile | 2 +- compat-include/linux/average.h | 2 +- compat-include/linux/build_bug.h | 2 +- compat-include/linux/cache.h | 2 +- compat-include/linux/compiler.h | 3 ++- compat-include/linux/ethtool.h | 2 +- compat-include/linux/eventpoll.h | 2 +- compat-include/linux/fs.h | 2 +- compat-include/linux/if_bridge.h | 2 +- compat-include/linux/igmp.h | 2 +- compat-include/linux/list.h | 2 +- compat-include/linux/netdevice.h | 2 +- compat-include/linux/netlink.h | 2 +- compat-include/linux/nl80211.h | 2 +- compat-include/linux/seq_file.h | 2 +- compat-include/linux/skbuff.h | 2 +- compat-include/linux/timer.h | 2 +- compat-include/linux/types.h | 2 +- compat-include/net/addrconf.h | 2 +- compat-include/net/cfg80211.h | 2 +- compat-include/net/genetlink.h | 2 +- compat-include/net/ip6_checksum.h | 2 +- compat-include/net/netlink.h | 2 +- compat-include/uapi/linux/eventpoll.h | 2 +- compat-include/uapi/linux/nl80211.h | 2 +- compat-sources/Makefile | 2 +- compat.h | 2 +- gen-compat-autoconf.sh | 2 +- include/uapi/linux/batadv_packet.h | 2 +- include/uapi/linux/batman_adv.h | 2 +- net/batman-adv/Kconfig | 2 +- net/batman-adv/Makefile | 2 +- net/batman-adv/bat_algo.c | 2 +- net/batman-adv/bat_algo.h | 2 +- net/batman-adv/bat_iv_ogm.c | 2 +- net/batman-adv/bat_iv_ogm.h | 2 +- net/batman-adv/bat_v.c | 2 +- net/batman-adv/bat_v.h | 2 +- net/batman-adv/bat_v_elp.c | 2 +- net/batman-adv/bat_v_elp.h | 2 +- net/batman-adv/bat_v_ogm.c | 2 +- net/batman-adv/bat_v_ogm.h | 2 +- net/batman-adv/bitarray.c | 2 +- net/batman-adv/bitarray.h | 2 +- net/batman-adv/bridge_loop_avoidance.c | 2 +- net/batman-adv/bridge_loop_avoidance.h | 2 +- net/batman-adv/debugfs.c | 2 +- net/batman-adv/debugfs.h | 2 +- net/batman-adv/distributed-arp-table.c | 2 +- net/batman-adv/distributed-arp-table.h | 2 +- net/batman-adv/fragmentation.c | 2 +- net/batman-adv/fragmentation.h | 2 +- net/batman-adv/gateway_client.c | 2 +- net/batman-adv/gateway_client.h | 2 +- net/batman-adv/gateway_common.c | 2 +- net/batman-adv/gateway_common.h | 2 +- net/batman-adv/hard-interface.c | 2 +- net/batman-adv/hard-interface.h | 2 +- net/batman-adv/hash.c | 2 +- net/batman-adv/hash.h | 2 +- net/batman-adv/icmp_socket.c | 2 +- net/batman-adv/icmp_socket.h | 2 +- net/batman-adv/log.c | 2 +- net/batman-adv/log.h | 2 +- net/batman-adv/main.c | 2 +- net/batman-adv/main.h | 2 +- net/batman-adv/multicast.c | 2 +- net/batman-adv/multicast.h | 2 +- net/batman-adv/netlink.c | 2 +- net/batman-adv/netlink.h | 2 +- net/batman-adv/network-coding.c | 2 +- net/batman-adv/network-coding.h | 2 +- net/batman-adv/originator.c | 2 +- net/batman-adv/originator.h | 2 +- net/batman-adv/routing.c | 2 +- net/batman-adv/routing.h | 2 +- net/batman-adv/send.c | 2 +- net/batman-adv/send.h | 2 +- net/batman-adv/soft-interface.c | 2 +- net/batman-adv/soft-interface.h | 2 +- net/batman-adv/sysfs.c | 2 +- net/batman-adv/sysfs.h | 2 +- net/batman-adv/tp_meter.c | 2 +- net/batman-adv/tp_meter.h | 2 +- net/batman-adv/trace.c | 2 +- net/batman-adv/trace.h | 2 +- net/batman-adv/translation-table.c | 2 +- net/batman-adv/translation-table.h | 2 +- net/batman-adv/tvlv.c | 2 +- net/batman-adv/tvlv.h | 2 +- net/batman-adv/types.h | 2 +- 91 files changed, 92 insertions(+), 91 deletions(-) diff --git a/Makefile b/Makefile index 08ac8f65..bccea1b3 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -# Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +# Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: # # Marek Lindner, Simon Wunderlich # diff --git a/compat-include/linux/average.h b/compat-include/linux/average.h index c8b58ec3..b768fba7 100644 --- a/compat-include/linux/average.h +++ b/compat-include/linux/average.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/compat-include/linux/build_bug.h b/compat-include/linux/build_bug.h index 5d6657bc..e071e580 100644 --- a/compat-include/linux/build_bug.h +++ b/compat-include/linux/build_bug.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/compat-include/linux/cache.h b/compat-include/linux/cache.h index 0fc5478d..c8f4f394 100644 --- a/compat-include/linux/cache.h +++ b/compat-include/linux/cache.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/compat-include/linux/compiler.h b/compat-include/linux/compiler.h index 45cd49fa..f4a84b11 100644 --- a/compat-include/linux/compiler.h +++ b/compat-include/linux/compiler.h @@ -1,4 +1,5 @@ -/* Copyright (C) 2007-2017 B.A.T.M.A.N. contributors: +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/compat-include/linux/ethtool.h b/compat-include/linux/ethtool.h index caa70071..20071656 100644 --- a/compat-include/linux/ethtool.h +++ b/compat-include/linux/ethtool.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2016-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2016-2019 B.A.T.M.A.N. contributors: * * Antonio Quartulli * diff --git a/compat-include/linux/eventpoll.h b/compat-include/linux/eventpoll.h index 40a7203b..eb38199b 100644 --- a/compat-include/linux/eventpoll.h +++ b/compat-include/linux/eventpoll.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/compat-include/linux/fs.h b/compat-include/linux/fs.h index e0d6f7c7..30c97dc3 100644 --- a/compat-include/linux/fs.h +++ b/compat-include/linux/fs.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/compat-include/linux/if_bridge.h b/compat-include/linux/if_bridge.h index ff1ff3ae..63e727d2 100644 --- a/compat-include/linux/if_bridge.h +++ b/compat-include/linux/if_bridge.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/compat-include/linux/igmp.h b/compat-include/linux/igmp.h index 7452b221..59f55522 100644 --- a/compat-include/linux/igmp.h +++ b/compat-include/linux/igmp.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/compat-include/linux/list.h b/compat-include/linux/list.h index c542236e..0aa887d8 100644 --- a/compat-include/linux/list.h +++ b/compat-include/linux/list.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/compat-include/linux/netdevice.h b/compat-include/linux/netdevice.h index 8f099cf4..19acd7c2 100644 --- a/compat-include/linux/netdevice.h +++ b/compat-include/linux/netdevice.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/compat-include/linux/netlink.h b/compat-include/linux/netlink.h index eb42b2b6..4497d667 100644 --- a/compat-include/linux/netlink.h +++ b/compat-include/linux/netlink.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/compat-include/linux/nl80211.h b/compat-include/linux/nl80211.h index 9871910a..71126a1d 100644 --- a/compat-include/linux/nl80211.h +++ b/compat-include/linux/nl80211.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/compat-include/linux/seq_file.h b/compat-include/linux/seq_file.h index e810f225..1077cfc0 100644 --- a/compat-include/linux/seq_file.h +++ b/compat-include/linux/seq_file.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/compat-include/linux/skbuff.h b/compat-include/linux/skbuff.h index fbfd0e02..edda41d9 100644 --- a/compat-include/linux/skbuff.h +++ b/compat-include/linux/skbuff.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/compat-include/linux/timer.h b/compat-include/linux/timer.h index 262c3861..83b4bc92 100644 --- a/compat-include/linux/timer.h +++ b/compat-include/linux/timer.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/compat-include/linux/types.h b/compat-include/linux/types.h index f33f2bb2..c1571e9a 100644 --- a/compat-include/linux/types.h +++ b/compat-include/linux/types.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2017 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/compat-include/net/addrconf.h b/compat-include/net/addrconf.h index 9d8cd2ae..ca9d6935 100644 --- a/compat-include/net/addrconf.h +++ b/compat-include/net/addrconf.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/compat-include/net/cfg80211.h b/compat-include/net/cfg80211.h index 79c028af..d4153b96 100644 --- a/compat-include/net/cfg80211.h +++ b/compat-include/net/cfg80211.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/compat-include/net/genetlink.h b/compat-include/net/genetlink.h index 026500c3..8e8f1e3c 100644 --- a/compat-include/net/genetlink.h +++ b/compat-include/net/genetlink.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/compat-include/net/ip6_checksum.h b/compat-include/net/ip6_checksum.h index 521345dd..5382e886 100644 --- a/compat-include/net/ip6_checksum.h +++ b/compat-include/net/ip6_checksum.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/compat-include/net/netlink.h b/compat-include/net/netlink.h index c395dafb..ce57a19e 100644 --- a/compat-include/net/netlink.h +++ b/compat-include/net/netlink.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/compat-include/uapi/linux/eventpoll.h b/compat-include/uapi/linux/eventpoll.h index 3cf71a19..d4a26d60 100644 --- a/compat-include/uapi/linux/eventpoll.h +++ b/compat-include/uapi/linux/eventpoll.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/compat-include/uapi/linux/nl80211.h b/compat-include/uapi/linux/nl80211.h index 3e743249..8fda321f 100644 --- a/compat-include/uapi/linux/nl80211.h +++ b/compat-include/uapi/linux/nl80211.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/compat-sources/Makefile b/compat-sources/Makefile index 7aabaac6..fd4e6db1 100644 --- a/compat-sources/Makefile +++ b/compat-sources/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -# Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +# Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: # # Marek Lindner, Simon Wunderlich # diff --git a/compat.h b/compat.h index 559df2f3..b3327fa1 100644 --- a/compat.h +++ b/compat.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/gen-compat-autoconf.sh b/gen-compat-autoconf.sh index a4eb1136..7a8c8eef 100755 --- a/gen-compat-autoconf.sh +++ b/gen-compat-autoconf.sh @@ -1,6 +1,6 @@ #! /bin/sh # SPDX-License-Identifier: GPL-2.0 -# Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +# Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: # # Marek Lindner, Simon Wunderlich # diff --git a/include/uapi/linux/batadv_packet.h b/include/uapi/linux/batadv_packet.h index 894d8d2f..7eb2936a 100644 --- a/include/uapi/linux/batadv_packet.h +++ b/include/uapi/linux/batadv_packet.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h index 324a0e11..a28e76a7 100644 --- a/include/uapi/linux/batman_adv.h +++ b/include/uapi/linux/batman_adv.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: MIT */ -/* Copyright (C) 2016-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2016-2019 B.A.T.M.A.N. contributors: * * Matthias Schiffer * diff --git a/net/batman-adv/Kconfig b/net/batman-adv/Kconfig index c386e698..a31db5e9 100644 --- a/net/batman-adv/Kconfig +++ b/net/batman-adv/Kconfig @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -# Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +# Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: # # Marek Lindner, Simon Wunderlich # diff --git a/net/batman-adv/Makefile b/net/batman-adv/Makefile index 9b58160f..a887ecc3 100644 --- a/net/batman-adv/Makefile +++ b/net/batman-adv/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -# Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +# Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: # # Marek Lindner, Simon Wunderlich # diff --git a/net/batman-adv/bat_algo.c b/net/batman-adv/bat_algo.c index ea309ad0..7b7e1564 100644 --- a/net/batman-adv/bat_algo.c +++ b/net/batman-adv/bat_algo.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/bat_algo.h b/net/batman-adv/bat_algo.h index 534b790c..25e7bb51 100644 --- a/net/batman-adv/bat_algo.h +++ b/net/batman-adv/bat_algo.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2011-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2011-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Linus Lüssing * diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index f97e566f..de61091a 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/bat_iv_ogm.h b/net/batman-adv/bat_iv_ogm.h index 3dc6a7a4..785f6666 100644 --- a/net/batman-adv/bat_iv_ogm.h +++ b/net/batman-adv/bat_iv_ogm.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/bat_v.c b/net/batman-adv/bat_v.c index 90e33f84..445594ed 100644 --- a/net/batman-adv/bat_v.c +++ b/net/batman-adv/bat_v.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2013-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2013-2019 B.A.T.M.A.N. contributors: * * Linus Lüssing, Marek Lindner * diff --git a/net/batman-adv/bat_v.h b/net/batman-adv/bat_v.h index ec4a2a56..465a4fc2 100644 --- a/net/batman-adv/bat_v.h +++ b/net/batman-adv/bat_v.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2011-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2011-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Linus Lüssing * diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c index e8090f09..7b80f6f8 100644 --- a/net/batman-adv/bat_v_elp.c +++ b/net/batman-adv/bat_v_elp.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2011-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2011-2019 B.A.T.M.A.N. contributors: * * Linus Lüssing, Marek Lindner * diff --git a/net/batman-adv/bat_v_elp.h b/net/batman-adv/bat_v_elp.h index e8c7b7fd..75f189ee 100644 --- a/net/batman-adv/bat_v_elp.h +++ b/net/batman-adv/bat_v_elp.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2013-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2013-2019 B.A.T.M.A.N. contributors: * * Linus Lüssing, Marek Lindner * diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c index 2948b41b..c9698ad4 100644 --- a/net/batman-adv/bat_v_ogm.c +++ b/net/batman-adv/bat_v_ogm.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2013-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2013-2019 B.A.T.M.A.N. contributors: * * Antonio Quartulli * diff --git a/net/batman-adv/bat_v_ogm.h b/net/batman-adv/bat_v_ogm.h index e5be14c9..f67cf7ee 100644 --- a/net/batman-adv/bat_v_ogm.h +++ b/net/batman-adv/bat_v_ogm.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2013-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2013-2019 B.A.T.M.A.N. contributors: * * Antonio Quartulli * diff --git a/net/batman-adv/bitarray.c b/net/batman-adv/bitarray.c index a296a4d8..63e134e7 100644 --- a/net/batman-adv/bitarray.c +++ b/net/batman-adv/bitarray.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2006-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2006-2019 B.A.T.M.A.N. contributors: * * Simon Wunderlich, Marek Lindner * diff --git a/net/batman-adv/bitarray.h b/net/batman-adv/bitarray.h index 48f68328..f3a05ad9 100644 --- a/net/batman-adv/bitarray.h +++ b/net/batman-adv/bitarray.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2006-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2006-2019 B.A.T.M.A.N. contributors: * * Simon Wunderlich, Marek Lindner * diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 5fdde294..ef39aabd 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2011-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2011-2019 B.A.T.M.A.N. contributors: * * Simon Wunderlich * diff --git a/net/batman-adv/bridge_loop_avoidance.h b/net/batman-adv/bridge_loop_avoidance.h index 71f95a3e..31771c75 100644 --- a/net/batman-adv/bridge_loop_avoidance.h +++ b/net/batman-adv/bridge_loop_avoidance.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2011-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2011-2019 B.A.T.M.A.N. contributors: * * Simon Wunderlich * diff --git a/net/batman-adv/debugfs.c b/net/batman-adv/debugfs.c index d4a7702e..3b9d1ad2 100644 --- a/net/batman-adv/debugfs.c +++ b/net/batman-adv/debugfs.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2010-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2010-2019 B.A.T.M.A.N. contributors: * * Marek Lindner * diff --git a/net/batman-adv/debugfs.h b/net/batman-adv/debugfs.h index 8de018e5..c0b86940 100644 --- a/net/batman-adv/debugfs.h +++ b/net/batman-adv/debugfs.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2010-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2010-2019 B.A.T.M.A.N. contributors: * * Marek Lindner * diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index b9ffe182..7a4b75aa 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2011-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2011-2019 B.A.T.M.A.N. contributors: * * Antonio Quartulli * diff --git a/net/batman-adv/distributed-arp-table.h b/net/batman-adv/distributed-arp-table.h index a0459602..ea7fc7e0 100644 --- a/net/batman-adv/distributed-arp-table.h +++ b/net/batman-adv/distributed-arp-table.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2011-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2011-2019 B.A.T.M.A.N. contributors: * * Antonio Quartulli * diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c index 5b71a289..b506d15b 100644 --- a/net/batman-adv/fragmentation.c +++ b/net/batman-adv/fragmentation.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2013-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2013-2019 B.A.T.M.A.N. contributors: * * Martin Hundebøll * diff --git a/net/batman-adv/fragmentation.h b/net/batman-adv/fragmentation.h index 944512e0..abdac265 100644 --- a/net/batman-adv/fragmentation.h +++ b/net/batman-adv/fragmentation.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2013-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2013-2019 B.A.T.M.A.N. contributors: * * Martin Hundebøll * diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 9d8e5eda..0a6b9b30 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2009-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2009-2019 B.A.T.M.A.N. contributors: * * Marek Lindner * diff --git a/net/batman-adv/gateway_client.h b/net/batman-adv/gateway_client.h index f0b86fcb..b5732c8b 100644 --- a/net/batman-adv/gateway_client.h +++ b/net/batman-adv/gateway_client.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2009-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2009-2019 B.A.T.M.A.N. contributors: * * Marek Lindner * diff --git a/net/batman-adv/gateway_common.c b/net/batman-adv/gateway_common.c index 936c107f..53d03adc 100644 --- a/net/batman-adv/gateway_common.c +++ b/net/batman-adv/gateway_common.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2009-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2009-2019 B.A.T.M.A.N. contributors: * * Marek Lindner * diff --git a/net/batman-adv/gateway_common.h b/net/batman-adv/gateway_common.h index 80afb279..89bae100 100644 --- a/net/batman-adv/gateway_common.h +++ b/net/batman-adv/gateway_common.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2009-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2009-2019 B.A.T.M.A.N. contributors: * * Marek Lindner * diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 508f4416..28c1fb8d 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/hard-interface.h b/net/batman-adv/hard-interface.h index d1c0f618..48de28c8 100644 --- a/net/batman-adv/hard-interface.h +++ b/net/batman-adv/hard-interface.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/hash.c b/net/batman-adv/hash.c index 9194f4d8..56a08ce1 100644 --- a/net/batman-adv/hash.c +++ b/net/batman-adv/hash.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2006-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2006-2019 B.A.T.M.A.N. contributors: * * Simon Wunderlich, Marek Lindner * diff --git a/net/batman-adv/hash.h b/net/batman-adv/hash.h index 0e36fa1c..37507b6d 100644 --- a/net/batman-adv/hash.h +++ b/net/batman-adv/hash.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2006-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2006-2019 B.A.T.M.A.N. contributors: * * Simon Wunderlich, Marek Lindner * diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c index d70f363c..d34bb79e 100644 --- a/net/batman-adv/icmp_socket.c +++ b/net/batman-adv/icmp_socket.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner * diff --git a/net/batman-adv/icmp_socket.h b/net/batman-adv/icmp_socket.h index 958be22b..5f892652 100644 --- a/net/batman-adv/icmp_socket.h +++ b/net/batman-adv/icmp_socket.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner * diff --git a/net/batman-adv/log.c b/net/batman-adv/log.c index 02e55b78..f97849a8 100644 --- a/net/batman-adv/log.c +++ b/net/batman-adv/log.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2010-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2010-2019 B.A.T.M.A.N. contributors: * * Marek Lindner * diff --git a/net/batman-adv/log.h b/net/batman-adv/log.h index 35f4f397..660e9bcc 100644 --- a/net/batman-adv/log.h +++ b/net/batman-adv/log.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index d1ed839f..75750870 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index b5720663..05cb9080 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c index 69244e45..5de6a375 100644 --- a/net/batman-adv/multicast.c +++ b/net/batman-adv/multicast.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2014-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2014-2019 B.A.T.M.A.N. contributors: * * Linus Lüssing * diff --git a/net/batman-adv/multicast.h b/net/batman-adv/multicast.h index 3b04ab13..466013fe 100644 --- a/net/batman-adv/multicast.h +++ b/net/batman-adv/multicast.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2014-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2014-2019 B.A.T.M.A.N. contributors: * * Linus Lüssing * diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index 2dc3304c..5fe833cc 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2016-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2016-2019 B.A.T.M.A.N. contributors: * * Matthias Schiffer * diff --git a/net/batman-adv/netlink.h b/net/batman-adv/netlink.h index 571d9a5a..216484b8 100644 --- a/net/batman-adv/netlink.h +++ b/net/batman-adv/netlink.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2016-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2016-2019 B.A.T.M.A.N. contributors: * * Matthias Schiffer * diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c index 34caf129..278762bd 100644 --- a/net/batman-adv/network-coding.c +++ b/net/batman-adv/network-coding.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2012-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2012-2019 B.A.T.M.A.N. contributors: * * Martin Hundebøll, Jeppe Ledet-Pedersen * diff --git a/net/batman-adv/network-coding.h b/net/batman-adv/network-coding.h index 65c34681..96ef0a51 100644 --- a/net/batman-adv/network-coding.h +++ b/net/batman-adv/network-coding.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2012-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2012-2019 B.A.T.M.A.N. contributors: * * Martin Hundebøll, Jeppe Ledet-Pedersen * diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 56a981af..e5cdf89e 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2009-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2009-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h index a8b4c7b6..dca1e4a3 100644 --- a/net/batman-adv/originator.h +++ b/net/batman-adv/originator.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index cc3ed93a..be31d340 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h index db54c2d9..0102d69d 100644 --- a/net/batman-adv/routing.h +++ b/net/batman-adv/routing.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index 4a35f5c2..66a8b3e4 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/send.h b/net/batman-adv/send.h index 64cce07b..1f613292 100644 --- a/net/batman-adv/send.h +++ b/net/batman-adv/send.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 5db5a0a4..587c50d5 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/soft-interface.h b/net/batman-adv/soft-interface.h index daf87f07..538bb661 100644 --- a/net/batman-adv/soft-interface.h +++ b/net/batman-adv/soft-interface.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner * diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c index 09427fc6..e1b81626 100644 --- a/net/batman-adv/sysfs.c +++ b/net/batman-adv/sysfs.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2010-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2010-2019 B.A.T.M.A.N. contributors: * * Marek Lindner * diff --git a/net/batman-adv/sysfs.h b/net/batman-adv/sysfs.h index c1e3fb69..705ffbe7 100644 --- a/net/batman-adv/sysfs.h +++ b/net/batman-adv/sysfs.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2010-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2010-2019 B.A.T.M.A.N. contributors: * * Marek Lindner * diff --git a/net/batman-adv/tp_meter.c b/net/batman-adv/tp_meter.c index 11520de9..500109bb 100644 --- a/net/batman-adv/tp_meter.c +++ b/net/batman-adv/tp_meter.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2012-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2012-2019 B.A.T.M.A.N. contributors: * * Edo Monticelli, Antonio Quartulli * diff --git a/net/batman-adv/tp_meter.h b/net/batman-adv/tp_meter.h index 68e60097..6b4d0f73 100644 --- a/net/batman-adv/tp_meter.h +++ b/net/batman-adv/tp_meter.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2012-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2012-2019 B.A.T.M.A.N. contributors: * * Edo Monticelli, Antonio Quartulli * diff --git a/net/batman-adv/trace.c b/net/batman-adv/trace.c index 8e102421..f77c917e 100644 --- a/net/batman-adv/trace.c +++ b/net/batman-adv/trace.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2010-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2010-2019 B.A.T.M.A.N. contributors: * * Sven Eckelmann * diff --git a/net/batman-adv/trace.h b/net/batman-adv/trace.h index 104784be..5e557905 100644 --- a/net/batman-adv/trace.h +++ b/net/batman-adv/trace.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2010-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2010-2019 B.A.T.M.A.N. contributors: * * Sven Eckelmann * diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 8dcd4968..f73d7913 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich, Antonio Quartulli * diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h index 01b6c8ea..61bca75e 100644 --- a/net/batman-adv/translation-table.h +++ b/net/batman-adv/translation-table.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich, Antonio Quartulli * diff --git a/net/batman-adv/tvlv.c b/net/batman-adv/tvlv.c index 40e69c93..7e947b01 100644 --- a/net/batman-adv/tvlv.c +++ b/net/batman-adv/tvlv.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/tvlv.h b/net/batman-adv/tvlv.h index ef5867f4..c0f033b1 100644 --- a/net/batman-adv/tvlv.h +++ b/net/batman-adv/tvlv.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index cbe17da3..a21b34ed 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2019 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * -- 2.19.2 From sven at narfation.org Mon Dec 31 23:59:58 2018 From: sven at narfation.org (Sven Eckelmann) Date: Mon, 31 Dec 2018 23:59:58 +0100 Subject: [B.A.T.M.A.N.] [PATCH 0/3] batman-adv & co: Update copyright years for 2019 Message-ID: <20181231230001.17417-1-sven@narfation.org> Hi, here is just the annual update of the copyright years for batman-adv, batctl and alfred. Kind regards, Sven Sven Eckelmann (1): alfred: Update copyright years for 2019 batctl: Update copyright years for 2019 batman-adv: Update copyright years for 2019 -- 2.19.2