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