source: mainline/uspace/srv/net/inetsrv/sroute.c

Last change on this file was 36fcd0a, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 9 months ago

Fix 32b build

  • Property mode set to 100644
File size: 8.9 KB
Line 
1/*
2 * Copyright (c) 2024 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup inet
30 * @{
31 */
32/**
33 * @file
34 * @brief
35 */
36
37#include <bitops.h>
38#include <errno.h>
39#include <fibril_synch.h>
40#include <io/log.h>
41#include <ipc/loc.h>
42#include <sif.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <str.h>
46#include "sroute.h"
47#include "inetsrv.h"
48#include "inet_link.h"
49
50static FIBRIL_MUTEX_INITIALIZE(sroute_list_lock);
51static LIST_INITIALIZE(sroute_list);
52static sysarg_t sroute_id = 0;
53
54inet_sroute_t *inet_sroute_new(void)
55{
56 inet_sroute_t *sroute = calloc(1, sizeof(inet_sroute_t));
57
58 if (sroute == NULL) {
59 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed allocating static route object. "
60 "Out of memory.");
61 return NULL;
62 }
63
64 link_initialize(&sroute->sroute_list);
65 fibril_mutex_lock(&sroute_list_lock);
66 sroute->id = ++sroute_id;
67 fibril_mutex_unlock(&sroute_list_lock);
68
69 return sroute;
70}
71
72void inet_sroute_delete(inet_sroute_t *sroute)
73{
74 if (sroute->name != NULL)
75 free(sroute->name);
76 free(sroute);
77}
78
79void inet_sroute_add(inet_sroute_t *sroute)
80{
81 fibril_mutex_lock(&sroute_list_lock);
82 list_append(&sroute->sroute_list, &sroute_list);
83 fibril_mutex_unlock(&sroute_list_lock);
84}
85
86void inet_sroute_remove(inet_sroute_t *sroute)
87{
88 fibril_mutex_lock(&sroute_list_lock);
89 list_remove(&sroute->sroute_list);
90 fibril_mutex_unlock(&sroute_list_lock);
91}
92
93/** Find static route object matching address @a addr.
94 *
95 * @param addr Address
96 */
97inet_sroute_t *inet_sroute_find(inet_addr_t *addr)
98{
99 ip_ver_t addr_ver = inet_addr_get(addr, NULL, NULL);
100
101 inet_sroute_t *best = NULL;
102 uint8_t best_bits = 0;
103
104 fibril_mutex_lock(&sroute_list_lock);
105
106 list_foreach(sroute_list, sroute_list, inet_sroute_t, sroute) {
107 uint8_t dest_bits;
108 ip_ver_t dest_ver = inet_naddr_get(&sroute->dest, NULL, NULL,
109 &dest_bits);
110
111 /* Skip comparison with different address family */
112 if (addr_ver != dest_ver)
113 continue;
114
115 /* Look for the most specific route */
116 if ((best != NULL) && (best_bits >= dest_bits))
117 continue;
118
119 if (inet_naddr_compare_mask(&sroute->dest, addr)) {
120 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_sroute_find: found candidate %p",
121 sroute);
122
123 best = sroute;
124 best_bits = dest_bits;
125 }
126 }
127
128 if (best == NULL)
129 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_sroute_find: Not found");
130
131 fibril_mutex_unlock(&sroute_list_lock);
132
133 return best;
134}
135
136/** Find static route with a specific name.
137 *
138 * @param name Address object name
139 * @return Address object
140 */
141inet_sroute_t *inet_sroute_find_by_name(const char *name)
142{
143 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_sroute_find_by_name('%s')",
144 name);
145
146 fibril_mutex_lock(&sroute_list_lock);
147
148 list_foreach(sroute_list, sroute_list, inet_sroute_t, sroute) {
149 if (str_cmp(sroute->name, name) == 0) {
150 fibril_mutex_unlock(&sroute_list_lock);
151 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_sroute_find_by_name: found %p",
152 sroute);
153 return sroute;
154 }
155 }
156
157 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_sroute_find_by_name: Not found");
158 fibril_mutex_unlock(&sroute_list_lock);
159
160 return NULL;
161}
162
163/** Find static route with the given ID.
164 *
165 * @param id Address object ID
166 * @return Address object
167 */
168inet_sroute_t *inet_sroute_get_by_id(sysarg_t id)
169{
170 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_sroute_get_by_id(%zu)", (size_t)id);
171
172 fibril_mutex_lock(&sroute_list_lock);
173
174 list_foreach(sroute_list, sroute_list, inet_sroute_t, sroute) {
175 if (sroute->id == id) {
176 fibril_mutex_unlock(&sroute_list_lock);
177 return sroute;
178 }
179 }
180
181 fibril_mutex_unlock(&sroute_list_lock);
182
183 return NULL;
184}
185
186/** Get IDs of all static routes. */
187errno_t inet_sroute_get_id_list(sysarg_t **rid_list, size_t *rcount)
188{
189 sysarg_t *id_list;
190 size_t count, i;
191
192 fibril_mutex_lock(&sroute_list_lock);
193 count = list_count(&sroute_list);
194
195 id_list = calloc(count, sizeof(sysarg_t));
196 if (id_list == NULL) {
197 fibril_mutex_unlock(&sroute_list_lock);
198 return ENOMEM;
199 }
200
201 i = 0;
202 list_foreach(sroute_list, sroute_list, inet_sroute_t, sroute) {
203 id_list[i++] = sroute->id;
204 }
205
206 fibril_mutex_unlock(&sroute_list_lock);
207
208 *rid_list = id_list;
209 *rcount = count;
210
211 return EOK;
212}
213
214/** Load static route from SIF node.
215 *
216 * @param nroute SIF node to load static route from
217 * @return EOK on success or an error code
218 */
219static errno_t inet_sroute_load(sif_node_t *nroute)
220{
221 errno_t rc;
222 const char *sid;
223 const char *sdest;
224 const char *srouter;
225 const char *name;
226 char *endptr;
227 int id;
228 inet_naddr_t dest;
229 inet_addr_t router;
230 inet_sroute_t *sroute;
231
232 sid = sif_node_get_attr(nroute, "id");
233 if (sid == NULL)
234 return EIO;
235
236 sdest = sif_node_get_attr(nroute, "dest");
237 if (sdest == NULL)
238 return EIO;
239
240 srouter = sif_node_get_attr(nroute, "router");
241 if (srouter == NULL)
242 return EIO;
243
244 name = sif_node_get_attr(nroute, "name");
245 if (name == NULL)
246 return EIO;
247
248 id = strtoul(sid, &endptr, 10);
249 if (*endptr != '\0')
250 return EIO;
251
252 rc = inet_naddr_parse(sdest, &dest, NULL);
253 if (rc != EOK)
254 return EIO;
255
256 rc = inet_addr_parse(srouter, &router, NULL);
257 if (rc != EOK)
258 return EIO;
259
260 sroute = inet_sroute_new();
261 if (sroute == NULL)
262 return ENOMEM;
263
264 sroute->id = id;
265 sroute->dest = dest;
266 sroute->router = router;
267 sroute->name = str_dup(name);
268
269 if (sroute->name == NULL) {
270 inet_sroute_delete(sroute);
271 return ENOMEM;
272 }
273
274 inet_sroute_add(sroute);
275 return EOK;
276}
277
278/** Load static routes from SIF node.
279 *
280 * @param nroutes SIF node to load static routes from
281 * @return EOK on success or an error code
282 */
283errno_t inet_sroutes_load(sif_node_t *nroutes)
284{
285 sif_node_t *nroute;
286 const char *ntype;
287 errno_t rc;
288
289 nroute = sif_node_first_child(nroutes);
290 while (nroute != NULL) {
291 ntype = sif_node_get_type(nroute);
292 if (str_cmp(ntype, "route") != 0) {
293 rc = EIO;
294 goto error;
295 }
296
297 rc = inet_sroute_load(nroute);
298 if (rc != EOK)
299 goto error;
300
301 nroute = sif_node_next_child(nroute);
302 }
303
304 return EOK;
305error:
306 return rc;
307}
308
309/** Save static route to SIF node.
310 *
311 * @param sroute Static route
312 * @param nroute SIF node to save static route to
313 * @return EOK on success or an error code
314 */
315static errno_t inet_sroute_save(inet_sroute_t *sroute, sif_node_t *nroute)
316{
317 char *str = NULL;
318 errno_t rc;
319 int rv;
320
321 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_sroute_save(%p, %p)",
322 sroute, nroute);
323
324 /* id */
325
326 rv = asprintf(&str, "%zu", sroute->id);
327 if (rv < 0) {
328 str = NULL;
329 rc = ENOMEM;
330 goto error;
331 }
332
333 rc = sif_node_set_attr(nroute, "id", str);
334 if (rc != EOK)
335 goto error;
336
337 free(str);
338 str = NULL;
339
340 /* dest */
341
342 rc = inet_naddr_format(&sroute->dest, &str);
343 if (rc != EOK)
344 goto error;
345
346 rc = sif_node_set_attr(nroute, "dest", str);
347 if (rc != EOK)
348 goto error;
349
350 free(str);
351 str = NULL;
352
353 /* router */
354
355 rc = inet_addr_format(&sroute->router, &str);
356 if (rc != EOK)
357 goto error;
358
359 rc = sif_node_set_attr(nroute, "router", str);
360 if (rc != EOK)
361 goto error;
362
363 /* name */
364
365 rc = sif_node_set_attr(nroute, "name", sroute->name);
366 if (rc != EOK)
367 goto error;
368
369 free(str);
370
371 return rc;
372error:
373 if (str != NULL)
374 free(str);
375 return rc;
376}
377
378/** Save static routes to SIF node.
379 *
380 * @param nroutes SIF node to save static routes to
381 * @return EOK on success or an error code
382 */
383errno_t inet_sroutes_save(sif_node_t *nroutes)
384{
385 sif_node_t *nroute;
386 errno_t rc;
387
388 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_sroutes_save()");
389
390 fibril_mutex_lock(&sroute_list_lock);
391
392 list_foreach(sroute_list, sroute_list, inet_sroute_t, sroute) {
393 if (sroute->temp == false) {
394 rc = sif_node_append_child(nroutes, "route", &nroute);
395 if (rc != EOK)
396 goto error;
397
398 rc = inet_sroute_save(sroute, nroute);
399 if (rc != EOK)
400 goto error;
401 }
402 }
403
404 fibril_mutex_unlock(&sroute_list_lock);
405 return EOK;
406error:
407 fibril_mutex_unlock(&sroute_list_lock);
408 return rc;
409}
410
411/** @}
412 */
Note: See TracBrowser for help on using the repository browser.