]>
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>
42 char name
[IF_NAMESIZE
];
52 static const struct nw_port_type_map
{
55 } nw_port_type_map
[] = {
56 { NW_PORT_DUMMY
, "dummy" },
57 { NW_PORT_UNKNOWN
, NULL
},
60 static nw_port_type_t
nw_port_type_from_string(const char* s
) {
61 const struct nw_port_type_map
* map
= NULL
;
63 for (map
= nw_port_type_map
; *map
->name
; map
++) {
64 if (strcmp(map
->name
, s
) == 0)
68 return NW_PORT_UNKNOWN
;
71 static void nw_port_free(nw_port
* port
) {
73 nw_link_unref(port
->link
);
75 nw_config_unref(port
->config
);
77 nw_daemon_unref(port
->daemon
);
82 static int nw_port_setup_address(nw_port
* port
) {
85 // Read ADDRESS from configuration
86 const char* s
= nw_config_get(port
->config
, "ADDRESS");
88 ERROR("Port %s: Address isn't set\n", port
->name
);
93 r
= nw_address_from_string(&port
->address
, s
);
95 ERROR("Port %s: Could not parse address: %m\n", port
->name
);
99 // Check if this address is usable
100 r
= nw_address_is_multicast(&port
->address
);
102 DEBUG("Port %s: Multicast bit is set on Ethernet address\n", port
->name
);
109 // Generate a random Ethernet address
110 r
= nw_address_generate(&port
->address
);
112 ERROR("Could not generate a random Ethernet address: %m\n");
119 static int nw_port_setup_common(nw_port
* port
) {
123 r
= nw_port_setup_address(port
);
130 static nw_port_type_t
nw_port_setup_type(nw_port
* port
) {
131 const char* type
= nw_config_get(port
->config
, "TYPE");
133 return NW_PORT_UNKNOWN
;
135 return nw_port_type_from_string(type
);
138 static int nw_port_set_link(nw_port
* port
, nw_link
* link
) {
139 // Do nothing if the same link is being re-assigned
140 if (port
->link
== link
)
143 // Dereference the former link if set
145 nw_link_unref(port
->link
);
147 // Store the new link
149 port
->link
= nw_link_ref(link
);
151 DEBUG("Port %s: Assigned link %d\n", port
->name
, nw_link_ifindex(port
->link
));
153 // Or clear the pointer if no link has been provided
157 DEBUG("Port %s: Removed link\n", port
->name
);
163 static int nw_port_setup(nw_port
* port
) {
164 nw_link
* link
= NULL
;
169 link
= nw_daemon_get_link_by_name(port
->daemon
, port
->name
);
171 r
= nw_port_set_link(port
, link
);
176 // Compose the path to the main configuration file
177 r
= nw_path_join(path
, PORT_CONFIG_DIR
, port
->name
);
181 // Initialize the configuration
182 r
= nw_config_create(&port
->config
, path
);
187 port
->type
= nw_port_setup_type(port
);
189 ERROR("Could not determine type of port %s\n", port
->name
);
193 // Perform some common initialization
194 r
= nw_port_setup_common(port
);
198 // Call any custom initialization
199 switch (port
->type
) {
200 // These do not need any special initialization
202 case NW_PORT_UNKNOWN
:
213 int nw_port_create(nw_port
** port
, nw_daemon
* daemon
, const char* name
) {
216 // Allocate a new object
217 nw_port
* p
= calloc(1, sizeof(*p
));
221 // Store a reference to the daemon
222 p
->daemon
= nw_daemon_ref(daemon
);
224 // Initialize reference counter
228 r
= nw_string_set(p
->name
, name
);
233 r
= nw_port_setup(p
);
245 nw_port
* nw_port_ref(nw_port
* port
) {
251 nw_port
* nw_port_unref(nw_port
* port
) {
252 if (--port
->nrefs
> 0)
259 int nw_port_save(nw_port
* port
) {
262 r
= nw_config_write(port
->config
);
269 const char* nw_port_name(nw_port
* port
) {
273 char* nw_port_bus_path(nw_port
* port
) {
277 // Encode the bus path
278 r
= sd_bus_path_encode("/org/ipfire/network1/port", port
->name
, &p
);
285 int __nw_port_set_link(nw_daemon
* daemon
, nw_port
* port
, void* data
) {
286 nw_link
* link
= (nw_link
*)data
;
288 // Fetch the link name
289 const char* ifname
= nw_link_ifname(link
);
291 ERROR("Link does not have a name set\n");
295 // Set link if the name matches
296 if (strcmp(port
->name
, ifname
) == 0)
297 return nw_port_set_link(port
, link
);
299 // If we have the link set but the name did not match, we will remove it
300 else if (port
->link
== link
)
301 return nw_port_set_link(port
, NULL
);
306 int __nw_port_drop_link(nw_daemon
* daemon
, nw_port
* port
, void* data
) {
307 nw_link
* link
= (nw_link
*)data
;
309 // Drop the link if it matches
310 if (port
->link
== link
)
311 return nw_port_set_link(port
, NULL
);
316 const nw_address_t
* nw_port_get_address(nw_port
* port
) {
317 return &port
->address
;
320 static int nw_port_is_disabled(nw_port
* port
) {
321 return nw_config_get_bool(port
->config
, "DISABLED");
324 int nw_port_reconfigure(nw_port
* port
) {
327 // If the port is disabled, we will try to destroy it
328 if (nw_port_is_disabled(port
)) {
330 r
= nw_link_destroy(port
->link
);
341 int nw_port_has_carrier(nw_port
* port
) {
345 return nw_link_has_carrier(port
->link
);