From patchwork Sat Sep 24 15:58:05 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sven Eckelmann X-Patchwork-Id: 16707 X-Patchwork-Delegate: mareklindner@neomailbox.ch 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 2C85282F91; Sat, 24 Sep 2016 17:58:52 +0200 (CEST) Authentication-Results: open-mesh.org; dmarc=none header.from=narfation.org Authentication-Results: open-mesh.org; dkim=fail reason="verification failed; unprotected key" header.d=narfation.org header.i=@narfation.org header.b=pLZ3IcBE; dkim-adsp=fail (unprotected policy); dkim-atps=neutral Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=79.140.41.39; helo=v3-1039.vlinux.de; envelope-from=sven@narfation.org; receiver=b.a.t.m.a.n@lists.open-mesh.org Authentication-Results: open-mesh.org; dmarc=pass header.from=narfation.org Received: from v3-1039.vlinux.de (narfation.org [79.140.41.39]) by open-mesh.org (Postfix) with ESMTPS id E294C82F1B for ; Sat, 24 Sep 2016 17:58:26 +0200 (CEST) Received: from sven-desktop.home.narfation.org (p200300C593C7D9F90000000000002E17.dip0.t-ipconnect.de [IPv6:2003:c5:93c7:d9f9::2e17]) by v3-1039.vlinux.de (Postfix) with ESMTPSA id 329791100CF; Sat, 24 Sep 2016 17:58:25 +0200 (CEST) Authentication-Results: v3-1039.vlinux.de; dmarc=none header.from=narfation.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=narfation.org; s=20121; t=1474732705; bh=38qAHxmi+ilrXq/DiWuLuWC5We9WMYBEAe2Mw0SgUOc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=pLZ3IcBEB0biVOQqIm+Ykapf9DZpO2UqPAhZAm1sXhyr4NsnkfdLFwt9MC7+d0+tN jJSKxobMfLzjcsmS5+RkgpM3evedt9HwrJpgd1UEBC1pjDl2cMI5xThWfmzJ9s8Nsm Ws1E79EXOAU17TVsG7SaGtGn3pZgjNDmRQ9BCGeg= From: Sven Eckelmann To: b.a.t.m.a.n@lists.open-mesh.org Date: Sat, 24 Sep 2016 17:58:05 +0200 Message-Id: <20160924155806.9115-6-sven@narfation.org> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20160924155806.9115-1-sven@narfation.org> References: <20160924155806.9115-1-sven@narfation.org> Subject: [B.A.T.M.A.N.] [PATCH v2 6/7] batctl: Move interface command to extra file X-BeenThere: b.a.t.m.a.n@lists.open-mesh.org X-Mailman-Version: 2.1.18 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 interface command has nothing to do anymore more with all the other configuration in sysfs. Thus all the "interface" command functions should be placed in a separate file. Signed-off-by: Sven Eckelmann --- v2: - rename "new" command to "create" as requested by Linus Luessing and John Harrison Makefile | 1 + functions.h | 2 + interface.c | 457 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ interface.h | 29 ++++ main.c | 1 + sys.c | 420 ------------------------------------------------------- sys.h | 1 - 7 files changed, 490 insertions(+), 421 deletions(-) create mode 100644 interface.c create mode 100644 interface.h diff --git a/Makefile b/Makefile index 0cec413..5dc8fe8 100755 --- a/Makefile +++ b/Makefile @@ -30,6 +30,7 @@ OBJ += debug.o OBJ += functions.o OBJ += genl.o OBJ += hash.o +OBJ += interface.o OBJ += ioctl.o OBJ += list-batman.o OBJ += main.o diff --git a/functions.h b/functions.h index 7757731..4c350f8 100644 --- a/functions.h +++ b/functions.h @@ -31,6 +31,8 @@ #define ETH_STR_LEN 17 #define BATMAN_ADV_TAG "batman-adv:" +#define PATH_BUFF_LEN 200 + /* return time delta from start to end in milliseconds */ void start_timer(void); double end_timer(void); diff --git a/interface.c b/interface.c new file mode 100644 index 0000000..9d5590d --- /dev/null +++ b/interface.c @@ -0,0 +1,457 @@ +/* + * Copyright (C) 2009-2016 B.A.T.M.A.N. contributors: + * + * Marek Lindner + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "interface.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "main.h" +#include "sys.h" +#include "functions.h" + +static void interface_usage(void) +{ + fprintf(stderr, "Usage: batctl [options] interface [parameters] [add|del iface(s)]\n"); + fprintf(stderr, " batctl [options] interface [parameters] [create|destroy]\n"); + fprintf(stderr, "parameters:\n"); + fprintf(stderr, " \t -M disable automatic creation/removal of batman-adv interface\n"); + fprintf(stderr, " \t -h print this help\n"); +} + +static struct nla_policy link_policy[IFLA_MAX + 1] = { + [IFLA_IFNAME] = { .type = NLA_STRING, .maxlen = IFNAMSIZ }, + [IFLA_MASTER] = { .type = NLA_U32 }, +}; + +struct print_interfaces_rtnl_arg { + int ifindex; +}; + +static int print_interfaces_rtnl_parse(struct nl_msg *msg, void *arg) +{ + struct print_interfaces_rtnl_arg *print_arg = arg; + struct nlattr *attrs[IFLA_MAX + 1]; + char path_buff[PATH_BUFF_LEN]; + struct ifinfomsg *ifm; + char *ifname; + int ret; + const char *status; + int master; + + ifm = nlmsg_data(nlmsg_hdr(msg)); + ret = nlmsg_parse(nlmsg_hdr(msg), sizeof(*ifm), attrs, IFLA_MAX, + link_policy); + if (ret < 0) + goto err; + + if (!attrs[IFLA_IFNAME]) + goto err; + + if (!attrs[IFLA_MASTER]) + goto err; + + ifname = nla_get_string(attrs[IFLA_IFNAME]); + master = nla_get_u32(attrs[IFLA_MASTER]); + + /* required on older kernels which don't prefilter the results */ + if (master != print_arg->ifindex) + goto err; + + 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"; + else + status = line_ptr; + + printf("%s: %s", ifname, status); + + free(line_ptr); + line_ptr = NULL; + +err: + return NL_OK; +} + +static int print_interfaces(char *mesh_iface) +{ + struct print_interfaces_rtnl_arg print_arg; + + if (!file_exists(module_ver_path)) { + fprintf(stderr, "Error - batman-adv module has not been loaded\n"); + return EXIT_FAILURE; + } + + print_arg.ifindex = if_nametoindex(mesh_iface); + if (!print_arg.ifindex) + return EXIT_FAILURE; + + query_rtnl_link(print_arg.ifindex, print_interfaces_rtnl_parse, + &print_arg); + + return EXIT_SUCCESS; +} + +struct count_interfaces_rtnl_arg { + int ifindex; + unsigned int count; +}; + +static int count_interfaces_rtnl_parse(struct nl_msg *msg, void *arg) +{ + struct count_interfaces_rtnl_arg *count_arg = arg; + struct nlattr *attrs[IFLA_MAX + 1]; + struct ifinfomsg *ifm; + int ret; + int master; + + ifm = nlmsg_data(nlmsg_hdr(msg)); + ret = nlmsg_parse(nlmsg_hdr(msg), sizeof(*ifm), attrs, IFLA_MAX, + link_policy); + if (ret < 0) + goto err; + + if (!attrs[IFLA_IFNAME]) + goto err; + + if (!attrs[IFLA_MASTER]) + goto err; + + master = nla_get_u32(attrs[IFLA_MASTER]); + + /* required on older kernels which don't prefilter the results */ + if (master != count_arg->ifindex) + goto err; + + count_arg->count++; + +err: + return NL_OK; +} + +static unsigned int count_interfaces(char *mesh_iface) +{ + struct count_interfaces_rtnl_arg count_arg; + + count_arg.count = 0; + count_arg.ifindex = if_nametoindex(mesh_iface); + if (!count_arg.ifindex) + return 0; + + query_rtnl_link(count_arg.ifindex, count_interfaces_rtnl_parse, + &count_arg); + + return count_arg.count; +} + +static int create_interface(const char *mesh_iface) +{ + struct ifinfomsg rt_hdr = { + .ifi_family = IFLA_UNSPEC, + }; + struct nlattr *linkinfo; + struct nl_msg *msg; + int err = 0; + int ret; + + msg = nlmsg_alloc_simple(RTM_NEWLINK, + NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK); + if (!msg) { + return -ENOMEM; + } + + ret = nlmsg_append(msg, &rt_hdr, sizeof(rt_hdr), NLMSG_ALIGNTO); + if (ret < 0) { + err = -ENOMEM; + goto err_free_msg; + } + + ret = nla_put_string(msg, IFLA_IFNAME, mesh_iface); + if (ret < 0) { + err = -ENOMEM; + goto err_free_msg; + } + + linkinfo = nla_nest_start(msg, IFLA_LINKINFO); + if (!linkinfo) { + err = -ENOMEM; + goto err_free_msg; + } + + ret = nla_put_string(msg, IFLA_INFO_KIND, "batadv"); + if (ret < 0) { + err = -ENOMEM; + goto err_free_msg; + } + + nla_nest_end(msg, linkinfo); + + err = netlink_simple_request(msg); + +err_free_msg: + nlmsg_free(msg); + + return err; +} + +static int destroy_interface(const char *mesh_iface) +{ + struct ifinfomsg rt_hdr = { + .ifi_family = IFLA_UNSPEC, + }; + struct nl_msg *msg; + int err = 0; + int ret; + + msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST | NLM_F_ACK); + if (!msg) { + return -ENOMEM; + } + + ret = nlmsg_append(msg, &rt_hdr, sizeof(rt_hdr), NLMSG_ALIGNTO); + if (ret < 0) { + err = -ENOMEM; + goto err_free_msg; + } + + ret = nla_put_string(msg, IFLA_IFNAME, mesh_iface); + if (ret < 0) { + err = -ENOMEM; + goto err_free_msg; + } + + err = netlink_simple_request(msg); + +err_free_msg: + nlmsg_free(msg); + + return err; +} + +static int set_master_interface(const char *iface, unsigned int ifmaster) +{ + struct ifinfomsg rt_hdr = { + .ifi_family = IFLA_UNSPEC, + }; + struct nl_msg *msg; + int err = 0; + int ret; + + msg = nlmsg_alloc_simple(RTM_SETLINK, NLM_F_REQUEST | NLM_F_ACK); + if (!msg) { + return -ENOMEM; + } + + ret = nlmsg_append(msg, &rt_hdr, sizeof(rt_hdr), NLMSG_ALIGNTO); + if (ret < 0) { + err = -ENOMEM; + goto err_free_msg; + } + + ret = nla_put_string(msg, IFLA_IFNAME, iface); + if (ret < 0) { + err = -ENOMEM; + goto err_free_msg; + } + + ret = nla_put_u32(msg, IFLA_MASTER, ifmaster); + if (ret < 0) { + err = -ENOMEM; + goto err_free_msg; + } + + err = netlink_simple_request(msg); + +err_free_msg: + nlmsg_free(msg); + + return err; +} + +int interface(char *mesh_iface, int argc, char **argv) +{ + int i, optchar; + int ret; + unsigned int ifindex; + unsigned int ifmaster; + const char *long_op; + unsigned int cnt; + int rest_argc; + char **rest_argv; + bool manual_mode = false; + + while ((optchar = getopt(argc, argv, "hM")) != -1) { + switch (optchar) { + case 'h': + interface_usage(); + return EXIT_SUCCESS; + case 'M': + manual_mode = true; + break; + default: + interface_usage(); + return EXIT_FAILURE; + } + } + + rest_argc = argc - optind; + rest_argv = &argv[optind]; + + if (rest_argc == 0) + return print_interfaces(mesh_iface); + + if ((strcmp(rest_argv[0], "add") != 0) && (strcmp(rest_argv[0], "a") != 0) && + (strcmp(rest_argv[0], "del") != 0) && (strcmp(rest_argv[0], "d") != 0) && + (strcmp(rest_argv[0], "create") != 0) && (strcmp(rest_argv[0], "c") != 0) && + (strcmp(rest_argv[0], "destroy") != 0) && (strcmp(rest_argv[0], "D") != 0)) { + fprintf(stderr, "Error - unknown argument specified: %s\n", rest_argv[0]); + interface_usage(); + goto err; + } + + if (strcmp(rest_argv[0], "destroy") == 0) + rest_argv[0][0] = 'D'; + + switch (rest_argv[0][0]) { + case 'a': + case 'd': + if (rest_argc == 1) { + fprintf(stderr, + "Error - missing interface name(s) after '%s'\n", + rest_argv[0]); + interface_usage(); + goto err; + } + break; + case 'c': + case 'D': + if (rest_argc != 1) { + fprintf(stderr, + "Error - extra parameter after '%s'\n", + rest_argv[0]); + interface_usage(); + goto err; + } + break; + default: + break; + } + + switch (rest_argv[0][0]) { + case 'c': + ret = create_interface(mesh_iface); + if (ret < 0) { + fprintf(stderr, + "Error - failed to add create batman-adv interface: %s\n", + strerror(-ret)); + goto err; + } + return EXIT_SUCCESS; + case 'D': + ret = destroy_interface(mesh_iface); + if (ret < 0) { + fprintf(stderr, + "Error - failed to destroy batman-adv interface: %s\n", + strerror(-ret)); + goto err; + } + return EXIT_SUCCESS; + default: + break; + } + + /* get index of batman-adv interface - or try to create it */ + ifmaster = if_nametoindex(mesh_iface); + if (!manual_mode && !ifmaster && rest_argv[0][0] == 'a') { + ret = create_interface(mesh_iface); + if (ret < 0) { + fprintf(stderr, + "Error - failed to create batman-adv interface: %s\n", + strerror(-ret)); + goto err; + } + + ifmaster = if_nametoindex(mesh_iface); + } + + if (!ifmaster) { + ret = -ENODEV; + fprintf(stderr, + "Error - failed to find batman-adv interface: %s\n", + strerror(-ret)); + goto err; + } + + /* make sure that batman-adv is loaded or was loaded by create_interface */ + if (!file_exists(module_ver_path)) { + fprintf(stderr, "Error - batman-adv module has not been loaded\n"); + goto err; + } + + for (i = 1; i < rest_argc; i++) { + ifindex = if_nametoindex(rest_argv[i]); + + if (!ifindex) { + fprintf(stderr, "Error - interface does not exist: %s\n", rest_argv[i]); + continue; + } + + if (rest_argv[0][0] == 'a') + ifindex = ifmaster; + else + ifindex = 0; + + ret = set_master_interface(rest_argv[i], ifindex); + if (ret < 0) { + if (rest_argv[0][0] == 'a') + long_op = "add"; + else + long_op = "delete"; + + fprintf(stderr, "Error - failed to %s interface %s: %s\n", + long_op, rest_argv[i], strerror(-ret)); + goto err; + } + } + + /* check if there is no interface left and then destroy mesh_iface */ + if (!manual_mode && rest_argv[0][0] == 'd') { + cnt = count_interfaces(mesh_iface); + if (cnt == 0) + destroy_interface(mesh_iface); + } + + return EXIT_SUCCESS; + +err: + return EXIT_FAILURE; +} diff --git a/interface.h b/interface.h new file mode 100644 index 0000000..0ea7bd5 --- /dev/null +++ b/interface.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2009-2016 B.A.T.M.A.N. contributors: + * + * Marek Lindner + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#ifndef _BATCTL_INTERFACE_H +#define _BATCTL_INTERFACE_H + +#include "main.h" + +int interface(char *mesh_iface, int argc, char **argv); + +#endif diff --git a/main.c b/main.c index 5e1ecc7..e67fc40 100644 --- a/main.c +++ b/main.c @@ -29,6 +29,7 @@ #include "main.h" #include "sys.h" #include "debug.h" +#include "interface.h" #include "ping.h" #include "translate.h" #include "traceroute.h" diff --git a/sys.c b/sys.c index 2cbccea..59cbdae 100644 --- a/sys.c +++ b/sys.c @@ -38,8 +38,6 @@ #include "functions.h" #include "debug.h" -#define PATH_BUFF_LEN 200 - const char *sysfs_param_enable[] = { "enable", "disable", @@ -118,424 +116,6 @@ const struct settings_data batctl_settings[BATCTL_SETTINGS_NUM] = { }, }; -static void interface_usage(void) -{ - fprintf(stderr, "Usage: batctl [options] interface [parameters] [add|del iface(s)]\n"); - fprintf(stderr, " batctl [options] interface [parameters] [create|destroy]\n"); - fprintf(stderr, "parameters:\n"); - fprintf(stderr, " \t -M disable automatic creation/removal of batman-adv interface\n"); - fprintf(stderr, " \t -h print this help\n"); -} - -static struct nla_policy link_policy[IFLA_MAX + 1] = { - [IFLA_IFNAME] = { .type = NLA_STRING, .maxlen = IFNAMSIZ }, - [IFLA_MASTER] = { .type = NLA_U32 }, -}; - -struct print_interfaces_rtnl_arg { - int ifindex; -}; - -static int print_interfaces_rtnl_parse(struct nl_msg *msg, void *arg) -{ - struct print_interfaces_rtnl_arg *print_arg = arg; - struct nlattr *attrs[IFLA_MAX + 1]; - char path_buff[PATH_BUFF_LEN]; - struct ifinfomsg *ifm; - char *ifname; - int ret; - const char *status; - int master; - - ifm = nlmsg_data(nlmsg_hdr(msg)); - ret = nlmsg_parse(nlmsg_hdr(msg), sizeof(*ifm), attrs, IFLA_MAX, - link_policy); - if (ret < 0) - goto err; - - if (!attrs[IFLA_IFNAME]) - goto err; - - if (!attrs[IFLA_MASTER]) - goto err; - - ifname = nla_get_string(attrs[IFLA_IFNAME]); - master = nla_get_u32(attrs[IFLA_MASTER]); - - /* required on older kernels which don't prefilter the results */ - if (master != print_arg->ifindex) - goto err; - - 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"; - else - status = line_ptr; - - printf("%s: %s", ifname, status); - - free(line_ptr); - line_ptr = NULL; - -err: - return NL_OK; -} - -static int print_interfaces(char *mesh_iface) -{ - struct print_interfaces_rtnl_arg print_arg; - - if (!file_exists(module_ver_path)) { - fprintf(stderr, "Error - batman-adv module has not been loaded\n"); - return EXIT_FAILURE; - } - - print_arg.ifindex = if_nametoindex(mesh_iface); - if (!print_arg.ifindex) - return EXIT_FAILURE; - - query_rtnl_link(print_arg.ifindex, print_interfaces_rtnl_parse, - &print_arg); - - return EXIT_SUCCESS; -} - -struct count_interfaces_rtnl_arg { - int ifindex; - unsigned int count; -}; - -static int count_interfaces_rtnl_parse(struct nl_msg *msg, void *arg) -{ - struct count_interfaces_rtnl_arg *count_arg = arg; - struct nlattr *attrs[IFLA_MAX + 1]; - struct ifinfomsg *ifm; - int ret; - int master; - - ifm = nlmsg_data(nlmsg_hdr(msg)); - ret = nlmsg_parse(nlmsg_hdr(msg), sizeof(*ifm), attrs, IFLA_MAX, - link_policy); - if (ret < 0) - goto err; - - if (!attrs[IFLA_IFNAME]) - goto err; - - if (!attrs[IFLA_MASTER]) - goto err; - - master = nla_get_u32(attrs[IFLA_MASTER]); - - /* required on older kernels which don't prefilter the results */ - if (master != count_arg->ifindex) - goto err; - - count_arg->count++; - -err: - return NL_OK; -} - -static unsigned int count_interfaces(char *mesh_iface) -{ - struct count_interfaces_rtnl_arg count_arg; - - count_arg.count = 0; - count_arg.ifindex = if_nametoindex(mesh_iface); - if (!count_arg.ifindex) - return 0; - - query_rtnl_link(count_arg.ifindex, count_interfaces_rtnl_parse, - &count_arg); - - return count_arg.count; -} - -static int create_interface(const char *mesh_iface) -{ - struct ifinfomsg rt_hdr = { - .ifi_family = IFLA_UNSPEC, - }; - struct nlattr *linkinfo; - struct nl_msg *msg; - int err = 0; - int ret; - - msg = nlmsg_alloc_simple(RTM_NEWLINK, - NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK); - if (!msg) { - return -ENOMEM; - } - - ret = nlmsg_append(msg, &rt_hdr, sizeof(rt_hdr), NLMSG_ALIGNTO); - if (ret < 0) { - err = -ENOMEM; - goto err_free_msg; - } - - ret = nla_put_string(msg, IFLA_IFNAME, mesh_iface); - if (ret < 0) { - err = -ENOMEM; - goto err_free_msg; - } - - linkinfo = nla_nest_start(msg, IFLA_LINKINFO); - if (!linkinfo) { - err = -ENOMEM; - goto err_free_msg; - } - - ret = nla_put_string(msg, IFLA_INFO_KIND, "batadv"); - if (ret < 0) { - err = -ENOMEM; - goto err_free_msg; - } - - nla_nest_end(msg, linkinfo); - - err = netlink_simple_request(msg); - -err_free_msg: - nlmsg_free(msg); - - return err; -} - -static int destroy_interface(const char *mesh_iface) -{ - struct ifinfomsg rt_hdr = { - .ifi_family = IFLA_UNSPEC, - }; - struct nl_msg *msg; - int err = 0; - int ret; - - msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST | NLM_F_ACK); - if (!msg) { - return -ENOMEM; - } - - ret = nlmsg_append(msg, &rt_hdr, sizeof(rt_hdr), NLMSG_ALIGNTO); - if (ret < 0) { - err = -ENOMEM; - goto err_free_msg; - } - - ret = nla_put_string(msg, IFLA_IFNAME, mesh_iface); - if (ret < 0) { - err = -ENOMEM; - goto err_free_msg; - } - - err = netlink_simple_request(msg); - -err_free_msg: - nlmsg_free(msg); - - return err; -} - -static int set_master_interface(const char *iface, unsigned int ifmaster) -{ - struct ifinfomsg rt_hdr = { - .ifi_family = IFLA_UNSPEC, - }; - struct nl_msg *msg; - int err = 0; - int ret; - - msg = nlmsg_alloc_simple(RTM_SETLINK, NLM_F_REQUEST | NLM_F_ACK); - if (!msg) { - return -ENOMEM; - } - - ret = nlmsg_append(msg, &rt_hdr, sizeof(rt_hdr), NLMSG_ALIGNTO); - if (ret < 0) { - err = -ENOMEM; - goto err_free_msg; - } - - ret = nla_put_string(msg, IFLA_IFNAME, iface); - if (ret < 0) { - err = -ENOMEM; - goto err_free_msg; - } - - ret = nla_put_u32(msg, IFLA_MASTER, ifmaster); - if (ret < 0) { - err = -ENOMEM; - goto err_free_msg; - } - - err = netlink_simple_request(msg); - -err_free_msg: - nlmsg_free(msg); - - return err; -} - -int interface(char *mesh_iface, int argc, char **argv) -{ - int i, optchar; - int ret; - unsigned int ifindex; - unsigned int ifmaster; - const char *long_op; - unsigned int cnt; - int rest_argc; - char **rest_argv; - bool manual_mode = false; - - while ((optchar = getopt(argc, argv, "hM")) != -1) { - switch (optchar) { - case 'h': - interface_usage(); - return EXIT_SUCCESS; - case 'M': - manual_mode = true; - break; - default: - interface_usage(); - return EXIT_FAILURE; - } - } - - rest_argc = argc - optind; - rest_argv = &argv[optind]; - - if (rest_argc == 0) - return print_interfaces(mesh_iface); - - if ((strcmp(rest_argv[0], "add") != 0) && (strcmp(rest_argv[0], "a") != 0) && - (strcmp(rest_argv[0], "del") != 0) && (strcmp(rest_argv[0], "d") != 0) && - (strcmp(rest_argv[0], "create") != 0) && (strcmp(rest_argv[0], "c") != 0) && - (strcmp(rest_argv[0], "destroy") != 0) && (strcmp(rest_argv[0], "D") != 0)) { - fprintf(stderr, "Error - unknown argument specified: %s\n", rest_argv[0]); - interface_usage(); - goto err; - } - - if (strcmp(rest_argv[0], "destroy") == 0) - rest_argv[0][0] = 'D'; - - switch (rest_argv[0][0]) { - case 'a': - case 'd': - if (rest_argc == 1) { - fprintf(stderr, - "Error - missing interface name(s) after '%s'\n", - rest_argv[0]); - interface_usage(); - goto err; - } - break; - case 'c': - case 'D': - if (rest_argc != 1) { - fprintf(stderr, - "Error - extra parameter after '%s'\n", - rest_argv[0]); - interface_usage(); - goto err; - } - break; - default: - break; - } - - switch (rest_argv[0][0]) { - case 'c': - ret = create_interface(mesh_iface); - if (ret < 0) { - fprintf(stderr, - "Error - failed to create batman-adv interface: %s\n", - strerror(-ret)); - goto err; - } - return EXIT_SUCCESS; - case 'D': - ret = destroy_interface(mesh_iface); - if (ret < 0) { - fprintf(stderr, - "Error - failed to destroy batman-adv interface: %s\n", - strerror(-ret)); - goto err; - } - return EXIT_SUCCESS; - default: - break; - } - - /* get index of batman-adv interface - or try to create it */ - ifmaster = if_nametoindex(mesh_iface); - if (!manual_mode && !ifmaster && rest_argv[0][0] == 'a') { - ret = create_interface(mesh_iface); - if (ret < 0) { - fprintf(stderr, - "Error - failed to create batman-adv interface: %s\n", - strerror(-ret)); - goto err; - } - - ifmaster = if_nametoindex(mesh_iface); - } - - if (!ifmaster) { - ret = -ENODEV; - fprintf(stderr, - "Error - failed to find batman-adv interface: %s\n", - strerror(-ret)); - goto err; - } - - /* make sure that batman-adv is loaded or was loaded by create_interface */ - if (!file_exists(module_ver_path)) { - fprintf(stderr, "Error - batman-adv module has not been loaded\n"); - goto err; - } - - for (i = 1; i < rest_argc; i++) { - ifindex = if_nametoindex(rest_argv[i]); - - if (!ifindex) { - fprintf(stderr, "Error - interface does not exist: %s\n", rest_argv[i]); - continue; - } - - if (rest_argv[0][0] == 'a') - ifindex = ifmaster; - else - ifindex = 0; - - ret = set_master_interface(rest_argv[i], ifindex); - if (ret < 0) { - if (rest_argv[0][0] == 'a') - long_op = "add"; - else - long_op = "delete"; - - fprintf(stderr, "Error - failed to %s interface %s: %s\n", - long_op, rest_argv[i], strerror(-ret)); - goto err; - } - } - - /* check if there is no interface left and then destroy mesh_iface */ - if (!manual_mode && rest_argv[0][0] == 'd') { - cnt = count_interfaces(mesh_iface); - if (cnt == 0) - destroy_interface(mesh_iface); - } - - return EXIT_SUCCESS; - -err: - return EXIT_FAILURE; -} - static void log_level_usage(void) { fprintf(stderr, "Usage: batctl [options] loglevel [parameters] [level[ level[ level]]...]\n"); diff --git a/sys.h b/sys.h index da2769d..be9480e 100644 --- a/sys.h +++ b/sys.h @@ -70,7 +70,6 @@ extern const char *sysfs_param_enable[]; extern const char *sysfs_param_server[]; extern const struct settings_data batctl_settings[BATCTL_SETTINGS_NUM]; -int interface(char *mesh_iface, int argc, char **argv); int handle_loglevel(char *mesh_iface, int argc, char **argv); int handle_sys_setting(char *mesh_iface, int setting, int argc, char **argv); int handle_gw_setting(char *mesh_iface, int argc, char **argv);