@@ -199,6 +199,58 @@ static int print_interfaces(char *mesh_iface)
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 = {
@@ -283,11 +335,54 @@ err_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)
{
- char *path_buff;
- int i, res, optchar;
+ int i, optchar;
int ret;
+ unsigned int ifindex;
+ unsigned int ifmaster;
+ const char *long_op;
+ unsigned int cnt;
while ((optchar = getopt(argc, argv, "h")) != -1) {
switch (optchar) {
@@ -363,46 +458,69 @@ int interface(char *mesh_iface, int argc, char **argv)
break;
}
- path_buff = malloc(PATH_BUFF_LEN);
- if (!path_buff) {
- fprintf(stderr, "Error - could not allocate path buffer: out of memory ?\n");
- goto err;
- }
+ /* get index of batman-adv interface - or try to create it */
+ ifmaster = if_nametoindex(mesh_iface);
+ if (!ifmaster && argv[1][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;
+ }
- for (i = 2; i < argc; i++) {
- snprintf(path_buff, PATH_BUFF_LEN, SYS_MESH_IFACE_FMT, argv[i]);
+ ifmaster = if_nametoindex(mesh_iface);
+ }
- if (!file_exists(path_buff)) {
- snprintf(path_buff, PATH_BUFF_LEN, SYS_IFACE_DIR, argv[i]);
+ if (!ifmaster) {
+ ret = -ENODEV;
+ fprintf(stderr,
+ "Error - failed to find batman-adv interface: %s\n",
+ strerror(-ret));
+ goto err;
+ }
- if (!file_exists(path_buff)) {
- fprintf(stderr, "Error - interface does not exist: %s\n", argv[i]);
- continue;
- }
+ /* 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;
+ }
- if (!file_exists(module_ver_path)) {
- fprintf(stderr, "Error - batman-adv module has not been loaded\n");
- goto err_buff;
- }
+ for (i = 2; i < argc; i++) {
+ ifindex = if_nametoindex(argv[i]);
- fprintf(stderr, "Error - interface type not supported by batman-adv: %s\n", argv[i]);
+ if (!ifindex) {
+ fprintf(stderr, "Error - interface does not exist: %s\n", argv[i]);
continue;
}
if (argv[1][0] == 'a')
- res = write_file("", path_buff, mesh_iface, NULL);
+ ifindex = ifmaster;
else
- res = write_file("", path_buff, "none", NULL);
+ ifindex = 0;
- if (res != EXIT_SUCCESS)
- goto err_buff;
+ ret = set_master_interface(argv[i], ifindex);
+ if (ret < 0) {
+ if (argv[1][0] == 'a')
+ long_op = "add";
+ else
+ long_op = "delete";
+
+ fprintf(stderr, "Error - failed to %s interface %s: %s\n",
+ long_op, argv[i], strerror(-ret));
+ goto err;
+ }
+ }
+
+ /* check if there is no interface left and then destroy mesh_iface */
+ if (argv[1][0] == 'd') {
+ cnt = count_interfaces(mesh_iface);
+ if (cnt == 0)
+ destroy_interface(mesh_iface);
}
- free(path_buff);
return EXIT_SUCCESS;
-err_buff:
- free(path_buff);
err:
return EXIT_FAILURE;
}