diff options
author | Sander Vrijders <[email protected]> | 2016-10-25 13:22:51 +0200 |
---|---|---|
committer | Sander Vrijders <[email protected]> | 2016-10-26 11:52:53 +0200 |
commit | f0646875d0bc941e339d305d0c68b13543cd6f2a (patch) | |
tree | 0a3dde0e4f6284ece935d6eff99f26234126f1ab /src/ipcpd/shim-eth-llc/main.c | |
parent | 1c06b9ff80a2bf7ee6042534fee6098f7e452b59 (diff) | |
download | ouroboros-f0646875d0bc941e339d305d0c68b13543cd6f2a.tar.gz ouroboros-f0646875d0bc941e339d305d0c68b13543cd6f2a.zip |
lib, irmd, ipcpd: Add name querying to IPCPs
This adds the ability to query IPCPs if a name can be reached through
them, e.g. if a name is available in a DIF. This means that in the
shim-udp a DNS query is performed, in the shim-eth-llc an ARP-like
query has been added, in the local a check is done to see if the name
is registered, and in the normal currently no application is reachable
through it.
Diffstat (limited to 'src/ipcpd/shim-eth-llc/main.c')
-rw-r--r-- | src/ipcpd/shim-eth-llc/main.c | 114 |
1 files changed, 101 insertions, 13 deletions
diff --git a/src/ipcpd/shim-eth-llc/main.c b/src/ipcpd/shim-eth-llc/main.c index 6046d939..d4ea8eba 100644 --- a/src/ipcpd/shim-eth-llc/main.c +++ b/src/ipcpd/shim-eth-llc/main.c @@ -20,10 +20,11 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <ouroboros/config.h> - #define _DEFAULT_SOURCE +#define OUROBOROS_PREFIX "ipcpd/shim-eth-llc" + +#include <ouroboros/config.h> #include <ouroboros/errno.h> #include <ouroboros/list.h> #include <ouroboros/utils.h> @@ -32,12 +33,10 @@ #include <ouroboros/ipcp-dev.h> #include <ouroboros/fcntl.h> #include <ouroboros/fqueue.h> - -#define OUROBOROS_PREFIX "ipcpd/shim-eth-llc" - #include <ouroboros/logs.h> #include "ipcp.h" +#include "shim_eth_llc_messages.pb-c.h" #include <net/if.h> #include <signal.h> @@ -65,8 +64,6 @@ #include <poll.h> #include <sys/mman.h> -#include "shim_eth_llc_messages.pb-c.h" - typedef ShimEthLlcMsg shim_eth_llc_msg_t; #define THIS_TYPE IPCP_SHIM_ETH_LLC @@ -80,6 +77,7 @@ typedef ShimEthLlcMsg shim_eth_llc_msg_t; + SHIM_ETH_LLC_MAX_SDU_SIZE) #define EVENT_WAIT_TIMEOUT 100 /* us */ +#define NAME_QUERY_TIMEOUT 100000000 /* ns */ /* global for trapping signal */ int irmd_api; @@ -313,6 +311,7 @@ static int eth_llc_ipcp_sap_alloc(uint8_t * dst_addr, shim_eth_llc_msg_t msg = SHIM_ETH_LLC_MSG__INIT; msg.code = SHIM_ETH_LLC_MSG_CODE__FLOW_REQ; + msg.has_ssap = true; msg.ssap = ssap; msg.dst_name = dst_name; msg.src_ae_name = src_ae_name; @@ -328,6 +327,7 @@ static int eth_llc_ipcp_sap_alloc_resp(uint8_t * dst_addr, shim_eth_llc_msg_t msg = SHIM_ETH_LLC_MSG__INIT; msg.code = SHIM_ETH_LLC_MSG_CODE__FLOW_REPLY; + msg.has_ssap = true; msg.ssap = ssap; msg.has_dsap = true; msg.dsap = dsap; @@ -341,8 +341,9 @@ static int eth_llc_ipcp_sap_dealloc(uint8_t * dst_addr, uint8_t ssap) { shim_eth_llc_msg_t msg = SHIM_ETH_LLC_MSG__INIT; - msg.code = SHIM_ETH_LLC_MSG_CODE__FLOW_DEALLOC; - msg.ssap = ssap; + msg.code = SHIM_ETH_LLC_MSG_CODE__FLOW_DEALLOC; + msg.has_ssap = true; + msg.ssap = ssap; return eth_llc_ipcp_send_mgmt_frame(&msg, dst_addr); } @@ -438,6 +439,42 @@ static int eth_llc_ipcp_flow_dealloc_req(uint8_t ssap) return 0; } +static int eth_llc_ipcp_name_query_req(char * name, uint8_t * r_addr) +{ + shim_eth_llc_msg_t msg = SHIM_ETH_LLC_MSG__INIT; + + if (ipcp_data_reg_has(ipcpi.data, name)) { + msg.code = SHIM_ETH_LLC_MSG_CODE__NAME_QUERY_REPLY; + msg.dst_name = name; + + eth_llc_ipcp_send_mgmt_frame(&msg, r_addr); + } + + return 0; +} + +static int eth_llc_ipcp_name_query_reply(char * name, uint8_t * r_addr) +{ + uint64_t address = 0; + struct list_head * pos; + + memcpy(&address, r_addr, MAC_SIZE); + + ipcp_data_dir_add_entry(ipcpi.data, name, address); + + pthread_mutex_lock(&ipcpi.data->dir_queries_lock); + list_for_each(pos, &ipcpi.data->dir_queries) { + struct dir_query * e = + list_entry(pos, struct dir_query, next); + if (strcmp(e->name, name) == 0) { + ipcp_data_dir_query_respond(e); + } + } + pthread_mutex_unlock(&ipcpi.data->dir_queries_lock); + + return 0; +} + static int eth_llc_ipcp_mgmt_frame(uint8_t * buf, size_t len, uint8_t * r_addr) { shim_eth_llc_msg_t * msg = shim_eth_llc_msg__unpack(NULL, len, buf); @@ -448,7 +485,7 @@ static int eth_llc_ipcp_mgmt_frame(uint8_t * buf, size_t len, uint8_t * r_addr) switch (msg->code) { case SHIM_ETH_LLC_MSG_CODE__FLOW_REQ: - if (ipcp_data_is_in_registry(ipcpi.data, msg->dst_name)) { + if (ipcp_data_reg_has(ipcpi.data, msg->dst_name)) { eth_llc_ipcp_sap_req(msg->ssap, r_addr, msg->dst_name, @@ -464,6 +501,12 @@ static int eth_llc_ipcp_mgmt_frame(uint8_t * buf, size_t len, uint8_t * r_addr) case SHIM_ETH_LLC_MSG_CODE__FLOW_DEALLOC: eth_llc_ipcp_flow_dealloc_req(msg->ssap); break; + case SHIM_ETH_LLC_MSG_CODE__NAME_QUERY_REQ: + eth_llc_ipcp_name_query_req(msg->dst_name, r_addr); + break; + case SHIM_ETH_LLC_MSG_CODE__NAME_QUERY_REPLY: + eth_llc_ipcp_name_query_reply(msg->dst_name, r_addr); + break; default: LOG_ERR("Unknown message received %d.", msg->code); shim_eth_llc_msg__free_unpacked(msg, NULL); @@ -854,7 +897,7 @@ static int eth_llc_ipcp_name_reg(char * name) { pthread_rwlock_rdlock(&ipcpi.state_lock); - if (ipcp_data_add_reg_entry(ipcpi.data, name)) { + if (ipcp_data_reg_add_entry(ipcpi.data, name)) { pthread_rwlock_unlock(&ipcpi.state_lock); LOG_ERR("Failed to add %s to local registry.", name); return -1; @@ -871,13 +914,49 @@ static int eth_llc_ipcp_name_unreg(char * name) { pthread_rwlock_rdlock(&ipcpi.state_lock); - ipcp_data_del_reg_entry(ipcpi.data, name); + ipcp_data_reg_del_entry(ipcpi.data, name); pthread_rwlock_unlock(&ipcpi.state_lock); return 0; } +static int eth_llc_ipcp_name_query(char * name) +{ + uint8_t r_addr[MAC_SIZE]; + struct timespec timeout = {0, NAME_QUERY_TIMEOUT}; + shim_eth_llc_msg_t msg = SHIM_ETH_LLC_MSG__INIT; + struct dir_query * query; + int ret; + + if (ipcp_data_dir_has(ipcpi.data, name)) + return 0; + + msg.code = SHIM_ETH_LLC_MSG_CODE__NAME_QUERY_REQ; + msg.dst_name = name; + + memset(r_addr, 0xff, MAC_SIZE); + + query = ipcp_data_dir_query_create(name); + if (query == NULL) + return -1; + + pthread_mutex_lock(&ipcpi.data->dir_queries_lock); + list_add(&query->next, &ipcpi.data->dir_queries); + pthread_mutex_unlock(&ipcpi.data->dir_queries_lock); + + eth_llc_ipcp_send_mgmt_frame(&msg, r_addr); + + ret = ipcp_data_dir_query_wait(query, &timeout); + + pthread_mutex_lock(&ipcpi.data->dir_queries_lock); + list_del(&query->next); + ipcp_data_dir_query_destroy(query); + pthread_mutex_unlock(&ipcpi.data->dir_queries_lock); + + return ret; +} + static int eth_llc_ipcp_flow_alloc(int fd, char * dst_name, char * src_ae_name, @@ -885,6 +964,7 @@ static int eth_llc_ipcp_flow_alloc(int fd, { uint8_t ssap = 0; uint8_t r_addr[MAC_SIZE]; + uint64_t addr = 0; LOG_DBG("Allocating flow to %s.", dst_name); @@ -902,6 +982,13 @@ static int eth_llc_ipcp_flow_alloc(int fd, return -1; /* -ENOTENROLLED */ } + if (!ipcp_data_dir_has(ipcpi.data, dst_name)) { + pthread_rwlock_unlock(&ipcpi.state_lock); + LOG_ERR("Destination unreachable."); + return -1; + } + addr = ipcp_data_dir_get_addr(ipcpi.data, dst_name); + pthread_rwlock_wrlock(ð_llc_data.flows_lock); ssap = bmp_allocate(eth_llc_data.saps); @@ -917,7 +1004,7 @@ static int eth_llc_ipcp_flow_alloc(int fd, pthread_rwlock_unlock(ð_llc_data.flows_lock); pthread_rwlock_unlock(&ipcpi.state_lock); - memset(r_addr, 0xff, MAC_SIZE); + memcpy(r_addr, &addr, MAC_SIZE); if (eth_llc_ipcp_sap_alloc(r_addr, ssap, @@ -1025,6 +1112,7 @@ static struct ipcp_ops eth_llc_ops = { .ipcp_enroll = NULL, .ipcp_name_reg = eth_llc_ipcp_name_reg, .ipcp_name_unreg = eth_llc_ipcp_name_unreg, + .ipcp_name_query = eth_llc_ipcp_name_query, .ipcp_flow_alloc = eth_llc_ipcp_flow_alloc, .ipcp_flow_alloc_resp = eth_llc_ipcp_flow_alloc_resp, .ipcp_flow_dealloc = eth_llc_ipcp_flow_dealloc |