summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/sys/net.c106
-rw-r--r--include/cmsys.h10
2 files changed, 109 insertions, 7 deletions
diff --git a/common/sys/net.c b/common/sys/net.c
index ba08ff7f..883b4d48 100644
--- a/common/sys/net.c
+++ b/common/sys/net.c
@@ -9,9 +9,12 @@
#include <unistd.h>
#include <ctype.h>
#include <assert.h>
+#include <errno.h>
#include "cmsys.h"
+#define DEFAULT_TCP_QLEN (10)
+
uint32_t
ipstr2int(const char *ip)
{
@@ -40,9 +43,10 @@ ipstr2int(const char *ip)
// *:port (bind to addr_any, allow remote connect)
// all others formats are UNIX domain socket path.
-int tobind(const char * addr)
+int tobindex(const char *addr, int qlen, int (*_setsock)(int), int do_listen)
{
- int sockfd, val = 1;
+ const int v_on = 1;
+ int sockfd;
assert(addr && *addr);
@@ -57,6 +61,12 @@ int tobind(const char * addr)
servaddr.sun_family = AF_UNIX;
strlcpy(servaddr.sun_path, addr, sizeof(servaddr.sun_path));
+ setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
+ (void *)&v_on, sizeof(v_on));
+
+ if (_setsock)
+ _setsock(sockfd);
+
// remove the file first if it exists.
unlink(servaddr.sun_path);
@@ -81,7 +91,10 @@ int tobind(const char * addr)
assert(port && atoi(port) != 0);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
- (char *)&val, sizeof(val));
+ (void *)&v_on, sizeof(v_on));
+
+ if (_setsock)
+ _setsock(sockfd);
if (!buf[0])
servaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
@@ -101,7 +114,7 @@ int tobind(const char * addr)
}
}
- if (listen(sockfd, 10) < 0) {
+ if (do_listen && listen(sockfd, qlen) < 0) {
perror("listen()");
exit(1);
}
@@ -109,6 +122,11 @@ int tobind(const char * addr)
return sockfd;
}
+int tobind(const char * addr)
+{
+ return tobindex(addr, DEFAULT_TCP_QLEN, NULL, 1);
+}
+
int toconnect(const char *addr)
{
int sock;
@@ -194,3 +212,83 @@ int towrite(int fd, const void *buf, int len)
}
return l;
}
+
+/**
+ * fd sharing by piaip
+ */
+
+// return: -1 if error, otherwise success.
+int send_remote_fd(int tunnel, int fd)
+{
+ struct msghdr msg = {0};
+ struct iovec vec = {0};
+ struct cmsghdr *cmsg;
+ char ccmsg [CMSG_SPACE(sizeof(fd))];
+ char dummy = 0;
+ int rv;
+
+ vec.iov_base = &dummy; // must send/receive at least one byte
+ vec.iov_len = 1;
+ msg.msg_iov = &vec;
+ msg.msg_iovlen = 1;
+ msg.msg_control = ccmsg;
+ msg.msg_controllen = sizeof(ccmsg);
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+ *(int*)CMSG_DATA(cmsg) = fd;
+
+ // adjust msg again
+ msg.msg_controllen = cmsg->cmsg_len;
+ msg.msg_flags = 0;
+
+ do {
+ // ignore EINTR
+ rv = sendmsg(tunnel, &msg, 0);
+ } while (rv == -1 && errno == EINTR);
+
+ if (rv == -1) {
+ perror("sendmsg");
+ return rv;
+ }
+
+ return 0;
+}
+
+// return: remote fd (-1 if error)
+int recv_remote_fd(int tunnel)
+{
+ struct msghdr msg;
+ struct iovec iov;
+ char dummy;
+ int rv;
+ int connfd = -1;
+ char ccmsg[CMSG_SPACE(sizeof(connfd))];
+ struct cmsghdr *cmsg;
+
+ iov.iov_base = &dummy;
+ iov.iov_len = 1;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = ccmsg;
+ msg.msg_controllen = sizeof(ccmsg);
+
+ do {
+ // ignore EINTR
+ rv = recvmsg(tunnel, &msg, 0);
+ } while (rv == -1 && errno == EINTR);
+
+ if (rv == -1) {
+ perror("recvmsg");
+ return -1;
+ }
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ assert(cmsg->cmsg_type == SCM_RIGHTS);
+ if (cmsg->cmsg_type != SCM_RIGHTS)
+ return -1;
+
+ return *(int*)CMSG_DATA(cmsg);
+}
diff --git a/include/cmsys.h b/include/cmsys.h
index d680ae2a..833dc7aa 100644
--- a/include/cmsys.h
+++ b/include/cmsys.h
@@ -76,10 +76,11 @@ extern void PttLock(int fd, int start, int size, int mode);
/* net.c */
extern uint32_t ipstr2int(const char *ip);
-extern int tobind(const char *addr);
+extern int tobind (const char *addr);
+extern int tobindex (const char *addr, int qlen, int (*setsock)(int), int do_listen);
extern int toconnect(const char *addr);
-extern int toread(int fd, void *buf, int len);
-extern int towrite(int fd, const void *buf, int len);
+extern int toread (int fd, void *buf, int len);
+extern int towrite (int fd, const void *buf, int len);
/* sort.c */
extern int cmp_int(const void *a, const void *b);
@@ -174,6 +175,9 @@ extern void Vector_sublist(const struct Vector *src, struct Vector *dst, const c
extern int Vector_remove(struct Vector *self, const char *name);
extern int Vector_search(const struct Vector *self, const char *name);
+extern int send_remote_fd(int tunnel, int fd);
+extern int recv_remote_fd(int tunnel);
+
/* telnet.c */
struct TelnetCallback {
void (*term_resize)(int w, int h);