#define RCVBUF_SZ 524288 /*!< 512 KB, this will be doubled by kernel */
enum scheme {
- SCHEME_LOCAL = 0x00,
- SCHEME_REMOTE = 0x01,
- SCHEME_UNKNOWN = 0x02,
+ 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 type;
+ int (*create_socket)(const char *peer, int port, struct sockaddr *addr);
+ int (*setup_handle)(int handle);
};
int errno;
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(*un_addr);
- bzero(un_addr, len);
-
- if (strlen(peer) >= sizeof(un_addr->sun_path)) {
- ErrPrint("peer %s is too long to remember it\\n", peer);
- return -1;
- }
-
- /* We can believe this has no prob, because
- * we already check the size of add.rsun_path
- */
- strcpy(un_addr->sun_path, peer);
- un_addr->sun_family = AF_UNIX;
-
- handle = socket(PF_UNIX, SOCK_STREAM, 0);
- if (handle < 0) {
- ErrPrint("Failed to create a socket %s\n", strerror(errno));
- return -1;
- }
-
- return handle;
+ int len;
+ int handle;
+ struct sockaddr_un *un_addr = (struct sockaddr_un *)addr;
+
+ len = sizeof(*un_addr);
+ bzero(un_addr, len);
+
+ if (strlen(peer) >= sizeof(un_addr->sun_path)) {
+ ErrPrint("peer %s is too long to remember it\\n", peer);
+ return -1;
+ }
+
+ /* We can believe this has no prob, because
+ * we already check the size of add.rsun_path
+ */
+ strcpy(un_addr->sun_path, peer);
+ un_addr->sun_family = AF_UNIX;
+
+ handle = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (handle < 0) {
+ handle = -errno;
+ ErrPrint("Failed to create a socket %s\n", strerror(errno));
+ }
+
+ return handle;
}
static inline int create_inet_socket(const char *peer, int port, struct sockaddr *addr)
{
- int handle;
- 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;
+ int handle;
+ 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 create_systemd_socket(const char *peer, int port, struct sockaddr *addr)
{
- int handle = -1;
- int cnt;
-
- cnt = sd_listen_fds(0);
- if (cnt > 1) {
- ErrPrint("To many file descriptors are received on socket activation: %d\n", cnt);
- } else if (cnt == 1) {
- handle = SD_LISTEN_FDS_START + 0;
- } else {
- handle = create_inet_socket(peer, port, addr);
- }
-
- return handle;
+ int handle = -1;
+ int cnt;
+
+ cnt = sd_listen_fds(0);
+ if (cnt > 1) {
+ ErrPrint("To many file descriptors are received on socket activation: %d\n", cnt);
+ } else if (cnt == 1) {
+ handle = SD_LISTEN_FDS_START + 0;
+ } else {
+ handle = create_inet_socket(peer, port, addr);
+ }
+
+ return handle;
}
static inline int setup_unix_handle(int handle)
{
- int on = 1;
- int sndbuf = SNDBUF_SZ;
- int rcvbuf = RCVBUF_SZ;
-
- 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;
- }
+ int on = 1;
+ int sndbuf = SNDBUF_SZ;
+ int rcvbuf = RCVBUF_SZ;
- (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));
+ 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;
+ }
- return 0;
+ (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;
+ int on = 1;
- (void)setsockopt(handle, IPPROTO_IP, TCP_NODELAY, &on, sizeof(on));
+ (void)setsockopt(handle, IPPROTO_IP, TCP_NODELAY, &on, sizeof(on));
- return 0;
+ 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_SD_LOCAL_SCHEME, COM_CORE_SD_LOCAL_SCHEME_LEN)) {
- vtable->type = (int)SCHEME_LOCAL;
- peer += COM_CORE_SD_LOCAL_SCHEME_LEN;
-
- addr = strdup(peer);
- if (!addr) {
- ErrPrint("Heap: %s\n", strerror(errno));
- }
-
- vtable->create_socket = create_systemd_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;
- }
+ int _port;
+ char *addr = NULL;
-out:
- return addr;
-}
+ if (!port)
+ port = &_port;
-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);
+ *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("peer: [%s] is not valid\n", peer);
- return -EINVAL;
+ ErrPrint("Heap: %s\n", strerror(errno));
}
- 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;
- }
+ vtable->create_socket = create_unix_socket;
+ vtable->setup_handle = setup_unix_handle;
+ } else if (!strncasecmp(peer, COM_CORE_SD_LOCAL_SCHEME, COM_CORE_SD_LOCAL_SCHEME_LEN)) {
+ vtable->type = (int)SCHEME_LOCAL;
+ peer += COM_CORE_SD_LOCAL_SCHEME_LEN;
- handle = vtable.create_socket(addr, port, sockaddr);
- free(addr);
- if (handle < 0) {
- return handle;
+ addr = strdup(peer);
+ if (!addr) {
+ ErrPrint("Heap: %s\n", strerror(errno));
}
- 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 ret;
+ vtable->create_socket = create_systemd_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;
}
- ret = vtable.setup_handle(handle);
- if (ret < 0) {
- if (close(handle) < 0) {
- ErrPrint("close: %s\n", strerror(errno));
- }
+ addr = malloc(len + 1);
+ if (!addr) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ goto out;
+ }
- return ret;
+ if (len > 0) {
+ strncpy(addr, peer, len);
}
- return handle;
-}
+ addr[len] = '\0';
-EAPI int secure_socket_create_server(const char *peer)
-{
- int port;
- char *addr;
- int handle;
- int ret;
- struct sockaddr *sockaddr;
- struct sockaddr_in in_addr;
- struct sockaddr_un un_addr;
- struct function_table vtable;
- int addrlen;
+ 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;
+ }
- addr = parse_scheme(peer, &port, &vtable);
+ 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("Failed to parse scheme\n");
- return -EFAULT;
+ ErrPrint("Heap: %s\n", strerror(errno));
+ goto out;
}
- switch (vtable.type) {
+ 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;
+ sockaddr = (struct sockaddr *)&un_addr;
+ addrlen = sizeof(un_addr);
+ break;
case SCHEME_REMOTE:
- sockaddr = (struct sockaddr *)&in_addr;
- addrlen = sizeof(in_addr);
- break;
+ sockaddr = (struct sockaddr *)&in_addr;
+ addrlen = sizeof(in_addr);
+ break;
default:
- free(addr);
- return -EINVAL;
- }
+ free(addr);
+ return -EINVAL;
+ }
- handle = vtable.create_socket(addr, port, sockaddr);
- free(addr);
- if (handle < 0) {
- return handle;
- }
+ handle = vtable.create_socket(addr, port, sockaddr);
+ free(addr);
+ if (handle < 0) {
+ return handle;
+ }
- 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 ret;
+ 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));
}
- 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 ret;
- }
+ return ret;
+ }
- if (vtable.type == SCHEME_LOCAL) {
- if (chmod(peer, 0666) < 0) {
- ErrPrint("Failed to change the permission of a socket (%s)\n", strerror(errno));
- }
+ ret = vtable.setup_handle(handle);
+ if (ret < 0) {
+ if (close(handle) < 0) {
+ ErrPrint("close: %s\n", strerror(errno));
}
- return handle;
+ return ret;
+ }
+
+ return handle;
}
-EAPI int secure_socket_get_connection_handle(int server_handle)
+EAPI int secure_socket_create_server(const char *peer)
{
- struct sockaddr_in in_addr;
- struct sockaddr_un un_addr;
- struct sockaddr *addr;
- int handle;
- int ret;
- socklen_t size = sizeof(un_addr);
-
- /* 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);
+ int port;
+ char *addr;
+ int handle;
+ 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 -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;
+ }
+
+ 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 ret;
+ }
- handle = accept(server_handle, addr, &size);
- if (handle < 0) {
- ret = -errno;
- ErrPrint("Failed to accept a new client %s\n", strerror(errno));
- return ret;
+ 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 ret;
+ }
- if (addr->sa_family == AF_UNIX) {
- ret = setup_unix_handle(handle);
- if (ret < 0) {
- if (close(handle) < 0) {
- ErrPrint("close: %s\n", strerror(errno));
- }
-
- 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));
- }
-
- handle = ret;
- }
- } else {
- ErrPrint("Unknown address family: %d\n", addr->sa_family);
+ 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;
+ return handle;
}
-EAPI int secure_socket_send(int handle, const char *buffer, int size)
+EAPI int secure_socket_get_connection_handle(int server_handle)
{
- struct msghdr msg;
- struct iovec iov;
- int ret;
+ struct sockaddr_in in_addr;
+ struct sockaddr_un un_addr;
+ struct sockaddr *addr;
+ int handle;
+ int ret;
+ socklen_t size = sizeof(un_addr);
+
+ /* 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);
+ }
+
+ handle = accept(server_handle, addr, &size);
+ if (handle < 0) {
+ ret = -errno;
+ ErrPrint("Failed to accept a new client %s\n", strerror(errno));
+ return ret;
+ }
+
+ 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 (!buffer || size <= 0) {
- ErrPrint("Reject: 0 byte data sending\n");
- return -EINVAL;
+ handle = ret;
}
-
- memset(&msg, 0, sizeof(msg));
- iov.iov_base = (char *)buffer;
- iov.iov_len = size;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
-
- ret = sendmsg(handle, &msg, 0);
+ } else if (addr->sa_family == AF_INET) {
+ ret = setup_inet_handle(handle);
if (ret < 0) {
- ret = -errno;
- if (errno == EAGAIN || errno == EWOULDBLOCK) {
- ErrPrint("handle[%d] size[%d] Try again [%s]\n", handle, size, strerror(errno));
- return -EAGAIN;
- }
- ErrPrint("Failed to send message [%s]\n", strerror(errno));
- return ret;
+ if (close(handle) < 0) {
+ ErrPrint("close: %s\n", strerror(errno));
+ }
+
+ handle = ret;
}
+ } else {
+ ErrPrint("Unknown address family: %d\n", addr->sa_family);
+ }
- return iov.iov_len;
+ return handle;
}
-EAPI int secure_socket_recv(int handle, char *buffer, int size, int *sender_pid)
+EAPI int secure_socket_send_with_fd(int handle, const char *buffer, int size, int fd)
{
- struct msghdr msg;
+ struct msghdr msg;
+ struct iovec iov;
+ union {
+ struct cmsghdr hdr;
+ char control[CMSG_SPACE(sizeof(int))];
+ } cmsgu;
+ int ret;
+
+ if (!buffer || size <= 0) {
+ ErrPrint("Reject: 0 byte data sending\n");
+ return -EINVAL;
+ }
+
+ memset(&msg, 0, sizeof(msg));
+ iov.iov_base = (char *)buffer;
+ iov.iov_len = size;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ if (fd >= 0) {
struct cmsghdr *cmsg;
- struct iovec iov;
- char control[1024];
- int _pid;
- int ret;
+ int *cdata;
- if (size <= 0 || !buffer) {
- return -EINVAL;
- }
+ msg.msg_control = cmsgu.control;
+ msg.msg_controllen = sizeof(cmsgu.control);
- if (!sender_pid) {
- sender_pid = &_pid;
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cdata = (int *)CMSG_DATA(cmsg);
+ *cdata = fd;
+ }
+
+ ret = sendmsg(handle, &msg, 0);
+ if (ret < 0) {
+ ret = -errno;
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ ErrPrint("handle[%d] size[%d] Try again [%s]\n", handle, size, strerror(errno));
+ return -EAGAIN;
}
+ ErrPrint("Failed to send message [%s]\n", strerror(errno));
+ return ret;
+ }
- memset(&msg, 0, sizeof(msg));
- iov.iov_base = buffer;
- iov.iov_len = size;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_control = control;
- msg.msg_controllen = sizeof(control);
-
- ret = recvmsg(handle, &msg, 0);
- if (ret == 0) {
- /*!< Disconnected */
- DbgPrint("Disconnected\n");
- return 0;
- }
+ return iov.iov_len;
+}
- if (ret < 0) {
- ret = -errno;
- if (errno == EAGAIN || errno == EWOULDBLOCK) {
- ErrPrint("handle[%d] size[%d] Try again [%s]\n", handle, size, strerror(errno));
- return -EAGAIN;
- }
-
- ErrPrint("Failed to recvmsg [%s]\n", strerror(errno));
- return ret;
- }
+EAPI int secure_socket_send(int handle, const char *buffer, int size)
+{
+ return secure_socket_send_with_fd(handle, buffer, size, -1);
+}
- *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) {
- struct ucred *cred;
+EAPI int secure_socket_recv_with_fd(int handle, char *buffer, int size, int *sender_pid, int *fd)
+{
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct iovec iov;
+ char control[1024];
+ int _pid;
+ int ret;
+
+ 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;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = control;
+ msg.msg_controllen = sizeof(control);
+
+ ret = recvmsg(handle, &msg, 0);
+ if (ret == 0) {
+ /*!< Disconnected */
+ DbgPrint("Disconnected\n");
+ return 0;
+ }
- cred = (struct ucred *)CMSG_DATA(cmsg);
- *sender_pid = cred->pid;
- }
+ if (ret < 0) {
+ ret = -errno;
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ ErrPrint("handle[%d] size[%d] Try again [%s]\n", handle, size, strerror(errno));
+ return -EAGAIN;
+ }
- cmsg = CMSG_NXTHDR(&msg, cmsg);
+ ErrPrint("Failed to recvmsg [%s]\n", strerror(errno));
+ 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) {
+ struct ucred *cred;
+
+ cred = (struct ucred *)CMSG_DATA(cmsg);
+ *sender_pid = cred->pid;
+ } else if (fd && cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
+ int *cdata;
+ cdata = (int *)CMSG_DATA(cmsg);
+ *fd = *cdata;
}
- return iov.iov_len;
+ cmsg = CMSG_NXTHDR(&msg, cmsg);
+ }
+
+ return iov.iov_len;
+}
+
+EAPI int secure_socket_recv(int handle, char *buffer, int size, int *sender_pid)
+{
+ return secure_socket_recv_with_fd(handle, buffer, size, sender_pid, NULL);
}
EAPI int secure_socket_destroy_handle(int handle)
{
- if (close(handle) < 0) {
- ErrPrint("close: %s\n", strerror(errno));
- return -1;
- }
- return 0;
+ if (close(handle) < 0) {
+ int ret;
+ ret = -errno;
+ ErrPrint("close: %s\n", strerror(errno));
+ return ret;
+ }
+
+ return 0;
}
#undef _GNU_SOURCE