Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/inetsrv/inet_link.c

    r1bbc6dc r3e6bca8  
    11/*
    2  * Copyright (c) 2024 Jiri Svoboda
     2 * Copyright (c) 2021 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3737#include <errno.h>
    3838#include <fibril_synch.h>
    39 #include <inet/dhcp.h>
    4039#include <inet/eth_addr.h>
    4140#include <inet/iplink.h>
     
    165164}
    166165
    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  */
    172 static errno_t inet_link_open_locked(service_id_t sid)
     166errno_t inet_link_open(service_id_t sid)
    173167{
    174168        inet_link_t *ilink;
     
    176170        errno_t rc;
    177171
    178         assert(fibril_mutex_is_locked(&inet_links_lock));
    179 
    180         log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_link_open_locked()");
     172        log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_link_open()");
    181173        ilink = inet_link_new();
    182174        if (ilink == NULL)
     
    221213        log_msg(LOG_DEFAULT, LVL_DEBUG, "Opened IP link '%s'", ilink->svc_name);
    222214
     215        fibril_mutex_lock(&inet_links_lock);
     216
    223217        if (inet_link_get_by_id_locked(sid) != NULL) {
     218                fibril_mutex_unlock(&inet_links_lock);
    224219                log_msg(LOG_DEFAULT, LVL_DEBUG, "Link %zu already open",
    225220                    sid);
     
    229224
    230225        list_append(&ilink->link_list, &inet_links);
     226        fibril_mutex_unlock(&inet_links_lock);
    231227
    232228        inet_addrobj_t *addr = NULL;
     
    243239                addr->ilink = ilink;
    244240                addr->name = str_dup("v4a");
    245                 addr->temp = true;
    246241
    247242                rc = inet_addrobj_add(addr);
     
    280275                addr6->ilink = ilink;
    281276                addr6->name = str_dup("v6a");
    282                 addr6->temp = true;
    283277
    284278                rc = inet_addrobj_add(addr6);
     
    309303}
    310304
    311 /** Open new IP link..
    312  *
    313  * @param sid IP link service ID
    314  * @return EOK on success or an error code
    315  */
    316 errno_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 
    327305/** Send IPv4 datagram over Internet link
    328306 *
     
    498476}
    499477
    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  */
    505 static 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  */
    522 inet_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 
    533478/** Get IDs of all links. */
    534479errno_t inet_link_get_id_list(sysarg_t **rid_list, size_t *rcount)
     
    559504}
    560505
    561 /** Check for new IP links.
    562  *
    563  * @return EOK on success or an error code
    564  */
    565 static 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  */
    646 static 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  */
    655 errno_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  */
    673 void 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. */
    693 errno_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;
    760 error:
    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 
    769506/** @}
    770507 */
Note: See TracChangeset for help on using the changeset viewer.