]> git.ipfire.org Git - people/ms/network.git/blame - src/networkd/zones.c
networkd: Store a reference to the daemon in zone
[people/ms/network.git] / src / networkd / zones.c
CommitLineData
0c8e7342
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
21#include <dirent.h>
22#include <stdlib.h>
23#include <string.h>
24#include <sys/queue.h>
25
dd84704e 26#include "daemon.h"
0c8e7342
MT
27#include "logging.h"
28#include "zone.h"
29#include "zones.h"
30
31struct nw_zones_entry {
2361667e 32 nw_zone* zone;
0c8e7342
MT
33
34 // Link to the other entries
35 STAILQ_ENTRY(nw_zones_entry) nodes;
36};
37
38struct nw_zones {
dd84704e 39 nw_daemon* daemon;
0c8e7342
MT
40 int nrefs;
41
ebc65f19 42 // Zone Entries
0c8e7342 43 STAILQ_HEAD(entries, nw_zones_entry) entries;
ebc65f19
MT
44
45 // A counter of the zone entries
46 unsigned int num;
0c8e7342
MT
47};
48
dd84704e 49static int nw_zones_create(nw_zones** zones, nw_daemon* daemon) {
2361667e 50 nw_zones* z = calloc(1, sizeof(*z));
0c8e7342
MT
51 if (!z)
52 return 1;
53
dd84704e
MT
54 // Store a reference to the daemon
55 z->daemon = nw_daemon_ref(daemon);
56
0c8e7342
MT
57 // Initialize the reference counter
58 z->nrefs = 1;
59
60 // Initialize entries
61 STAILQ_INIT(&z->entries);
62
63 // Reference the pointer
64 *zones = z;
65
66 return 0;
67}
68
2361667e 69static void nw_zones_free(nw_zones* zones) {
0c8e7342
MT
70 struct nw_zones_entry* entry = NULL;
71
72 while (!STAILQ_EMPTY(&zones->entries)) {
73 entry = STAILQ_FIRST(&zones->entries);
74
75 // Dereference the zone
76 nw_zone_unref(entry->zone);
77
78 // Remove the entry from the list
79 STAILQ_REMOVE_HEAD(&zones->entries, nodes);
80
81 // Free the entry
82 free(entry);
83 }
dd84704e
MT
84
85 if (zones->daemon)
86 nw_daemon_unref(zones->daemon);
87
88 free(zones);
0c8e7342
MT
89}
90
2361667e 91nw_zones* nw_zones_ref(nw_zones* zones) {
0c8e7342
MT
92 zones->nrefs++;
93
94 return zones;
95}
96
2361667e 97nw_zones* nw_zones_unref(nw_zones* zones) {
0c8e7342
MT
98 if (--zones->nrefs > 0)
99 return zones;
100
101 nw_zones_free(zones);
102 return NULL;
103}
104
2361667e 105static int nw_zones_add_zone(nw_zones* zones, nw_zone* zone) {
0c8e7342
MT
106 // Allocate a new entry
107 struct nw_zones_entry* entry = calloc(1, sizeof(*entry));
108 if (!entry)
109 return 1;
110
111 // Reference the zone
112 entry->zone = nw_zone_ref(zone);
113
114 // Add it to the list
115 STAILQ_INSERT_TAIL(&zones->entries, entry, nodes);
116
ebc65f19
MT
117 // Increment the counter
118 zones->num++;
119
0c8e7342
MT
120 return 0;
121}
122
123static int nw_zones_load_filter(const struct dirent* path) {
124 const char* fn = path->d_name;
125
126 // Ignore everything starting with '.'
127 if (*fn == '.')
128 return 0;
129
130 // Ignore anything that isn't a directory
131 if (path->d_type != DT_DIR)
132 return 0;
133
134 return 1;
135}
136
2361667e 137static int __nw_zones_load(nw_zones* zones) {
0c8e7342
MT
138 struct dirent** paths = NULL;
139 int n;
140 int r = 0;
141
2361667e 142 nw_zone* zone = NULL;
0c8e7342
MT
143
144 // Scan the zones directory
145 n = scandir(CONFIG_DIR "/zones", &paths, nw_zones_load_filter, alphasort);
146 if (n < 0) {
147 ERROR("Could not load zones: %m\n");
148 return 1;
149 }
150
151 DEBUG("Found %d zone(s)\n", n);
152
153 // Load all zones
154 for (int i = 0; i < n; i++) {
155 const char* name = paths[i]->d_name;
156
157 DEBUG("Loading zone '%s'...\n", name);
158
159 // Create a new zone object
dd84704e 160 r = nw_zone_create(&zone, zones->daemon, name);
0c8e7342
MT
161 if (r)
162 goto ERROR;
163
164 // Store the zone
165 r = nw_zones_add_zone(zones, zone);
166 if (r) {
167 nw_zone_unref(zone);
168 goto ERROR;
169 }
170
171 nw_zone_unref(zone);
172 }
173
174ERROR:
175 // Free paths
176 if (paths) {
177 for (int i = 0; i < n; i++) {
178 free(paths[i]);
179 }
180 free(paths);
181 }
182
183 return r;
184}
185
dd84704e 186int nw_zones_load(nw_zones** zones, nw_daemon* daemon) {
0c8e7342
MT
187 int r;
188
189 // Create a new zones object
dd84704e 190 r = nw_zones_create(zones, daemon);
0c8e7342
MT
191 if (r)
192 return r;
193
194 // Load all zones
195 r = __nw_zones_load(*zones);
196 if (r)
197 goto ERROR;
198
199 return 0;
200
201ERROR:
202 nw_zones_unref(*zones);
203 return r;
204}
205
2361667e 206size_t nw_zones_num(nw_zones* zones) {
0c8e7342
MT
207 struct nw_zones_entry* entry = NULL;
208 size_t length = 0;
209
210 // Count all zones
211 STAILQ_FOREACH(entry, &zones->entries, nodes)
212 length++;
213
214 return length;
215}
216
2361667e 217nw_zone* nw_zones_get_by_name(nw_zones* zones, const char* name) {
0c8e7342
MT
218 struct nw_zones_entry* entry = NULL;
219
220 STAILQ_FOREACH(entry, &zones->entries, nodes) {
221 const char* __name = nw_zone_name(entry->zone);
222
223 // If the name matches, return a reference to the zone
224 if (strcmp(name, __name) == 0)
225 return nw_zone_ref(entry->zone);
226 }
227
228 // No match found
229 return NULL;
230}
ebc65f19 231
2361667e 232int nw_zones_bus_paths(nw_zones* zones, char*** paths) {
ebc65f19
MT
233 struct nw_zones_entry* entry = NULL;
234 char* path = NULL;
235
236 // Allocate an array for all paths
237 char** p = calloc(zones->num + 1, sizeof(*p));
238 if (!p)
239 return 1;
240
241 unsigned int i = 0;
242
243 // Walk through all zones
244 STAILQ_FOREACH(entry, &zones->entries, nodes) {
245 // Generate the bus path
246 path = nw_zone_bus_path(entry->zone);
247 if (!path)
248 goto ERROR;
249
250 // Append the bus path to the array
251 p[i++] = path;
252 }
253
254 // Return pointer
255 *paths = p;
256
257 return 0;
258
259ERROR:
260 if (p) {
261 for (char** e = p; *e; e++)
262 free(*e);
263 free(p);
264 }
265
266 return 1;
267}