From: Sven Eckelmann <sven@narfation.org>
To: b.a.t.m.a.n@lists.open-mesh.org
Subject: [B.A.T.M.A.N.] [PATCH v3 2/9] batctl: Add command to create/destroy batman-adv interface
Date: Tue, 18 Oct 2016 16:17:24 +0200 [thread overview]
Message-ID: <20161018141731.7970-2-sven@narfation.org> (raw)
In-Reply-To: <2403515.P9aVkiGJpp@bentobox>
The command "create" 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 <sven@narfation.org>
---
v3:
- rebased on current master
- changed __unused to __maybe_unused
v2:
- rename "new" command to "create" as requested by Linus Luessing and
John Harrison
---
functions.c | 59 ++++++++++++++++++++++++
functions.h | 1 +
man/batctl.8 | 3 ++
sys.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
4 files changed, 201 insertions(+), 5 deletions(-)
diff --git a/functions.c b/functions.c
index 8470b49..85482b4 100644
--- a/functions.c
+++ b/functions.c
@@ -954,3 +954,62 @@ err_free_sock:
return err;
}
+
+static int ack_errno_handler(struct sockaddr_nl *nla __maybe_unused,
+ struct nlmsgerr *nlerr,
+ void *arg)
+{
+ int *err = arg;
+
+ *err = nlerr->error;
+
+ return NL_STOP;
+}
+
+static int ack_wait_handler(struct nl_msg *msg __maybe_unused,
+ void *arg __maybe_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 d5a5ce0..37b5632 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 [\fBcreate\fP|\fBdestroy\fP]"
+A batman-adv interface without attached interfaces can be created using "create". 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..c18c6b8 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] [create|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 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;
+}
+
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], "create") != 0) && (strcmp(argv[1], "c") != 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 'c':
+ 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 '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;
}
path_buff = malloc(PATH_BUFF_LEN);
--
2.9.3
next prev parent reply other threads:[~2016-10-18 14:17 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-10-18 14:16 [B.A.T.M.A.N.] [PATCH v3 0/9] batctl: rtnetlink interface manipulation + userspace icmp Sven Eckelmann
2016-10-18 14:17 ` [B.A.T.M.A.N.] [PATCH v3 1/9] batctl: Use rtnl to query list of softif devices Sven Eckelmann
2016-10-18 14:17 ` Sven Eckelmann [this message]
2016-10-18 14:17 ` [B.A.T.M.A.N.] [PATCH v3 3/9] batctl: Use rtnl to add/remove interfaces Sven Eckelmann
2016-10-18 14:17 ` [B.A.T.M.A.N.] [PATCH v3 4/9] batctl: Parse interface arguments relative to last parsed option Sven Eckelmann
2016-10-18 14:17 ` [B.A.T.M.A.N.] [PATCH v3 5/9] batctl: Allow to disable automatic interface create/destroy Sven Eckelmann
2016-10-18 14:17 ` [B.A.T.M.A.N.] [PATCH v3 6/9] batctl: Move interface command to extra file Sven Eckelmann
2016-10-18 14:17 ` [B.A.T.M.A.N.] [PATCH v3 7/9] batctl: Move check_mesh_iface* to functions.c Sven Eckelmann
2016-10-18 14:17 ` [B.A.T.M.A.N.] [PATCH v3 8/9] batctl: Add helper to generate instant random bytes Sven Eckelmann
2016-10-18 14:17 ` [B.A.T.M.A.N.] [PATCH v3 9/9] batctl: Implement non-routing batadv_icmp in userspace Sven Eckelmann
2016-10-24 11:18 ` [B.A.T.M.A.N.] [PATCH v3 0/9] batctl: rtnetlink interface manipulation + userspace icmp Simon Wunderlich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20161018141731.7970-2-sven@narfation.org \
--to=sven@narfation.org \
--cc=b.a.t.m.a.n@lists.open-mesh.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox