From fe6b60909d455abdac7885ceaba1097749e7aeb1 Mon Sep 17 00:00:00 2001 From: Dimitri Staessens Date: Mon, 24 Feb 2020 22:30:22 +0100 Subject: lib, ipcpd: piggyback ECDHE on flow allocation The initial implementation for the ECDHE key exchange was doing the key exchange after a flow was established. The public keys are now sent allowg on the flow allocation messages, so that an encrypted tunnel can be created within 1 RTT. The flow allocation steps had to be extended to pass the opaque data ('piggybacking'). Signed-off-by: Dimitri Staessens Signed-off-by: Sander Vrijders --- src/ipcpd/broadcast/main.c | 2 +- src/ipcpd/eth/eth.c | 93 +++++++++++++++++++++++++++++++--------------- src/ipcpd/ipcp.c | 15 ++++++-- src/ipcpd/ipcp.h | 10 +++-- src/ipcpd/local/main.c | 15 +++++--- src/ipcpd/udp/main.c | 92 ++++++++++++++++++++++++++++++--------------- src/ipcpd/unicast/fa.c | 60 ++++++++++++++++++------------ src/ipcpd/unicast/fa.h | 12 ++++-- 8 files changed, 199 insertions(+), 100 deletions(-) (limited to 'src/ipcpd') diff --git a/src/ipcpd/broadcast/main.c b/src/ipcpd/broadcast/main.c index 05338ee4..120b2bf1 100644 --- a/src/ipcpd/broadcast/main.c +++ b/src/ipcpd/broadcast/main.c @@ -235,7 +235,7 @@ static int broadcast_ipcp_join(int fd, notifier_event(NOTIFY_DT_CONN_ADD, &conn); - ipcp_flow_alloc_reply(fd, 0); + ipcp_flow_alloc_reply(fd, 0, NULL, 0); return 0; } diff --git a/src/ipcpd/eth/eth.c b/src/ipcpd/eth/eth.c index 0c9daff4..6b17912b 100644 --- a/src/ipcpd/eth/eth.c +++ b/src/ipcpd/eth/eth.c @@ -138,7 +138,7 @@ #define ALLOC_TIMEO 10 /* ms */ #define NAME_QUERY_TIMEO 2000 /* ms */ #define MGMT_TIMEO 100 /* ms */ -#define MGMT_FRAME_SIZE 512 +#define MGMT_FRAME_SIZE 2048 #define FLOW_REQ 0 #define FLOW_REPLY 1 @@ -201,6 +201,7 @@ struct mgmt_frame { struct list_head next; uint8_t r_addr[MAC_SIZE]; uint8_t buf[MGMT_FRAME_SIZE]; + size_t len; }; struct { @@ -458,7 +459,9 @@ static int eth_ipcp_alloc(const uint8_t * dst_addr, uint8_t ssap, #endif const uint8_t * hash, - qosspec_t qs) + qosspec_t qs, + const void * data, + size_t dlen) { uint8_t * buf; struct mgmt_msg * msg; @@ -467,7 +470,7 @@ static int eth_ipcp_alloc(const uint8_t * dst_addr, len = sizeof(*msg) + ipcp_dir_hash_len(); - buf = malloc(len + ETH_HEADER_TOT_SIZE); + buf = malloc(len + ETH_HEADER_TOT_SIZE + dlen); if (buf == NULL) return -1; @@ -489,6 +492,7 @@ static int eth_ipcp_alloc(const uint8_t * dst_addr, msg->cypher_s = hton16(qs.cypher_s); memcpy(msg + 1, hash, ipcp_dir_hash_len()); + memcpy(buf + len + ETH_HEADER_TOT_SIZE, data, dlen); ret = eth_ipcp_send_frame(dst_addr, #if defined(BUILD_ETH_DIX) @@ -497,26 +501,28 @@ static int eth_ipcp_alloc(const uint8_t * dst_addr, reverse_bits(MGMT_SAP), reverse_bits(MGMT_SAP), #endif - buf, len); + buf, len + dlen); free(buf); return ret; } -static int eth_ipcp_alloc_resp(uint8_t * dst_addr, +static int eth_ipcp_alloc_resp(uint8_t * dst_addr, #if defined(BUILD_ETH_DIX) - uint16_t seid, - uint16_t deid, + uint16_t seid, + uint16_t deid, #elif defined(BUILD_ETH_LLC) - uint8_t ssap, - uint8_t dsap, + uint8_t ssap, + uint8_t dsap, #endif - int response) + int response, + const void * data, + size_t len) { struct mgmt_msg * msg; uint8_t * buf; - buf = malloc(sizeof(*msg) + ETH_HEADER_TOT_SIZE); + buf = malloc(sizeof(*msg) + ETH_HEADER_TOT_SIZE + len); if (buf == NULL) return -1; @@ -532,6 +538,8 @@ static int eth_ipcp_alloc_resp(uint8_t * dst_addr, #endif msg->response = response; + memcpy(msg + 1, data, len); + if (eth_ipcp_send_frame(dst_addr, #if defined(BUILD_ETH_DIX) MGMT_EID, @@ -539,7 +547,7 @@ static int eth_ipcp_alloc_resp(uint8_t * dst_addr, reverse_bits(MGMT_SAP), reverse_bits(MGMT_SAP), #endif - buf, sizeof(*msg))) { + buf, sizeof(*msg) + len)) { free(buf); return -1; } @@ -556,7 +564,9 @@ static int eth_ipcp_req(uint8_t * r_addr, uint8_t r_sap, #endif const uint8_t * dst, - qosspec_t qs) + qosspec_t qs, + const void * data, + size_t len) { struct timespec ts = {0, ALLOC_TIMEO * MILLION}; struct timespec abstime; @@ -580,7 +590,7 @@ static int eth_ipcp_req(uint8_t * r_addr, } /* reply to IRM, called under lock to prevent race */ - fd = ipcp_flow_req_arr(dst, ipcp_dir_hash_len(), qs); + fd = ipcp_flow_req_arr(dst, ipcp_dir_hash_len(), qs, data, len); if (fd < 0) { pthread_mutex_unlock(&ipcpi.alloc_lock); log_err("Could not get new flow from IRMd."); @@ -607,19 +617,20 @@ static int eth_ipcp_req(uint8_t * r_addr, #elif defined(BUILD_ETH_LLC) log_dbg("New flow request, fd %d, remote SAP %d.", fd, r_sap); #endif - return 0; } -static int eth_ipcp_alloc_reply(uint8_t * r_addr, +static int eth_ipcp_alloc_reply(uint8_t * r_addr, #if defined(BUILD_ETH_DIX) - uint16_t seid, - uint16_t deid, + uint16_t seid, + uint16_t deid, #elif defined(BUILD_ETH_LLC) - uint8_t ssap, - int dsap, + uint8_t ssap, + int dsap, #endif - int response) + int response, + const void * data, + size_t len) { int ret = 0; int fd = -1; @@ -657,7 +668,7 @@ static int eth_ipcp_alloc_reply(uint8_t * r_addr, #elif defined(BUILD_ETH_LLC) log_dbg("Flow reply, fd %d, SSAP %d, DSAP %d.", fd, ssap, dsap); #endif - if ((ret = ipcp_flow_alloc_reply(fd, response)) < 0) + if ((ret = ipcp_flow_alloc_reply(fd, response, data, len)) < 0) return -1; return ret; @@ -717,15 +728,21 @@ static int eth_ipcp_name_query_reply(const uint8_t * hash, } static int eth_ipcp_mgmt_frame(const uint8_t * buf, + size_t len, uint8_t * r_addr) { struct mgmt_msg * msg; + size_t msg_len; qosspec_t qs; msg = (struct mgmt_msg *) buf; switch (msg->code) { case FLOW_REQ: + msg_len = sizeof(*msg) + ipcp_dir_hash_len(); + + assert(len >= msg_len); + qs.delay = ntoh32(msg->delay); qs.bandwidth = ntoh64(msg->bandwidth); qs.availability = msg->availability; @@ -744,10 +761,14 @@ static int eth_ipcp_mgmt_frame(const uint8_t * buf, msg->ssap, #endif buf + sizeof(*msg), - qs); + qs, + buf + msg_len, + len - msg_len); } break; case FLOW_REPLY: + assert(len >= sizeof(*msg)); + eth_ipcp_alloc_reply(r_addr, #if defined(BUILD_ETH_DIX) ntohs(msg->seid), @@ -756,7 +777,9 @@ static int eth_ipcp_mgmt_frame(const uint8_t * buf, msg->ssap, msg->dsap, #endif - msg->response); + msg->response, + buf + sizeof(*msg), + len - sizeof(*msg)); break; case NAME_QUERY_REQ: eth_ipcp_name_query_req(buf + sizeof(*msg), r_addr); @@ -814,7 +837,7 @@ static void * eth_ipcp_mgmt_handler(void * o) list_del(&frame->next); pthread_mutex_unlock(ð_data.mgmt_lock); - eth_ipcp_mgmt_frame(frame->buf, frame->r_addr); + eth_ipcp_mgmt_frame(frame->buf, frame->len, frame->r_addr); free(frame); } @@ -951,6 +974,7 @@ static void * eth_ipcp_packet_reader(void * o) memcpy(frame->buf, &e_frame->payload, length); memcpy(frame->r_addr, e_frame->src_hwaddr, MAC_SIZE); + frame->len = length; pthread_mutex_lock(ð_data.mgmt_lock); list_add(&frame->next, ð_data.mgmt_frames); @@ -1613,7 +1637,9 @@ static int eth_ipcp_query(const uint8_t * hash) static int eth_ipcp_flow_alloc(int fd, const uint8_t * hash, - qosspec_t qs) + qosspec_t qs, + const void * data, + size_t len) { #ifdef BUILD_ETH_LLC uint8_t ssap = 0; @@ -1652,7 +1678,10 @@ static int eth_ipcp_flow_alloc(int fd, #elif defined(BUILD_ETH_LLC) ssap, #endif - hash, qs) < 0) { + hash, + qs, + data, + len) < 0) { #ifdef BUILD_ETH_LLC pthread_rwlock_wrlock(ð_data.flows_lock); bmp_release(eth_data.saps, eth_data.fd_to_ef[fd].sap); @@ -1672,8 +1701,10 @@ static int eth_ipcp_flow_alloc(int fd, return 0; } -static int eth_ipcp_flow_alloc_resp(int fd, - int response) +static int eth_ipcp_flow_alloc_resp(int fd, + int response, + const void * data, + size_t len) { struct timespec ts = {0, ALLOC_TIMEO * MILLION}; struct timespec abstime; @@ -1730,7 +1761,9 @@ static int eth_ipcp_flow_alloc_resp(int fd, #elif defined(BUILD_ETH_LLC) ssap, r_sap, #endif - response) < 0) { + response, + data, + len) < 0) { #ifdef BUILD_ETH_LLC pthread_rwlock_wrlock(ð_data.flows_lock); bmp_release(eth_data.saps, eth_data.fd_to_ef[fd].sap); diff --git a/src/ipcpd/ipcp.c b/src/ipcpd/ipcp.c index 8f9fcd7d..95d2f783 100644 --- a/src/ipcpd/ipcp.c +++ b/src/ipcpd/ipcp.c @@ -408,6 +408,8 @@ static void * mainloop(void * o) } assert(msg->hash.len == ipcp_dir_hash_len()); + assert(msg->pk.len > 0 ? msg->pk.data != NULL + : msg->pk.data == NULL); if (ipcp_get_state() != IPCP_OPERATIONAL) { log_err("IPCP in wrong state."); @@ -429,7 +431,9 @@ static void * mainloop(void * o) ret_msg.result = ipcpi.ops->ipcp_flow_alloc(fd, msg->hash.data, - qs); + qs, + msg->pk.data, + msg->pk.len); break; case IPCP_MSG_CODE__IPCP_FLOW_JOIN: ret_msg.has_result = true; @@ -488,9 +492,14 @@ static void * mainloop(void * o) } } + assert(msg->pk.len > 0 ? msg->pk.data != NULL + : msg->pk.data == NULL); + ret_msg.result = ipcpi.ops->ipcp_flow_alloc_resp(fd, - msg->response); + msg->response, + msg->pk.data, + msg->pk.len); break; case IPCP_MSG_CODE__IPCP_FLOW_DEALLOC: ret_msg.has_result = true; @@ -568,7 +577,7 @@ static int parse_args(int argc, if (!(argc == 4 || argc == 3)) return -1; - /* argument 1: pid of irmd */ + /* argument 1: pid of irm */ if (atoi(argv[1]) == 0) return -1; diff --git a/src/ipcpd/ipcp.h b/src/ipcpd/ipcp.h index 6afac3ea..02c74f50 100644 --- a/src/ipcpd/ipcp.h +++ b/src/ipcpd/ipcp.h @@ -60,14 +60,18 @@ struct ipcp_ops { int (* ipcp_flow_alloc)(int fd, const uint8_t * dst, - qosspec_t qs); + qosspec_t qs, + const void * data, + size_t len); int (* ipcp_flow_join)(int fd, const uint8_t * dst, qosspec_t qs); - int (* ipcp_flow_alloc_resp)(int fd, - int response); + int (* ipcp_flow_alloc_resp)(int fd, + int response, + const void * data, + size_t len); int (* ipcp_flow_dealloc)(int fd); }; diff --git a/src/ipcpd/local/main.c b/src/ipcpd/local/main.c index 009a3fde..a2e20017 100644 --- a/src/ipcpd/local/main.c +++ b/src/ipcpd/local/main.c @@ -186,14 +186,15 @@ static int ipcp_local_query(const uint8_t * hash) static int ipcp_local_flow_alloc(int fd, const uint8_t * dst, - qosspec_t qs) + qosspec_t qs, + const void * data, + size_t len) { struct timespec ts = {0, ALLOC_TIMEOUT * MILLION}; struct timespec abstime; int out_fd = -1; log_dbg("Allocating flow to " HASH_FMT " on fd %d.", HASH_VAL(dst), fd); - assert(dst); clock_gettime(PTHREAD_COND_CLOCK, &abstime); @@ -215,7 +216,7 @@ static int ipcp_local_flow_alloc(int fd, assert(ipcpi.alloc_id == -1); - out_fd = ipcp_flow_req_arr(dst, ipcp_dir_hash_len(), qs); + out_fd = ipcp_flow_req_arr(dst, ipcp_dir_hash_len(), qs, data, len); if (out_fd < 0) { pthread_mutex_unlock(&ipcpi.alloc_lock); log_dbg("Flow allocation failed: %d", out_fd); @@ -241,8 +242,10 @@ static int ipcp_local_flow_alloc(int fd, return 0; } -static int ipcp_local_flow_alloc_resp(int fd, - int response) +static int ipcp_local_flow_alloc_resp(int fd, + int response, + const void * data, + size_t len) { struct timespec ts = {0, ALLOC_TIMEOUT * MILLION}; struct timespec abstime; @@ -290,7 +293,7 @@ static int ipcp_local_flow_alloc_resp(int fd, fset_add(local_data.flows, fd); - if ((ret = ipcp_flow_alloc_reply(out_fd, response)) < 0) + if ((ret = ipcp_flow_alloc_reply(out_fd, response, data, len)) < 0) return -1; log_info("Flow allocation completed, fds (%d, %d).", out_fd, fd); diff --git a/src/ipcpd/udp/main.c b/src/ipcpd/udp/main.c index 1f0bebf0..04c21a8b 100644 --- a/src/ipcpd/udp/main.c +++ b/src/ipcpd/udp/main.c @@ -62,8 +62,8 @@ #define IPCP_UDP_MAX_PACKET_SIZE 8980 #define OUR_HEADER_LEN sizeof(uint32_t) /* adds eid */ -#define IPCP_UDP_BUF_SIZE 256 -#define IPCP_UDP_MSG_SIZE 256 +#define IPCP_UDP_BUF_SIZE 8980 +#define IPCP_UDP_MSG_SIZE 8980 #define DNS_TTL 86400 #define FD_UPDATE_TIMEOUT 100 /* microseconds */ @@ -74,7 +74,8 @@ #define LOCAL_IP (udp_data.s_saddr.sin_addr.s_addr) #define MGMT_EID 0 -#define MGMT_FRAME_SIZE 512 +#define MGMT_FRAME_SIZE (sizeof(struct mgmt_msg)) +#define MGMT_FRAME_BUF_SIZE 2048 /* Keep order for alignment. */ struct mgmt_msg { @@ -97,7 +98,8 @@ struct mgmt_msg { struct mgmt_frame { struct list_head next; struct sockaddr_in r_saddr; - uint8_t buf[MGMT_FRAME_SIZE]; + uint8_t buf[MGMT_FRAME_BUF_SIZE]; + size_t len; }; /* UDP flow */ @@ -186,15 +188,19 @@ static void udp_data_fini(void) static int ipcp_udp_port_alloc(int skfd, uint32_t s_eid, const uint8_t * dst, - qosspec_t qs) + qosspec_t qs, + const void * data, + size_t dlen) { uint8_t * buf; struct mgmt_msg * msg; size_t len; + assert(dlen > 0 ? data != NULL : data == NULL); + len = sizeof(*msg) + ipcp_dir_hash_len(); - buf = malloc(len); + buf = malloc(len + dlen); if (buf == NULL) return -1; @@ -212,8 +218,9 @@ static int ipcp_udp_port_alloc(int skfd, msg->cypher_s = hton16(qs.cypher_s); memcpy(msg + 1, dst, ipcp_dir_hash_len()); + memcpy(buf + len, data, dlen); - if (write(skfd, msg, len) < 0) { + if (write(skfd, msg, len + dlen) < 0) { free(buf); return -1; } @@ -223,14 +230,16 @@ static int ipcp_udp_port_alloc(int skfd, return 0; } -static int ipcp_udp_port_alloc_resp(int skfd, - uint32_t s_eid, - uint32_t d_eid, - int8_t response) +static int ipcp_udp_port_alloc_resp(int skfd, + uint32_t s_eid, + uint32_t d_eid, + int8_t response, + const void * data, + size_t len) { struct mgmt_msg * msg; - msg = malloc(sizeof(*msg)); + msg = malloc(sizeof(*msg) + len); if (msg == NULL) return -1; @@ -240,7 +249,9 @@ static int ipcp_udp_port_alloc_resp(int skfd, msg->d_eid = hton32(d_eid); msg->response = response; - if (write(skfd, msg, sizeof(*msg)) < 0) { + memcpy(msg + 1, data, len); + + if (write(skfd, msg, sizeof(*msg) + len) < 0) { free(msg); return -1; } @@ -253,7 +264,9 @@ static int ipcp_udp_port_alloc_resp(int skfd, static int ipcp_udp_port_req(struct sockaddr_in * c_saddr, int d_eid, const uint8_t * dst, - qosspec_t qs) + qosspec_t qs, + const void * data, + size_t len) { struct timespec ts = {0, FD_UPDATE_TIMEOUT * 1000}; struct timespec abstime; @@ -294,7 +307,7 @@ static int ipcp_udp_port_req(struct sockaddr_in * c_saddr, } /* reply to IRM */ - fd = ipcp_flow_req_arr(dst, ipcp_dir_hash_len(), qs); + fd = ipcp_flow_req_arr(dst, ipcp_dir_hash_len(), qs, data, len); if (fd < 0) { pthread_mutex_unlock(&ipcpi.alloc_lock); log_err("Could not get new flow from IRMd."); @@ -320,9 +333,11 @@ static int ipcp_udp_port_req(struct sockaddr_in * c_saddr, return 0; } -static int ipcp_udp_port_alloc_reply(uint32_t s_eid, - uint32_t d_eid, - int8_t response) +static int ipcp_udp_port_alloc_reply(uint32_t s_eid, + uint32_t d_eid, + int8_t response, + const void * data, + size_t len) { struct sockaddr_in t_saddr; socklen_t t_saddr_len; @@ -356,7 +371,7 @@ static int ipcp_udp_port_alloc_reply(uint32_t s_eid, return -1; } - if (ipcp_flow_alloc_reply(s_eid, response) < 0) { + if (ipcp_flow_alloc_reply(s_eid, response, data, len) < 0) { log_dbg("Failed to reply to flow allocation."); return -1; } @@ -368,15 +383,21 @@ static int ipcp_udp_port_alloc_reply(uint32_t s_eid, } static int ipcp_udp_mgmt_frame(const uint8_t * buf, + size_t len, struct sockaddr_in c_saddr) { struct mgmt_msg * msg; + size_t msg_len; qosspec_t qs; msg = (struct mgmt_msg *) buf; switch (msg->code) { case FLOW_REQ: + msg_len = sizeof(*msg) + ipcp_dir_hash_len(); + + assert(len >= msg_len); + qs.delay = ntoh32(msg->delay); qs.bandwidth = ntoh64(msg->bandwidth); qs.availability = msg->availability; @@ -387,11 +408,17 @@ static int ipcp_udp_mgmt_frame(const uint8_t * buf, qs.cypher_s = ntoh16(msg->cypher_s); return ipcp_udp_port_req(&c_saddr, ntoh32(msg->s_eid), - (uint8_t *) (msg + 1), qs); + (uint8_t *) (msg + 1), qs, + buf + msg_len, + len - msg_len); case FLOW_REPLY: + assert(len >= sizeof(*msg)); + return ipcp_udp_port_alloc_reply(ntoh32(msg->s_eid), ntoh32(msg->d_eid), - msg->response); + msg->response, + buf + sizeof(*msg), + len - sizeof(*msg)); default: log_err("Unknown message received %d.", msg->code); return -1; @@ -421,7 +448,7 @@ static void * ipcp_udp_mgmt_handler(void * o) pthread_mutex_unlock(&udp_data.mgmt_lock); - ipcp_udp_mgmt_frame(frame->buf, frame->r_saddr); + ipcp_udp_mgmt_frame(frame->buf, frame->len, frame->r_saddr); free(frame); } @@ -468,8 +495,8 @@ static void * ipcp_udp_packet_reader(void * o) /* pass onto mgmt queue */ if (eid == MGMT_EID) { - if (n > IPCP_UDP_MSG_SIZE) { - log_warn("Dropped oversize management frame."); + if ((size_t) n < MGMT_FRAME_SIZE) { + log_warn("Dropped runt mgmt frame."); continue; } @@ -479,6 +506,7 @@ static void * ipcp_udp_packet_reader(void * o) memcpy(frame->buf, buf, n); memcpy(&frame->r_saddr, &r_saddr, sizeof(r_saddr)); + frame->len = n; pthread_mutex_lock(&udp_data.mgmt_lock); list_add(&frame->next, &udp_data.mgmt_frames); @@ -962,7 +990,9 @@ static int ipcp_udp_query(const uint8_t * hash) static int ipcp_udp_flow_alloc(int fd, const uint8_t * dst, - qosspec_t qs) + qosspec_t qs, + const void * data, + size_t len) { struct sockaddr_in r_saddr; /* Server address */ struct sockaddr_in c_saddr; /* Client address */ @@ -1026,7 +1056,7 @@ static int ipcp_udp_flow_alloc(int fd, return -1; } - if (ipcp_udp_port_alloc(skfd, fd, dst, qs) < 0) { + if (ipcp_udp_port_alloc(skfd, fd, dst, qs, data, len) < 0) { log_err("Could not allocate port."); close(skfd); return -1; @@ -1047,15 +1077,17 @@ static int ipcp_udp_flow_alloc(int fd, return 0; } -static int ipcp_udp_flow_alloc_resp(int fd, - int response) +static int ipcp_udp_flow_alloc_resp(int fd, + int resp, + const void * data, + size_t len) { struct timespec ts = {0, FD_UPDATE_TIMEOUT * 1000}; struct timespec abstime; int skfd; int d_eid; - if (response) + if (resp) return 0; clock_gettime(PTHREAD_COND_CLOCK, &abstime); @@ -1088,7 +1120,7 @@ static int ipcp_udp_flow_alloc_resp(int fd, pthread_rwlock_unlock(&udp_data.flows_lock); - if (ipcp_udp_port_alloc_resp(skfd, d_eid, fd, response) < 0) { + if (ipcp_udp_port_alloc_resp(skfd, d_eid, fd, resp, data, len) < 0) { pthread_rwlock_rdlock(&udp_data.flows_lock); fset_del(udp_data.np1_flows, fd); pthread_rwlock_unlock(&udp_data.flows_lock); diff --git a/src/ipcpd/unicast/fa.c b/src/ipcpd/unicast/fa.c index 9ed9f710..e0727e85 100644 --- a/src/ipcpd/unicast/fa.c +++ b/src/ipcpd/unicast/fa.c @@ -51,6 +51,7 @@ #define FLOW_REQ 0 #define FLOW_REPLY 1 +#define MSGBUFSZ 2048 struct fa_msg { uint64_t s_addr; @@ -106,7 +107,7 @@ static void packet_handler(int fd, static void destroy_conn(int fd) { - fa.r_eid[fd] = -1; + fa.r_eid[fd] = -1; fa.r_addr[fd] = INVALID_ADDR; } @@ -146,10 +147,12 @@ static void * fa_handle_packet(void * o) while (true) { struct timespec abstime; int fd; - uint8_t * buf; + uint8_t buf[MSGBUFSZ]; struct fa_msg * msg; qosspec_t qs; struct cmd * cmd; + size_t len; + size_t msg_len; pthread_mutex_lock(&fa.mtx); @@ -164,10 +167,10 @@ static void * fa_handle_packet(void * o) pthread_cleanup_pop(true); - buf = malloc(sizeof(*msg) + ipcp_dir_hash_len()); - if (buf == NULL) { - log_err("Failed to allocate memory."); - ipcp_sdb_release(cmd->sdb); + len = shm_du_buff_tail(cmd->sdb) - shm_du_buff_head(cmd->sdb); + + if (len > MSGBUFSZ) { + log_err("Message over buffer size."); free(cmd); continue; } @@ -176,12 +179,7 @@ static void * fa_handle_packet(void * o) /* Depending on the message call the function in ipcp-dev.h */ - assert(sizeof(*msg) + ipcp_dir_hash_len() >= - (unsigned long int) (shm_du_buff_tail(cmd->sdb) - - shm_du_buff_head(cmd->sdb))); - - memcpy(msg, shm_du_buff_head(cmd->sdb), - shm_du_buff_tail(cmd->sdb) - shm_du_buff_head(cmd->sdb)); + memcpy(msg, shm_du_buff_head(cmd->sdb), len); ipcp_sdb_release(cmd->sdb); @@ -189,6 +187,10 @@ static void * fa_handle_packet(void * o) switch (msg->code) { case FLOW_REQ: + msg_len = sizeof(*msg) + ipcp_dir_hash_len(); + + assert(len >= msg_len); + clock_gettime(PTHREAD_COND_CLOCK, &abstime); pthread_mutex_lock(&ipcpi.alloc_lock); @@ -205,7 +207,6 @@ static void * fa_handle_packet(void * o) pthread_mutex_unlock(&ipcpi.alloc_lock); log_dbg("Won't allocate over non-operational" "IPCP."); - free(msg); continue; } @@ -222,11 +223,12 @@ static void * fa_handle_packet(void * o) fd = ipcp_flow_req_arr((uint8_t *) (msg + 1), ipcp_dir_hash_len(), - qs); + qs, + buf + msg_len, + len - msg_len); if (fd < 0) { pthread_mutex_unlock(&ipcpi.alloc_lock); log_err("Failed to get fd for flow."); - free(msg); continue; } @@ -244,12 +246,16 @@ static void * fa_handle_packet(void * o) break; case FLOW_REPLY: + assert(len >= sizeof(*msg)); + pthread_rwlock_wrlock(&fa.flows_lock); fa.r_eid[ntoh32(msg->r_eid)] = ntoh32(msg->s_eid); ipcp_flow_alloc_reply(ntoh32(msg->r_eid), - msg->response); + msg->response, + buf + sizeof(*msg), + len - sizeof(*msg)); if (msg->response < 0) destroy_conn(ntoh32(msg->r_eid)); @@ -263,8 +269,6 @@ static void * fa_handle_packet(void * o) log_err("Got an unknown flow allocation message."); break; } - - free(msg); } } @@ -363,18 +367,23 @@ void fa_stop(void) int fa_alloc(int fd, const uint8_t * dst, - qosspec_t qs) + qosspec_t qs, + const void * data, + size_t dlen) { struct fa_msg * msg; uint64_t addr; struct shm_du_buff * sdb; qoscube_t qc; + size_t len; addr = dir_query(dst); if (addr == 0) return -1; - if (ipcp_sdb_reserve(&sdb, sizeof(*msg) + ipcp_dir_hash_len())) + len = sizeof(*msg) + ipcp_dir_hash_len(); + + if (ipcp_sdb_reserve(&sdb, len + dlen)) return -1; msg = (struct fa_msg *) shm_du_buff_head(sdb); @@ -391,6 +400,7 @@ int fa_alloc(int fd, msg->cypher_s = hton16(qs.cypher_s); memcpy(msg + 1, dst, ipcp_dir_hash_len()); + memcpy(shm_du_buff_head(sdb) + len, data, dlen); qc = qos_spec_to_cube(qs); @@ -409,8 +419,10 @@ int fa_alloc(int fd, return 0; } -int fa_alloc_resp(int fd, - int response) +int fa_alloc_resp(int fd, + int response, + const void * data, + size_t len) { struct timespec ts = {0, TIMEOUT * 1000}; struct timespec abstime; @@ -439,7 +451,7 @@ int fa_alloc_resp(int fd, pthread_mutex_unlock(&ipcpi.alloc_lock); - if (ipcp_sdb_reserve(&sdb, sizeof(*msg) + ipcp_dir_hash_len())) { + if (ipcp_sdb_reserve(&sdb, sizeof(*msg) + len)) { destroy_conn(fd); return -1; } @@ -452,6 +464,8 @@ int fa_alloc_resp(int fd, msg->s_eid = hton32(fd); msg->response = response; + memcpy(msg + 1, data, len); + if (response < 0) { destroy_conn(fd); ipcp_sdb_release(sdb); diff --git a/src/ipcpd/unicast/fa.h b/src/ipcpd/unicast/fa.h index 8ced5e84..12a10a0c 100644 --- a/src/ipcpd/unicast/fa.h +++ b/src/ipcpd/unicast/fa.h @@ -36,10 +36,14 @@ void fa_stop(void); int fa_alloc(int fd, const uint8_t * dst, - qosspec_t qs); - -int fa_alloc_resp(int fd, - int response); + qosspec_t qs, + const void * data, + size_t len); + +int fa_alloc_resp(int fd, + int response, + const void * data, + size_t len); int fa_dealloc(int fd); -- cgit v1.2.3