source: mainline/uspace/srv/net/inetsrv/addrobj.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: 11.3 KB
RevLine 
[ceba4bed]1/*
[1bbc6dc]2 * Copyright (c) 2024 Jiri Svoboda
[ceba4bed]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>
[0e94b979]38#include <errno.h>
[ceba4bed]39#include <fibril_synch.h>
[b4edc96]40#include <inet/eth_addr.h>
[ceba4bed]41#include <io/log.h>
42#include <ipc/loc.h>
[1bbc6dc]43#include <sif.h>
44#include <stdio.h>
[ceba4bed]45#include <stdlib.h>
[fa101c4]46#include <str.h>
[ceba4bed]47#include "addrobj.h"
[b4ec1ea]48#include "inetsrv.h"
[ceba4bed]49#include "inet_link.h"
[a17356fd]50#include "ndp.h"
[ceba4bed]51
[bf9e6fc]52static inet_addrobj_t *inet_addrobj_find_by_name_locked(const char *, inet_link_t *);
53
[ceba4bed]54static FIBRIL_MUTEX_INITIALIZE(addr_list_lock);
55static LIST_INITIALIZE(addr_list);
[0e94b979]56static sysarg_t addr_id = 0;
[ceba4bed]57
58inet_addrobj_t *inet_addrobj_new(void)
59{
60 inet_addrobj_t *addr = calloc(1, sizeof(inet_addrobj_t));
61
62 if (addr == NULL) {
[a1a101d]63 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed allocating address object. "
[ceba4bed]64 "Out of memory.");
65 return NULL;
66 }
67
68 link_initialize(&addr->addr_list);
[0e94b979]69 fibril_mutex_lock(&addr_list_lock);
70 addr->id = ++addr_id;
71 fibril_mutex_unlock(&addr_list_lock);
[ceba4bed]72
73 return addr;
74}
75
76void inet_addrobj_delete(inet_addrobj_t *addr)
77{
[0e94b979]78 if (addr->name != NULL)
79 free(addr->name);
[ceba4bed]80 free(addr);
81}
82
[b7fd2a0]83errno_t inet_addrobj_add(inet_addrobj_t *addr)
[ceba4bed]84{
[bf9e6fc]85 inet_addrobj_t *aobj;
86
[ceba4bed]87 fibril_mutex_lock(&addr_list_lock);
[bf9e6fc]88 aobj = inet_addrobj_find_by_name_locked(addr->name, addr->ilink);
89 if (aobj != NULL) {
90 /* Duplicate address name */
91 fibril_mutex_unlock(&addr_list_lock);
[8a637a4]92 return EEXIST;
[bf9e6fc]93 }
94
[ceba4bed]95 list_append(&addr->addr_list, &addr_list);
96 fibril_mutex_unlock(&addr_list_lock);
[bf9e6fc]97
98 return EOK;
[ceba4bed]99}
100
101void inet_addrobj_remove(inet_addrobj_t *addr)
102{
103 fibril_mutex_lock(&addr_list_lock);
104 list_remove(&addr->addr_list);
105 fibril_mutex_unlock(&addr_list_lock);
106}
107
[e767dbf]108/** Find address object matching address @a addr.
109 *
[02a09ed]110 * @param addr Address
111 * @oaram find iaf_net to find network (using mask),
112 * iaf_addr to find local address (exact match)
113 *
[e767dbf]114 */
115inet_addrobj_t *inet_addrobj_find(inet_addr_t *addr, inet_addrobj_find_t find)
[ceba4bed]116{
117 fibril_mutex_lock(&addr_list_lock);
[a35b458]118
[feeac0d]119 list_foreach(addr_list, addr_list, inet_addrobj_t, naddr) {
[30c5d13]120 switch (find) {
121 case iaf_net:
122 if (inet_naddr_compare_mask(&naddr->naddr, addr)) {
123 fibril_mutex_unlock(&addr_list_lock);
124 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_find: found %p",
125 naddr);
126 return naddr;
127 }
128 break;
129 case iaf_addr:
130 if (inet_naddr_compare(&naddr->naddr, addr)) {
131 fibril_mutex_unlock(&addr_list_lock);
132 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_find: found %p",
133 naddr);
134 return naddr;
135 }
136 break;
[ceba4bed]137 }
138 }
[a35b458]139
[a1a101d]140 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_find: Not found");
[ceba4bed]141 fibril_mutex_unlock(&addr_list_lock);
[a35b458]142
[ceba4bed]143 return NULL;
144}
145
[fa101c4]146/** Find address object on a link, with a specific name.
147 *
148 * @param name Address object name
149 * @param ilink Inet link
150 * @return Address object
151 */
[bf9e6fc]152static inet_addrobj_t *inet_addrobj_find_by_name_locked(const char *name, inet_link_t *ilink)
[fa101c4]153{
[bf9e6fc]154 assert(fibril_mutex_is_locked(&addr_list_lock));
[fa101c4]155
[a1a101d]156 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_find_by_name_locked('%s', '%s')",
[bf9e6fc]157 name, ilink->svc_name);
[fa101c4]158
[feeac0d]159 list_foreach(addr_list, addr_list, inet_addrobj_t, naddr) {
[fa101c4]160 if (naddr->ilink == ilink && str_cmp(naddr->name, name) == 0) {
[a1a101d]161 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_find_by_name_locked: found %p",
[fa101c4]162 naddr);
163 return naddr;
164 }
165 }
166
[a1a101d]167 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_find_by_name_locked: Not found");
[fa101c4]168
169 return NULL;
170}
171
[bf9e6fc]172/** Find address object on a link, with a specific name.
173 *
174 * @param name Address object name
175 * @param ilink Inet link
176 * @return Address object
177 */
178inet_addrobj_t *inet_addrobj_find_by_name(const char *name, inet_link_t *ilink)
179{
180 inet_addrobj_t *aobj;
181
[a1a101d]182 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_find_by_name('%s', '%s')",
[bf9e6fc]183 name, ilink->svc_name);
184
185 fibril_mutex_lock(&addr_list_lock);
186 aobj = inet_addrobj_find_by_name_locked(name, ilink);
187 fibril_mutex_unlock(&addr_list_lock);
188
189 return aobj;
190}
191
[8bf672d]192/** Find address object with the given ID.
[0e94b979]193 *
194 * @param id Address object ID
195 * @return Address object
196 */
197inet_addrobj_t *inet_addrobj_get_by_id(sysarg_t id)
198{
[a1a101d]199 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_get_by_id(%zu)", (size_t)id);
[0e94b979]200
201 fibril_mutex_lock(&addr_list_lock);
202
[feeac0d]203 list_foreach(addr_list, addr_list, inet_addrobj_t, naddr) {
[0e94b979]204 if (naddr->id == id) {
205 fibril_mutex_unlock(&addr_list_lock);
206 return naddr;
207 }
208 }
209
210 fibril_mutex_unlock(&addr_list_lock);
211
212 return NULL;
213}
214
[1bbc6dc]215/** Count number of non-temporary address objects configured for link.
216 *
217 * @param ilink Inet link
218 * @return Number of address objects configured for this link
219 */
220unsigned inet_addrobj_cnt_by_link(inet_link_t *ilink)
221{
222 unsigned cnt;
223
224 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_cnt_by_link()");
225
226 fibril_mutex_lock(&addr_list_lock);
227
228 cnt = 0;
229 list_foreach(addr_list, addr_list, inet_addrobj_t, naddr) {
230 if (naddr->ilink == ilink && naddr->temp == false)
231 ++cnt;
232 }
233
234 fibril_mutex_unlock(&addr_list_lock);
235 return cnt;
236}
237
[8bf672d]238/** Send datagram from address object */
[b7fd2a0]239errno_t inet_addrobj_send_dgram(inet_addrobj_t *addr, inet_addr_t *ldest,
[8bf672d]240 inet_dgram_t *dgram, uint8_t proto, uint8_t ttl, int df)
[ceba4bed]241{
242 inet_addr_t lsrc_addr;
[a2e3ee6]243 inet_naddr_addr(&addr->naddr, &lsrc_addr);
[f023251]244
[a17356fd]245 addr32_t lsrc_v4;
246 addr128_t lsrc_v6;
[f023251]247 ip_ver_t lsrc_ver = inet_addr_get(&lsrc_addr, &lsrc_v4, &lsrc_v6);
248
[a17356fd]249 addr32_t ldest_v4;
250 addr128_t ldest_v6;
[f023251]251 ip_ver_t ldest_ver = inet_addr_get(ldest, &ldest_v4, &ldest_v6);
252
253 if (lsrc_ver != ldest_ver)
[a17356fd]254 return EINVAL;
[f023251]255
[b7fd2a0]256 errno_t rc;
[b4edc96]257 eth_addr_t ldest_mac;
[f023251]258
259 switch (ldest_ver) {
260 case ip_v4:
[a17356fd]261 return inet_link_send_dgram(addr->ilink, lsrc_v4, ldest_v4,
262 dgram, proto, ttl, df);
[f023251]263 case ip_v6:
[a17356fd]264 /*
265 * Translate local destination IPv6 address.
266 */
[f05edcb]267 rc = ndp_translate(lsrc_v6, ldest_v6, &ldest_mac, addr->ilink);
[a17356fd]268 if (rc != EOK)
269 return rc;
[f023251]270
[f05edcb]271 return inet_link_send_dgram6(addr->ilink, &ldest_mac, dgram,
[a17356fd]272 proto, ttl, df);
[f023251]273 default:
274 assert(false);
275 break;
[a17356fd]276 }
[f023251]277
[a17356fd]278 return ENOTSUP;
[ceba4bed]279}
280
[0e94b979]281/** Get IDs of all address objects. */
[b7fd2a0]282errno_t inet_addrobj_get_id_list(sysarg_t **rid_list, size_t *rcount)
[0e94b979]283{
284 sysarg_t *id_list;
285 size_t count, i;
286
287 fibril_mutex_lock(&addr_list_lock);
288 count = list_count(&addr_list);
289
290 id_list = calloc(count, sizeof(sysarg_t));
291 if (id_list == NULL) {
292 fibril_mutex_unlock(&addr_list_lock);
293 return ENOMEM;
294 }
295
296 i = 0;
[feeac0d]297 list_foreach(addr_list, addr_list, inet_addrobj_t, addr) {
[0e94b979]298 id_list[i++] = addr->id;
299 }
300
301 fibril_mutex_unlock(&addr_list_lock);
302
303 *rid_list = id_list;
304 *rcount = count;
305
306 return EOK;
307}
308
[1bbc6dc]309/** Load address object from SIF node.
310 *
311 * @param anode SIF node to load address object from
312 * @return EOK on success or an error code
313 */
314static errno_t inet_addrobj_load(sif_node_t *anode)
315{
316 errno_t rc;
317 const char *sid;
318 const char *snaddr;
319 const char *slink;
320 const char *name;
321 char *endptr;
322 int id;
323 inet_naddr_t naddr;
324 inet_addrobj_t *addr;
325 inet_link_t *link;
326
327 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_load()");
328
329 sid = sif_node_get_attr(anode, "id");
330 if (sid == NULL)
331 return EIO;
332
333 snaddr = sif_node_get_attr(anode, "naddr");
334 if (snaddr == NULL)
335 return EIO;
336
337 slink = sif_node_get_attr(anode, "link");
338 if (slink == NULL)
339 return EIO;
340
341 name = sif_node_get_attr(anode, "name");
342 if (name == NULL)
343 return EIO;
344
345 log_msg(LOG_DEFAULT, LVL_NOTE, "inet_addrobj_load(): id='%s' "
346 "naddr='%s' link='%s' name='%s'", sid, snaddr, slink, name);
347
348 id = strtoul(sid, &endptr, 10);
349 if (*endptr != '\0')
350 return EIO;
351
352 rc = inet_naddr_parse(snaddr, &naddr, NULL);
353 if (rc != EOK)
354 return EIO;
355
356 link = inet_link_get_by_svc_name(slink);
357 if (link == NULL) {
358 log_msg(LOG_DEFAULT, LVL_ERROR, "Link '%s' not found",
359 slink);
360 return EIO;
361 }
362
363 addr = inet_addrobj_new();
364 if (addr == NULL)
365 return ENOMEM;
366
367 addr->id = id;
368 addr->naddr = naddr;
369 addr->ilink = link;
370 addr->name = str_dup(name);
371
372 if (addr->name == NULL) {
373 inet_addrobj_delete(addr);
374 return ENOMEM;
375 }
376
377 inet_addrobj_add(addr);
378 return EOK;
379}
380
381/** Load address objects from SIF node.
382 *
383 * @param naddrs SIF node to load address objects from
384 * @return EOK on success or an error code
385 */
386errno_t inet_addrobjs_load(sif_node_t *naddrs)
387{
388 sif_node_t *naddr;
389 const char *ntype;
390 errno_t rc;
391
392 naddr = sif_node_first_child(naddrs);
393 while (naddr != NULL) {
394 ntype = sif_node_get_type(naddr);
395 if (str_cmp(ntype, "address") != 0) {
396 rc = EIO;
397 goto error;
398 }
399
400 rc = inet_addrobj_load(naddr);
401 if (rc != EOK)
402 goto error;
403
404 naddr = sif_node_next_child(naddr);
405 }
406
407 return EOK;
408error:
409 return rc;
410
411}
412
413/** Save address object to SIF node.
414 *
415 * @param addr Address object
416 * @param naddr SIF node to save addres to
417 * @return EOK on success or an error code
418 */
419static errno_t inet_addrobj_save(inet_addrobj_t *addr, sif_node_t *naddr)
420{
421 char *str = NULL;
422 errno_t rc;
423 int rv;
424
425 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_save(%p, %p)",
426 addr, naddr);
427
428 /* id */
429
[36fcd0a]430 rv = asprintf(&str, "%zu", addr->id);
[1bbc6dc]431 if (rv < 0) {
432 str = NULL;
433 rc = ENOMEM;
434 goto error;
435 }
436
437 rc = sif_node_set_attr(naddr, "id", str);
438 if (rc != EOK)
439 goto error;
440
441 free(str);
442 str = NULL;
443
444 /* dest */
445
446 rc = inet_naddr_format(&addr->naddr, &str);
447 if (rc != EOK)
448 goto error;
449
450 rc = sif_node_set_attr(naddr, "naddr", str);
451 if (rc != EOK)
452 goto error;
453
454 free(str);
455 str = NULL;
456
457 /* link */
458
459 rc = sif_node_set_attr(naddr, "link", addr->ilink->svc_name);
460 if (rc != EOK)
461 goto error;
462
463 /* name */
464
465 rc = sif_node_set_attr(naddr, "name", addr->name);
466 if (rc != EOK)
467 goto error;
468
469 free(str);
470
471 return rc;
472error:
473 if (str != NULL)
474 free(str);
475 return rc;
476}
477
478/** Save address objects to SIF node.
479 *
480 * @param cnode SIF node to save address objects to
481 * @return EOK on success or an error code
482 */
483errno_t inet_addrobjs_save(sif_node_t *cnode)
484{
485 sif_node_t *naddr;
486 errno_t rc;
487
488 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobjs_save()");
489
490 fibril_mutex_lock(&addr_list_lock);
491
492 list_foreach(addr_list, addr_list, inet_addrobj_t, addr) {
493 if (addr->temp == false) {
494 rc = sif_node_append_child(cnode, "address", &naddr);
495 if (rc != EOK)
496 goto error;
497
498 rc = inet_addrobj_save(addr, naddr);
499 if (rc != EOK)
500 goto error;
501 }
502 }
503
504 fibril_mutex_unlock(&addr_list_lock);
505 return EOK;
506error:
507 fibril_mutex_unlock(&addr_list_lock);
508 return rc;
509}
510
[ceba4bed]511/** @}
512 */
Note: See TracBrowser for help on using the repository browser.