]>
git.ipfire.org Git - people/ms/network.git/blob - src/networkd/port.c
1 /*#############################################################################
3 # IPFire.org - A linux based firewall #
4 # Copyright (C) 2023 IPFire Network Development Team #
6 # This program is free software: you can redistribute it and/or modify #
7 # it under the terms of the GNU General Public License as published by #
8 # the Free Software Foundation, either version 3 of the License, or #
9 # (at your option) any later version. #
11 # This program is distributed in the hope that it will be useful, #
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 # GNU General Public License for more details. #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
19 #############################################################################*/
26 #include <systemd/sd-bus.h>
33 #include "stats-collector.h"
43 char name
[IF_NAMESIZE
];
53 static const struct nw_port_type_map
{
56 } nw_port_type_map
[] = {
57 { NW_PORT_DUMMY
, "dummy" },
58 { NW_PORT_UNKNOWN
, NULL
},
61 static nw_port_type_t
nw_port_type_from_string(const char* s
) {
62 const struct nw_port_type_map
* map
= NULL
;
64 for (map
= nw_port_type_map
; *map
->name
; map
++) {
65 if (strcmp(map
->name
, s
) == 0)
69 return NW_PORT_UNKNOWN
;
72 static void nw_port_free(nw_port
* port
) {
74 nw_link_unref(port
->link
);
76 nw_config_unref(port
->config
);
78 nw_daemon_unref(port
->daemon
);
83 static int nw_port_setup_address(nw_port
* port
) {
86 // Read ADDRESS from configuration
87 const char* s
= nw_config_get(port
->config
, "ADDRESS");
89 ERROR("Port %s: Address isn't set\n", port
->name
);
94 r
= nw_address_from_string(&port
->address
, s
);
96 ERROR("Port %s: Could not parse address: %m\n", port
->name
);
100 // Check if this address is usable
101 r
= nw_address_is_multicast(&port
->address
);
103 DEBUG("Port %s: Multicast bit is set on Ethernet address\n", port
->name
);
110 // Generate a random Ethernet address
111 r
= nw_address_generate(&port
->address
);
113 ERROR("Could not generate a random Ethernet address: %m\n");
120 static int nw_port_setup_common(nw_port
* port
) {
124 r
= nw_port_setup_address(port
);
131 static nw_port_type_t
nw_port_setup_type(nw_port
* port
) {
132 const char* type
= nw_config_get(port
->config
, "TYPE");
134 return NW_PORT_UNKNOWN
;
136 return nw_port_type_from_string(type
);
139 static int nw_port_set_link(nw_port
* port
, nw_link
* link
) {
140 // Do nothing if the same link is being re-assigned
141 if (port
->link
== link
)
144 // Dereference the former link if set
146 nw_link_unref(port
->link
);
148 // Store the new link
150 port
->link
= nw_link_ref(link
);
152 DEBUG("Port %s: Assigned link %d\n", port
->name
, nw_link_ifindex(port
->link
));
154 // Or clear the pointer if no link has been provided
158 DEBUG("Port %s: Removed link\n", port
->name
);
164 static int nw_port_setup(nw_port
* port
) {
165 nw_link
* link
= NULL
;
170 link
= nw_daemon_get_link_by_name(port
->daemon
, port
->name
);
172 r
= nw_port_set_link(port
, link
);
177 // Compose the path to the main configuration file
178 r
= nw_path_join(path
, PORT_CONFIG_DIR
, port
->name
);
182 // Initialize the configuration
183 r
= nw_config_create(&port
->config
, path
);
188 port
->type
= nw_port_setup_type(port
);
190 ERROR("Could not determine type of port %s\n", port
->name
);
194 // Perform some common initialization
195 r
= nw_port_setup_common(port
);
199 // Call any custom initialization
200 switch (port
->type
) {
201 // These do not need any special initialization
203 case NW_PORT_UNKNOWN
:
214 int nw_port_create(nw_port
** port
, nw_daemon
* daemon
, const char* name
) {
217 // Allocate a new object
218 nw_port
* p
= calloc(1, sizeof(*p
));
222 // Store a reference to the daemon
223 p
->daemon
= nw_daemon_ref(daemon
);
225 // Initialize reference counter
229 r
= nw_string_set(p
->name
, name
);
234 r
= nw_port_setup(p
);
246 nw_port
* nw_port_ref(nw_port
* port
) {
252 nw_port
* nw_port_unref(nw_port
* port
) {
253 if (--port
->nrefs
> 0)
260 int nw_port_save(nw_port
* port
) {
263 r
= nw_config_write(port
->config
);
270 const char* nw_port_name(nw_port
* port
) {
274 char* nw_port_bus_path(nw_port
* port
) {
278 // Encode the bus path
279 r
= sd_bus_path_encode("/org/ipfire/network1/port", port
->name
, &p
);
286 int __nw_port_set_link(nw_daemon
* daemon
, nw_port
* port
, void* data
) {
287 nw_link
* link
= (nw_link
*)data
;
289 // Fetch the link name
290 const char* ifname
= nw_link_ifname(link
);
292 ERROR("Link does not have a name set\n");
296 // Set link if the name matches
297 if (strcmp(port
->name
, ifname
) == 0)
298 return nw_port_set_link(port
, link
);
300 // If we have the link set but the name did not match, we will remove it
301 else if (port
->link
== link
)
302 return nw_port_set_link(port
, NULL
);
307 int __nw_port_drop_link(nw_daemon
* daemon
, nw_port
* port
, void* data
) {
308 nw_link
* link
= (nw_link
*)data
;
310 // Drop the link if it matches
311 if (port
->link
== link
)
312 return nw_port_set_link(port
, NULL
);
317 const nw_address_t
* nw_port_get_address(nw_port
* port
) {
318 return &port
->address
;
321 static int nw_port_is_disabled(nw_port
* port
) {
322 return nw_config_get_bool(port
->config
, "DISABLED");
325 static int nw_port_create_link(nw_port
* port
) {
326 return 0; // XXX TODO
329 int nw_port_reconfigure(nw_port
* port
) {
332 // If the port is disabled, we will try to destroy it
333 if (nw_port_is_disabled(port
)) {
335 r
= nw_link_destroy(port
->link
);
343 // If there is no link, we will try to create it
345 r
= nw_port_create_link(port
);
355 int nw_port_has_carrier(nw_port
* port
) {
359 return nw_link_has_carrier(port
->link
);
366 const struct rtnl_link_stats64
* nw_port_get_stats64(nw_port
* port
) {
370 return nw_link_get_stats64(port
->link
);
373 int __nw_port_update_stats(nw_daemon
* daemon
, nw_port
* port
, void* data
) {
374 nw_link
* link
= (nw_link
*)data
;
376 // Emit stats if link matches
377 if (port
->link
== link
)
378 return nw_stats_collector_emit_port_stats(daemon
, port
);
383 int nw_port_update_stats(nw_port
* port
) {
385 return nw_link_update_stats(port
->link
);