From patchwork Wed Jul 13 15:30:17 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sven Eckelmann X-Patchwork-Id: 16506 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 2408C82643; Wed, 13 Jul 2016 17:30:36 +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=PKlu0tHo; 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 C7A16826FE for ; Wed, 13 Jul 2016 17:30:28 +0200 (CEST) Received: from sven-desktop.home.narfation.org (p2003007C6F04E6FED85BF65F15063EF0.dip0.t-ipconnect.de [IPv6:2003:7c:6f04:e6fe:d85b:f65f:1506:3ef0]) by v3-1039.vlinux.de (Postfix) with ESMTPSA id 4E3451100F1; Wed, 13 Jul 2016 17:30:28 +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=1468423828; bh=LGfp/7HbQDsymAj8qeC9NBxf8bioaeB5ACGrrwsqjts=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PKlu0tHo9gQuAlt6+Oilp1/7AG94hZSUQsBLmSZ5oIKhPLRea2ah76xapn2uhIvvH uggf+oLkKPfHDZGt/QNN57Hb/9KpHD45alsmwW9iiO4H2CP1uKQJPoq8PfrtYjPqjC v1VdrPw1oAMnOCN4ZQ048cnJOyidgpTzWNFswL2U= From: Sven Eckelmann To: b.a.t.m.a.n@lists.open-mesh.org Date: Wed, 13 Jul 2016 17:30:17 +0200 Message-Id: <1468423822-28324-2-git-send-email-sven@narfation.org> X-Mailer: git-send-email 2.8.1 In-Reply-To: <1468423822-28324-1-git-send-email-sven@narfation.org> References: <35819279.yt4EnXKmx6@bentobox> <1468423822-28324-1-git-send-email-sven@narfation.org> Subject: [B.A.T.M.A.N.] [PATCH 2/7] batctl: Add command to create/destroy batman-adv interface 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 command "new" can be used to create a batman-adv interface without any interface attached. This is helpful when the interfaces should be configured independently of the first attached interface. The command "destroy" can be used to destroy a batman-adv interface without going through all attached interfaces and delete them manually. Signed-off-by: Sven Eckelmann --- functions.c | 58 ++++++++++++++++++++++++ functions.h | 1 + man/batctl.8 | 3 ++ sys.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 200 insertions(+), 5 deletions(-) diff --git a/functions.c b/functions.c index 327ef18..962efcf 100644 --- a/functions.c +++ b/functions.c @@ -953,3 +953,61 @@ err_free_sock: return err; } + +static int ack_errno_handler(struct sockaddr_nl *nla __unused, + struct nlmsgerr *nlerr, + void *arg) +{ + int *err = arg; + + *err = nlerr->error; + + return NL_STOP; +} + +static int ack_wait_handler(struct nl_msg *msg __unused, void *arg __unused) +{ + return NL_STOP; +} + +int netlink_simple_request(struct nl_msg *msg) +{ + struct nl_sock *sock; + struct nl_cb *cb; + int err = 0; + int ret; + + sock = nl_socket_alloc(); + if (!sock) + return -ENOMEM; + + ret = nl_connect(sock, NETLINK_ROUTE); + if (ret < 0) { + err = -ENOMEM; + goto err_free_sock; + } + + cb = nl_cb_alloc(NL_CB_DEFAULT); + if (!cb) { + err = -ENOMEM; + goto err_free_sock; + } + + nl_cb_err(cb, NL_CB_CUSTOM, ack_errno_handler, &err); + nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, NULL); + + ret = nl_send_auto_complete(sock, msg); + if (ret < 0) + goto err_free_cb; + + // ack_errno_handler sets err on errors + err = 0; + nl_recvmsgs(sock, cb); + +err_free_cb: + nl_cb_put(cb); +err_free_sock: + nl_socket_free(sock); + + return err; +} diff --git a/functions.h b/functions.h index a6090b6..7757731 100644 --- a/functions.h +++ b/functions.h @@ -47,6 +47,7 @@ struct ether_addr *translate_mac(const char *mesh_iface, 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 print_routing_algos(void); extern char *line_ptr; diff --git a/man/batctl.8 b/man/batctl.8 index 8bac727..8dcf18a 100644 --- a/man/batctl.8 +++ b/man/batctl.8 @@ -56,6 +56,9 @@ performances, is also included. If no parameter is given or the first parameter is neither "add" nor "del" the current interface settings are displayed. In order to add or delete interfaces specify "add" or "del" as first argument and append the interface names you wish to add or delete. Multiple interfaces can be specified. +.IP "\fBinterface\fP|\fBif\fP [\fBnew\fP|\fBdestroy\fP]" +A batman-adv interface without attached interfaces can be created using "new". The parameter "destroy" can be used to +free all attached interfaces and remove batman-adv interface. .br .IP "\fBorig_interval\fP|\fBit\fP [\fBinterval\fP]" If no parameter is given the current originator interval setting is displayed otherwise the parameter is used to set the diff --git a/sys.c b/sys.c index 0140b28..252864b 100644 --- a/sys.c +++ b/sys.c @@ -120,6 +120,7 @@ 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] [new|destroy]\n"); fprintf(stderr, "parameters:\n"); fprintf(stderr, " \t -h print this help\n"); } @@ -198,10 +199,95 @@ static int print_interfaces(char *mesh_iface) return EXIT_SUCCESS; } +static int new_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; +} + int interface(char *mesh_iface, int argc, char **argv) { char *path_buff; int i, res, optchar; + int ret; while ((optchar = getopt(argc, argv, "h")) != -1) { switch (optchar) { @@ -218,16 +304,63 @@ int interface(char *mesh_iface, int argc, char **argv) return print_interfaces(mesh_iface); if ((strcmp(argv[1], "add") != 0) && (strcmp(argv[1], "a") != 0) && - (strcmp(argv[1], "del") != 0) && (strcmp(argv[1], "d") != 0)) { + (strcmp(argv[1], "del") != 0) && (strcmp(argv[1], "d") != 0) && + (strcmp(argv[1], "new") != 0) && (strcmp(argv[1], "n") != 0) && + (strcmp(argv[1], "destroy") != 0) && (strcmp(argv[1], "D") != 0)) { fprintf(stderr, "Error - unknown argument specified: %s\n", argv[1]); interface_usage(); goto err; } - if (argc == 2) { - fprintf(stderr, "Error - missing interface name(s) after '%s'\n", argv[1]); - interface_usage(); - goto err; + if (strcmp(argv[1], "destroy") == 0) + argv[1][0] = 'D'; + + switch (argv[1][0]) { + case 'a': + case 'd': + if (argc == 2) { + fprintf(stderr, + "Error - missing interface name(s) after '%s'\n", + argv[1]); + interface_usage(); + goto err; + } + break; + case 'n': + case 'D': + if (argc != 2) { + fprintf(stderr, + "Error - extra parameter after '%s'\n", + argv[1]); + interface_usage(); + goto err; + } + break; + default: + break; + } + + switch (argv[1][0]) { + case 'n': + ret = new_interface(mesh_iface); + if (ret < 0) { + fprintf(stderr, + "Error - failed to add new 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; } path_buff = malloc(PATH_BUFF_LEN);