source: mainline/uspace/srv/net/inetsrv/inet_link.c@ ca48672

Last change on this file since ca48672 was 1bbc6dc, checked in by Jiri Svoboda <jiri@…>, 9 months ago

Network configuration persistence.

nconfsrv is folded into inetsrv
DHCP is disabled when a static address is configured on a link

  • Property mode set to 100644
File size: 17.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 <errno.h>
38#include <fibril_synch.h>
39#include <inet/dhcp.h>
40#include <inet/eth_addr.h>
41#include <inet/iplink.h>
42#include <io/log.h>
43#include <loc.h>
44#include <stdbool.h>
45#include <stdlib.h>
46#include <str.h>
47#include <str_error.h>
48#include "addrobj.h"
49#include "inetsrv.h"
50#include "inet_link.h"
51#include "pdu.h"
52
53static bool first_link = true;
54static bool first_link6 = true;
55
56static FIBRIL_MUTEX_INITIALIZE(ip_ident_lock);
57static uint16_t ip_ident = 0;
58
59static errno_t inet_iplink_recv(iplink_t *, iplink_recv_sdu_t *, ip_ver_t);
60static errno_t inet_iplink_change_addr(iplink_t *, eth_addr_t *);
61static inet_link_t *inet_link_get_by_id_locked(sysarg_t);
62
63static iplink_ev_ops_t inet_iplink_ev_ops = {
64 .recv = inet_iplink_recv,
65 .change_addr = inet_iplink_change_addr,
66};
67
68static LIST_INITIALIZE(inet_links);
69static FIBRIL_MUTEX_INITIALIZE(inet_links_lock);
70
71static addr128_t link_local_node_ip =
72 { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xfe, 0, 0, 0 };
73
74static void inet_link_local_node_ip(eth_addr_t *mac_addr,
75 addr128_t ip_addr)
76{
77 uint8_t b[ETH_ADDR_SIZE];
78
79 memcpy(ip_addr, link_local_node_ip, 16);
80 eth_addr_encode(mac_addr, b);
81
82 ip_addr[8] = b[0] ^ 0x02;
83 ip_addr[9] = b[1];
84 ip_addr[10] = b[2];
85 ip_addr[13] = b[3];
86 ip_addr[14] = b[4];
87 ip_addr[15] = b[5];
88}
89
90static errno_t inet_iplink_recv(iplink_t *iplink, iplink_recv_sdu_t *sdu, ip_ver_t ver)
91{
92 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_iplink_recv()");
93
94 errno_t rc;
95 inet_packet_t packet;
96 inet_link_t *ilink;
97
98 ilink = (inet_link_t *)iplink_get_userptr(iplink);
99
100 switch (ver) {
101 case ip_v4:
102 rc = inet_pdu_decode(sdu->data, sdu->size, ilink->svc_id,
103 &packet);
104 break;
105 case ip_v6:
106 rc = inet_pdu_decode6(sdu->data, sdu->size, ilink->svc_id,
107 &packet);
108 break;
109 default:
110 log_msg(LOG_DEFAULT, LVL_DEBUG, "invalid IP version");
111 return EINVAL;
112 }
113
114 if (rc != EOK) {
115 log_msg(LOG_DEFAULT, LVL_DEBUG, "failed decoding PDU");
116 return rc;
117 }
118
119 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_iplink_recv: link_id=%zu", packet.link_id);
120 log_msg(LOG_DEFAULT, LVL_DEBUG, "call inet_recv_packet()");
121 rc = inet_recv_packet(&packet);
122 log_msg(LOG_DEFAULT, LVL_DEBUG, "call inet_recv_packet -> %s", str_error_name(rc));
123 free(packet.data);
124
125 return rc;
126}
127
128static errno_t inet_iplink_change_addr(iplink_t *iplink, eth_addr_t *mac)
129{
130 eth_addr_str_t saddr;
131
132 eth_addr_format(mac, &saddr);
133 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_iplink_change_addr(): "
134 "new addr=%s", saddr.str);
135
136 list_foreach(inet_links, link_list, inet_link_t, ilink) {
137 if (ilink->sess == iplink->sess)
138 ilink->mac = *mac;
139 }
140
141 return EOK;
142}
143
144static inet_link_t *inet_link_new(void)
145{
146 inet_link_t *ilink = calloc(1, sizeof(inet_link_t));
147
148 if (ilink == NULL) {
149 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed allocating link structure. "
150 "Out of memory.");
151 return NULL;
152 }
153
154 link_initialize(&ilink->link_list);
155
156 return ilink;
157}
158
159static void inet_link_delete(inet_link_t *ilink)
160{
161 if (ilink->svc_name != NULL)
162 free(ilink->svc_name);
163
164 free(ilink);
165}
166
167/** Open new IP link while inet_links_lock is held.
168 *
169 * @param sid IP link service ID
170 * @return EOK on success or an error code
171 */
172static errno_t inet_link_open_locked(service_id_t sid)
173{
174 inet_link_t *ilink;
175 inet_addr_t iaddr;
176 errno_t rc;
177
178 assert(fibril_mutex_is_locked(&inet_links_lock));
179
180 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_link_open_locked()");
181 ilink = inet_link_new();
182 if (ilink == NULL)
183 return ENOMEM;
184
185 ilink->svc_id = sid;
186 ilink->iplink = NULL;
187
188 rc = loc_service_get_name(sid, &ilink->svc_name);
189 if (rc != EOK) {
190 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting service name.");
191 goto error;
192 }
193
194 ilink->sess = loc_service_connect(sid, INTERFACE_IPLINK, 0);
195 if (ilink->sess == NULL) {
196 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed connecting '%s'", ilink->svc_name);
197 goto error;
198 }
199
200 rc = iplink_open(ilink->sess, &inet_iplink_ev_ops, ilink, &ilink->iplink);
201 if (rc != EOK) {
202 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed opening IP link '%s'",
203 ilink->svc_name);
204 goto error;
205 }
206
207 rc = iplink_get_mtu(ilink->iplink, &ilink->def_mtu);
208 if (rc != EOK) {
209 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed determinning MTU of link '%s'",
210 ilink->svc_name);
211 goto error;
212 }
213
214 /*
215 * Get the MAC address of the link. If the link has a MAC
216 * address, we assume that it supports NDP.
217 */
218 rc = iplink_get_mac48(ilink->iplink, &ilink->mac);
219 ilink->mac_valid = (rc == EOK);
220
221 log_msg(LOG_DEFAULT, LVL_DEBUG, "Opened IP link '%s'", ilink->svc_name);
222
223 if (inet_link_get_by_id_locked(sid) != NULL) {
224 log_msg(LOG_DEFAULT, LVL_DEBUG, "Link %zu already open",
225 sid);
226 rc = EEXIST;
227 goto error;
228 }
229
230 list_append(&ilink->link_list, &inet_links);
231
232 inet_addrobj_t *addr = NULL;
233
234 /* XXX FIXME Cannot rely on loopback being the first IP link service!! */
235 if (first_link) {
236 addr = inet_addrobj_new();
237
238 inet_naddr(&addr->naddr, 127, 0, 0, 1, 24);
239 first_link = false;
240 }
241
242 if (addr != NULL) {
243 addr->ilink = ilink;
244 addr->name = str_dup("v4a");
245 addr->temp = true;
246
247 rc = inet_addrobj_add(addr);
248 if (rc == EOK) {
249 inet_naddr_addr(&addr->naddr, &iaddr);
250 rc = iplink_addr_add(ilink->iplink, &iaddr);
251 if (rc != EOK) {
252 log_msg(LOG_DEFAULT, LVL_ERROR,
253 "Failed setting IPv4 address on internet link.");
254 inet_addrobj_remove(addr);
255 inet_addrobj_delete(addr);
256 }
257 } else {
258 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding IPv4 address.");
259 inet_addrobj_delete(addr);
260 }
261 }
262
263 inet_addrobj_t *addr6 = NULL;
264
265 if (first_link6) {
266 addr6 = inet_addrobj_new();
267
268 inet_naddr6(&addr6->naddr, 0, 0, 0, 0, 0, 0, 0, 1, 128);
269 first_link6 = false;
270 } else if (ilink->mac_valid) {
271 addr6 = inet_addrobj_new();
272
273 addr128_t link_local;
274 inet_link_local_node_ip(&ilink->mac, link_local);
275
276 inet_naddr_set6(link_local, 64, &addr6->naddr);
277 }
278
279 if (addr6 != NULL) {
280 addr6->ilink = ilink;
281 addr6->name = str_dup("v6a");
282 addr6->temp = true;
283
284 rc = inet_addrobj_add(addr6);
285 if (rc == EOK) {
286 inet_naddr_addr(&addr6->naddr, &iaddr);
287 rc = iplink_addr_add(ilink->iplink, &iaddr);
288 if (rc != EOK) {
289 log_msg(LOG_DEFAULT, LVL_ERROR,
290 "Failed setting IPv6 address on internet link.");
291 inet_addrobj_remove(addr6);
292 inet_addrobj_delete(addr6);
293 }
294 } else {
295 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding IPv6 address.");
296 inet_addrobj_delete(addr6);
297 }
298 }
299
300 log_msg(LOG_DEFAULT, LVL_DEBUG, "Configured link '%s'.", ilink->svc_name);
301 return EOK;
302
303error:
304 if (ilink->iplink != NULL)
305 iplink_close(ilink->iplink);
306
307 inet_link_delete(ilink);
308 return rc;
309}
310
311/** Open new IP link..
312 *
313 * @param sid IP link service ID
314 * @return EOK on success or an error code
315 */
316errno_t inet_link_open(service_id_t sid)
317{
318 errno_t rc;
319
320 fibril_mutex_lock(&inet_links_lock);
321 rc = inet_link_open_locked(sid);
322 fibril_mutex_unlock(&inet_links_lock);
323
324 return rc;
325}
326
327/** Send IPv4 datagram over Internet link
328 *
329 * @param ilink Internet link
330 * @param lsrc Source IPv4 address
331 * @param ldest Destination IPv4 address
332 * @param dgram IPv4 datagram body
333 * @param proto Protocol
334 * @param ttl Time-to-live
335 * @param df Do-not-Fragment flag
336 *
337 * @return EOK on success
338 * @return ENOMEM when not enough memory to create the datagram
339 * @return ENOTSUP if networking mode is not supported
340 *
341 */
342errno_t inet_link_send_dgram(inet_link_t *ilink, addr32_t lsrc, addr32_t ldest,
343 inet_dgram_t *dgram, uint8_t proto, uint8_t ttl, int df)
344{
345 addr32_t src_v4;
346 ip_ver_t src_ver = inet_addr_get(&dgram->src, &src_v4, NULL);
347 if (src_ver != ip_v4)
348 return EINVAL;
349
350 addr32_t dest_v4;
351 ip_ver_t dest_ver = inet_addr_get(&dgram->dest, &dest_v4, NULL);
352 if (dest_ver != ip_v4)
353 return EINVAL;
354
355 /*
356 * Fill packet structure. Fragmentation is performed by
357 * inet_pdu_encode().
358 */
359
360 iplink_sdu_t sdu;
361
362 sdu.src = lsrc;
363 sdu.dest = ldest;
364
365 inet_packet_t packet;
366
367 packet.src = dgram->src;
368 packet.dest = dgram->dest;
369 packet.tos = dgram->tos;
370 packet.proto = proto;
371 packet.ttl = ttl;
372
373 /* Allocate identifier */
374 fibril_mutex_lock(&ip_ident_lock);
375 packet.ident = ++ip_ident;
376 fibril_mutex_unlock(&ip_ident_lock);
377
378 packet.df = df;
379 packet.data = dgram->data;
380 packet.size = dgram->size;
381
382 errno_t rc;
383 size_t offs = 0;
384
385 do {
386 /* Encode one fragment */
387
388 size_t roffs;
389 rc = inet_pdu_encode(&packet, src_v4, dest_v4, offs, ilink->def_mtu,
390 &sdu.data, &sdu.size, &roffs);
391 if (rc != EOK)
392 return rc;
393
394 /* Send the PDU */
395 rc = iplink_send(ilink->iplink, &sdu);
396
397 free(sdu.data);
398 offs = roffs;
399 } while (offs < packet.size);
400
401 return rc;
402}
403
404/** Send IPv6 datagram over Internet link
405 *
406 * @param ilink Internet link
407 * @param ldest Destination MAC address
408 * @param dgram IPv6 datagram body
409 * @param proto Next header
410 * @param ttl Hop limit
411 * @param df Do-not-Fragment flag (unused)
412 *
413 * @return EOK on success
414 * @return ENOMEM when not enough memory to create the datagram
415 *
416 */
417errno_t inet_link_send_dgram6(inet_link_t *ilink, eth_addr_t *ldest,
418 inet_dgram_t *dgram, uint8_t proto, uint8_t ttl, int df)
419{
420 addr128_t src_v6;
421 ip_ver_t src_ver = inet_addr_get(&dgram->src, NULL, &src_v6);
422 if (src_ver != ip_v6)
423 return EINVAL;
424
425 addr128_t dest_v6;
426 ip_ver_t dest_ver = inet_addr_get(&dgram->dest, NULL, &dest_v6);
427 if (dest_ver != ip_v6)
428 return EINVAL;
429
430 iplink_sdu6_t sdu6;
431 sdu6.dest = *ldest;
432
433 /*
434 * Fill packet structure. Fragmentation is performed by
435 * inet_pdu_encode6().
436 */
437
438 inet_packet_t packet;
439
440 packet.src = dgram->src;
441 packet.dest = dgram->dest;
442 packet.tos = dgram->tos;
443 packet.proto = proto;
444 packet.ttl = ttl;
445
446 /* Allocate identifier */
447 fibril_mutex_lock(&ip_ident_lock);
448 packet.ident = ++ip_ident;
449 fibril_mutex_unlock(&ip_ident_lock);
450
451 packet.df = df;
452 packet.data = dgram->data;
453 packet.size = dgram->size;
454
455 errno_t rc;
456 size_t offs = 0;
457
458 do {
459 /* Encode one fragment */
460
461 size_t roffs;
462 rc = inet_pdu_encode6(&packet, src_v6, dest_v6, offs, ilink->def_mtu,
463 &sdu6.data, &sdu6.size, &roffs);
464 if (rc != EOK)
465 return rc;
466
467 /* Send the PDU */
468 rc = iplink_send6(ilink->iplink, &sdu6);
469
470 free(sdu6.data);
471 offs = roffs;
472 } while (offs < packet.size);
473
474 return rc;
475}
476
477static inet_link_t *inet_link_get_by_id_locked(sysarg_t link_id)
478{
479 assert(fibril_mutex_is_locked(&inet_links_lock));
480
481 list_foreach(inet_links, link_list, inet_link_t, ilink) {
482 if (ilink->svc_id == link_id)
483 return ilink;
484 }
485
486 return NULL;
487}
488
489inet_link_t *inet_link_get_by_id(sysarg_t link_id)
490{
491 inet_link_t *ilink;
492
493 fibril_mutex_lock(&inet_links_lock);
494 ilink = inet_link_get_by_id_locked(link_id);
495 fibril_mutex_unlock(&inet_links_lock);
496
497 return ilink;
498}
499
500/** Find link by service name while inet_links_lock is held.
501 *
502 * @param svc_name Service name
503 * @return Link or @c NULL if not found
504 */
505static inet_link_t *inet_link_get_by_svc_name_locked(const char *svc_name)
506{
507 assert(fibril_mutex_is_locked(&inet_links_lock));
508
509 list_foreach(inet_links, link_list, inet_link_t, ilink) {
510 if (str_cmp(ilink->svc_name, svc_name) == 0)
511 return ilink;
512 }
513
514 return NULL;
515}
516
517/** Find link by service name.
518 *
519 * @param svc_name Service name
520 * @return Link or @c NULL if not found
521 */
522inet_link_t *inet_link_get_by_svc_name(const char *svc_name)
523{
524 inet_link_t *ilink;
525
526 fibril_mutex_lock(&inet_links_lock);
527 ilink = inet_link_get_by_svc_name_locked(svc_name);
528 fibril_mutex_unlock(&inet_links_lock);
529
530 return ilink;
531}
532
533/** Get IDs of all links. */
534errno_t inet_link_get_id_list(sysarg_t **rid_list, size_t *rcount)
535{
536 sysarg_t *id_list;
537 size_t count, i;
538
539 fibril_mutex_lock(&inet_links_lock);
540 count = list_count(&inet_links);
541
542 id_list = calloc(count, sizeof(sysarg_t));
543 if (id_list == NULL) {
544 fibril_mutex_unlock(&inet_links_lock);
545 return ENOMEM;
546 }
547
548 i = 0;
549 list_foreach(inet_links, link_list, inet_link_t, ilink) {
550 id_list[i++] = ilink->svc_id;
551 }
552
553 fibril_mutex_unlock(&inet_links_lock);
554
555 *rid_list = id_list;
556 *rcount = count;
557
558 return EOK;
559}
560
561/** Check for new IP links.
562 *
563 * @return EOK on success or an error code
564 */
565static errno_t inet_link_check_new(void)
566{
567 bool already_known;
568 category_id_t iplink_cat;
569 service_id_t *svcs;
570 inet_link_cfg_info_t info;
571 size_t count, i;
572 errno_t rc;
573
574 fibril_mutex_lock(&inet_links_lock);
575
576 rc = loc_category_get_id("iplink", &iplink_cat, IPC_FLAG_BLOCKING);
577 if (rc != EOK) {
578 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed resolving category "
579 "'iplink'.");
580 fibril_mutex_unlock(&inet_links_lock);
581 return ENOENT;
582 }
583
584 rc = loc_category_get_svcs(iplink_cat, &svcs, &count);
585 if (rc != EOK) {
586 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting list of IP "
587 "links.");
588 fibril_mutex_unlock(&inet_links_lock);
589 return EIO;
590 }
591
592 for (i = 0; i < count; i++) {
593 already_known = false;
594
595 list_foreach(inet_links, link_list, inet_link_t, ilink) {
596 if (ilink->svc_id == svcs[i]) {
597 already_known = true;
598 break;
599 }
600 }
601
602 if (!already_known) {
603 log_msg(LOG_DEFAULT, LVL_NOTE, "Found IP link '%lu'",
604 (unsigned long) svcs[i]);
605 rc = inet_link_open_locked(svcs[i]);
606 if (rc != EOK) {
607 log_msg(LOG_DEFAULT, LVL_ERROR, "Could not "
608 "add IP link.");
609 }
610 } else {
611 /* Clear so it won't be autoconfigured below */
612 svcs[i] = 0;
613 }
614 }
615
616 fibril_mutex_unlock(&inet_links_lock);
617
618 /*
619 * Auto-configure new links. Note that newly discovered links
620 * cannot have any configured address objects, because we only
621 * retain configuration for present links.
622 */
623 for (i = 0; i < count; i++) {
624 if (svcs[i] != 0) {
625 info.svc_id = svcs[i];
626 rc = loc_service_get_name(info.svc_id, &info.svc_name);
627 if (rc != EOK) {
628 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed "
629 "getting service name.");
630 return rc;
631 }
632
633 inet_link_autoconf_link(&info);
634 free(info.svc_name);
635 info.svc_name = NULL;
636 }
637 }
638
639 return EOK;
640}
641
642/** IP link category change callback.
643 *
644 * @param arg Not used
645 */
646static void inet_link_cat_change_cb(void *arg)
647{
648 (void) inet_link_check_new();
649}
650
651/** Start IP link discovery.
652 *
653 * @return EOK on success or an error code
654 */
655errno_t inet_link_discovery_start(void)
656{
657 errno_t rc;
658
659 rc = loc_register_cat_change_cb(inet_link_cat_change_cb, NULL);
660 if (rc != EOK) {
661 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering callback "
662 "for IP link discovery: %s.", str_error(rc));
663 return rc;
664 }
665
666 return inet_link_check_new();
667}
668
669/** Start DHCP autoconfiguration on IP link.
670 *
671 * @param info Link information
672 */
673void inet_link_autoconf_link(inet_link_cfg_info_t *info)
674{
675 errno_t rc;
676
677 log_msg(LOG_DEFAULT, LVL_NOTE, "inet_link_autoconf_link");
678
679 if (str_lcmp(info->svc_name, "net/eth", str_length("net/eth")) == 0) {
680 log_msg(LOG_DEFAULT, LVL_NOTE, "inet_link_autoconf_link : dhcp link add for link '%s' (%u)",
681 info->svc_name, (unsigned)info->svc_id);
682 rc = dhcp_link_add(info->svc_id);
683 log_msg(LOG_DEFAULT, LVL_NOTE, "inet_link_autoconf_link : dhcp link add for link '%s' (%u) DONE",
684 info->svc_name, (unsigned)info->svc_id);
685 if (rc != EOK) {
686 log_msg(LOG_DEFAULT, LVL_WARN, "Failed configuring "
687 "DHCP on link '%s'.\n", info->svc_name);
688 }
689 }
690}
691
692/** Start DHCP autoconfiguration on IP links. */
693errno_t inet_link_autoconf(void)
694{
695 inet_link_cfg_info_t *link_info;
696 size_t link_cnt;
697 size_t acnt;
698 size_t i;
699 errno_t rc;
700
701 log_msg(LOG_DEFAULT, LVL_NOTE, "inet_link_autoconf : initialize DHCP");
702 rc = dhcp_init();
703 if (rc != EOK) {
704 log_msg(LOG_DEFAULT, LVL_WARN, "Failed initializing DHCP "
705 "service.");
706 return rc;
707 }
708
709 log_msg(LOG_DEFAULT, LVL_NOTE, "inet_link_autoconf : initialize DHCP done");
710
711 fibril_mutex_lock(&inet_links_lock);
712 link_cnt = list_count(&inet_links);
713
714 link_info = calloc(link_cnt, sizeof(inet_link_cfg_info_t));
715 if (link_info == NULL) {
716 fibril_mutex_unlock(&inet_links_lock);
717 return ENOMEM;
718 }
719
720 i = 0;
721 list_foreach(inet_links, link_list, inet_link_t, ilink) {
722 assert(i < link_cnt);
723
724 acnt = inet_addrobj_cnt_by_link(ilink);
725 if (acnt != 0) {
726 /*
727 * No autoconfiguration if link has configured
728 * addresses.
729 */
730 continue;
731 }
732
733 link_info[i].svc_id = ilink->svc_id;
734 link_info[i].svc_name = str_dup(ilink->svc_name);
735 if (link_info[i].svc_name == NULL) {
736 fibril_mutex_unlock(&inet_links_lock);
737 goto error;
738 }
739
740 ++i;
741 }
742
743 fibril_mutex_unlock(&inet_links_lock);
744
745 /* Update link_cnt to include only links slated for autoconfig. */
746 link_cnt = i;
747
748 log_msg(LOG_DEFAULT, LVL_NOTE, "inet_link_autoconf : autoconf links...");
749
750 for (i = 0; i < link_cnt; i++)
751 inet_link_autoconf_link(&link_info[i]);
752
753 for (i = 0; i < link_cnt; i++) {
754 if (link_info[i].svc_name != NULL)
755 free(link_info[i].svc_name);
756 }
757
758 log_msg(LOG_DEFAULT, LVL_NOTE, "inet_link_autoconf : autoconf links done");
759 return EOK;
760error:
761 for (i = 0; i < link_cnt; i++) {
762 if (link_info[i].svc_name != NULL)
763 free(link_info[i].svc_name);
764 }
765 free(link_info);
766 return ENOMEM;
767}
768
769/** @}
770 */
Note: See TracBrowser for help on using the repository browser.