HelenOS sources
This source file includes following definitions.
- inet_addrobj_new
- inet_addrobj_delete
- inet_addrobj_add
- inet_addrobj_remove
- inet_addrobj_find
- inet_addrobj_find_by_name_locked
- inet_addrobj_find_by_name
- inet_addrobj_get_by_id
- inet_addrobj_cnt_by_link
- inet_addrobj_send_dgram
- inet_addrobj_get_id_list
- inet_addrobj_load
- inet_addrobjs_load
- inet_addrobj_save
- inet_addrobjs_save
#include <bitops.h>
#include <errno.h>
#include <fibril_synch.h>
#include <inet/eth_addr.h>
#include <io/log.h>
#include <ipc/loc.h>
#include <sif.h>
#include <stdio.h>
#include <stdlib.h>
#include <str.h>
#include "addrobj.h"
#include "inetsrv.h"
#include "inet_link.h"
#include "ndp.h"
static inet_addrobj_t *inet_addrobj_find_by_name_locked(const char *, inet_link_t *);
static FIBRIL_MUTEX_INITIALIZE(addr_list_lock);
static LIST_INITIALIZE(addr_list);
static sysarg_t addr_id = 0;
inet_addrobj_t *inet_addrobj_new(void)
{
inet_addrobj_t *addr = calloc(1, sizeof(inet_addrobj_t));
if (addr == NULL) {
log_msg(LOG_DEFAULT, LVL_ERROR, "Failed allocating address object. "
"Out of memory.");
return NULL;
}
link_initialize(&addr->addr_list);
fibril_mutex_lock(&addr_list_lock);
addr->id = ++addr_id;
fibril_mutex_unlock(&addr_list_lock);
return addr;
}
void inet_addrobj_delete(inet_addrobj_t *addr)
{
if (addr->name != NULL)
free(addr->name);
free(addr);
}
errno_t inet_addrobj_add(inet_addrobj_t *addr)
{
inet_addrobj_t *aobj;
fibril_mutex_lock(&addr_list_lock);
aobj = inet_addrobj_find_by_name_locked(addr->name, addr->ilink);
if (aobj != NULL) {
fibril_mutex_unlock(&addr_list_lock);
return EEXIST;
}
list_append(&addr->addr_list, &addr_list);
fibril_mutex_unlock(&addr_list_lock);
return EOK;
}
void inet_addrobj_remove(inet_addrobj_t *addr)
{
fibril_mutex_lock(&addr_list_lock);
list_remove(&addr->addr_list);
fibril_mutex_unlock(&addr_list_lock);
}
inet_addrobj_t *inet_addrobj_find(inet_addr_t *addr, inet_addrobj_find_t find)
{
fibril_mutex_lock(&addr_list_lock);
list_foreach(addr_list, addr_list, inet_addrobj_t, naddr) {
switch (find) {
case iaf_net:
if (inet_naddr_compare_mask(&naddr->naddr, addr)) {
fibril_mutex_unlock(&addr_list_lock);
log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_find: found %p",
naddr);
return naddr;
}
break;
case iaf_addr:
if (inet_naddr_compare(&naddr->naddr, addr)) {
fibril_mutex_unlock(&addr_list_lock);
log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_find: found %p",
naddr);
return naddr;
}
break;
}
}
log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_find: Not found");
fibril_mutex_unlock(&addr_list_lock);
return NULL;
}
static inet_addrobj_t *inet_addrobj_find_by_name_locked(const char *name, inet_link_t *ilink)
{
assert(fibril_mutex_is_locked(&addr_list_lock));
log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_find_by_name_locked('%s', '%s')",
name, ilink->svc_name);
list_foreach(addr_list, addr_list, inet_addrobj_t, naddr) {
if (naddr->ilink == ilink && str_cmp(naddr->name, name) == 0) {
log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_find_by_name_locked: found %p",
naddr);
return naddr;
}
}
log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_find_by_name_locked: Not found");
return NULL;
}
inet_addrobj_t *inet_addrobj_find_by_name(const char *name, inet_link_t *ilink)
{
inet_addrobj_t *aobj;
log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_find_by_name('%s', '%s')",
name, ilink->svc_name);
fibril_mutex_lock(&addr_list_lock);
aobj = inet_addrobj_find_by_name_locked(name, ilink);
fibril_mutex_unlock(&addr_list_lock);
return aobj;
}
inet_addrobj_t *inet_addrobj_get_by_id(sysarg_t id)
{
log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_get_by_id(%zu)", (size_t)id);
fibril_mutex_lock(&addr_list_lock);
list_foreach(addr_list, addr_list, inet_addrobj_t, naddr) {
if (naddr->id == id) {
fibril_mutex_unlock(&addr_list_lock);
return naddr;
}
}
fibril_mutex_unlock(&addr_list_lock);
return NULL;
}
unsigned inet_addrobj_cnt_by_link(inet_link_t *ilink)
{
unsigned cnt;
log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_cnt_by_link()");
fibril_mutex_lock(&addr_list_lock);
cnt = 0;
list_foreach(addr_list, addr_list, inet_addrobj_t, naddr) {
if (naddr->ilink == ilink && naddr->temp == false)
++cnt;
}
fibril_mutex_unlock(&addr_list_lock);
return cnt;
}
errno_t inet_addrobj_send_dgram(inet_addrobj_t *addr, inet_addr_t *ldest,
inet_dgram_t *dgram, uint8_t proto, uint8_t ttl, int df)
{
inet_addr_t lsrc_addr;
inet_naddr_addr(&addr->naddr, &lsrc_addr);
addr32_t lsrc_v4;
addr128_t lsrc_v6;
ip_ver_t lsrc_ver = inet_addr_get(&lsrc_addr, &lsrc_v4, &lsrc_v6);
addr32_t ldest_v4;
addr128_t ldest_v6;
ip_ver_t ldest_ver = inet_addr_get(ldest, &ldest_v4, &ldest_v6);
if (lsrc_ver != ldest_ver)
return EINVAL;
errno_t rc;
eth_addr_t ldest_mac;
switch (ldest_ver) {
case ip_v4:
return inet_link_send_dgram(addr->ilink, lsrc_v4, ldest_v4,
dgram, proto, ttl, df);
case ip_v6:
rc = ndp_translate(lsrc_v6, ldest_v6, &ldest_mac, addr->ilink);
if (rc != EOK)
return rc;
return inet_link_send_dgram6(addr->ilink, &ldest_mac, dgram,
proto, ttl, df);
default:
assert(false);
break;
}
return ENOTSUP;
}
errno_t inet_addrobj_get_id_list(sysarg_t **rid_list, size_t *rcount)
{
sysarg_t *id_list;
size_t count, i;
fibril_mutex_lock(&addr_list_lock);
count = list_count(&addr_list);
id_list = calloc(count, sizeof(sysarg_t));
if (id_list == NULL) {
fibril_mutex_unlock(&addr_list_lock);
return ENOMEM;
}
i = 0;
list_foreach(addr_list, addr_list, inet_addrobj_t, addr) {
id_list[i++] = addr->id;
}
fibril_mutex_unlock(&addr_list_lock);
*rid_list = id_list;
*rcount = count;
return EOK;
}
static errno_t inet_addrobj_load(sif_node_t *anode)
{
errno_t rc;
const char *sid;
const char *snaddr;
const char *slink;
const char *name;
char *endptr;
int id;
inet_naddr_t naddr;
inet_addrobj_t *addr;
inet_link_t *link;
log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_load()");
sid = sif_node_get_attr(anode, "id");
if (sid == NULL)
return EIO;
snaddr = sif_node_get_attr(anode, "naddr");
if (snaddr == NULL)
return EIO;
slink = sif_node_get_attr(anode, "link");
if (slink == NULL)
return EIO;
name = sif_node_get_attr(anode, "name");
if (name == NULL)
return EIO;
log_msg(LOG_DEFAULT, LVL_NOTE, "inet_addrobj_load(): id='%s' "
"naddr='%s' link='%s' name='%s'", sid, snaddr, slink, name);
id = strtoul(sid, &endptr, 10);
if (*endptr != '\0')
return EIO;
rc = inet_naddr_parse(snaddr, &naddr, NULL);
if (rc != EOK)
return EIO;
link = inet_link_get_by_svc_name(slink);
if (link == NULL) {
log_msg(LOG_DEFAULT, LVL_ERROR, "Link '%s' not found",
slink);
return EIO;
}
addr = inet_addrobj_new();
if (addr == NULL)
return ENOMEM;
addr->id = id;
addr->naddr = naddr;
addr->ilink = link;
addr->name = str_dup(name);
if (addr->name == NULL) {
inet_addrobj_delete(addr);
return ENOMEM;
}
inet_addrobj_add(addr);
return EOK;
}
errno_t inet_addrobjs_load(sif_node_t *naddrs)
{
sif_node_t *naddr;
const char *ntype;
errno_t rc;
naddr = sif_node_first_child(naddrs);
while (naddr != NULL) {
ntype = sif_node_get_type(naddr);
if (str_cmp(ntype, "address") != 0) {
rc = EIO;
goto error;
}
rc = inet_addrobj_load(naddr);
if (rc != EOK)
goto error;
naddr = sif_node_next_child(naddr);
}
return EOK;
error:
return rc;
}
static errno_t inet_addrobj_save(inet_addrobj_t *addr, sif_node_t *naddr)
{
char *str = NULL;
errno_t rc;
int rv;
log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobj_save(%p, %p)",
addr, naddr);
rv = asprintf(&str, "%zu", addr->id);
if (rv < 0) {
str = NULL;
rc = ENOMEM;
goto error;
}
rc = sif_node_set_attr(naddr, "id", str);
if (rc != EOK)
goto error;
free(str);
str = NULL;
rc = inet_naddr_format(&addr->naddr, &str);
if (rc != EOK)
goto error;
rc = sif_node_set_attr(naddr, "naddr", str);
if (rc != EOK)
goto error;
free(str);
str = NULL;
rc = sif_node_set_attr(naddr, "link", addr->ilink->svc_name);
if (rc != EOK)
goto error;
rc = sif_node_set_attr(naddr, "name", addr->name);
if (rc != EOK)
goto error;
free(str);
return rc;
error:
if (str != NULL)
free(str);
return rc;
}
errno_t inet_addrobjs_save(sif_node_t *cnode)
{
sif_node_t *naddr;
errno_t rc;
log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_addrobjs_save()");
fibril_mutex_lock(&addr_list_lock);
list_foreach(addr_list, addr_list, inet_addrobj_t, addr) {
if (addr->temp == false) {
rc = sif_node_append_child(cnode, "address", &naddr);
if (rc != EOK)
goto error;
rc = inet_addrobj_save(addr, naddr);
if (rc != EOK)
goto error;
}
}
fibril_mutex_unlock(&addr_list_lock);
return EOK;
error:
fibril_mutex_unlock(&addr_list_lock);
return rc;
}
HelenOS homepage, sources at GitHub