diff options
| -rw-r--r-- | src/ipcpd/ipcp.c | 4 | ||||
| -rw-r--r-- | src/ipcpd/ipcp.h | 3 | ||||
| -rw-r--r-- | src/ipcpd/shim-udp/main.c | 341 | ||||
| -rw-r--r-- | src/irmd/main.c | 69 | ||||
| -rw-r--r-- | src/lib/ipcpd_messages.proto | 1 | ||||
| -rw-r--r-- | src/lib/irmd_messages.proto | 3 | ||||
| -rw-r--r-- | src/tools/echo/echo_server.c | 5 | 
7 files changed, 395 insertions, 31 deletions
| diff --git a/src/ipcpd/ipcp.c b/src/ipcpd/ipcp.c index 0b652ff6..e0dac20b 100644 --- a/src/ipcpd/ipcp.c +++ b/src/ipcpd/ipcp.c @@ -174,8 +174,8 @@ int ipcp_main_loop(struct ipcp * _ipcp)                                  LOG_ERR("Flow_alloc unsupported.");                                  break;                          } -                        ret_msg.has_result = true; -                        ret_msg.result = _ipcp->ops->ipcp_flow_alloc( +                        ret_msg.has_fd = true; +                        ret_msg.fd = _ipcp->ops->ipcp_flow_alloc(                                  msg->port_id,                                  msg->dst_ap_name,                                  msg->ap_name, diff --git a/src/ipcpd/ipcp.h b/src/ipcpd/ipcp.h index 9decac8b..f640d78b 100644 --- a/src/ipcpd/ipcp.h +++ b/src/ipcpd/ipcp.h @@ -26,6 +26,9 @@  #include "ipcp-ops.h"  #include "ipcp-data.h" +/* needed to run over shim DIFs */ +#define ANONYMOUS_AP "__ANONYMOUS__" +  enum ipcp_state {          IPCP_INIT = 0,          IPCP_ENROLLING, diff --git a/src/ipcpd/shim-udp/main.c b/src/ipcpd/shim-udp/main.c index df731490..14b08ba8 100644 --- a/src/ipcpd/shim-udp/main.c +++ b/src/ipcpd/shim-udp/main.c @@ -29,6 +29,7 @@  #include <ouroboros/utils.h>  #include <ouroboros/ipcp.h>  #include <ouroboros/dif_config.h> +#include <ouroboros/sockets.h>  #define OUROBOROS_PREFIX "ipcpd/shim-udp" @@ -36,6 +37,7 @@  #include <string.h>  #include <sys/socket.h> +#include <sys/select.h>  #include <arpa/inet.h>  #include <netdb.h>  #include <netinet/in.h> @@ -44,9 +46,15 @@  #include <pthread.h>  #define THIS_TYPE IPCP_SHIM_UDP +#define LISTEN_PORT htons(0x0D1F) +#define SHIM_UDP_BUF_SIZE 256 +#define SHIM_UDP_MAX_SDU_SIZE 8980  #define shim_data(type) ((struct ipcp_udp_data *) type->data) +#define local_ip (((struct ipcp_udp_data *)                              \ +                         _ipcp->data)->s_saddr.sin_addr.s_addr) +  /* global for trapping signal */  int irmd_pid; @@ -64,16 +72,19 @@ struct ipcp_udp_data {          uint32_t ip_addr;          uint32_t dns_addr; +        /* listen server */ +        struct sockaddr_in s_saddr; +        int                s_fd; + +        fd_set flow_fd_s; +        flow_t * fd_to_flow_ptr[FD_SETSIZE]; +          pthread_mutex_t   lock;  };  struct udp_flow {          /* FLOW MUST BE FIRST !!!! */          flow_t flow; - -        uint16_t localport; - -        struct sockaddr_in * remote;          int    fd;  }; @@ -100,6 +111,7 @@ struct ipcp_udp_data * ipcp_udp_data_create(char * ap_name,          struct ipcp_data *     data;          instance_name_t *      instance_name;          enum ipcp_type         ipcp_type; +        int                    n;          instance_name = instance_name_create();          if (instance_name  == NULL) { @@ -110,12 +122,12 @@ struct ipcp_udp_data * ipcp_udp_data_create(char * ap_name,          instance_name = instance_name_init_with(                  instance_name, ap_name, (uint16_t)atoi(ap_id)); -        if (instance_name  == NULL) { +        if (instance_name == NULL) {                  LOG_ERR("Failed to create instance name struct.");                  return NULL;          } -        udp_data= malloc (sizeof *udp_data); +        udp_data = malloc(sizeof *udp_data);          if (udp_data == NULL) {                  LOG_DBGF("Failed to allocate.");                  return NULL; @@ -128,13 +140,170 @@ struct ipcp_udp_data * ipcp_udp_data_create(char * ap_name,                  return NULL;          } +        FD_ZERO(&udp_data->flow_fd_s); +        for (n = 0; n < FD_SETSIZE; ++n) +                udp_data->fd_to_flow_ptr[n] = NULL; +          return udp_data;  } +static void * ipcp_udp_listener() +{ +        char buf[SHIM_UDP_BUF_SIZE]; +        int     n = 0; + +        struct sockaddr_in f_saddr; +        struct sockaddr_in c_saddr; +        struct hostent  *  hostp; +        struct udp_flow *  flow; +        int                sfd = shim_data(_ipcp)->s_fd; + +        irm_msg_t          msg = IRM_MSG__INIT; +        irm_msg_t *        ret_msg ; + +        while (true) { +                n = sizeof c_saddr; +                n = recvfrom(sfd, buf, SHIM_UDP_BUF_SIZE, 0, +                             (struct sockaddr *) &c_saddr, (unsigned *) &n); +                if (n < 0) +                        continue; + +                /* flow alloc request from other host */ +                hostp = gethostbyaddr((const char *)&c_saddr.sin_addr.s_addr, +                                      sizeof(c_saddr.sin_addr.s_addr), AF_INET); +                if (hostp == NULL) +                        continue; + +                /* create a new socket for the server */ +                flow = malloc(sizeof *flow); +                if (flow == NULL) +                        continue; + +                flow->fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); +                if (flow->fd == -1) { +                        free(flow); +                        continue; +                } + +                memset((char *)&f_saddr, 0, sizeof f_saddr); +                f_saddr.sin_family      = AF_INET; +                f_saddr.sin_addr.s_addr = local_ip; + +                /* +                 * FIXME: we could have a port dedicated per registered AP +                 * Not that critical for UDP, but will be for LLC +                 */ + +                f_saddr.sin_port        = 0; + +                /* +                 * store the remote address in the file descriptor +                 * this avoids having to store the sockaddr_in in +                 * the flow structure +                 */ + +                if (connect(flow->fd, +                            (struct sockaddr *)&c_saddr, sizeof c_saddr) < 0) { +                        close(flow->fd); +                        free(flow); +                        continue; +                } + +                /* reply to IRM */ + +                msg.code = IRM_MSG_CODE__IPCP_FLOW_REQ_ARR; +                msg.ap_name = ANONYMOUS_AP; +                msg.ae_name = ""; /* no AE */ +                msg.has_reg_ap_id = true; +                msg.reg_ap_id = ipcp_data_get_reg_ap_id(_ipcp->data, buf); + +                ret_msg = send_recv_irm_msg(&msg); +                if (ret_msg == NULL) { +                        LOG_ERR("Could not send message to IRM."); +                        close(flow->fd); +                        free(flow); +                        continue; +                } + +                if (!ret_msg->has_port_id) { +                        LOG_ERR("Didn't get port_id."); +                        free(ret_msg); +                        close(flow->fd); +                        free(flow); +                        continue; +                } + +                flow->flow.port_id = ret_msg->port_id; +                flow->flow.oflags  = FLOW_O_DEFAULT; +                flow->flow.state   = FLOW_PENDING; + +                if(ipcp_data_add_flow(_ipcp->data, (flow_t *) flow)) { +                        LOG_DBGF("Could not add flow."); +                        free(ret_msg); +                        close(flow->fd); +                        free(flow); +                        continue; +                } + +                FD_SET(flow->fd, &shim_data(_ipcp)->flow_fd_s); +                shim_data(_ipcp)->fd_to_flow_ptr[flow->fd] = &flow->flow; + +        } +} + +static void * ipcp_udp_sdu_reader() +{ +        int n; +        int fd; +        char buf[SHIM_UDP_MAX_SDU_SIZE]; + +        struct sockaddr_in r_saddr; + +        while (true) { +                flow_t * flow; + +                if (select(FD_SETSIZE, +                           &shim_data(_ipcp)->flow_fd_s, +                           NULL, NULL, NULL) +                    < 0) +                        continue; + +                for (fd = 0; fd < FD_SETSIZE; ++fd) { +                        if (!FD_ISSET(fd, &shim_data(_ipcp)->flow_fd_s)) +                                continue; + +                        n = sizeof r_saddr; +                        n = recvfrom(fd, +                                     buf, +                                     SHIM_UDP_MAX_SDU_SIZE, +                                     0, +                                     (struct sockaddr *) &r_saddr, +                                     (unsigned *) &n); + +                        flow = shim_data(_ipcp)->fd_to_flow_ptr[fd]; +                        if (flow->state == FLOW_PENDING) { +                                if (connect(fd, +                                            (struct sockaddr *)&r_saddr, +                                            sizeof r_saddr) +                                    < 0) +                                       continue; +                                flow->state = FLOW_ALLOCATED; +                        } + +                        /* send the sdu to the correct port_id */ +                        LOG_MISSING; +                } +        } + +        return (void *) 0; +} +  int ipcp_udp_bootstrap(struct dif_config * conf)  {          char ipstr[INET_ADDRSTRLEN];          char dnsstr[INET_ADDRSTRLEN]; +        pthread_t handler; +        pthread_t sdu_reader;          if (conf->type != THIS_TYPE) {                  LOG_ERR("Config doesn't match IPCP type."); @@ -162,6 +331,28 @@ int ipcp_udp_bootstrap(struct dif_config * conf)          shim_data(_ipcp)->ip_addr  = conf->ip_addr;          shim_data(_ipcp)->dns_addr = conf->dns_addr; +        /* UDP listen server */ + +        if ((shim_data(_ipcp)->s_fd = +             socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { +                LOG_DBGF("Can't create socket."); +                return -1; +        } + +        shim_data(_ipcp)->s_saddr.sin_family      = AF_INET; +        shim_data(_ipcp)->s_saddr.sin_addr.s_addr = conf->ip_addr; +        shim_data(_ipcp)->s_saddr.sin_port        = LISTEN_PORT; + +        if (bind(shim_data(_ipcp)->s_fd, +                 (struct sockaddr *)&shim_data(_ipcp)->s_saddr, +                 sizeof shim_data(_ipcp)->s_saddr ) < 0) { +                LOG_ERR("Couldn't bind to %s.", ipstr); +                return -1; +        } + +        pthread_create(&handler, NULL, ipcp_udp_listener, NULL); +        pthread_create(&sdu_reader, NULL, ipcp_udp_sdu_reader, NULL); +          _ipcp->state = IPCP_ENROLLED;          LOG_DBG("Bootstrapped shim IPCP over UDP %s-%d.", @@ -175,8 +366,6 @@ int ipcp_udp_bootstrap(struct dif_config * conf)  int ipcp_udp_ap_reg(char * ap_name, uint32_t reg_ap_id)  { -        LOG_DBG("Registering local ap %s, %u.", ap_name, reg_ap_id); -          if (_ipcp->state != IPCP_ENROLLED) {                  LOG_DBGF("Won't register with non-enrolled IPCP.");                  return -1; @@ -187,6 +376,9 @@ int ipcp_udp_ap_reg(char * ap_name, uint32_t reg_ap_id)                  return -1;          } +        LOG_DBG("Registered local ap %s, %u.", ap_name, reg_ap_id); + +        /* FIXME: register application with DNS server */          LOG_MISSING;          return 0; @@ -194,17 +386,11 @@ int ipcp_udp_ap_reg(char * ap_name, uint32_t reg_ap_id)  int ipcp_udp_ap_unreg(uint32_t reg_ap_id)  { -        char * name  = strdup(ipcp_data_get_reg_ap_name(_ipcp->data, -                                                        reg_ap_id)); -        LOG_DBG("Unregistering %s.", name); -          ipcp_data_del_reg_entry(_ipcp->data, reg_ap_id); -        /* we are using dns */ +        /* FIXME: unregister application from DNS server */          LOG_MISSING; -        free (name); -          return 0;  } @@ -214,11 +400,132 @@ int ipcp_udp_flow_alloc(uint32_t          port_id,                          char *            src_ae_name,                          struct qos_spec * qos)  { +        struct udp_flow *  flow = NULL; +        struct sockaddr_in l_saddr; +        struct sockaddr_in r_saddr; + +        irm_msg_t   msg = IRM_MSG__INIT; +        irm_msg_t * ret_msg = NULL; + +        if (dst_ap_name == NULL || src_ap_name == NULL || src_ae_name == NULL) +                return -1; + +        LOG_DBG("Received flow allocation request from %s to %s.", +                src_ap_name, dst_ap_name); + +        if (strlen(dst_ap_name) > 255 +            || strlen(src_ap_name) > 255 +            || strlen(src_ae_name) > 255) { +                LOG_ERR("Name too long for this shim."); +                return -1; +        } + +        if (qos != NULL) +                LOG_DBGF("QoS requested. UDP/IP can't do that."); + +        flow = malloc(sizeof *flow); +        if (flow == NULL) +                return -1; + +        flow->fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); +        if (flow->fd == -1) { +                free(flow); +                return -1; +        } + +        /* this socket is for the flow */ +        memset((char *)&l_saddr, 0, sizeof l_saddr); +        l_saddr.sin_family      = AF_INET; +        l_saddr.sin_addr.s_addr = local_ip; +        l_saddr.sin_port        = 0; + +        if (bind(flow->fd, (struct sockaddr *) &l_saddr, sizeof l_saddr) < 0) { +                char ipstr[INET_ADDRSTRLEN]; +                inet_ntop(AF_INET, +                          &l_saddr.sin_addr.s_addr, +                          ipstr, +                          INET_ADDRSTRLEN); +                close(flow->fd); +                free(flow); +                return -1; +        } + +        /* FIXME: use calls to specify DDNS server */ + +#define IP_ADDR 0x7f000001; /* localhost */ + +        LOG_MISSING; + +        memset((char *)&r_saddr, 0, sizeof r_saddr); +        r_saddr.sin_family      = AF_INET; +        /* FIXME: pull in correct IP address */ +        r_saddr.sin_addr.s_addr = IP_ADDR; /* FIXME */ +        r_saddr.sin_port        = LISTEN_PORT; + +        /* at least try to get the packet on the wire */ +        while (sendto(flow->fd, dst_ap_name, strlen(dst_ap_name), 0, +                      (struct sockaddr *) &r_saddr, sizeof r_saddr) < 0) + +        flow->flow.port_id = port_id; +        flow->flow.oflags  = FLOW_O_DEFAULT; +        flow->flow.state   = FLOW_PENDING; + +        /* add flow to the list */ + +        pthread_mutex_lock(&_ipcp->data->flow_lock); + +        if(ipcp_data_add_flow(_ipcp->data, (flow_t *)flow)) { +                LOG_DBGF("Could not add flow."); +                pthread_mutex_unlock(&_ipcp->data->flow_lock); +                close(flow->fd); +                free(flow); +                return -1; +        } + +        pthread_mutex_unlock(&_ipcp->data->flow_lock); + +        /* tell IRMd that flow allocation "worked" */ + +        msg.code = IRM_MSG_CODE__IPCP_FLOW_ALLOC_REPLY; +        msg.has_port_id = true; +        msg.port_id = flow->flow.port_id; +        msg.has_response = true; +        msg.response = 0; + +        ret_msg = send_recv_irm_msg(&msg); +        if (ret_msg == NULL) { +                close(flow->fd); +                ipcp_data_del_flow(_ipcp->data, flow->flow.port_id); +                return -1; +        } + +        FD_SET(flow->fd, &shim_data(_ipcp)->flow_fd_s); +        shim_data(_ipcp)->fd_to_flow_ptr[flow->fd] = &flow->flow; +          return 0;  } +  int ipcp_udp_flow_alloc_resp(uint32_t port_id, -                             int      result) +                             int      response)  { +        struct udp_flow * flow = +                (struct udp_flow *) ipcp_data_find_flow(_ipcp->data, port_id); +        if (flow == NULL) { +                return -1; +        } + +        if (response) { +                ipcp_data_del_flow(_ipcp->data, port_id); +                return 0; +        } + +        /* awaken pending flow */ + +        if (flow->flow.state != FLOW_PENDING) +                return -1; + +        flow->flow.state = FLOW_ALLOCATED; +          return 0;  } @@ -255,7 +562,7 @@ struct ipcp * ipcp_udp_create(char * ap_name, char * i_id)                  return NULL;          } -        ops = malloc (sizeof *ops); +        ops = malloc(sizeof *ops);          if (ops == NULL) {                  free(data);                  free(i); diff --git a/src/irmd/main.c b/src/irmd/main.c index 13076cd1..374bfb6c 100644 --- a/src/irmd/main.c +++ b/src/irmd/main.c @@ -87,6 +87,24 @@ static struct ipcp_entry * find_ipcp_by_name(instance_name_t * api)          return tmp;  } +static pid_t find_pid_by_dif_name(char * dif_name) +{ +        struct list_head * pos = NULL; + +        list_for_each(pos, &instance->ipcps) { +                struct ipcp_entry * tmp = +                        list_entry(pos, struct ipcp_entry, next); + +                if (tmp->dif_name == NULL) +                        return tmp->pid; + +                if (strcmp(dif_name, tmp->dif_name) == 0) +                        return tmp->pid; +        } + +        return 0; +} +  static int create_ipcp(instance_name_t * api,                         enum ipcp_type    ipcp_type)  { @@ -266,7 +284,41 @@ static int ap_reg(char * ap_name,                    char ** difs,                    size_t difs_size)  { -        return -1; +        pid_t pid = 0; +        int i; +        int ret = 0; + +        if (instance->ipcps.next == NULL) +                LOG_ERR("No IPCPs in this system."); + +        /* +         * FIXME: this should be resolved by NSM +         * Now it just takes the first DIF +         */ + +        if (strcmp(difs[0], "*") == 0) { +                difs[0] = list_entry(instance->ipcps.next, +                                     struct ipcp_entry, +                                     next)->dif_name; +                difs_size = 1; +        } + +        for (i = 0; i < difs_size; ++i) { +                pid = find_pid_by_dif_name(difs[i]); +                if (pid == 0) { +                        LOG_ERR("%s: No such DIF.", difs[i]); +                        continue; +                } + +                /* FIXME: get proper reg_ap_id */ +                if (ipcp_ap_reg(pid, rand(),ap_name)) { +                        LOG_ERR("Could not register %s in DIF %s.", +                                ap_name, difs[i]); +                        ret = -1; +                } +        } + +        return ret;  }  static int ap_unreg(char * ap_name, @@ -366,7 +418,6 @@ int main()          sigaction(SIGTERM, &sig_act, NULL);          sigaction(SIGHUP,  &sig_act, NULL); -          if (access("/dev/shm/" SHM_DU_MAP_FILENAME, F_OK) != -1)                  unlink("/dev/shm/" SHM_DU_MAP_FILENAME); @@ -480,8 +531,8 @@ int main()                                                  msg->oflags);                          break;                  case IRM_MSG_CODE__IRM_FLOW_ALLOC_RES: -                        ret_msg.has_result = true; -                        ret_msg.result = flow_alloc_res(msg->fd); +                        ret_msg.has_response = true; +                        ret_msg.response = flow_alloc_res(msg->fd);                          break;                  case IRM_MSG_CODE__IRM_FLOW_DEALLOC:                          ret_msg.has_result = true; @@ -493,15 +544,15 @@ int main()                                                     msg->oflags);                          break;                  case IRM_MSG_CODE__IPCP_FLOW_REQ_ARR: -                        ret_msg.has_fd = true; -                        ret_msg.fd = flow_req_arr(msg->port_id, -                                                  msg->ap_name, -                                                  msg->ae_name); +                        ret_msg.has_port_id = true; +                        ret_msg.port_id = flow_req_arr(msg->port_id, +                                                       msg->ap_name, +                                                       msg->ae_name);                          break;                  case IRM_MSG_CODE__IPCP_FLOW_ALLOC_REPLY:                          ret_msg.has_result = true;                          ret_msg.result = flow_alloc_reply(msg->port_id, -                                                          msg->result); +                                                          msg->response);                          break;                  case IRM_MSG_CODE__IPCP_FLOW_DEALLOC:                          ret_msg.has_result = true; diff --git a/src/lib/ipcpd_messages.proto b/src/lib/ipcpd_messages.proto index 796638c7..850c64e4 100644 --- a/src/lib/ipcpd_messages.proto +++ b/src/lib/ipcpd_messages.proto @@ -26,4 +26,5 @@ message ipcp_msg {          optional string ae_name      = 10;          optional dif_config_msg conf = 11;          optional int32 result        = 12; +        optional int32 fd            = 13;  }; diff --git a/src/lib/irmd_messages.proto b/src/lib/irmd_messages.proto index 92ea439e..d484a007 100644 --- a/src/lib/irmd_messages.proto +++ b/src/lib/irmd_messages.proto @@ -31,11 +31,12 @@ message irm_msg {          optional uint32 ipcp_type    =  5;          repeated string dif_name     =  6;          optional int32 fd            =  7; -        optional int32 result        =  8; +        optional int32 response      =  8;          optional int32 oflags        =  9;          optional string dst_ap_name  = 10;          optional uint32 port_id      = 11;          optional uint32 reg_ap_id    = 12;          optional int32 pid           = 13;          optional dif_config_msg conf = 14; +        optional int32 result        = 15;  }; diff --git a/src/tools/echo/echo_server.c b/src/tools/echo/echo_server.c index b1547d8c..e457e22b 100644 --- a/src/tools/echo/echo_server.c +++ b/src/tools/echo/echo_server.c @@ -64,15 +64,16 @@ int server_main()                  return -1;          } +        printf("Echo server started...\n"); +          while (true) {                  client_fd = flow_accept(server_fd,                                          client_name, NULL);                  if (client_fd < 0) { -                        printf("Failed to accept flow\n");                          continue;                  } -                printf("New flow from %s", client_name); +                printf("New flow from %s\n", client_name);                  if (flow_alloc_resp(client_fd, 0)) {                          printf("Failed to give an allocate response\n"); | 
