]>
Commit | Line | Data |
---|---|---|
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 | ||
31 | struct 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 | ||
38 | struct 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 | 49 | static 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 | 69 | static 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 | 91 | nw_zones* nw_zones_ref(nw_zones* zones) { |
0c8e7342 MT |
92 | zones->nrefs++; |
93 | ||
94 | return zones; | |
95 | } | |
96 | ||
2361667e | 97 | nw_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 | 105 | static 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 | ||
123 | static 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 | 137 | static 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 | ||
174 | ERROR: | |
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 | 186 | int 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 | ||
201 | ERROR: | |
202 | nw_zones_unref(*zones); | |
203 | return r; | |
204 | } | |
205 | ||
2361667e | 206 | size_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 | 217 | nw_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 | 232 | int 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 | ||
259 | ERROR: | |
260 | if (p) { | |
261 | for (char** e = p; *e; e++) | |
262 | free(*e); | |
263 | free(p); | |
264 | } | |
265 | ||
266 | return 1; | |
267 | } |