/* ================================================== */
+static int
+set_socket_nonblock(int sock_fd)
+{
+ if (fcntl(sock_fd, F_SETFL, O_NONBLOCK)) {
+ DEBUG_LOG("Could not set O_NONBLOCK : %s", strerror(errno));
+ return 0;
+ }
+
+ return 1;
+}
+
+/* ================================================== */
+
static int
open_socket(int domain, int type, int flags)
{
#ifdef SOCK_NONBLOCK
(socket_flags & SOCK_NONBLOCK) == 0 &&
#endif
- fcntl(sock_fd, F_SETFL, O_NONBLOCK)) {
- DEBUG_LOG("Could not set O_NONBLOCK : %s", strerror(errno));
+ !set_socket_nonblock(sock_fd)) {
close(sock_fd);
return INVALID_SOCK_FD;
}
if (saddr_len == 0)
return 0;
- if (connect(sock_fd, &saddr.sa, saddr_len) < 0) {
+ if (connect(sock_fd, &saddr.sa, saddr_len) < 0 && errno != EINPROGRESS) {
DEBUG_LOG("Could not connect socket to %s : %s",
UTI_IPSockAddrToString(addr), strerror(errno));
return 0;
goto error;
if (remote_addr || local_addr)
- DEBUG_LOG("Opened %s socket fd=%d%s%s%s%s",
- family == IPADDR_INET4 ? "IPv4" : "IPv6",
+ DEBUG_LOG("Opened %s%s socket fd=%d%s%s%s%s",
+ type == SOCK_DGRAM ? "UDP" : type == SOCK_STREAM ? "TCP" : "?",
+ family == IPADDR_INET4 ? "v4" : "v6",
sock_fd,
remote_addr ? " remote=" : "",
remote_addr ? UTI_IPSockAddrToString(remote_addr) : "",
be for a socket error. Clear the error to avoid a busy loop. */
if (flags & SCK_FLAG_MSG_ERRQUEUE) {
int error = 0;
- socklen_t len = sizeof (error);
- if (getsockopt(sock_fd, SOL_SOCKET, SO_ERROR, &error, &len))
- DEBUG_LOG("Could not get SO_ERROR");
- if (error)
+ if (SCK_GetIntOption(sock_fd, SOL_SOCKET, SO_ERROR, &error))
errno = error;
}
#endif
/* ================================================== */
+int
+SCK_OpenTcpSocket(IPSockAddr *remote_addr, IPSockAddr *local_addr, int flags)
+{
+ return open_ip_socket(remote_addr, local_addr, SOCK_STREAM, flags);
+}
+
+/* ================================================== */
+
int
SCK_OpenUnixDatagramSocket(const char *remote_addr, const char *local_addr, int flags)
{
/* ================================================== */
+int
+SCK_GetIntOption(int sock_fd, int level, int name, int *value)
+{
+ socklen_t len = sizeof (*value);
+
+ if (getsockopt(sock_fd, level, name, value, &len) < 0) {
+ DEBUG_LOG("getsockopt() failed fd=%d level=%d name=%d : %s",
+ sock_fd, level, name, strerror(errno));
+ return 0;
+ }
+
+ return 1;
+}
+
+/* ================================================== */
+
int
SCK_EnableKernelRxTimestamping(int sock_fd)
{
/* ================================================== */
+int
+SCK_ListenOnSocket(int sock_fd, int backlog)
+{
+ if (listen(sock_fd, backlog) < 0) {
+ DEBUG_LOG("listen() failed : %s", strerror(errno));
+ return 0;
+ }
+
+ return 1;
+}
+
+/* ================================================== */
+
+int
+SCK_AcceptConnection(int sock_fd, IPSockAddr *remote_addr)
+{
+ union sockaddr_all saddr;
+ socklen_t saddr_len = sizeof (saddr);
+ int conn_fd;
+
+ conn_fd = accept(sock_fd, &saddr.sa, &saddr_len);
+ if (conn_fd < 0) {
+ DEBUG_LOG("accept() failed : %s", strerror(errno));
+ return INVALID_SOCK_FD;
+ }
+
+ if (!UTI_FdSetCloexec(conn_fd) || !set_socket_nonblock(conn_fd)) {
+ close(conn_fd);
+ return INVALID_SOCK_FD;
+ }
+
+ SCK_SockaddrToIPSockAddr(&saddr.sa, saddr_len, remote_addr);
+
+ return conn_fd;
+}
+
+/* ================================================== */
+
+int
+SCK_ShutdownConnection(int sock_fd)
+{
+ if (shutdown(sock_fd, SHUT_RDWR) < 0) {
+ DEBUG_LOG("shutdown() failed : %s", strerror(errno));
+ return 0;
+ }
+
+ return 1;
+}
+
+/* ================================================== */
+
int
SCK_Receive(int sock_fd, void *buffer, unsigned int length, int flags)
{
extern int SCK_OpenUnixStreamSocket(const char *remote_addr, const char *local_addr,
int flags);
-/* Set a socket option */
-extern int SCK_SetIntOption(int sock_fd, int level, int option, int value);
+/* Set and get a socket option of int size */
+extern int SCK_SetIntOption(int sock_fd, int level, int name, int value);
+extern int SCK_GetIntOption(int sock_fd, int level, int name, int *value);
+
/* Enable RX timestamping socket option */
extern int SCK_EnableKernelRxTimestamping(int sock_fd);
+/* Operate on a stream socket - listen()/accept()/shutdown() wrappers */
+extern int SCK_ListenOnSocket(int sock_fd, int backlog);
+extern int SCK_AcceptConnection(int sock_fd, IPSockAddr *remote_addr);
+extern int SCK_ShutdownConnection(int sock_fd);
+
/* Receive and send data on connected sockets - recv()/send() wrappers */
extern int SCK_Receive(int sock_fd, void *buffer, unsigned int length, int flags);
extern int SCK_Send(int sock_fd, void *buffer, unsigned int length, int flags);
SCMP_SYS(stat), SCMP_SYS(stat64), SCMP_SYS(statfs), SCMP_SYS(statfs64),
SCMP_SYS(unlink), SCMP_SYS(unlinkat),
/* Socket */
- SCMP_SYS(bind), SCMP_SYS(connect), SCMP_SYS(getsockname), SCMP_SYS(getsockopt),
- SCMP_SYS(recv), SCMP_SYS(recvfrom), SCMP_SYS(recvmmsg), SCMP_SYS(recvmsg),
- SCMP_SYS(send), SCMP_SYS(sendmmsg), SCMP_SYS(sendmsg), SCMP_SYS(sendto),
+ SCMP_SYS(accept), SCMP_SYS(bind), SCMP_SYS(connect), SCMP_SYS(getsockname),
+ SCMP_SYS(getsockopt), SCMP_SYS(recv), SCMP_SYS(recvfrom),
+ SCMP_SYS(recvmmsg), SCMP_SYS(recvmsg), SCMP_SYS(send), SCMP_SYS(sendmmsg),
+ SCMP_SYS(sendmsg), SCMP_SYS(sendto), SCMP_SYS(shutdown),
/* TODO: check socketcall arguments */
SCMP_SYS(socketcall),
/* General I/O */