diff options
Diffstat (limited to 'src/ipcpd')
| -rw-r--r-- | src/ipcpd/broadcast/main.c | 2 | ||||
| -rw-r--r-- | src/ipcpd/eth/eth.c | 93 | ||||
| -rw-r--r-- | src/ipcpd/ipcp.c | 15 | ||||
| -rw-r--r-- | src/ipcpd/ipcp.h | 10 | ||||
| -rw-r--r-- | src/ipcpd/local/main.c | 15 | ||||
| -rw-r--r-- | src/ipcpd/udp/main.c | 92 | ||||
| -rw-r--r-- | src/ipcpd/unicast/fa.c | 60 | ||||
| -rw-r--r-- | src/ipcpd/unicast/fa.h | 12 | 
8 files changed, 199 insertions, 100 deletions
| 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); | 
