diff options
author | Sung-jae Park <nicesj.park@samsung.com> | 2013-08-03 13:51:53 +0900 |
---|---|---|
committer | Sung-jae Park <nicesj.park@samsung.com> | 2013-08-03 13:51:53 +0900 |
commit | 835a6a0b53856d7b417a9b040ebe7bf5f298427f (patch) | |
tree | 1f94021d8fe08174a119f85a4e08a7697ae08a45 | |
parent | ccb9e303b332ee938e8ebe4e789026c2ad2fe97b (diff) | |
parent | b1b1264655cfc12a60dfb6ec172bd91d04708d5c (diff) | |
download | com-core-835a6a0b53856d7b417a9b040ebe7bf5f298427f.tar.gz com-core-835a6a0b53856d7b417a9b040ebe7bf5f298427f.tar.bz2 com-core-835a6a0b53856d7b417a9b040ebe7bf5f298427f.zip |
Merge branch 'devel/home/master'
-rw-r--r-- | include/secure_socket.h | 12 | ||||
-rw-r--r-- | packaging/libcom-core.spec | 8 | ||||
-rw-r--r-- | src/com-core_packet-router.c | 2 | ||||
-rw-r--r-- | src/secure_socket.c | 352 |
4 files changed, 284 insertions, 90 deletions
diff --git a/include/secure_socket.h b/include/secure_socket.h index 64a7832..c5c7c35 100644 --- a/include/secure_socket.h +++ b/include/secure_socket.h @@ -22,6 +22,18 @@ extern "C" { #endif +/*! + * local:///tmp/.socket.file => /tmp/.socket.file + */ +#define COM_CORE_LOCAL_SCHEME "local://" +#define COM_CORE_LOCAL_SCHEME_LEN (8) + +/*! + * remote://IPADDR:PORT + * remote://:PORT => Using INADDR_ANY in this case + */ +#define COM_CORE_REMOTE_SCHEME "remote://" +#define COM_CORE_REMOTE_SCHEME_LEN (9) /* * Create client connection diff --git a/packaging/libcom-core.spec b/packaging/libcom-core.spec index b4abc22..facc9d8 100644 --- a/packaging/libcom-core.spec +++ b/packaging/libcom-core.spec @@ -1,6 +1,6 @@ Name: libcom-core Summary: Library for the light-weight IPC -Version: 0.4.5 +Version: 0.5.0 Release: 1 Group: HomeTF/Framework License: Apache License @@ -24,6 +24,12 @@ Light-weight IPC supporting library (dev) %setup -q %build +%if 0%{?tizen_build_binary_release_type_eng} +export CFLAGS="${CFLAGS} -DTIZEN_ENGINEER_MODE" +export CXXFLAGS="${CXXFLAGS} -DTIZEN_ENGINEER_MODE" +export FFLAGS="${FFLAGS} -DTIZEN_ENGINEER_MODE" +%endif + cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} make %{?jobs:-j%jobs} diff --git a/src/com-core_packet-router.c b/src/com-core_packet-router.c index 57f45d0..f716751 100644 --- a/src/com-core_packet-router.c +++ b/src/com-core_packet-router.c @@ -888,7 +888,7 @@ static inline int route_packet(struct router *router, int handle, struct packet * \NOTE * Running Threads: Main / Client / Server */ -static inline int put_send_packet(struct router *router, int handle, struct packet *packet) +static int put_send_packet(struct router *router, int handle, struct packet *packet) { if (packet) { struct packet_item *item; diff --git a/src/secure_socket.c b/src/secure_socket.c index 98185c7..d3ae477 100644 --- a/src/secure_socket.c +++ b/src/secure_socket.c @@ -22,11 +22,13 @@ #include <sys/types.h> #include <sys/stat.h> #include <sys/socket.h> +#include <netdb.h> #include <arpa/inet.h> #include <sys/un.h> #include <netinet/in.h> #include <netinet/tcp.h> #include <errno.h> +#include <stdlib.h> #include <dlog.h> @@ -34,21 +36,34 @@ #include "debug.h" #include "util.h" -#define BACKLOG 50 /*!< Accept only 50 connections as default */ -#define SNDBUF_SZ 262144 -#define RCVBUF_SZ 524288 +#define BACKLOG 50 /*!< Accept only 50 connections as default */ +#define SNDBUF_SZ 262144 /*!< 256 KB, this will be doubled by kernel */ +#define RCVBUF_SZ 524288 /*!< 512 KB, this will be doubled by kernel */ + +enum scheme { + SCHEME_LOCAL = 0x00, + SCHEME_REMOTE = 0x01, + SCHEME_UNKNOWN = 0x02, +}; + +struct function_table { + int type; + int (*create_socket)(const char *peer, int port, struct sockaddr *addr); + int (*setup_handle)(int handle); +}; int errno; -static inline int create_socket(const char *peer, struct sockaddr_un *addr) +static inline int create_unix_socket(const char *peer, int port, struct sockaddr *addr) { int len; int handle; + struct sockaddr_un *un_addr = (struct sockaddr_un *)addr; - len = sizeof(*addr); - bzero(addr, len); + len = sizeof(*un_addr); + bzero(un_addr, len); - if (strlen(peer) >= sizeof(addr->sun_path)) { + if (strlen(peer) >= sizeof(un_addr->sun_path)) { ErrPrint("peer %s is too long to remember it\\n", peer); return -1; } @@ -56,8 +71,8 @@ static inline int create_socket(const char *peer, struct sockaddr_un *addr) /* We can believe this has no prob, because * we already check the size of add.rsun_path */ - strcpy(addr->sun_path, peer); - addr->sun_family = AF_UNIX; + strcpy(un_addr->sun_path, peer); + un_addr->sun_family = AF_UNIX; handle = socket(PF_UNIX, SOCK_STREAM, 0); if (handle < 0) { @@ -68,52 +83,183 @@ static inline int create_socket(const char *peer, struct sockaddr_un *addr) return handle; } -EAPI int secure_socket_create_client(const char *peer) +static inline int create_inet_socket(const char *peer, int port, struct sockaddr *addr) { - struct sockaddr_un addr; int handle; - int state; + struct sockaddr_in *in_addr = (struct sockaddr_in *)addr; + + bzero(in_addr, sizeof(*in_addr)); + + in_addr->sin_port = htons(port); + in_addr->sin_family = AF_INET; + if (*peer == '\0') + in_addr->sin_addr.s_addr = htonl(INADDR_ANY); + else + in_addr->sin_addr.s_addr = inet_addr(peer); + + handle = socket(AF_INET, SOCK_STREAM, 0); + if (handle < 0) { + handle = -errno; + ErrPrint("socket: %s\n", strerror(errno)); + } + + return handle; +} + +static inline int setup_unix_handle(int handle) +{ int on = 1; int sndbuf = SNDBUF_SZ; int rcvbuf = RCVBUF_SZ; - handle = create_socket(peer, &addr); + if (setsockopt(handle, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) { + int ret; + ret = -errno; + ErrPrint("Failed to change sock opt : %s\n", strerror(errno)); + return ret; + } + + (void)setsockopt(handle, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)); + (void)setsockopt(handle, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)); + (void)setsockopt(handle, IPPROTO_IP, TCP_NODELAY, &on, sizeof(on)); + + return 0; +} + +static inline int setup_inet_handle(int handle) +{ + int on = 1; + + (void)setsockopt(handle, IPPROTO_IP, TCP_NODELAY, &on, sizeof(on)); + + return 0; +} + +static inline char *parse_scheme(const char *peer, int *port, struct function_table *vtable) +{ + int _port; + char *addr = NULL; + + if (!port) + port = &_port; + + *port = 0; + + if (!strncasecmp(peer, COM_CORE_LOCAL_SCHEME, COM_CORE_LOCAL_SCHEME_LEN)) { + vtable->type = (int)SCHEME_LOCAL; + peer += COM_CORE_LOCAL_SCHEME_LEN; + + addr = strdup(peer); + if (!addr) + ErrPrint("Heap: %s\n", strerror(errno)); + + vtable->create_socket = create_unix_socket; + vtable->setup_handle = setup_unix_handle; + } else if (!strncasecmp(peer, COM_CORE_REMOTE_SCHEME, COM_CORE_REMOTE_SCHEME_LEN)) { + register int len; + char *endptr; + + vtable->type = (int)SCHEME_REMOTE; + peer += COM_CORE_REMOTE_SCHEME_LEN; + + for (len = 0; peer[len] && peer[len] != ':'; len++); + if (peer[len] != ':') { + ErrPrint("Invalid syntax: %s\n", peer); + goto out; + } + + addr = malloc(len + 1); + if (!addr) { + ErrPrint("Heap: %s\n", strerror(errno)); + goto out; + } + + if (len > 0) + strncpy(addr, peer, len); + addr[len] = '\0'; + + peer += len + 1; + *port = strtoul(peer, &endptr, 10); + if (*endptr != '\0' || peer == endptr) { + ErrPrint("Invalid: %s[%d]\n", peer - len - 1, len + 1); + free(addr); + addr = NULL; + goto out; + } + + vtable->create_socket = create_inet_socket; + vtable->setup_handle = setup_inet_handle; + } else { + /* Fallback to local scheme */ + vtable->type = (int)SCHEME_LOCAL; + addr = strdup(peer); + if (!addr) { + ErrPrint("Heap: %s\n", strerror(errno)); + goto out; + } + + vtable->create_socket = create_unix_socket; + vtable->setup_handle = setup_unix_handle; + } + +out: + return addr; +} + +EAPI int secure_socket_create_client(const char *peer) +{ + int port; + char *addr; + int ret; + struct function_table vtable; + struct sockaddr *sockaddr; + struct sockaddr_in in_addr; + struct sockaddr_un un_addr; + int handle; + int addrlen; + + addr = parse_scheme(peer, &port, &vtable); + if (!addr) { + ErrPrint("peer: [%s] is not valid\n", peer); + return -EINVAL; + } + + switch (vtable.type) { + case SCHEME_LOCAL: + sockaddr = (struct sockaddr *)&un_addr; + addrlen = sizeof(un_addr); + break; + case SCHEME_REMOTE: + sockaddr = (struct sockaddr *)&in_addr; + addrlen = sizeof(in_addr); + break; + default: + free(addr); + return -EINVAL; + } + + handle = vtable.create_socket(addr, port, sockaddr); + free(addr); if (handle < 0) return handle; - state = connect(handle, (struct sockaddr *)&addr, sizeof(addr)); - if (state < 0) { + ret = connect(handle, sockaddr, addrlen); + if (ret < 0) { + ret = -errno; ErrPrint("Failed to connect to server [%s] %s\n", peer, strerror(errno)); if (close(handle) < 0) ErrPrint("close: %s\n", strerror(errno)); - return -ENOTCONN; + return ret; } - if (setsockopt(handle, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) { - ErrPrint("Failed to change sock opt : %s\n", strerror(errno)); + ret = vtable.setup_handle(handle); + if (ret < 0) { if (close(handle) < 0) ErrPrint("close: %s\n", strerror(errno)); - return -EFAULT; - } - - if (setsockopt(handle, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) < 0) { - ErrPrint("Failed to change rcvbuf size: %s\n", strerror(errno)); - } else { - DbgPrint("rcvbuf: %d\n", rcvbuf); - } - - if (setsockopt(handle, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) < 0) { - ErrPrint("Failed to change rcvbuf size: %s\n", strerror(errno)); - } else { - DbgPrint("sndbuf: %d\n", sndbuf); - } - if (setsockopt(handle, IPPROTO_IP, TCP_NODELAY, &on, sizeof(on)) < 0) { - ErrPrint("Failed to change rcvbuf size: %s\n", strerror(errno)); - } else { - DbgPrint("TCP_NODELAY: %d\n", on); + return ret; } return handle; @@ -121,84 +267,110 @@ EAPI int secure_socket_create_client(const char *peer) EAPI int secure_socket_create_server(const char *peer) { + int port; + char *addr; int handle; - int state; - struct sockaddr_un addr; + int ret; + struct sockaddr *sockaddr; + struct sockaddr_in in_addr; + struct sockaddr_un un_addr; + struct function_table vtable; + int addrlen; + + addr = parse_scheme(peer, &port, &vtable); + if (!addr) { + ErrPrint("Failed to parse scheme\n"); + return -EFAULT; + } - handle = create_socket(peer, &addr); + switch (vtable.type) { + case SCHEME_LOCAL: + sockaddr = (struct sockaddr *)&un_addr; + addrlen = sizeof(un_addr); + break; + case SCHEME_REMOTE: + sockaddr = (struct sockaddr *)&in_addr; + addrlen = sizeof(in_addr); + break; + default: + free(addr); + return -EINVAL; + } + + handle = vtable.create_socket(addr, port, sockaddr); + free(addr); if (handle < 0) return handle; - state = bind(handle, &addr, sizeof(addr)); - if (state < 0) { - state = -errno; - - ErrPrint("Failed to bind a socket %s\n", strerror(errno)); + ret = bind(handle, sockaddr, addrlen); + if (ret < 0) { + ret = -errno; + ErrPrint("bind: %s\n", strerror(errno)); if (close(handle) < 0) ErrPrint("close: %s\n", strerror(errno)); - - return state; + return ret; } - state = listen(handle, BACKLOG); - if (state < 0) { - state = -errno; - ErrPrint("Failed to listen a socket %s\n", strerror(errno)); - + ret = listen(handle, BACKLOG); + if (ret < 0) { + ret = -errno; + ErrPrint("listen: %s\n", strerror(errno)); if (close(handle) < 0) ErrPrint("close: %s\n", strerror(errno)); - - return state; + return ret; } - if (chmod(peer, 0666) < 0) - ErrPrint("Failed to change the permission of a socket (%s)\n", - strerror(errno)); + if (vtable.type == SCHEME_LOCAL) { + if (chmod(peer, 0666) < 0) + ErrPrint("Failed to change the permission of a socket (%s)\n", strerror(errno)); + } return handle; } EAPI int secure_socket_get_connection_handle(int server_handle) { - struct sockaddr_un addr; + struct sockaddr_in in_addr; + struct sockaddr_un un_addr; + struct sockaddr *addr; int handle; - int on = 1; - socklen_t size = sizeof(addr); - int sndbuf = SNDBUF_SZ; - int rcvbuf = RCVBUF_SZ; + int ret; + socklen_t size = sizeof(un_addr); - handle = accept(server_handle, (struct sockaddr *)&addr, &size); - if (handle < 0) { - handle = -errno; - ErrPrint("Failed to accept a new client %s\n", strerror(errno)); - return handle; + /* Finding the largest buffer */ + if (sizeof(in_addr) > sizeof(un_addr)) { + addr = (struct sockaddr *)&in_addr; + size = sizeof(in_addr); + } else { + addr = (struct sockaddr *)&un_addr; + size = sizeof(un_addr); } - if (setsockopt(handle, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) { - int ret; + handle = accept(server_handle, addr, &size); + if (handle < 0) { ret = -errno; - ErrPrint("Failed to change sock opt : %s\n", strerror(errno)); - if (close(handle) < 0) - ErrPrint("close: %s\n", strerror(errno)); + ErrPrint("Failed to accept a new client %s\n", strerror(errno)); return ret; } - if (setsockopt(handle, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) < 0) { - ErrPrint("Failed to change rcvbuf size: %s\n", strerror(errno)); - } else { - DbgPrint("rcvbuf: %d\n", rcvbuf); - } + if (addr->sa_family == AF_UNIX) { + ret = setup_unix_handle(handle); + if (ret < 0) { + if (close(handle) < 0) + ErrPrint("close: %s\n", strerror(errno)); - if (setsockopt(handle, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) < 0) { - ErrPrint("Failed to change rcvbuf size: %s\n", strerror(errno)); - } else { - DbgPrint("sndbuf: %d\n", sndbuf); - } + handle = ret; + } + } else if (addr->sa_family == AF_INET) { + ret = setup_inet_handle(handle); + if (ret < 0) { + if (close(handle) < 0) + ErrPrint("close: %s\n", strerror(errno)); - if (setsockopt(handle, IPPROTO_IP, TCP_NODELAY, &on, sizeof(on)) < 0) { - ErrPrint("Failed to change rcvbuf size: %s\n", strerror(errno)); + handle = ret; + } } else { - DbgPrint("TCP_NODELAY: %d\n", on); + ErrPrint("Unknown address family: %d\n", addr->sa_family); } return handle; @@ -241,11 +413,15 @@ EAPI int secure_socket_recv(int handle, char *buffer, int size, int *sender_pid) struct cmsghdr *cmsg; struct iovec iov; char control[1024]; + int _pid; int ret; - if (!sender_pid || size <= 0 || !buffer) + if (size <= 0 || !buffer) return -EINVAL; + if (!sender_pid) + sender_pid = &_pid; + memset(&msg, 0, sizeof(msg)); iov.iov_base = buffer; iov.iov_len = size; @@ -272,11 +448,12 @@ EAPI int secure_socket_recv(int handle, char *buffer, int size, int *sender_pid) return ret; } + *sender_pid = -1; /* In case of remote socket, cannot delivery this */ cmsg = CMSG_FIRSTHDR(&msg); while (cmsg) { - if (cmsg->cmsg_level == SOL_SOCKET - && cmsg->cmsg_type == SCM_CREDENTIALS) { + if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS) { struct ucred *cred; + cred = (struct ucred *)CMSG_DATA(cmsg); *sender_pid = cred->pid; } @@ -289,7 +466,6 @@ EAPI int secure_socket_recv(int handle, char *buffer, int size, int *sender_pid) EAPI int secure_socket_destroy_handle(int handle) { - DbgPrint("Close socket handle %d\n", handle); if (close(handle) < 0) { ErrPrint("close: %s\n", strerror(errno)); return -1; |