[PATCH netifd] team: add simple bonding/teaming module

Petr Štetiar ynezz at true.cz
Sat Jan 16 07:55:01 EST 2021


Pavel Šimerda <code at simerda.eu> [2021-01-12 04:36:36]:

Hi,

> The module requires libteam's teamd and teamdctl commands.

This looks like an alien to the OpenWrt ecosystem, basically you're using
netifd just as a launcher for teamd, teamdctl without any proper error
handling instead of ubus for configuration etc.

> Signed-off-by: Pavel Šimerda <code at simerda.eu>
> ---
>  CMakeLists.txt |   2 +-
>  team.c         | 178 +++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 179 insertions(+), 1 deletion(-)
>  create mode 100644 team.c
> 
> diff --git a/CMakeLists.txt b/CMakeLists.txt
> index 9d19817..351e303 100644
> --- a/CMakeLists.txt
> +++ b/CMakeLists.txt
> @@ -19,7 +19,7 @@ SET(SOURCES
>  	main.c utils.c system.c tunnel.c handler.c
>  	interface.c interface-ip.c interface-event.c
>  	iprule.c proto.c proto-static.c proto-shell.c
> -	config.c device.c bridge.c veth.c vlan.c alias.c
> +	config.c device.c bridge.c team.c veth.c vlan.c alias.c
>  	macvlan.c ubus.c vlandev.c wireless.c)
>  
>  
> diff --git a/team.c b/team.c
> new file mode 100644
> index 0000000..9b67566
> --- /dev/null
> +++ b/team.c
> @@ -0,0 +1,178 @@
> +/*
> + * netifd - network interface daemon
> + * Copyright (C) 2021 Pavel Šimerda <code at simerda.eu>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2
> + * 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.
> + */
> +#include <string.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <assert.h>
> +#include <errno.h>
> +#include <signal.h>
> +#include <sys/wait.h>
> +#include <unistd.h>
> +
> +#include "netifd.h"
> +#include "device.h"
> +#include "interface.h"
> +#include "system.h"
> +
> +enum {
> +	TEAM_ATTR_IFNAME,
> +	__TEAM_ATTR_MAX
> +};
> +
> +static const struct blobmsg_policy team_attrs[__TEAM_ATTR_MAX] = {
> +	[TEAM_ATTR_IFNAME] = { "ifname", BLOBMSG_TYPE_ARRAY },
> +};
> +
> +static const struct uci_blob_param_info team_attr_info[__TEAM_ATTR_MAX] = {
> +	[TEAM_ATTR_IFNAME] = { .type = BLOBMSG_TYPE_STRING },
> +};
> +
> +static const struct uci_blob_param_list team_attr_list = {
> +	.n_params = __TEAM_ATTR_MAX,
> +	.params = team_attrs,
> +	.info = team_attr_info,
> +
> +	.n_next = 1,
> +	.next = { &device_attr_list },
> +};
> +
> +struct team_device {
> +	struct device dev;
> +	device_state_cb set_state;
> +
> +	struct blob_attr *config_data;
> +	struct blob_attr *ifnames;
> +
> +	int pid;
> +};
> +
> +static int
> +team_set_state(struct device *dev, bool up)
> +{
> +	struct team_device *teamdev = container_of(dev, struct team_device, dev);
> +
> +	if (up) {
> +		int pid;
> +		struct blob_attr *cur;
> +		int rem;
> +		char buffer[64];
> +
> +		printf("TEAM start teamd\n");

if this is needed at all, take a look around and use proper debug logging

> +		pid = fork();
> +		if (pid == -1)
> +			return -errno;
> +		if (pid == 0)
> +			execlp("teamd", "teamd", "-t", dev->ifname, NULL);

this is external dependency and you lack any check for that

> +		teamdev->pid = pid;
> +		// TODO: Better handling of newly created devices.

better? there is no handling of anything

> +		sleep(1);
> +		if (teamdev->ifnames) {
> +			printf("TEAM port init\n");
> +			blobmsg_for_each_attr(cur, teamdev->ifnames, rem) {
> +				printf("TEAM one port init\n");
> +				snprintf(buffer, sizeof buffer,
> +					"teamdctl %s port add %s",
> +					dev->ifname,
> +					blobmsg_get_string(cur));
> +				system(buffer);

puting aside usage of system() for service configuration this smells, you're
passing possibly malicious input directly to system() in the service running
as root, what could go wrong?

> +			}
> +		}
> +		teamdev->set_state(dev, up);
> +		return 0;
> +	} else {
> +		printf("TEAM: killing %d\n", teamdev->pid);
> +		if (teamdev->pid) {
> +			kill(teamdev->pid, SIGTERM);
> +			waitpid(teamdev->pid, NULL, 0);
> +			teamdev->pid = 0;
> +		}
> +		return 0;
> +	}
> +}
> +
> +static enum dev_change_type
> +team_reload(struct device *dev, struct blob_attr *attr)
> +{
> +	struct team_device *teamdev = container_of(dev, struct team_device, dev);
> +	struct blob_attr *tb_tm[__TEAM_ATTR_MAX];
> +
> +	attr = blob_memdup(attr);
> +
> +	blobmsg_parse(team_attrs, __TEAM_ATTR_MAX, tb_tm, blob_data(attr), blob_len(attr));
> +	teamdev->ifnames = tb_tm[TEAM_ATTR_IFNAME];
> +
> +	if (teamdev->pid) {
> +		// TODO: More fine-grained reconfiguration
> +		team_set_state(dev, false);
> +		team_set_state(dev, true);
> +	}
> +
> +	free(teamdev->config_data);
> +	teamdev->config_data = attr;
> +	return DEV_CONFIG_APPLIED;
> +}
> +
> +static struct device *
> +team_create(const char *name, struct device_type *devtype,
> +	struct blob_attr *attr)
> +{
> +	struct team_device *teamdev;
> +	struct device *dev = NULL;
> +
> +	teamdev = calloc(1, sizeof(*teamdev));
> +	if (!teamdev)
> +		return NULL;
> +	dev = &teamdev->dev;
> +
> +	if (device_init(dev, devtype, name) < 0) {
> +		device_cleanup(dev);
> +		free(teamdev);
> +		return NULL;
> +	}
> +
> +	teamdev->set_state = dev->set_state;
> +	dev->set_state = team_set_state;
> +
> +	device_set_present(dev, true);
> +	team_reload(dev, attr);
> +
> +	return dev;
> +}
> +
> +static void
> +team_free(struct device *dev)
> +{
> +	struct team_device *teamdev = container_of(dev, struct team_device, dev);
> +
> +	free(teamdev->config_data);
> +	free(teamdev);
> +}
> +
> +static struct device_type team_device_type = {
> +	.name = "team",
> +	.config_params = &team_attr_list,
> +
> +	.bridge_capability = true,
> +	.name_prefix = "tm",
> +
> +	.create = team_create,
> +	.reload = team_reload,
> +	.free = team_free,
> +};
> +
> +static void __init team_device_type_init(void)
> +{
> +	device_type_add(&team_device_type);
> +}
> -- 
> 2.29.2



More information about the openwrt-devel mailing list