]>
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 | ||
26 | #include "logging.h" | |
27 | #include "zone.h" | |
28 | #include "zones.h" | |
29 | ||
30 | struct nw_zones_entry { | |
31 | struct nw_zone* zone; | |
32 | ||
33 | // Link to the other entries | |
34 | STAILQ_ENTRY(nw_zones_entry) nodes; | |
35 | }; | |
36 | ||
37 | struct nw_zones { | |
38 | int nrefs; | |
39 | ||
40 | STAILQ_HEAD(entries, nw_zones_entry) entries; | |
41 | }; | |
42 | ||
43 | static 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 | ||
60 | static 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 | ||
77 | struct nw_zones* nw_zones_ref(struct nw_zones* zones) { | |
78 | zones->nrefs++; | |
79 | ||
80 | return zones; | |
81 | } | |
82 | ||
83 | struct 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 | ||
91 | static 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 | ||
106 | static 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 | ||
120 | static 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 | ||
157 | ERROR: | |
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 | ||
169 | int 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 | ||
184 | ERROR: | |
185 | nw_zones_unref(*zones); | |
186 | return r; | |
187 | } | |
188 | ||
189 | size_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 | ||
200 | struct 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 | } |