/* * Copyright (c) 2012 Jiri Svoboda * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @addtogroup inet * @{ */ /** * @file * @brief */ #include #include #include #include #include #include #include #include #include #include "addrobj.h" #include "inet.h" #include "inet_link.h" #include "inetcfg.h" static int inetcfg_addr_create_static(char *name, inet_naddr_t *naddr, sysarg_t link_id, sysarg_t *addr_id) { inet_link_t *ilink; inet_addrobj_t *addr; iplink_addr_t iaddr; int rc; ilink = inet_link_get_by_id(link_id); if (ilink == NULL) { log_msg(LVL_DEBUG, "Link %lu not found.", (unsigned long) link_id); return ENOENT; } addr = inet_addrobj_new(); addr->naddr = *naddr; addr->ilink = ilink; addr->name = str_dup(name); inet_addrobj_add(addr); iaddr.ipv4 = addr->naddr.ipv4; rc = iplink_addr_add(ilink->iplink, &iaddr); if (rc != EOK) { log_msg(LVL_ERROR, "Failed setting IP address on internet link."); inet_addrobj_remove(addr); inet_addrobj_delete(addr); return rc; } return EOK; } static int inetcfg_addr_delete(sysarg_t addr_id) { inet_addrobj_t *addr; addr = inet_addrobj_get_by_id(addr_id); if (addr == NULL) return ENOENT; inet_addrobj_remove(addr); inet_addrobj_delete(addr); return EOK; } static int inetcfg_addr_get(sysarg_t addr_id, inet_addr_info_t *ainfo) { inet_addrobj_t *addr; addr = inet_addrobj_get_by_id(addr_id); if (addr == NULL) return ENOENT; ainfo->naddr = addr->naddr; ainfo->ilink = addr->ilink->svc_id; ainfo->name = str_dup(addr->name); return EOK; } static int inetcfg_addr_get_id(char *name, sysarg_t link_id, sysarg_t *addr_id) { inet_link_t *ilink; inet_addrobj_t *addr; ilink = inet_link_get_by_id(link_id); if (ilink == NULL) { log_msg(LVL_DEBUG, "Link %zu not found.", (size_t) link_id); return ENOENT; } addr = inet_addrobj_find_by_name(name, ilink); if (addr == NULL) { log_msg(LVL_DEBUG, "Address '%s' not found.", name); return ENOENT; } *addr_id = addr->id; return EOK; } static int inetcfg_get_addr_list(sysarg_t **addrs, size_t *count) { return inet_addrobj_get_id_list(addrs, count); } static int inetcfg_get_link_list(sysarg_t **addrs, size_t *count) { return ENOTSUP; } static int inetcfg_link_get(sysarg_t link_id, inet_link_info_t *linfo) { inet_link_t *ilink; ilink = inet_link_get_by_id(link_id); if (ilink == NULL) { return ENOENT; } linfo->name = str_dup(ilink->svc_name); return EOK; } static void inetcfg_addr_create_static_srv(ipc_callid_t callid, ipc_call_t *call) { char *name; inet_naddr_t naddr; sysarg_t link_id; sysarg_t addr_id; int rc; log_msg(LVL_DEBUG, "inetcfg_addr_create_static_srv()"); rc = async_data_write_accept((void **) &name, true, 0, LOC_NAME_MAXLEN, 0, NULL); if (rc != EOK) { async_answer_0(callid, rc); return; } naddr.ipv4 = IPC_GET_ARG1(*call); naddr.bits = IPC_GET_ARG2(*call); link_id = IPC_GET_ARG3(*call); addr_id = 0; rc = inetcfg_addr_create_static(name, &naddr, link_id, &addr_id); free(name); async_answer_1(callid, rc, addr_id); } static void inetcfg_addr_delete_srv(ipc_callid_t callid, ipc_call_t *call) { sysarg_t addr_id; int rc; log_msg(LVL_DEBUG, "inetcfg_addr_delete_srv()"); addr_id = IPC_GET_ARG1(*call); rc = inetcfg_addr_delete(addr_id); async_answer_0(callid, rc); } static void inetcfg_addr_get_srv(ipc_callid_t callid, ipc_call_t *call) { ipc_callid_t rcallid; size_t max_size; sysarg_t addr_id; inet_addr_info_t ainfo; int rc; addr_id = IPC_GET_ARG1(*call); log_msg(LVL_DEBUG, "inetcfg_addr_get_srv()"); ainfo.naddr.ipv4 = 0; ainfo.naddr.bits = 0; ainfo.ilink = 0; ainfo.name = NULL; if (!async_data_read_receive(&rcallid, &max_size)) { async_answer_0(rcallid, EREFUSED); async_answer_0(callid, EREFUSED); return; } rc = inetcfg_addr_get(addr_id, &ainfo); if (rc != EOK) { async_answer_0(callid, rc); return; } sysarg_t retval = async_data_read_finalize(rcallid, ainfo.name, min(max_size, str_size(ainfo.name))); free(ainfo.name); async_answer_3(callid, retval, ainfo.naddr.ipv4, ainfo.naddr.bits, ainfo.ilink); } static void inetcfg_addr_get_id_srv(ipc_callid_t callid, ipc_call_t *call) { char *name; sysarg_t link_id; sysarg_t addr_id; int rc; log_msg(LVL_DEBUG, "inetcfg_addr_get_id_srv()"); link_id = IPC_GET_ARG1(*call); rc = async_data_write_accept((void **) &name, true, 0, LOC_NAME_MAXLEN, 0, NULL); if (rc != EOK) { async_answer_0(callid, rc); return; } addr_id = 0; rc = inetcfg_addr_get_id(name, link_id, &addr_id); free(name); async_answer_1(callid, rc, addr_id); } static void inetcfg_get_addr_list_srv(ipc_callid_t callid, ipc_call_t *call) { ipc_callid_t rcallid; size_t count; size_t max_size; size_t act_size; size_t size; sysarg_t *id_buf; int rc; log_msg(LVL_DEBUG, "inetcfg_get_addr_list_srv()"); if (!async_data_read_receive(&rcallid, &max_size)) { async_answer_0(rcallid, EREFUSED); async_answer_0(callid, EREFUSED); return; } rc = inetcfg_get_addr_list(&id_buf, &count); if (rc != EOK) { async_answer_0(rcallid, rc); async_answer_0(callid, rc); return; } act_size = count * sizeof(sysarg_t); size = min(act_size, max_size); sysarg_t retval = async_data_read_finalize(rcallid, id_buf, size); free(id_buf); async_answer_1(callid, retval, act_size); } static void inetcfg_link_get_srv(ipc_callid_t callid, ipc_call_t *call) { ipc_callid_t rcallid; size_t max_size; sysarg_t link_id; inet_link_info_t linfo; int rc; link_id = IPC_GET_ARG1(*call); log_msg(LVL_DEBUG, "inetcfg_link_get_srv()"); linfo.name = NULL; if (!async_data_read_receive(&rcallid, &max_size)) { async_answer_0(rcallid, EREFUSED); async_answer_0(callid, EREFUSED); return; } rc = inetcfg_link_get(link_id, &linfo); if (rc != EOK) { async_answer_0(rcallid, rc); async_answer_0(callid, rc); return; } sysarg_t retval = async_data_read_finalize(rcallid, linfo.name, min(max_size, str_size(linfo.name))); free(linfo.name); async_answer_0(callid, retval); } static void inetcfg_get_link_list_srv(ipc_callid_t callid, ipc_call_t *call) { ipc_callid_t rcallid; size_t max_size; size_t act_size; size_t size; sysarg_t *id_buf; int rc; log_msg(LVL_DEBUG, "inetcfg_get_link_list_srv()"); if (!async_data_read_receive(&rcallid, &max_size)) { async_answer_0(rcallid, EREFUSED); async_answer_0(callid, EREFUSED); return; } rc = inetcfg_get_link_list(&id_buf, &act_size); if (rc != EOK) { async_answer_0(rcallid, rc); async_answer_0(callid, rc); return; } size = min(act_size, max_size); sysarg_t retval = async_data_read_finalize(rcallid, id_buf, size); free(id_buf); async_answer_1(callid, retval, act_size); } void inet_cfg_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg) { log_msg(LVL_DEBUG, "inet_cfg_conn()"); /* Accept the connection */ async_answer_0(iid, EOK); while (true) { ipc_call_t call; ipc_callid_t callid = async_get_call(&call); sysarg_t method = IPC_GET_IMETHOD(call); if (!method) { /* The other side has hung up */ async_answer_0(callid, EOK); return; } switch (method) { case INETCFG_ADDR_CREATE_STATIC: inetcfg_addr_create_static_srv(callid, &call); break; case INETCFG_ADDR_DELETE: inetcfg_addr_delete_srv(callid, &call); break; case INETCFG_ADDR_GET: inetcfg_addr_get_srv(callid, &call); break; case INETCFG_ADDR_GET_ID: inetcfg_addr_get_id_srv(callid, &call); break; case INETCFG_GET_ADDR_LIST: inetcfg_get_addr_list_srv(callid, &call); break; case INETCFG_GET_LINK_LIST: inetcfg_get_link_list_srv(callid, &call); break; case INETCFG_LINK_GET: inetcfg_link_get_srv(callid, &call); break; default: async_answer_0(callid, EINVAL); } } } /** @} */