src/networkd/port-bus.h \
src/networkd/port-dummy.c \
src/networkd/port-dummy.h \
+ src/networkd/port-vlan.c \
+ src/networkd/port-vlan.h \
src/networkd/stats-collector.c \
src/networkd/stats-collector.h \
src/networkd/string.h \
--- /dev/null
+/*#############################################################################
+# #
+# IPFire.org - A linux based firewall #
+# Copyright (C) 2023 IPFire Network Development Team #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# 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, see <http://www.gnu.org/licenses/>. #
+# #
+#############################################################################*/
+
+#include "config.h"
+#include "daemon.h"
+#include "logging.h"
+#include "port.h"
+#include "port-vlan.h"
+#include "string.h"
+
+static int nw_port_vlan_config_read(nw_port* port) {
+ int r;
+
+ // VLAN ID
+ int id = nw_config_get_int(port->config, "VLAN_ID", NW_VLAN_ID_INVALID);
+ if (id) {
+ r = nw_port_set_vlan_id(port, id);
+ if (r)
+ return r;
+ }
+
+ // Parent Port
+ const char* parent = nw_config_get(port->config, "VLAN_PARENT");
+ if (parent) {
+ r = nw_string_set(port->vlan.__parent_name, parent);
+ if (r)
+ return r;
+ }
+
+ return 0;
+}
+
+static int nw_port_vlan_config_write(nw_port* port) {
+ int r;
+
+ // VLAN ID
+ r = nw_config_set_int(port->config, "VLAN_ID", port->vlan.id);
+ if (r)
+ return r;
+
+ // Parent Port
+ r = nw_config_set(port->config, "VLAN_PARENT",
+ (port->vlan.parent) ? nw_port_name(port->vlan.parent) : port->vlan.__parent_name);
+ if (r)
+ return r;
+
+ return 0;
+}
+
+nw_port_ops_t nw_port_ops_vlan = {
+ // Configuration
+ .config_read = nw_port_vlan_config_read,
+ .config_write = nw_port_vlan_config_write,
+};
+
+/*
+ VLAN
+*/
+int nw_port_get_vlan_id(nw_port* port) {
+ int r;
+
+ // Check type
+ r = nw_port_check_type(port, NW_PORT_VLAN);
+ if (r < 0)
+ return r;
+
+ return port->vlan.id;
+}
+
+int nw_port_set_vlan_id(nw_port* port, int id) {
+ int r;
+
+ // Check type
+ r = nw_port_check_type(port, NW_PORT_VLAN);
+ if (r < 0)
+ return r;
+
+ // Check if the VLAN ID is within range
+ if (id < NW_VLAN_ID_MIN || id > NW_VLAN_ID_MAX)
+ return -EINVAL;
+
+ // Store the ID
+ port->vlan.id = id;
+
+ DEBUG("Port %s: Set VLAN ID to %d\n", port->name, port->vlan.id);
+
+ return 0;
+}
+
+nw_port* nw_port_get_vlan_parent(nw_port* port) {
+ int r;
+
+ // Check type
+ r = nw_port_check_type(port, NW_PORT_VLAN);
+ if (r < 0)
+ return NULL;
+
+ // Try to find a reference to the parent if none exists
+ if (!port->vlan.parent && *port->vlan.__parent_name)
+ port->vlan.parent = nw_daemon_get_port_by_name(port->daemon, port->vlan.__parent_name);
+
+ if (port->vlan.parent)
+ return nw_port_ref(port->vlan.parent);
+
+ // No port found
+ return NULL;
+}
+
+int nw_port_set_vlan_parent(nw_port* port, nw_port* parent) {
+ int r;
+
+ // Check type
+ r = nw_port_check_type(port, NW_PORT_VLAN);
+ if (r < 0)
+ return r;
+
+ // Reset the former parent name
+ nw_string_empty(port->vlan.__parent_name);
+
+ // Dereference the former parent
+ if (port->vlan.parent) {
+ nw_port_unref(port->vlan.parent);
+ port->vlan.parent = NULL;
+ }
+
+ // Store the new parent
+ if (parent)
+ port->vlan.parent = nw_port_ref(parent);
+
+ DEBUG("Port %s: Set VLAN parent to %s\n", port->name, nw_port_name(port->vlan.parent));
+
+ return 0;
+}
--- /dev/null
+/*#############################################################################
+# #
+# IPFire.org - A linux based firewall #
+# Copyright (C) 2023 IPFire Network Development Team #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# 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, see <http://www.gnu.org/licenses/>. #
+# #
+#############################################################################*/
+
+#ifndef NETWORKD_PORT_VLAN_H
+#define NETWORKD_PORT_VLAN_H
+
+#include "port.h"
+
+extern nw_port_ops_t nw_port_ops_vlan;
+
+// ID
+int nw_port_get_vlan_id(nw_port* port);
+int nw_port_set_vlan_id(nw_port* port, int id);
+
+// Parent Port
+nw_port* nw_port_get_vlan_parent(nw_port* port);
+int nw_port_set_vlan_parent(nw_port* port, nw_port* parent);
+
+#endif /* NETWORKD_PORT_VLAN_H */
#include "logging.h"
#include "port.h"
#include "port-dummy.h"
+#include "port-vlan.h"
#include "stats-collector.h"
#include "string.h"
-struct nw_port {
- nw_daemon* daemon;
- int nrefs;
-
- // Link
- nw_link* link;
-
- nw_port_type_t type;
- char name[IF_NAMESIZE];
-
- // Configuration
- nw_config *config;
-
- // Common attributes
- nw_address_t address;
-
- // Type Operations
- nw_port_ops_t ops;
-
- // VLAN settings
- struct nw_port_vlan {
- nw_port* parent;
- int id;
-
- // If the parent has not been read from the configuration we will
- // save the name and try to find it later.
- char __parent_name[IF_NAMESIZE];
- } vlan;
-};
-
static const struct nw_port_type_map {
nw_port_type_t type;
const char* name;
return 0;
}
-static int nw_port_setup_vlan(nw_port* port) {
- int r;
-
- // VLAN ID
- int id = nw_config_get_int(port->config, "VLAN_ID", NW_VLAN_ID_INVALID);
- if (id) {
- r = nw_port_set_vlan_id(port, id);
- if (r)
- return r;
- }
-
- // Parent Port
- const char* parent = nw_config_get(port->config, "VLAN_PARENT");
- if (parent) {
- r = nw_string_set(port->vlan.__parent_name, parent);
- if (r)
- return r;
- }
-
- return 0;
-}
-
static int nw_port_set_link(nw_port* port, nw_link* link) {
// Do nothing if the same link is being re-assigned
if (port->link == link)
goto ERROR;
// Call any custom initialization
- switch (port->type) {
- case NW_PORT_VLAN:
- r = nw_port_setup_vlan(port);
- if (r)
- goto ERROR;
- break;
-
- // These do not need any special initialization
- case NW_PORT_DUMMY:
- case NW_PORT_UNKNOWN:
- break;
+ if (port->ops.config_read) {
+ r = port->ops.config_read(port);
+ if (r)
+ goto ERROR;
}
ERROR:
case NW_PORT_DUMMY:
p->ops = nw_port_ops_dummy;
break;
+
+ case NW_PORT_VLAN:
+ p->ops = nw_port_ops_vlan;
+ break;
}
// Store the name
return 0;
}
-static int nw_port_save_vlan(nw_port* port) {
- int r;
-
- // VLAN ID
- r = nw_config_set_int(port->config, "VLAN_ID", port->vlan.id);
- if (r)
- return r;
-
- // Parent Port
- r = nw_config_set(port->config, "VLAN_PARENT",
- (port->vlan.parent) ? nw_port_name(port->vlan.parent) : port->vlan.__parent_name);
- if (r)
- return r;
-
- return 0;
-}
-
int nw_port_save(nw_port* port) {
int r;
- switch (port->type) {
- // VLAN
- case NW_PORT_VLAN:
- r = nw_port_save_vlan(port);
- if (r)
- goto ERROR;
- break;
-
- // These types do not have any special settings
- case NW_PORT_DUMMY:
- case NW_PORT_UNKNOWN:
- break;
+ // Call the custom handler
+ if (port->ops.config_write) {
+ r = port->ops.config_write(port);
+ if (r)
+ goto ERROR;
}
+ // Write the configuration
r = nw_config_write(port->config);
if (r)
return r;
}
static int nw_port_create_link(nw_port* port) {
- return 0; // XXX TODO
+ int r;
+
+ // Fail if the function isn't set
+ if (!port->ops.create_link) {
+ errno = ENOTSUP;
+ return -errno;
+ }
+
+ // Create the link
+ r = port->ops.create_link(port);
+ if (r)
+ ERROR("Could not create link %s: %m\n", port->name);
+
+ return r;
}
int nw_port_reconfigure(nw_port* port) {
return 0;
}
-static int nw_port_check_type(nw_port* port, const nw_port_type_t type) {
+int nw_port_check_type(nw_port* port, const nw_port_type_t type) {
if (port->type == type)
return 0;
errno = ENOTSUP;
return -errno;
}
-
-/*
- VLAN
-*/
-int nw_port_get_vlan_id(nw_port* port) {
- int r;
-
- // Check type
- r = nw_port_check_type(port, NW_PORT_VLAN);
- if (r < 0)
- return r;
-
- return port->vlan.id;
-}
-
-int nw_port_set_vlan_id(nw_port* port, int id) {
- int r;
-
- // Check type
- r = nw_port_check_type(port, NW_PORT_VLAN);
- if (r < 0)
- return r;
-
- // Check if the VLAN ID is within range
- if (id < NW_VLAN_ID_MIN || id > NW_VLAN_ID_MAX)
- return -EINVAL;
-
- // Store the ID
- port->vlan.id = id;
-
- DEBUG("Port %s: Set VLAN ID to %d\n", port->name, port->vlan.id);
-
- return 0;
-}
-
-nw_port* nw_port_get_vlan_parent(nw_port* port) {
- int r;
-
- // Check type
- r = nw_port_check_type(port, NW_PORT_VLAN);
- if (r < 0)
- return NULL;
-
- // Try to find a reference to the parent if none exists
- if (!port->vlan.parent && *port->vlan.__parent_name)
- port->vlan.parent = nw_daemon_get_port_by_name(port->daemon, port->vlan.__parent_name);
-
- if (port->vlan.parent)
- return nw_port_ref(port->vlan.parent);
-
- // No port found
- return NULL;
-}
-
-int nw_port_set_vlan_parent(nw_port* port, nw_port* parent) {
- int r;
-
- // Check type
- r = nw_port_check_type(port, NW_PORT_VLAN);
- if (r < 0)
- return r;
-
- // Reset the former parent name
- nw_string_empty(port->vlan.__parent_name);
-
- // Dereference the former parent
- if (port->vlan.parent) {
- nw_port_unref(port->vlan.parent);
- port->vlan.parent = NULL;
- }
-
- // Store the new parent
- if (parent)
- port->vlan.parent = nw_port_ref(parent);
-
- DEBUG("Port %s: Set VLAN parent to %s\n", port->name, nw_port_name(port->vlan.parent));
-
- return 0;
-}
#ifndef NETWORKD_PORT_H
#define NETWORKD_PORT_H
+#ifndef IF_NAMESIZE
+#define IF_NAMESIZE 16
+#endif
+
#define PORT_CONFIG_DIR CONFIG_DIR "/ports"
typedef enum nw_port_type {
typedef struct nw_port_ops {
// Configuration
- int (*config_read)(nw_port* port, nw_config* config);
- int (*config_write)(nw_port* port, nw_config* config);
+ int (*config_read)(nw_port* port);
+ int (*config_write)(nw_port* port);
+
+ // Link
+ int (*create_link)(nw_port* port);
+ int (*destroy_link)(nw_port* port);
} nw_port_ops_t;
+struct nw_port {
+ nw_daemon* daemon;
+ int nrefs;
+
+ // Link
+ nw_link* link;
+
+ nw_port_type_t type;
+ char name[IF_NAMESIZE];
+
+ // Configuration
+ nw_config *config;
+
+ // Common attributes
+ nw_address_t address;
+
+ // Type Operations
+ nw_port_ops_t ops;
+
+ // VLAN settings
+ struct nw_port_vlan {
+ nw_port* parent;
+ int id;
+
+ // If the parent has not been read from the configuration we will
+ // save the name and try to find it later.
+ char __parent_name[IF_NAMESIZE];
+ } vlan;
+};
+
int nw_port_create(nw_port** port, nw_daemon* daemon,
nw_port_type_t type, const char* name);
int nw_port_create_from_config(nw_port** port, nw_daemon* daemon,
int nw_port_has_carrier(nw_port* port);
+int nw_port_check_type(nw_port* port, const nw_port_type_t type);
+
// Stats
const struct rtnl_link_stats64* nw_port_get_stats64(nw_port* port);
int __nw_port_update_stats(nw_daemon* daemon, nw_port* port, void* data);
int nw_port_update_stats(nw_port* port);
-// VLAN
-int nw_port_get_vlan_id(nw_port* port);
-int nw_port_set_vlan_id(nw_port* port, int id);
-
-nw_port* nw_port_get_vlan_parent(nw_port* port);
-int nw_port_set_vlan_parent(nw_port* port, nw_port* parent);
-
#endif /* NETWORKD_PORT_H */
typedef int (*nw_ports_walk_callback)(nw_daemon* daemon, nw_port* port, void* data);
#include "daemon.h"
+#include "port.h"
int nw_ports_create(nw_ports** ports, nw_daemon* daemon);