From patchwork Wed Apr 3 18:01:17 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sven Eckelmann X-Patchwork-Id: 17877 X-Patchwork-Delegate: sw@simonwunderlich.de Return-Path: X-Original-To: patchwork@open-mesh.org Delivered-To: patchwork@open-mesh.org Received: from open-mesh.org (localhost [IPv6:::1]) by open-mesh.org (Postfix) with ESMTP id 620F48252A; Wed, 3 Apr 2019 20:01:34 +0200 (CEST) Authentication-Results: open-mesh.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=narfation.org header.i=@narfation.org header.b="A1LAMj8x"; dkim-atps=neutral Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=2001:4d88:2000:7::2; helo=v3-1039.vlinux.de; envelope-from=sven@narfation.org; receiver= Received: from v3-1039.vlinux.de (narfation.org [IPv6:2001:4d88:2000:7::2]) by open-mesh.org (Postfix) with ESMTPS id 057BF82528 for ; Wed, 3 Apr 2019 20:01:31 +0200 (CEST) Received: from sven-desktop.home.narfation.org (unknown [IPv6:2a00:1ca0:1480:f1fc::4065]) by v3-1039.vlinux.de (Postfix) with ESMTPSA id E49731100DA; Wed, 3 Apr 2019 20:01:30 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=narfation.org; s=20121; t=1554314491; bh=5x4zmamrZPAnv/cxOP1M44GzykVEl/hhiueFFnBwQpk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=A1LAMj8x2H0N+RqdffoclzlXaG8FVzVv+NyDHD2wwnXMsyjKe5ys1CFtLduVBnHPs FQAsPsEmRmbHSEDBMytCLgbdUnhBjGMeeOoy/UfPPWlvQe5YlBawPPMKE2Na4nkMmr H/ku3tD5wfHeaF1lat3e++xjF7A2U/aL5v659ZJ8= From: Sven Eckelmann To: b.a.t.m.a.n@lists.open-mesh.org Date: Wed, 3 Apr 2019 20:01:17 +0200 Message-Id: <20190403180119.26800-2-sven@narfation.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190403180119.26800-1-sven@narfation.org> References: <20190403180119.26800-1-sven@narfation.org> MIME-Version: 1.0 Subject: [B.A.T.M.A.N.] [PATCH 1/3] batctl: Support checking of meshif without sysfs X-BeenThere: b.a.t.m.a.n@lists.open-mesh.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: The list for a Better Approach To Mobile Ad-hoc Networking List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: The list for a Better Approach To Mobile Ad-hoc Networking Errors-To: b.a.t.m.a.n-bounces@lists.open-mesh.org Sender: "B.A.T.M.A.N" batctl checks whether the supplied interface is a batadv interface. And for hardif filters, whether this hardif is part of the selected meshif. This was done traditionally using the sysfs files which batman-adv creates. It is now possible to build the kernel module without sysfs support. These checks must therefore also work when sysfs is not available. And since the sysfs interface support was replaced in batctl by netlink commands, the check should also be implemented using using NETLINK_ROUTE. Signed-off-by: Sven Eckelmann --- debug.c | 2 +- functions.c | 192 +++++++++++++++++++++++++++++++++++++++++++++++----- functions.h | 2 +- 3 files changed, 176 insertions(+), 20 deletions(-) diff --git a/debug.c b/debug.c index 4a3b6cb..597d59c 100644 --- a/debug.c +++ b/debug.c @@ -115,7 +115,7 @@ int handle_debug_table(struct state *state, int argc, char **argv) return EXIT_FAILURE; } - if (check_mesh_iface_ownership(state->mesh_iface, optarg) != EXIT_SUCCESS) + if (check_mesh_iface_ownership(state, optarg) != EXIT_SUCCESS) return EXIT_FAILURE; orig_iface = optarg; diff --git a/functions.c b/functions.c index 9720257..b52db08 100644 --- a/functions.c +++ b/functions.c @@ -1039,37 +1039,178 @@ int translate_mesh_iface(struct state *state) return 0; } -int check_mesh_iface(struct state *state) +struct rtnl_link_iface_data { + uint8_t kind_found:1; + uint8_t master_found:1; + char kind[IF_NAMESIZE]; + unsigned int master; +}; + +static int query_rtnl_link_single_parse(struct nl_msg *msg, void *arg) +{ + static struct nla_policy link_policy[IFLA_MAX + 1] = { + [IFLA_LINKINFO] = { .type = NLA_NESTED }, + [IFLA_MASTER] = { .type = NLA_U32 }, + }; + static struct nla_policy link_info_policy[IFLA_INFO_MAX + 1] = { + [IFLA_INFO_KIND] = { .type = NLA_STRING }, + }; + + struct rtnl_link_iface_data *link_data = arg; + struct nlattr *li[IFLA_INFO_MAX + 1]; + struct nlmsghdr *n = nlmsg_hdr(msg); + struct nlattr *tb[IFLA_MAX + 1]; + char *type; + int ret; + + if (!nlmsg_valid_hdr(n, sizeof(struct ifinfomsg))) + return NL_OK; + + ret = nlmsg_parse(n, sizeof(struct ifinfomsg), tb, IFLA_MAX, + link_policy); + if (ret < 0) + return NL_OK; + + if (tb[IFLA_MASTER]) { + link_data->master = nla_get_u32(tb[IFLA_MASTER]); + link_data->master_found = true; + } + + /* parse subattributes linkinfo */ + if (!tb[IFLA_LINKINFO]) + return NL_OK; + + ret = nla_parse_nested(li, IFLA_INFO_MAX, tb[IFLA_LINKINFO], + link_info_policy); + if (ret < 0) + return NL_OK; + + if (li[IFLA_INFO_KIND]) { + type = nla_get_string(li[IFLA_INFO_KIND]); + strncpy(link_data->kind, type, sizeof(link_data->kind)); + link_data->kind[sizeof(link_data->kind) - 1] = '\0'; + + link_data->kind_found = true; + } + + return NL_STOP; +} + +static int query_rtnl_link_single(int mesh_ifindex, + struct rtnl_link_iface_data *link_data) +{ + struct ifinfomsg ifinfo = { + .ifi_family = AF_UNSPEC, + .ifi_index = mesh_ifindex, + }; + struct nl_cb *cb = NULL; + struct nl_sock *sock; + int ret; + + link_data->kind_found = false; + link_data->master_found = false; + + sock = nl_socket_alloc(); + if (!sock) + return -1; + + ret = nl_connect(sock, NETLINK_ROUTE); + if (ret < 0) + goto free_sock; + + ret = nl_send_simple(sock, RTM_GETLINK, NLM_F_REQUEST, + &ifinfo, sizeof(ifinfo)); + if (ret < 0) + goto free_sock; + + cb = nl_cb_alloc(NL_CB_DEFAULT); + if (!cb) + goto free_sock; + + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, query_rtnl_link_single_parse, + link_data); + nl_recvmsgs(sock, cb); + + nl_cb_put(cb); +free_sock: + nl_socket_free(sock); + + return 0; +} + +int check_mesh_iface_netlink(struct state *state) +{ + struct rtnl_link_iface_data link_data; + + query_rtnl_link_single(state->mesh_ifindex, &link_data); + if (!link_data.kind_found) + return -1; + + if (strcmp(link_data.kind, "batadv") != 0) + return -1; + + return 0; +} + +static int check_mesh_iface_sysfs(struct state *state) { char path_buff[PATH_BUFF_LEN]; - int ret = -1; DIR *dir; - /* use the parent interface if this is a VLAN */ - 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); - /* try to open the mesh sys directory */ + snprintf(path_buff, PATH_BUFF_LEN, SYS_BATIF_PATH_FMT, + state->mesh_iface); + dir = opendir(path_buff); if (!dir) - goto out; + return -1; closedir(dir); + return 0; +} + +int check_mesh_iface(struct state *state) +{ + int ret; + state->mesh_ifindex = if_nametoindex(state->mesh_iface); if (state->mesh_ifindex == 0) - goto out; + return -1; - ret = 0; -out: - return ret; + ret = check_mesh_iface_netlink(state); + if (ret == 0) + return ret; + + ret = check_mesh_iface_sysfs(state); + if (ret == 0) + return ret; + + return -1; } -int check_mesh_iface_ownership(char *mesh_iface, char *hard_iface) +static int check_mesh_iface_ownership_netlink(struct state *state, + char *hard_iface) +{ + struct rtnl_link_iface_data link_data; + unsigned int hardif_index; + + hardif_index = if_nametoindex(hard_iface); + if (hardif_index == 0) + return EXIT_FAILURE; + + query_rtnl_link_single(hardif_index, &link_data); + if (!link_data.master_found) + return EXIT_FAILURE; + + if (state->mesh_ifindex != link_data.master) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} + +static int check_mesh_iface_ownership_sysfs(struct state *state, + char *hard_iface) { char path_buff[PATH_BUFF_LEN]; int res; @@ -1087,15 +1228,30 @@ int check_mesh_iface_ownership(char *mesh_iface, char *hard_iface) if (line_ptr[strlen(line_ptr) - 1] == '\n') line_ptr[strlen(line_ptr) - 1] = '\0'; - if (strcmp(line_ptr, mesh_iface) != 0) { + if (strcmp(line_ptr, state->mesh_iface) != 0) { fprintf(stderr, "Error - interface %s is part of batman network %s, not %s\n", - hard_iface, line_ptr, mesh_iface); + hard_iface, line_ptr, state->mesh_iface); return EXIT_FAILURE; } return EXIT_SUCCESS; } +int check_mesh_iface_ownership(struct state *state, char *hard_iface) +{ + int ret; + + ret = check_mesh_iface_ownership_netlink(state, hard_iface); + if (ret == EXIT_SUCCESS) + return EXIT_SUCCESS; + + ret = check_mesh_iface_ownership_sysfs(state, hard_iface); + if (ret == EXIT_SUCCESS) + return ret; + + return EXIT_FAILURE; +} + static int get_random_bytes_syscall(void *buf __maybe_unused, size_t buflen __maybe_unused) { diff --git a/functions.h b/functions.h index 23186e5..02f7823 100644 --- a/functions.h +++ b/functions.h @@ -53,7 +53,7 @@ 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); +int check_mesh_iface_ownership(struct state *state, char *hard_iface); void get_random_bytes(void *buf, size_t buflen); void check_root_or_die(const char *cmd); From patchwork Wed Apr 3 18:01:18 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sven Eckelmann X-Patchwork-Id: 17878 X-Patchwork-Delegate: sw@simonwunderlich.de Return-Path: X-Original-To: patchwork@open-mesh.org Delivered-To: patchwork@open-mesh.org Received: from open-mesh.org (localhost [IPv6:::1]) by open-mesh.org (Postfix) with ESMTP id D68DC82540; Wed, 3 Apr 2019 20:01:38 +0200 (CEST) Authentication-Results: open-mesh.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=narfation.org header.i=@narfation.org header.b="OM1dV5fB"; dkim-atps=neutral Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=79.140.41.39; helo=v3-1039.vlinux.de; envelope-from=sven@narfation.org; receiver= Received: from v3-1039.vlinux.de (narfation.org [79.140.41.39]) by open-mesh.org (Postfix) with ESMTPS id 3A54B82538 for ; Wed, 3 Apr 2019 20:01:36 +0200 (CEST) Received: from sven-desktop.home.narfation.org (unknown [IPv6:2a00:1ca0:1480:f1fc::4065]) by v3-1039.vlinux.de (Postfix) with ESMTPSA id 132291100DA; Wed, 3 Apr 2019 20:01:35 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=narfation.org; s=20121; t=1554314495; bh=yGNI9mGWuo4um10TPO1sYisIYazzcobgS1ta/i6P/3E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=OM1dV5fBRbWRdUnavS8r7C7Sz8qeY0vmqnew1Ta7GNLEciS0AGvw6TOsz/GSDIoCX t8jmQgsYA2BHRVH6p9bxk2bzXLuVx+ZLqeqp0vnKx83b+bxJCAQR/18cMtgKSZt3I/ nHE1BcfWQwzqWT1o4vNRNUcv/jS0piWXe+niVNrU= From: Sven Eckelmann To: b.a.t.m.a.n@lists.open-mesh.org Date: Wed, 3 Apr 2019 20:01:18 +0200 Message-Id: <20190403180119.26800-3-sven@narfation.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190403180119.26800-1-sven@narfation.org> References: <20190403180119.26800-1-sven@narfation.org> MIME-Version: 1.0 Subject: [B.A.T.M.A.N.] [PATCH 2/3] batctl: Reimplement VLAN translation using helper X-BeenThere: b.a.t.m.a.n@lists.open-mesh.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: The list for a Better Approach To Mobile Ad-hoc Networking List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: The list for a Better Approach To Mobile Ad-hoc Networking Errors-To: b.a.t.m.a.n-bounces@lists.open-mesh.org Sender: "B.A.T.M.A.N" The functionality to translate VLAN interfaces to mesh interfaces and VID is using NETLINK_ROUTE like the query_rtnl_link_single helper function. Only minimal changes are required to also provide the link to the underlying device and the VID. Signed-off-by: Sven Eckelmann --- functions.c | 229 ++++++++++++++++------------------------------------ 1 file changed, 71 insertions(+), 158 deletions(-) diff --git a/functions.c b/functions.c index b52db08..bb7f517 100644 --- a/functions.c +++ b/functions.c @@ -760,149 +760,6 @@ struct ether_addr *resolve_mac(const char *asc) return mac_result; } -struct vlan_get_link_nl_arg { - char *iface; - int vid; -}; - -static struct nla_policy info_data_link_policy[IFLA_MAX + 1] = { - [IFLA_LINKINFO] = { .type = NLA_NESTED }, - [IFLA_LINK] = { .type = NLA_U32 }, -}; - -static struct nla_policy info_data_link_info_policy[IFLA_INFO_MAX + 1] = { - [IFLA_INFO_DATA] = { .type = NLA_NESTED }, -}; - -static struct nla_policy vlan_policy[IFLA_VLAN_MAX + 1] = { - [IFLA_VLAN_ID] = { .type = NLA_U16 }, -}; - -/** - * vlan_get_link_parse - parse a get_link rtnl message and extract the important - * data - * @msg: the reply msg - * @arg: pointer to the buffer which will store the return values - * - * Saves the vid in arg::vid in case of success or -1 otherwise - */ -static int vlan_get_link_parse(struct nl_msg *msg, void *arg) -{ - struct vlan_get_link_nl_arg *nl_arg = arg; - struct nlmsghdr *n = nlmsg_hdr(msg); - struct nlattr *tb[IFLA_MAX + 1]; - struct nlattr *li[IFLA_INFO_MAX + 1]; - struct nlattr *vi[IFLA_VLAN_MAX + 1]; - int ret; - int idx; - - if (!nlmsg_valid_hdr(n, sizeof(struct ifinfomsg))) - return -NLE_MSG_TOOSHORT; - - ret = nlmsg_parse(n, sizeof(struct ifinfomsg), tb, IFLA_MAX, - info_data_link_policy); - if (ret < 0) - return ret; - - if (!tb[IFLA_LINK]) - return -NLE_MISSING_ATTR; - - /* parse subattributes linkinfo */ - if (!tb[IFLA_LINKINFO]) - return -NLE_MISSING_ATTR; - - ret = nla_parse_nested(li, IFLA_INFO_MAX, tb[IFLA_LINKINFO], - info_data_link_info_policy); - if (ret < 0) - return ret; - - if (!li[IFLA_INFO_KIND]) - return -NLE_MISSING_ATTR; - - if (strcmp(nla_data(li[IFLA_INFO_KIND]), "vlan") != 0) - goto err; - - /* parse subattributes info_data for vlan */ - if (!li[IFLA_INFO_DATA]) - return -NLE_MISSING_ATTR; - - ret = nla_parse_nested(vi, IFLA_VLAN_MAX, li[IFLA_INFO_DATA], - vlan_policy); - if (ret < 0) - return ret; - - if (!vi[IFLA_VLAN_ID]) - return -NLE_MISSING_ATTR; - - /* get parent link name */ - idx = *(int *)nla_data(tb[IFLA_LINK]); - - if (!if_indextoname(idx, nl_arg->iface)) - goto err; - - /* get the corresponding vid */ - nl_arg->vid = *(int *)nla_data(vi[IFLA_VLAN_ID]); - -err: - if (nl_arg->vid >= 0) - return NL_STOP; - else - return NL_OK; -} - -/** - * 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 - * (minimum IF_NAMESIZE) - * - * Returns the vlan identifier on success or -1 on error - */ -static int vlan_get_link(const char *ifname, char *parent) -{ - struct nl_sock *sock; - int ret; - struct ifinfomsg ifinfo = { - .ifi_family = AF_UNSPEC, - .ifi_index = if_nametoindex(ifname), - }; - struct nl_cb *cb = NULL; - struct vlan_get_link_nl_arg arg = { - .iface = parent, - .vid = -1, - }; - - sock = nl_socket_alloc(); - if (!sock) - goto err; - - ret = nl_connect(sock, NETLINK_ROUTE); - if (ret < 0) - goto err; - - ret = nl_send_simple(sock, RTM_GETLINK, NLM_F_REQUEST, - &ifinfo, sizeof(ifinfo)); - if (ret < 0) - goto err; - - cb = nl_cb_alloc(NL_CB_DEFAULT); - if (!cb) - goto err; - - nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, vlan_get_link_parse, &arg); - ret = nl_recvmsgs(sock, cb); - if (ret < 0) - goto err; - -err: - if (cb) - nl_cb_put(cb); - if (sock) - nl_socket_free(sock); - - return arg.vid; -} - int query_rtnl_link(int ifindex, nl_recvmsg_msg_cb_t func, void *arg) { struct ifinfomsg rt_hdr = { @@ -1025,25 +882,15 @@ int netlink_simple_request(struct nl_msg *msg) return err; } -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; -} - struct rtnl_link_iface_data { uint8_t kind_found:1; uint8_t master_found:1; + uint8_t link_found:1; + uint8_t vid_found:1; char kind[IF_NAMESIZE]; unsigned int master; + unsigned int link; + uint16_t vid; }; static int query_rtnl_link_single_parse(struct nl_msg *msg, void *arg) @@ -1051,13 +898,19 @@ static int query_rtnl_link_single_parse(struct nl_msg *msg, void *arg) static struct nla_policy link_policy[IFLA_MAX + 1] = { [IFLA_LINKINFO] = { .type = NLA_NESTED }, [IFLA_MASTER] = { .type = NLA_U32 }, + [IFLA_LINK] = { .type = NLA_U32 }, }; static struct nla_policy link_info_policy[IFLA_INFO_MAX + 1] = { [IFLA_INFO_KIND] = { .type = NLA_STRING }, + [IFLA_INFO_DATA] = { .type = NLA_NESTED }, + }; + static struct nla_policy vlan_policy[IFLA_VLAN_MAX + 1] = { + [IFLA_VLAN_ID] = { .type = NLA_U16 }, }; struct rtnl_link_iface_data *link_data = arg; struct nlattr *li[IFLA_INFO_MAX + 1]; + struct nlattr *vi[IFLA_VLAN_MAX + 1]; struct nlmsghdr *n = nlmsg_hdr(msg); struct nlattr *tb[IFLA_MAX + 1]; char *type; @@ -1076,6 +929,11 @@ static int query_rtnl_link_single_parse(struct nl_msg *msg, void *arg) link_data->master_found = true; } + if (tb[IFLA_LINK]) { + link_data->link = nla_get_u32(tb[IFLA_LINK]); + link_data->link_found = true; + } + /* parse subattributes linkinfo */ if (!tb[IFLA_LINKINFO]) return NL_OK; @@ -1093,6 +951,19 @@ static int query_rtnl_link_single_parse(struct nl_msg *msg, void *arg) link_data->kind_found = true; } + if (!li[IFLA_INFO_DATA]) + return NL_OK; + + ret = nla_parse_nested(vi, IFLA_VLAN_MAX, li[IFLA_INFO_DATA], + vlan_policy); + if (ret < 0) + return NL_OK; + + if (vi[IFLA_VLAN_ID]) { + link_data->vid = nla_get_u16(vi[IFLA_VLAN_ID]); + link_data->vid_found = true; + } + return NL_STOP; } @@ -1109,6 +980,8 @@ static int query_rtnl_link_single(int mesh_ifindex, link_data->kind_found = false; link_data->master_found = false; + link_data->link_found = false; + link_data->vid_found = false; sock = nl_socket_alloc(); if (!sock) @@ -1138,7 +1011,47 @@ static int query_rtnl_link_single(int mesh_ifindex, return 0; } -int check_mesh_iface_netlink(struct state *state) +int translate_mesh_iface(struct state *state) +{ + struct rtnl_link_iface_data link_data; + unsigned int arg_ifindex; + + arg_ifindex = if_nametoindex(state->arg_iface); + if (arg_ifindex == 0) + goto fallback_meshif; + + query_rtnl_link_single(arg_ifindex, &link_data); + if (!link_data.vid_found) + goto fallback_meshif; + + if (!link_data.link_found) + goto fallback_meshif; + + if (!link_data.kind_found) + goto fallback_meshif; + + if (strcmp(link_data.kind, "vlan") != 0) + goto fallback_meshif; + + if (!if_indextoname(link_data.link, state->mesh_iface)) + goto fallback_meshif; + + state->vid = link_data.vid; + + return 0; + +fallback_meshif: + /* if there is no vid then the argument must be the + * mesh interface + */ + snprintf(state->mesh_iface, sizeof(state->mesh_iface), "%s", + state->arg_iface); + state->vid = -1; + + return 0; +} + +static int check_mesh_iface_netlink(struct state *state) { struct rtnl_link_iface_data link_data; From patchwork Wed Apr 3 18:01:19 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sven Eckelmann X-Patchwork-Id: 17879 X-Patchwork-Delegate: sw@simonwunderlich.de Return-Path: X-Original-To: patchwork@open-mesh.org Delivered-To: patchwork@open-mesh.org Received: from open-mesh.org (localhost [IPv6:::1]) by open-mesh.org (Postfix) with ESMTP id A2F8F82550; Wed, 3 Apr 2019 20:01:42 +0200 (CEST) Authentication-Results: open-mesh.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=narfation.org header.i=@narfation.org header.b="HNYYJewd"; dkim-atps=neutral Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=2001:4d88:2000:7::2; helo=v3-1039.vlinux.de; envelope-from=sven@narfation.org; receiver= Received: from v3-1039.vlinux.de (narfation.org [IPv6:2001:4d88:2000:7::2]) by open-mesh.org (Postfix) with ESMTPS id 2C5398254A for ; Wed, 3 Apr 2019 20:01:40 +0200 (CEST) Received: from sven-desktop.home.narfation.org (unknown [IPv6:2a00:1ca0:1480:f1fc::4065]) by v3-1039.vlinux.de (Postfix) with ESMTPSA id 89CC01100DA; Wed, 3 Apr 2019 20:01:39 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=narfation.org; s=20121; t=1554314499; bh=RtT5taSXVCb/ZidrRUaNrBq/g5j6ddUYKW/CznW+nUE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HNYYJewdtoJDVPbjwrzpuxeY/7w7m5tStT/OhbczoT+uztKj5U/PRWjAWR3Qq5FXo aAuUfOXAa3w1RN9DNk6rLzglhhEpfnFQ99eGAs3+Un3TqDXmVmkfKKeZ1WusXNDLVg ZpNGHsn2Rs2oupoogsz6F1qypdyuJlFntYkbxAaU= From: Sven Eckelmann To: b.a.t.m.a.n@lists.open-mesh.org Date: Wed, 3 Apr 2019 20:01:19 +0200 Message-Id: <20190403180119.26800-4-sven@narfation.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190403180119.26800-1-sven@narfation.org> References: <20190403180119.26800-1-sven@narfation.org> MIME-Version: 1.0 Subject: [B.A.T.M.A.N.] [PATCH 3/3] batctl: Add netlink fallback for sysfs' iface_status X-BeenThere: b.a.t.m.a.n@lists.open-mesh.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: The list for a Better Approach To Mobile Ad-hoc Networking List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: The list for a Better Approach To Mobile Ad-hoc Networking Errors-To: b.a.t.m.a.n-bounces@lists.open-mesh.org Sender: "B.A.T.M.A.N" The batman-adv kernel module can now be compiled without support for sysfs. But the status of an interface in the list generated by `batctl interface` can only get the status via the per hardif sysfs file iface_status. To still have some information, fallback to BATADV_CMD_GET_HARDIF if the sysfs file is not available. Signed-off-by: Sven Eckelmann --- interface.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) diff --git a/interface.c b/interface.c index 667a308..630dd91 100644 --- a/interface.c +++ b/interface.c @@ -24,6 +24,8 @@ #include "sys.h" #include "functions.h" +#define IFACE_STATUS_LEN 256 + static void interface_usage(void) { fprintf(stderr, "Usage: batctl [options] interface [parameters] [add|del iface(s)]\n"); @@ -33,6 +35,92 @@ static void interface_usage(void) fprintf(stderr, " \t -h print this help\n"); } +static int get_iface_status_netlink_parse(struct nl_msg *msg, void *arg) +{ + + struct nlattr *attrs[NUM_BATADV_ATTR]; + struct nlmsghdr *nlh = nlmsg_hdr(msg); + char *iface_status = arg; + struct genlmsghdr *ghdr; + + if (!genlmsg_valid_hdr(nlh, 0)) + return NL_OK; + + ghdr = nlmsg_data(nlh); + if (ghdr->cmd != BATADV_CMD_GET_HARDIF) + return NL_OK; + + if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), + genlmsg_len(ghdr), batadv_netlink_policy)) + return NL_OK; + + if (attrs[BATADV_ATTR_ACTIVE]) + strncpy(iface_status, "active\n", IFACE_STATUS_LEN); + else + strncpy(iface_status, "inactive\n", IFACE_STATUS_LEN); + + iface_status[IFACE_STATUS_LEN - 1] = '\0'; + + return NL_STOP; +} + +static char *get_iface_status_netlink(unsigned int meshif, unsigned int hardif, + char *iface_status) +{ + struct nl_sock *sock; + struct nl_msg *msg; + int batadv_family; + struct nl_cb *cb; + int ret; + + strncpy(iface_status, "\n", IFACE_STATUS_LEN); + iface_status[IFACE_STATUS_LEN - 1] = '\0'; + + sock = nl_socket_alloc(); + if (!sock) + return iface_status; + + ret = genl_connect(sock); + if (ret < 0) + goto err_free_sock; + + batadv_family = genl_ctrl_resolve(sock, BATADV_NL_NAME); + if (ret < 0) + goto err_free_sock; + + cb = nl_cb_alloc(NL_CB_DEFAULT); + if (!cb) + goto err_free_sock; + + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, get_iface_status_netlink_parse, + iface_status); + + msg = nlmsg_alloc(); + if (!msg) + goto err_free_cb; + + genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, batadv_family, + 0, 0, BATADV_CMD_GET_HARDIF, 1); + + nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, meshif); + nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, hardif); + + ret = nl_send_auto_complete(sock, msg); + if (ret < 0) + goto err_free_msg; + + nl_recvmsgs(sock, cb); + +err_free_msg: + nlmsg_free(msg); +err_free_cb: + nl_cb_put(cb); +err_free_sock: + nl_socket_free(sock); + + return iface_status; +} + static struct nla_policy link_policy[IFLA_MAX + 1] = { [IFLA_IFNAME] = { .type = NLA_STRING, .maxlen = IFNAMSIZ }, [IFLA_MASTER] = { .type = NLA_U32 }, @@ -45,6 +133,7 @@ struct print_interfaces_rtnl_arg { static int print_interfaces_rtnl_parse(struct nl_msg *msg, void *arg) { struct print_interfaces_rtnl_arg *print_arg = arg; + char iface_status[IFACE_STATUS_LEN]; struct nlattr *attrs[IFLA_MAX + 1]; char path_buff[PATH_BUFF_LEN]; struct ifinfomsg *ifm; @@ -75,7 +164,8 @@ static int print_interfaces_rtnl_parse(struct nl_msg *msg, void *arg) snprintf(path_buff, sizeof(path_buff), SYS_IFACE_STATUS_FMT, ifname); ret = read_file("", path_buff, USE_READ_BUFF | SILENCE_ERRORS, 0, 0, 0); if (ret != EXIT_SUCCESS) - status = "\n"; + status = get_iface_status_netlink(master, ifm->ifi_index, + iface_status); else status = line_ptr;