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 #############################################################################*/
22 #include <linux/if_link.h>
25 #include <systemd/sd-bus.h>
31 #include "stats-collector.h"
35 static const nw_string_table_t nw_zone_type_id
[] = {
39 NW_STRING_TABLE_LOOKUP(nw_zone_type_id_t
, nw_zone_type_id
)
41 static void nw_zone_free(nw_zone
* zone
) {
43 nw_link_unref(zone
->link
);
45 nw_config_unref(zone
->config
);
47 nw_daemon_unref(zone
->daemon
);
52 static int nw_zone_set_link(nw_zone
* zone
, nw_link
* link
) {
53 // Do nothing if the same link is being re-assigned
54 if (zone
->link
== link
)
57 // Dereference the former link if set
59 nw_link_unref(zone
->link
);
63 zone
->link
= nw_link_ref(link
);
65 DEBUG("Zone %s: Assigned link %d\n", zone
->name
, nw_link_ifindex(zone
->link
));
67 // Or clear the pointer if no link has been provided
71 DEBUG("Zone %s: Removed link\n", zone
->name
);
77 static int nw_zone_setup(nw_zone
* zone
) {
82 link
= nw_daemon_get_link_by_name(zone
->daemon
, zone
->name
);
84 r
= nw_zone_set_link(zone
, link
);
96 int nw_zone_create(nw_zone
** zone
, nw_daemon
* daemon
, const nw_zone_type_id_t type
,
97 const char* name
, nw_config
* config
) {
101 // Allocate a new object
102 z
= calloc(1, sizeof(*z
));
106 // Store a reference to the daemon
107 z
->daemon
= nw_daemon_ref(daemon
);
109 // Initialize reference counter
113 r
= nw_string_set(z
->name
, name
);
117 // Copy the configuration
118 r
= nw_config_copy(config
, &z
->config
);
123 r
= nw_zone_setup(z
);
135 int nw_zone_open(nw_zone
** zone
, nw_daemon
* daemon
, const char* name
, FILE* f
) {
136 nw_config
* config
= NULL
;
139 // Initialize the configuration
140 r
= nw_config_create(&config
, f
);
145 const char* type
= nw_config_get(config
, "TYPE");
147 ERROR("Zone %s has no TYPE\n", name
);
153 r
= nw_zone_create(zone
, daemon
, nw_zone_type_id_from_string(type
), name
, config
);
159 nw_config_unref(config
);
164 nw_zone
* nw_zone_ref(nw_zone
* zone
) {
170 nw_zone
* nw_zone_unref(nw_zone
* zone
) {
171 if (--zone
->nrefs
> 0)
178 int __nw_zone_drop_port(nw_daemon
* daemon
, nw_zone
* zone
, void* data
) {
179 nw_port
* dropped_port
= (nw_port
*)data
;
187 int nw_zone_save(nw_zone
* zone
) {
188 nw_configd
* configd
= NULL
;
192 // Fetch configuration directory
193 configd
= nw_daemon_configd(zone
->daemon
, "zones");
200 f
= nw_configd_fopen(configd
, zone
->name
, "w");
206 // Write out the configuration
207 r
= nw_config_options_write(zone
->config
);
211 // Write the configuration
212 r
= nw_config_write(zone
->config
, f
);
218 nw_configd_unref(configd
);
222 ERROR("Could not save configuration for zone %s: %s\n", zone
->name
, strerror(-r
));
227 const char* nw_zone_name(nw_zone
* zone
) {
231 char* nw_zone_bus_path(nw_zone
* zone
) {
235 // Encode the bus path
236 r
= sd_bus_path_encode("/org/ipfire/network1/zone", zone
->name
, &p
);
243 int __nw_zone_set_link(nw_daemon
* daemon
, nw_zone
* zone
, void* data
) {
244 nw_link
* link
= (nw_link
*)data
;
246 // Fetch the link name
247 const char* ifname
= nw_link_ifname(link
);
249 ERROR("Link does not have a name set\n");
253 // Set link if the name matches
254 if (strcmp(zone
->name
, ifname
) == 0)
255 return nw_zone_set_link(zone
, link
);
257 // If we have the link set but the name did not match, we will remove it
258 else if (zone
->link
== link
)
259 return nw_zone_set_link(zone
, NULL
);
264 int __nw_zone_drop_link(nw_daemon
* daemon
, nw_zone
* zone
, void* data
) {
265 nw_link
* link
= (nw_link
*)data
;
267 // Drop the link if it matches
268 if (zone
->link
== link
)
269 return nw_zone_set_link(zone
, NULL
);
274 int nw_zone_reconfigure(nw_zone
* zone
) {
275 return 0; // XXX TODO
280 int nw_zone_has_carrier(nw_zone
* zone
) {
284 return nw_link_has_carrier(zone
->link
);
290 unsigned int nw_zone_mtu(nw_zone
* zone
) {
291 return nw_config_get_int(zone
->config
, "MTU", NETWORK_ZONE_DEFAULT_MTU
);
294 int nw_zone_set_mtu(nw_zone
* zone
, unsigned int mtu
) {
295 DEBUG("Change MTU of %s to %u\n", zone
->name
, mtu
);
297 return nw_config_set_int(zone
->config
, "MTU", mtu
);
304 const struct rtnl_link_stats64
* nw_zone_get_stats64(nw_zone
* zone
) {
308 return nw_link_get_stats64(zone
->link
);
311 int __nw_zone_update_stats(nw_daemon
* daemon
, nw_zone
* zone
, void* data
) {
312 nw_link
* link
= (nw_link
*)data
;
314 // Emit stats if link matches
315 if (zone
->link
== link
)
316 return nw_stats_collector_emit_zone_stats(daemon
, zone
);
321 int nw_zone_update_stats(nw_zone
* zone
) {
323 return nw_link_update_stats(zone
->link
);