]>
Commit | Line | Data |
---|---|---|
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 |
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 | ||
2361667e | 41 | static 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 |
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 | ||
2361667e | 77 | static 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 |
89 | ERROR: |
90 | if (link) | |
91 | nw_link_unref(link); | |
92 | ||
93 | return r; | |
00b5de56 MT |
94 | } |
95 | ||
25808f65 MT |
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; | |
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 | ||
130 | ERROR: | |
131 | nw_zone_free(z); | |
132 | return r; | |
133 | } | |
134 | ||
25808f65 MT |
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 | ||
2361667e | 164 | nw_zone* nw_zone_ref(nw_zone* zone) { |
e4eebc6e MT |
165 | zone->nrefs++; |
166 | ||
167 | return zone; | |
168 | } | |
169 | ||
2361667e | 170 | nw_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 |
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 | ||
605e975f | 187 | int 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 | 216 | ERROR: |
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 | 227 | const char* nw_zone_name(nw_zone* zone) { |
e4eebc6e MT |
228 | return zone->name; |
229 | } | |
ebc65f19 | 230 | |
2361667e | 231 | char* 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 |
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); | |
4e989bd5 | 260 | |
611d4aca MT |
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; | |
20375a08 MT |
272 | } |
273 | ||
b9769b09 MT |
274 | int nw_zone_reconfigure(nw_zone* zone) { |
275 | return 0; // XXX TODO | |
276 | } | |
277 | ||
20375a08 MT |
278 | // Carrier |
279 | ||
280 | int 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 | 290 | unsigned 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 | 294 | int 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 | ||
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 | } |