diff options
author | Sander Vrijders <[email protected]> | 2016-04-27 15:31:13 +0200 |
---|---|---|
committer | Sander Vrijders <[email protected]> | 2016-04-27 15:31:13 +0200 |
commit | 6809a2beea07a661a9c651cae1e100537c401bb7 (patch) | |
tree | 9f64215f326c3847699ae8856ae9cd0d609cbfac /src/ipcpd | |
parent | a618984537f7790cd274d097223b4029473044c2 (diff) | |
parent | a17657c4321dc0770e5431467261eb2bc579f79c (diff) | |
download | ouroboros-6809a2beea07a661a9c651cae1e100537c401bb7.tar.gz ouroboros-6809a2beea07a661a9c651cae1e100537c401bb7.zip |
Merged in dstaesse/ouroboros/udp-dev (pull request #60)
shim-udp: flow allocation added
Diffstat (limited to 'src/ipcpd')
-rw-r--r-- | src/ipcpd/ipcp-data.c | 112 | ||||
-rw-r--r-- | src/ipcpd/ipcp-data.h | 15 | ||||
-rw-r--r-- | src/ipcpd/ipcp-ops.h | 5 | ||||
-rw-r--r-- | src/ipcpd/ipcp.c | 29 | ||||
-rw-r--r-- | src/ipcpd/ipcp.h | 3 | ||||
-rw-r--r-- | src/ipcpd/shim-udp/CMakeLists.txt | 15 | ||||
-rw-r--r-- | src/ipcpd/shim-udp/main.c | 396 | ||||
-rw-r--r-- | src/ipcpd/shim-udp/tests/shim_udp_test.c | 22 |
8 files changed, 423 insertions, 174 deletions
diff --git a/src/ipcpd/ipcp-data.c b/src/ipcpd/ipcp-data.c index 1828fda9..106226de 100644 --- a/src/ipcpd/ipcp-data.c +++ b/src/ipcpd/ipcp-data.c @@ -35,8 +35,7 @@ struct reg_entry { struct list_head list; - char * ap_name; - uint32_t reg_ap_id; + char * name; }; struct dir_entry { @@ -45,16 +44,14 @@ struct dir_entry { uint64_t addr; }; -static struct reg_entry * reg_entry_create(const char * ap_name, - uint32_t reg_ap_id) +static struct reg_entry * reg_entry_create(const char * name) { struct reg_entry * entry = malloc(sizeof *entry); if (entry == NULL) return NULL; - entry->reg_ap_id = reg_ap_id; - entry->ap_name = strdup(ap_name); - if (entry->ap_name == NULL) + entry->name = strdup(name); + if (entry->name == NULL) return NULL; return entry; @@ -65,7 +62,7 @@ static void reg_entry_destroy(struct reg_entry * entry) if (entry == NULL) return; - free(entry->ap_name); + free(entry->name); free(entry); } @@ -107,18 +104,28 @@ struct ipcp_data * ipcp_data_create() } struct ipcp_data * ipcp_data_init(struct ipcp_data * dst, - instance_name_t * iname, - enum ipcp_type ipcp_type) + const char * ipcp_name, + enum ipcp_type ipcp_type) { if (dst == NULL) return NULL; - dst->iname = instance_name_dup(iname); + dst->iname = instance_name_create(); + if (dst->iname == NULL) + return NULL; + + if(instance_name_init_from(dst->iname, ipcp_name, getpid()) == NULL) { + instance_name_destroy(dst->iname); + return NULL; + } + dst->type = ipcp_type; dst->dum = shm_du_map_open(); - if (dst->dum == NULL) + if (dst->dum == NULL) { + instance_name_destroy(dst->iname); return NULL; + } /* init the lists */ INIT_LIST_HEAD(&dst->registry); @@ -194,25 +201,12 @@ void ipcp_data_destroy(struct ipcp_data * data) static struct reg_entry * find_reg_entry_by_name(struct ipcp_data * data, - const char * ap_name) -{ - struct list_head * h; - list_for_each(h, &data->registry) { - struct reg_entry * e = list_entry(h, struct reg_entry, list); - if (!strcmp(e->ap_name, ap_name)) - return e; - } - - return NULL; -} - -static struct reg_entry * find_reg_entry_by_id(struct ipcp_data * data, - uint32_t reg_ap_id) + const char * name) { struct list_head * h; list_for_each(h, &data->registry) { struct reg_entry * e = list_entry(h, struct reg_entry, list); - if (e->reg_ap_id == reg_ap_id) + if (!strcmp(e->name, name)) return e; } @@ -253,7 +247,7 @@ bool ipcp_data_is_in_directory(struct ipcp_data * data, } int ipcp_data_del_reg_entry(struct ipcp_data * data, - uint32_t reg_ap_id) + const char * name) { struct reg_entry * e; if (data == NULL) @@ -261,7 +255,7 @@ int ipcp_data_del_reg_entry(struct ipcp_data * data, pthread_mutex_lock(&data->reg_lock); - e = find_reg_entry_by_id(data, reg_ap_id); + e = find_reg_entry_by_name(data, name); if (e == NULL) { pthread_mutex_unlock(&data->reg_lock); return 0; /* nothing to do */ @@ -302,23 +296,21 @@ int ipcp_data_del_dir_entry(struct ipcp_data * data, } int ipcp_data_add_reg_entry(struct ipcp_data * data, - char * ap_name, - uint32_t reg_ap_id) + const char * name) { struct reg_entry * entry; - if (data == NULL || ap_name == NULL) + if (data == NULL || name == NULL) return -1; pthread_mutex_lock(&data->reg_lock); - if (find_reg_entry_by_name(data, ap_name) || - find_reg_entry_by_id(data, reg_ap_id)) { + if (find_reg_entry_by_name(data, name)) { pthread_mutex_unlock(&data->reg_lock); return -2; } - entry = reg_entry_create(ap_name, reg_ap_id); + entry = reg_entry_create(name); if (entry == NULL) { pthread_mutex_unlock(&data->reg_lock); return -1; @@ -332,7 +324,7 @@ int ipcp_data_add_reg_entry(struct ipcp_data * data, } int ipcp_data_add_dir_entry(struct ipcp_data * data, - char * ap_name, + const char * ap_name, uint64_t addr) { struct dir_entry * entry; @@ -366,54 +358,6 @@ bool ipcp_data_is_in_registry(struct ipcp_data * data, return find_reg_entry_by_name(data, ap_name) != NULL; } -uint32_t ipcp_data_get_reg_ap_id(struct ipcp_data * data, - const char * ap_name) -{ - struct reg_entry * entry; - uint32_t id; - - pthread_mutex_lock(&data->reg_lock); - - entry = find_reg_entry_by_name(data, ap_name); - - if (entry == NULL) { - pthread_mutex_unlock(&data->reg_lock); - return 0; /* undefined behaviour */ - } - - id = entry->reg_ap_id; - - pthread_mutex_unlock(&data->reg_lock); - - return id; -} - -const char * ipcp_data_get_reg_ap_name(struct ipcp_data * data, - uint32_t reg_ap_id) -{ - struct reg_entry * entry; - char * name; - - pthread_mutex_lock(&data->reg_lock); - - entry = find_reg_entry_by_id(data, reg_ap_id); - - if (entry == NULL) { - pthread_mutex_unlock(&data->reg_lock); - return NULL; - } - - name = strdup(entry->ap_name); - if (name == NULL) { - pthread_mutex_unlock(&data->reg_lock); - return NULL; - } - - pthread_mutex_unlock(&data->reg_lock); - - return name; -} - uint64_t ipcp_data_get_addr(struct ipcp_data * data, const char * ap_name) { diff --git a/src/ipcpd/ipcp-data.h b/src/ipcpd/ipcp-data.h index 3f036ef5..1dea8c3c 100644 --- a/src/ipcpd/ipcp-data.h +++ b/src/ipcpd/ipcp-data.h @@ -53,27 +53,22 @@ struct ipcp_data { struct ipcp_data * ipcp_data_create(); struct ipcp_data * ipcp_data_init(struct ipcp_data * dst, - instance_name_t * iname, + const char * ipcp_name, enum ipcp_type ipcp_type); void ipcp_data_destroy(struct ipcp_data * data); int ipcp_data_add_reg_entry(struct ipcp_data * data, - char * ap_name, - uint32_t reg_ap_id); + const char * name); int ipcp_data_del_reg_entry(struct ipcp_data * data, - uint32_t reg_ap_id); + const char * name); int ipcp_data_add_dir_entry(struct ipcp_data * data, - char * ap_name, + const char * ap_name, uint64_t addr); int ipcp_data_del_dir_entry(struct ipcp_data * data, const char * ap_name, uint64_t addr); bool ipcp_data_is_in_registry(struct ipcp_data * data, - const char * ap_name); -uint32_t ipcp_data_get_reg_ap_id(struct ipcp_data * data, - const char * ap_name); -const char * ipcp_data_get_reg_ap_name(struct ipcp_data * data, - uint32_t reg_ap_id); + const char * name); bool ipcp_data_is_in_directory(struct ipcp_data * data, const char * ap_name); uint64_t ipcp_data_get_addr(struct ipcp_data * data, diff --git a/src/ipcpd/ipcp-ops.h b/src/ipcpd/ipcp-ops.h index 5c917229..2ccb2e59 100644 --- a/src/ipcpd/ipcp-ops.h +++ b/src/ipcpd/ipcp-ops.h @@ -36,9 +36,8 @@ struct ipcp_ops { size_t len); int (* ipcp_unreg)(char ** dif_names, size_t len); - int (* ipcp_ap_reg)(char * ap_name, - uint32_t reg_ap_id); - int (* ipcp_ap_unreg)(uint32_t reg_ap_id); + int (* ipcp_name_reg)(char * name); + int (* ipcp_name_unreg)(char * name); int (* ipcp_flow_alloc)(uint32_t port_id, char * dst_ap_name, char * src_ap_name, diff --git a/src/ipcpd/ipcp.c b/src/ipcpd/ipcp.c index 0b652ff6..23c432f1 100644 --- a/src/ipcpd/ipcp.c +++ b/src/ipcpd/ipcp.c @@ -31,7 +31,7 @@ int ipcp_arg_check(int argc, char * argv[]) { - if (argc != 4) + if (argc != 3) return -1; /* argument 1: pid of irmd */ @@ -41,7 +41,6 @@ int ipcp_arg_check(int argc, char * argv[]) /* name conformity responsibility of NMS */ /* argument 2: ap name */ - /* argument 3: instance id */ return 0; } @@ -151,35 +150,35 @@ int ipcp_main_loop(struct ipcp * _ipcp) ret_msg.result = _ipcp->ops->ipcp_unreg( msg->dif_names, msg->len); break; - case IPCP_MSG_CODE__IPCP_AP_REG: - if (_ipcp->ops->ipcp_ap_reg == NULL) { + case IPCP_MSG_CODE__IPCP_NAME_REG: + if (_ipcp->ops->ipcp_name_reg == NULL) { LOG_ERR("Ap_reg unsupported."); break; } ret_msg.has_result = true; - ret_msg.result = _ipcp->ops->ipcp_ap_reg( - msg->ap_name, msg->reg_ap_id); + ret_msg.result = _ipcp->ops->ipcp_name_reg( + msg->name); break; - case IPCP_MSG_CODE__IPCP_AP_UNREG: - if (_ipcp->ops->ipcp_ap_unreg == NULL) { + case IPCP_MSG_CODE__IPCP_NAME_UNREG: + if (_ipcp->ops->ipcp_name_unreg == NULL) { LOG_ERR("Ap_unreg unsupported."); break; } ret_msg.has_result = true; - ret_msg.result = _ipcp->ops->ipcp_ap_unreg( - msg->reg_ap_id); + ret_msg.result = _ipcp->ops->ipcp_name_unreg( + msg->name); break; case IPCP_MSG_CODE__IPCP_FLOW_ALLOC: if (_ipcp->ops->ipcp_flow_alloc == NULL) { 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, - msg->ae_name, + msg->dst_name, + msg->src_ap_name, + msg->src_ae_name, NULL); break; case IPCP_MSG_CODE__IPCP_FLOW_ALLOC_RESP: 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/CMakeLists.txt b/src/ipcpd/shim-udp/CMakeLists.txt index 27907880..f730fa3a 100644 --- a/src/ipcpd/shim-udp/CMakeLists.txt +++ b/src/ipcpd/shim-udp/CMakeLists.txt @@ -10,6 +10,21 @@ include_directories(${CURRENT_BINARY_PARENT_DIR}) include_directories(${CMAKE_SOURCE_DIR}/include) include_directories(${CMAKE_BINARY_DIR}/include) +# Find library needed for gethostbyname. +include(CheckFunctionExists) +CHECK_FUNCTION_EXISTS("gethostbyname" CMAKE_HAVE_GETHOSTBYNAME) +IF(NOT CMAKE_HAVE_GETHOSTBYNAME) + CHECK_LIBRARY_EXISTS("nsl" "gethostbyname" "" CMAKE_LIB_NSL_HAS_GETHOSTBYNAME) + IF (CMAKE_LIB_NSL_HAS_GETHOSTBYNAME) + SET (X11_X_EXTRA_LIBS ${X11_X_EXTRA_LIBS} -lnsl) + ELSE (CMAKE_LIB_NSL_HAS_GETHOSTBYNAME) + CHECK_LIBRARY_EXISTS("bsd" "gethostbyname" "" CMAKE_LIB_BSD_HAS_GETHOSTBYNAME) + IF (CMAKE_LIB_BSD_HAS_GETHOSTBYNAME) + SET (X11_X_EXTRA_LIBS ${X11_X_EXTRA_LIBS} -lbsd) + ENDIF (CMAKE_LIB_BSD_HAS_GETHOSTBYNAME) + ENDIF (CMAKE_LIB_NSL_HAS_GETHOSTBYNAME) +ENDIF(NOT CMAKE_HAVE_GETHOSTBYNAME) + SET(IPCP_SHIM_UDP_TARGET ipcpd-shim-udp CACHE STRING "IPCP_SHIM_UDP_TARGET") set(SHIM_UDP_SOURCES diff --git a/src/ipcpd/shim-udp/main.c b/src/ipcpd/shim-udp/main.c index df731490..029df111 100644 --- a/src/ipcpd/shim-udp/main.c +++ b/src/ipcpd/shim-udp/main.c @@ -21,7 +21,6 @@ */ #include <ouroboros/config.h> - #include "ipcp.h" #include "flow.h" #include <ouroboros/shm_du_map.h> @@ -29,6 +28,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 +36,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 +45,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; @@ -58,22 +65,25 @@ struct ipcp * _ipcp; #endif struct ipcp_udp_data { - /* IPCP_DATA STRUCT MUST BE FIRST!! */ + /* keep ipcp_data first for polymorphism */ struct ipcp_data ipcp_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 !!!! */ + /* keep flow first for polymorphism */ flow_t flow; - - uint16_t localport; - - struct sockaddr_in * remote; int fd; }; @@ -85,7 +95,7 @@ void ipcp_sig_handler(int sig, siginfo_t * info, void * c) case SIGHUP: LOG_DBG("Terminating by order of %d. Bye.", info->si_pid); if (info->si_pid == irmd_pid) { - shm_du_map_close(_ipcp->data->dum); + /* shm_du_map_close(_ipcp->data->dum); */ exit(0); } default: @@ -93,29 +103,14 @@ void ipcp_sig_handler(int sig, siginfo_t * info, void * c) } } -struct ipcp_udp_data * ipcp_udp_data_create(char * ap_name, - char * ap_id) +struct ipcp_udp_data * ipcp_udp_data_create(char * ap_name) { struct ipcp_udp_data * udp_data; 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) { - LOG_ERR("Failed to create instance name struct."); - return NULL; - } - - instance_name = instance_name_init_with( - instance_name, ap_name, (uint16_t)atoi(ap_id)); - - 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; @@ -123,18 +118,175 @@ struct ipcp_udp_data * ipcp_udp_data_create(char * ap_name, ipcp_type = THIS_TYPE; data = (struct ipcp_data *) udp_data; - if (ipcp_data_init(data, instance_name, ipcp_type) == NULL) { + if (ipcp_data_init(data, ap_name, ipcp_type) == NULL) { free(udp_data); 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.dst_name = 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; + } + + return 0; +} + +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."); @@ -157,11 +309,33 @@ int ipcp_udp_bootstrap(struct dif_config * conf) dnsstr, INET_ADDRSTRLEN); else - strcpy(dnsstr, "not set"); + strcpy(dnsstr, "not set.\n"); 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.", @@ -173,52 +347,173 @@ int ipcp_udp_bootstrap(struct dif_config * conf) return 0; } -int ipcp_udp_ap_reg(char * ap_name, uint32_t reg_ap_id) +int ipcp_udp_name_reg(char * name) { - 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; } - if (ipcp_data_add_reg_entry(_ipcp->data, ap_name, reg_ap_id)) { - LOG_ERR("Failed to add AP to local registry."); + if (ipcp_data_add_reg_entry(_ipcp->data, name)) { + LOG_ERR("Failed to add %s to local registry.", name); return -1; } + LOG_DBG("Registered %s", name); + + /* FIXME: register application with DNS server */ LOG_MISSING; return 0; } -int ipcp_udp_ap_unreg(uint32_t reg_ap_id) +int ipcp_udp_name_unreg(char * name) { - 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, name); - ipcp_data_del_reg_entry(_ipcp->data, reg_ap_id); + LOG_DBG("Unregistered %s.", name); - /* we are using dns */ + /* FIXME: unregister application from DNS server */ LOG_MISSING; - free (name); - return 0; } int ipcp_udp_flow_alloc(uint32_t port_id, - char * dst_ap_name, + char * dst_name, char * src_ap_name, char * src_ae_name, struct qos_spec * qos) { + struct udp_flow * flow = NULL; + struct sockaddr_in l_saddr; + struct sockaddr_in r_saddr; + + struct hostent * h; + + irm_msg_t msg = IRM_MSG__INIT; + irm_msg_t * ret_msg = NULL; + + if (dst_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_name); + + if (strlen(dst_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; + } + + h = gethostbyname(dst_name); + if (h == NULL) { + close(flow->fd); + free(flow); + return -1; + } + + + memset((char *) &r_saddr, 0, sizeof r_saddr); + r_saddr.sin_family = AF_INET; + r_saddr.sin_addr.s_addr = (uint32_t) *(h->h_addr_list[0]); + r_saddr.sin_port = LISTEN_PORT; + + /* at least try to get the packet on the wire */ + while (sendto(flow->fd, dst_name, strlen(dst_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; } @@ -239,7 +534,7 @@ int ipcp_udp_du_read(uint32_t port_id, return 0; } -struct ipcp * ipcp_udp_create(char * ap_name, char * i_id) +struct ipcp * ipcp_udp_create(char * ap_name) { struct ipcp * i; struct ipcp_udp_data * data; @@ -249,13 +544,13 @@ struct ipcp * ipcp_udp_create(char * ap_name, char * i_id) if (i == NULL) return NULL; - data = ipcp_udp_data_create(ap_name, i_id); + data = ipcp_udp_data_create(ap_name); if (data == NULL) { free(i); return NULL; } - ops = malloc (sizeof *ops); + ops = malloc(sizeof *ops); if (ops == NULL) { free(data); free(i); @@ -266,8 +561,8 @@ struct ipcp * ipcp_udp_create(char * ap_name, char * i_id) ops->ipcp_enroll = NULL; /* shim */ ops->ipcp_reg = NULL; /* shim */ ops->ipcp_unreg = NULL; /* shim */ - ops->ipcp_ap_reg = ipcp_udp_ap_reg; - ops->ipcp_ap_unreg = ipcp_udp_ap_unreg; + ops->ipcp_name_reg = ipcp_udp_name_reg; + ops->ipcp_name_unreg = ipcp_udp_name_unreg; ops->ipcp_flow_alloc = ipcp_udp_flow_alloc; ops->ipcp_flow_alloc_resp = ipcp_udp_flow_alloc_resp; ops->ipcp_flow_dealloc = ipcp_udp_flow_dealloc; @@ -288,7 +583,6 @@ int main (int argc, char * argv[]) { /* argument 1: pid of irmd ? */ /* argument 2: ap name */ - /* argument 3: instance id */ struct sigaction sig_act; if (ipcp_arg_check(argc, argv)) { @@ -300,7 +594,7 @@ int main (int argc, char * argv[]) irmd_pid = atoi(argv[1]); /* init sig_act */ - memset (&sig_act, 0, sizeof sig_act); + memset(&sig_act, 0, sizeof sig_act); /* install signal traps */ sig_act.sa_sigaction = &ipcp_sig_handler; @@ -310,7 +604,7 @@ int main (int argc, char * argv[]) sigaction(SIGTERM, &sig_act, NULL); sigaction(SIGHUP, &sig_act, NULL); - _ipcp = ipcp_udp_create(argv[2], argv[3]); + _ipcp = ipcp_udp_create(argv[2]); if (_ipcp == NULL) { LOG_ERR("Won't."); exit(1); diff --git a/src/ipcpd/shim-udp/tests/shim_udp_test.c b/src/ipcpd/shim-udp/tests/shim_udp_test.c index 427d0e1e..d2b9c642 100644 --- a/src/ipcpd/shim-udp/tests/shim_udp_test.c +++ b/src/ipcpd/shim-udp/tests/shim_udp_test.c @@ -39,14 +39,13 @@ int shim_udp_test(int argc, char ** argv) /* argument 3: instance id */ struct shm_du_map * dum; char * ipcp_name = "test-shim-ipcp"; - char * i_id = "1"; int i = 0; char bogus[15]; - memset (&bogus, 0, 15); + memset(&bogus, 0, 15); struct dif_config conf; - memset (&conf, 0, sizeof conf); + memset(&conf, 0, sizeof conf); conf.dif_name = strdup("test-dif"); conf.type = IPCP_SHIM_UDP; conf.ip_addr = 0; @@ -57,32 +56,32 @@ int shim_udp_test(int argc, char ** argv) exit(1); } - _ipcp = ipcp_udp_create(ipcp_name, i_id); + _ipcp = ipcp_udp_create(ipcp_name); if (_ipcp == NULL) { LOG_ERR("Could not instantiate shim IPCP."); shm_du_map_close(dum); exit(1); } - if (ipcp_udp_bootstrap (&conf)) { + if (ipcp_udp_bootstrap(&conf)) { LOG_ERR("Could not bootstrap."); } - if(ipcp_udp_ap_reg("bogus ap", 1865)) { + if (ipcp_udp_name_reg("bogus name")) { LOG_ERR("Failed to register application."); shm_du_map_close(dum); exit(1); } - if (ipcp_udp_ap_unreg(1865)) { + if (ipcp_udp_name_unreg("bogus name")) { LOG_ERR("Failed to unregister application."); shm_du_map_close(dum); exit(1); } for (i = 0; i < 1000; ++i) { - sprintf (bogus, "bogus ap %4d", i); - if(ipcp_udp_ap_reg(bogus, i)) { + sprintf(bogus, "bogus name %4d", i); + if (ipcp_udp_name_reg(bogus)) { LOG_ERR("Failed to register application %s.", bogus); shm_du_map_close(dum); exit(1); @@ -90,8 +89,9 @@ int shim_udp_test(int argc, char ** argv) } for (i = 0; i < 1000; ++i) { - if(ipcp_udp_ap_unreg(i)) { - LOG_ERR("Failed to unregister application %d.", i); + sprintf(bogus, "bogus name %4d", i); + if(ipcp_udp_name_unreg(bogus)) { + LOG_ERR("Failed to unregister application %s.", bogus); shm_du_map_close(dum); exit(1); } |