]> git.ipfire.org Git - people/ms/network.git/blame - src/networkd/zones.c
networkd: Move zone list into an own object
[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
26#include "logging.h"
27#include "zone.h"
28#include "zones.h"
29
30struct nw_zones_entry {
31 struct nw_zone* zone;
32
33 // Link to the other entries
34 STAILQ_ENTRY(nw_zones_entry) nodes;
35};
36
37struct nw_zones {
38 int nrefs;
39
40 STAILQ_HEAD(entries, nw_zones_entry) entries;
41};
42
43static int nw_zones_create(struct nw_zones** zones) {
44 struct nw_zones* z = calloc(1, sizeof(*z));
45 if (!z)
46 return 1;
47
48 // Initialize the reference counter
49 z->nrefs = 1;
50
51 // Initialize entries
52 STAILQ_INIT(&z->entries);
53
54 // Reference the pointer
55 *zones = z;
56
57 return 0;
58}
59
60static void nw_zones_free(struct nw_zones* zones) {
61 struct nw_zones_entry* entry = NULL;
62
63 while (!STAILQ_EMPTY(&zones->entries)) {
64 entry = STAILQ_FIRST(&zones->entries);
65
66 // Dereference the zone
67 nw_zone_unref(entry->zone);
68
69 // Remove the entry from the list
70 STAILQ_REMOVE_HEAD(&zones->entries, nodes);
71
72 // Free the entry
73 free(entry);
74 }
75}
76
77struct nw_zones* nw_zones_ref(struct nw_zones* zones) {
78 zones->nrefs++;
79
80 return zones;
81}
82
83struct nw_zones* nw_zones_unref(struct nw_zones* zones) {
84 if (--zones->nrefs > 0)
85 return zones;
86
87 nw_zones_free(zones);
88 return NULL;
89}
90
91static int nw_zones_add_zone(struct nw_zones* zones, struct nw_zone* zone) {
92 // Allocate a new entry
93 struct nw_zones_entry* entry = calloc(1, sizeof(*entry));
94 if (!entry)
95 return 1;
96
97 // Reference the zone
98 entry->zone = nw_zone_ref(zone);
99
100 // Add it to the list
101 STAILQ_INSERT_TAIL(&zones->entries, entry, nodes);
102
103 return 0;
104}
105
106static int nw_zones_load_filter(const struct dirent* path) {
107 const char* fn = path->d_name;
108
109 // Ignore everything starting with '.'
110 if (*fn == '.')
111 return 0;
112
113 // Ignore anything that isn't a directory
114 if (path->d_type != DT_DIR)
115 return 0;
116
117 return 1;
118}
119
120static int __nw_zones_load(struct nw_zones* zones) {
121 struct dirent** paths = NULL;
122 int n;
123 int r = 0;
124
125 struct nw_zone* zone = NULL;
126
127 // Scan the zones directory
128 n = scandir(CONFIG_DIR "/zones", &paths, nw_zones_load_filter, alphasort);
129 if (n < 0) {
130 ERROR("Could not load zones: %m\n");
131 return 1;
132 }
133
134 DEBUG("Found %d zone(s)\n", n);
135
136 // Load all zones
137 for (int i = 0; i < n; i++) {
138 const char* name = paths[i]->d_name;
139
140 DEBUG("Loading zone '%s'...\n", name);
141
142 // Create a new zone object
143 r = nw_zone_create(&zone, name);
144 if (r)
145 goto ERROR;
146
147 // Store the zone
148 r = nw_zones_add_zone(zones, zone);
149 if (r) {
150 nw_zone_unref(zone);
151 goto ERROR;
152 }
153
154 nw_zone_unref(zone);
155 }
156
157ERROR:
158 // Free paths
159 if (paths) {
160 for (int i = 0; i < n; i++) {
161 free(paths[i]);
162 }
163 free(paths);
164 }
165
166 return r;
167}
168
169int nw_zones_load(struct nw_zones** zones) {
170 int r;
171
172 // Create a new zones object
173 r = nw_zones_create(zones);
174 if (r)
175 return r;
176
177 // Load all zones
178 r = __nw_zones_load(*zones);
179 if (r)
180 goto ERROR;
181
182 return 0;
183
184ERROR:
185 nw_zones_unref(*zones);
186 return r;
187}
188
189size_t nw_zones_num(struct nw_zones* zones) {
190 struct nw_zones_entry* entry = NULL;
191 size_t length = 0;
192
193 // Count all zones
194 STAILQ_FOREACH(entry, &zones->entries, nodes)
195 length++;
196
197 return length;
198}
199
200struct nw_zone* nw_zones_get_by_name(struct nw_zones* zones, const char* name) {
201 struct nw_zones_entry* entry = NULL;
202
203 STAILQ_FOREACH(entry, &zones->entries, nodes) {
204 const char* __name = nw_zone_name(entry->zone);
205
206 // If the name matches, return a reference to the zone
207 if (strcmp(name, __name) == 0)
208 return nw_zone_ref(entry->zone);
209 }
210
211 // No match found
212 return NULL;
213}