]> git.ipfire.org Git - people/ms/network.git/blame - src/networkd/zone.c
zones: Move "struct nw_zone" into header
[people/ms/network.git] / src / networkd / zone.c
CommitLineData
e4eebc6e
MT
1/*#############################################################################
2# #
3# IPFire.org - A linux based firewall #
4# Copyright (C) 2023 IPFire Network Development Team #
5# #
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. #
10# #
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. #
15# #
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/>. #
18# #
19#############################################################################*/
20
00b5de56 21#include <limits.h>
15240e08 22#include <linux/if_link.h>
e4eebc6e
MT
23#include <stdlib.h>
24
ebc65f19
MT
25#include <systemd/sd-bus.h>
26
e4eebc6e 27#include "config.h"
dd84704e 28#include "daemon.h"
4e989bd5 29#include "link.h"
9368a163 30#include "logging.h"
15240e08 31#include "stats-collector.h"
e4eebc6e
MT
32#include "string.h"
33#include "zone.h"
34
25808f65
MT
35static const nw_string_table_t nw_zone_type_id[] = {
36 { -1, NULL },
37};
38
39NW_STRING_TABLE_LOOKUP(nw_zone_type_id_t, nw_zone_type_id)
40
2361667e 41static void nw_zone_free(nw_zone* zone) {
4e989bd5
MT
42 if (zone->link)
43 nw_link_unref(zone->link);
e4eebc6e
MT
44 if (zone->config)
45 nw_config_unref(zone->config);
dd84704e
MT
46 if (zone->daemon)
47 nw_daemon_unref(zone->daemon);
e4eebc6e
MT
48
49 free(zone);
50}
51
611d4aca
MT
52static 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)
55 return 0;
56
57 // Dereference the former link if set
58 if (zone->link)
59 nw_link_unref(zone->link);
60
61 // Store the new link
62 if (link) {
63 zone->link = nw_link_ref(link);
64
65 DEBUG("Zone %s: Assigned link %d\n", zone->name, nw_link_ifindex(zone->link));
66
67 // Or clear the pointer if no link has been provided
68 } else {
69 zone->link = NULL;
70
71 DEBUG("Zone %s: Removed link\n", zone->name);
72 }
73
74 return 0;
75}
76
2361667e 77static int nw_zone_setup(nw_zone* zone) {
611d4aca 78 nw_link* link = NULL;
25808f65 79 int r = 0;
00b5de56 80
4e989bd5 81 // Find the link
611d4aca
MT
82 link = nw_daemon_get_link_by_name(zone->daemon, zone->name);
83 if (link) {
84 r = nw_zone_set_link(zone, link);
85 if (r)
86 goto ERROR;
4e989bd5
MT
87 }
88
611d4aca
MT
89ERROR:
90 if (link)
91 nw_link_unref(link);
92
93 return r;
00b5de56
MT
94}
95
25808f65
MT
96int nw_zone_create(nw_zone** zone, nw_daemon* daemon, const nw_zone_type_id_t type,
97 const char* name, nw_config* config) {
98 nw_zone* z = NULL;
e4eebc6e
MT
99 int r;
100
101 // Allocate a new object
25808f65 102 z = calloc(1, sizeof(*z));
e4eebc6e 103 if (!z)
25808f65 104 return -errno;
e4eebc6e 105
dd84704e
MT
106 // Store a reference to the daemon
107 z->daemon = nw_daemon_ref(daemon);
108
e4eebc6e
MT
109 // Initialize reference counter
110 z->nrefs = 1;
111
112 // Store the name
113 r = nw_string_set(z->name, name);
114 if (r)
115 goto ERROR;
116
25808f65
MT
117 // Copy the configuration
118 r = nw_config_copy(config, &z->config);
119 if (r < 0)
120 goto ERROR;
121
00b5de56
MT
122 // Setup the zone
123 r = nw_zone_setup(z);
124 if (r)
125 goto ERROR;
126
e4eebc6e
MT
127 *zone = z;
128 return 0;
129
130ERROR:
131 nw_zone_free(z);
132 return r;
133}
134
25808f65
MT
135int nw_zone_open(nw_zone** zone, nw_daemon* daemon, const char* name, FILE* f) {
136 nw_config* config = NULL;
137 int r;
138
139 // Initialize the configuration
140 r = nw_config_create(&config, f);
141 if (r < 0)
142 goto ERROR;
143
144 // Fetch the type
145 const char* type = nw_config_get(config, "TYPE");
146 if (!type) {
147 ERROR("Zone %s has no TYPE\n", name);
148 r = -ENOTSUP;
149 goto ERROR;
150 }
151
152 // Create a new zone
153 r = nw_zone_create(zone, daemon, nw_zone_type_id_from_string(type), name, config);
154 if (r < 0)
155 goto ERROR;
156
157ERROR:
158 if (config)
159 nw_config_unref(config);
160
161 return r;
162}
163
2361667e 164nw_zone* nw_zone_ref(nw_zone* zone) {
e4eebc6e
MT
165 zone->nrefs++;
166
167 return zone;
168}
169
2361667e 170nw_zone* nw_zone_unref(nw_zone* zone) {
e4eebc6e
MT
171 if (--zone->nrefs > 0)
172 return zone;
173
174 nw_zone_free(zone);
175 return NULL;
176}
177
c403eb4c
MT
178int __nw_zone_drop_port(nw_daemon* daemon, nw_zone* zone, void* data) {
179 nw_port* dropped_port = (nw_port*)data;
180
181 // XXX TODO
182 (void)dropped_port;
183
184 return 0;
185}
186
605e975f 187int nw_zone_save(nw_zone* zone) {
25808f65 188 nw_configd* configd = NULL;
8edf3da1 189 FILE* f = NULL;
605e975f
MT
190 int r;
191
25808f65
MT
192 // Fetch configuration directory
193 configd = nw_daemon_configd(zone->daemon, "zones");
194 if (!configd) {
195 r = -errno;
8edf3da1 196 goto ERROR;
25808f65 197 }
8edf3da1
MT
198
199 // Open file
25808f65 200 f = nw_configd_fopen(configd, zone->name, "w");
8edf3da1
MT
201 if (!f) {
202 r = -errno;
203 goto ERROR;
204 }
205
25808f65
MT
206 // Write out the configuration
207 r = nw_config_options_write(zone->config);
208 if (r < 0)
209 goto ERROR;
210
8edf3da1
MT
211 // Write the configuration
212 r = nw_config_write(zone->config, f);
25808f65 213 if (r < 0)
8edf3da1 214 goto ERROR;
605e975f 215
8edf3da1 216ERROR:
25808f65
MT
217 if (configd)
218 nw_configd_unref(configd);
8edf3da1
MT
219 if (f)
220 fclose(f);
25808f65
MT
221 if (r)
222 ERROR("Could not save configuration for zone %s: %s\n", zone->name, strerror(-r));
8edf3da1
MT
223
224 return r;
605e975f
MT
225}
226
2361667e 227const char* nw_zone_name(nw_zone* zone) {
e4eebc6e
MT
228 return zone->name;
229}
ebc65f19 230
2361667e 231char* nw_zone_bus_path(nw_zone* zone) {
ebc65f19
MT
232 char* p = NULL;
233 int r;
234
235 // Encode the bus path
236 r = sd_bus_path_encode("/org/ipfire/network1/zone", zone->name, &p);
237 if (r < 0)
238 return NULL;
239
240 return p;
241}
9368a163 242
611d4aca
MT
243int __nw_zone_set_link(nw_daemon* daemon, nw_zone* zone, void* data) {
244 nw_link* link = (nw_link*)data;
245
246 // Fetch the link name
247 const char* ifname = nw_link_ifname(link);
248 if (!ifname) {
249 ERROR("Link does not have a name set\n");
250 return 1;
251 }
252
253 // Set link if the name matches
254 if (strcmp(zone->name, ifname) == 0)
255 return nw_zone_set_link(zone, link);
256
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);
4e989bd5 260
611d4aca
MT
261 return 0;
262}
263
264int __nw_zone_drop_link(nw_daemon* daemon, nw_zone* zone, void* data) {
265 nw_link* link = (nw_link*)data;
266
267 // Drop the link if it matches
268 if (zone->link == link)
269 return nw_zone_set_link(zone, NULL);
270
271 return 0;
20375a08
MT
272}
273
b9769b09
MT
274int nw_zone_reconfigure(nw_zone* zone) {
275 return 0; // XXX TODO
276}
277
20375a08
MT
278// Carrier
279
280int nw_zone_has_carrier(nw_zone* zone) {
4e989bd5
MT
281 if (!zone->link)
282 return 0;
20375a08 283
4e989bd5 284 return nw_link_has_carrier(zone->link);
20375a08
MT
285}
286
9368a163
MT
287/*
288 MTU
289*/
2361667e 290unsigned int nw_zone_mtu(nw_zone* zone) {
9368a163
MT
291 return nw_config_get_int(zone->config, "MTU", NETWORK_ZONE_DEFAULT_MTU);
292}
293
2361667e 294int nw_zone_set_mtu(nw_zone* zone, unsigned int mtu) {
9368a163
MT
295 DEBUG("Change MTU of %s to %u\n", zone->name, mtu);
296
297 return nw_config_set_int(zone->config, "MTU", mtu);
298}
15240e08
MT
299
300/*
301 Stats
302*/
303
304const struct rtnl_link_stats64* nw_zone_get_stats64(nw_zone* zone) {
305 if (!zone->link)
306 return NULL;
307
308 return nw_link_get_stats64(zone->link);
309}
310
311int __nw_zone_update_stats(nw_daemon* daemon, nw_zone* zone, void* data) {
312 nw_link* link = (nw_link*)data;
313
314 // Emit stats if link matches
315 if (zone->link == link)
316 return nw_stats_collector_emit_zone_stats(daemon, zone);
317
318 return 0;
319}
320
321int nw_zone_update_stats(nw_zone* zone) {
322 if (zone->link)
323 return nw_link_update_stats(zone->link);
324
325 return 0;
326}