]> git.ipfire.org Git - people/ms/network.git/blob - src/networkd/zone.c
Makefile: Fix typo in localstatedir
[people/ms/network.git] / src / networkd / zone.c
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
21 #include <limits.h>
22 #include <linux/if_link.h>
23 #include <stdlib.h>
24
25 #include <systemd/sd-bus.h>
26
27 #include "config.h"
28 #include "daemon.h"
29 #include "link.h"
30 #include "logging.h"
31 #include "stats-collector.h"
32 #include "string.h"
33 #include "zone.h"
34
35 static const nw_string_table_t nw_zone_type_id[] = {
36 { -1, NULL },
37 };
38
39 NW_STRING_TABLE_LOOKUP(nw_zone_type_id_t, nw_zone_type_id)
40
41 static void nw_zone_free(nw_zone* zone) {
42 if (zone->link)
43 nw_link_unref(zone->link);
44 if (zone->config)
45 nw_config_unref(zone->config);
46 if (zone->daemon)
47 nw_daemon_unref(zone->daemon);
48
49 free(zone);
50 }
51
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)
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
77 static int nw_zone_setup(nw_zone* zone) {
78 nw_link* link = NULL;
79 int r = 0;
80
81 // Find the link
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;
87 }
88
89 ERROR:
90 if (link)
91 nw_link_unref(link);
92
93 return r;
94 }
95
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) {
98 nw_zone* z = NULL;
99 int r;
100
101 // Allocate a new object
102 z = calloc(1, sizeof(*z));
103 if (!z)
104 return -errno;
105
106 // Store a reference to the daemon
107 z->daemon = nw_daemon_ref(daemon);
108
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
117 // Copy the configuration
118 r = nw_config_copy(config, &z->config);
119 if (r < 0)
120 goto ERROR;
121
122 // Setup the zone
123 r = nw_zone_setup(z);
124 if (r)
125 goto ERROR;
126
127 *zone = z;
128 return 0;
129
130 ERROR:
131 nw_zone_free(z);
132 return r;
133 }
134
135 int 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
157 ERROR:
158 if (config)
159 nw_config_unref(config);
160
161 return r;
162 }
163
164 nw_zone* nw_zone_ref(nw_zone* zone) {
165 zone->nrefs++;
166
167 return zone;
168 }
169
170 nw_zone* nw_zone_unref(nw_zone* zone) {
171 if (--zone->nrefs > 0)
172 return zone;
173
174 nw_zone_free(zone);
175 return NULL;
176 }
177
178 int __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
187 int nw_zone_save(nw_zone* zone) {
188 nw_configd* configd = NULL;
189 FILE* f = NULL;
190 int r;
191
192 // Fetch configuration directory
193 configd = nw_daemon_configd(zone->daemon, "zones");
194 if (!configd) {
195 r = -errno;
196 goto ERROR;
197 }
198
199 // Open file
200 f = nw_configd_fopen(configd, zone->name, "w");
201 if (!f) {
202 r = -errno;
203 goto ERROR;
204 }
205
206 // Write out the configuration
207 r = nw_config_options_write(zone->config);
208 if (r < 0)
209 goto ERROR;
210
211 // Write the configuration
212 r = nw_config_write(zone->config, f);
213 if (r < 0)
214 goto ERROR;
215
216 ERROR:
217 if (configd)
218 nw_configd_unref(configd);
219 if (f)
220 fclose(f);
221 if (r)
222 ERROR("Could not save configuration for zone %s: %s\n", zone->name, strerror(-r));
223
224 return r;
225 }
226
227 const char* nw_zone_name(nw_zone* zone) {
228 return zone->name;
229 }
230
231 char* nw_zone_bus_path(nw_zone* zone) {
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 }
242
243 int __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);
260
261 return 0;
262 }
263
264 int __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;
272 }
273
274 int nw_zone_reconfigure(nw_zone* zone) {
275 return 0; // XXX TODO
276 }
277
278 // Carrier
279
280 int nw_zone_has_carrier(nw_zone* zone) {
281 if (!zone->link)
282 return 0;
283
284 return nw_link_has_carrier(zone->link);
285 }
286
287 /*
288 MTU
289 */
290 unsigned int nw_zone_mtu(nw_zone* zone) {
291 return nw_config_get_int(zone->config, "MTU", NETWORK_ZONE_DEFAULT_MTU);
292 }
293
294 int nw_zone_set_mtu(nw_zone* zone, unsigned int mtu) {
295 DEBUG("Change MTU of %s to %u\n", zone->name, mtu);
296
297 return nw_config_set_int(zone->config, "MTU", mtu);
298 }
299
300 /*
301 Stats
302 */
303
304 const 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
311 int __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
321 int nw_zone_update_stats(nw_zone* zone) {
322 if (zone->link)
323 return nw_link_update_stats(zone->link);
324
325 return 0;
326 }