@cryptotaxi247 / netdata-1 / commits / a91bfe373

allow netdata to listen at and connect to unix sockets; fixes #2656

Costa Tsaousis (ktsaou) committed Aug 31, 2017 at 00:05 UTC a91bfe3739c749e96b21d6d86b4099a3bfa088ac
3 files changed +101 -10
src/common.h
+1
@@ -80,6 +80,7 @@
80 #include <sys/time.h>
81 #include <sys/types.h>
82 #include <sys/wait.h>
83 +#include <sys/un.h>
84 #include <time.h>
85 #include <unistd.h>
86 #include <uuid/uuid.h>
src/socket.c
+99 -9
@@ -80,6 +80,43 @@ int sock_enlarge_out(int fd) {
80 // --------------------------------------------------------------------------------------------------------------------
81 // listening sockets
82
83 +int create_listen_socket_unix(const char *path, int listen_backlog) {
84 + int sock;
85 +
86 + debug(D_LISTENER, "LISTENER: UNIX creating new listening socket on path '%s'", path);
87 +
88 + sock = socket(AF_UNIX, SOCK_STREAM, 0);
89 + if(sock < 0) {
90 + error("LISTENER: UNIX socket() on path '%s' failed.", path);
91 + return -1;
92 + }
93 +
94 + sock_setnonblock(sock);
95 + sock_enlarge_in(sock);
96 +
97 + struct sockaddr_un name;
98 + memset(&name, 0, sizeof(struct sockaddr_un));
99 + name.sun_family = AF_UNIX;
100 + strncpy(name.sun_path, path, sizeof(name.sun_path)-1);
101 +
102 + unlink(path);
103 +
104 + if(bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) {
105 + close(sock);
106 + error("LISTENER: UNIX bind() on path '%s' failed.", path);
107 + return -1;
108 + }
109 +
110 + if(listen(sock, listen_backlog) < 0) {
111 + close(sock);
112 + error("LISTENER: UNIX listen() on path '%s' failed.", path);
113 + return -1;
114 + }
115 +
116 + debug(D_LISTENER, "LISTENER: Listening on UNIX path '%s'", path);
117 + return sock;
118 +}
119 +
120 int create_listen_socket4(int socktype, const char *ip, int port, int listen_backlog) {
121 int sock;
122
@@ -186,7 +223,12 @@ static inline int listen_sockets_add(LISTEN_SOCKETS *sockets, int fd, int sockty
223 sockets->fds[sockets->opened] = fd;
224
225 char buffer[100 + 1];
189 - snprintfz(buffer, 100, "%s:[%s]:%d", protocol, ip, port);
226 +
227 + if(port)
228 + snprintfz(buffer, 100, "%s:[%s]:%d", protocol, ip, port);
229 + else
230 + snprintfz(buffer, 100, "%s:[%s]", protocol, ip);
231 +
232 sockets->fds_names[sockets->opened] = strdupz(buffer);
233 sockets->fds_types[sockets->opened] = socktype;
234
@@ -230,7 +272,7 @@ void listen_sockets_close(LISTEN_SOCKETS *sockets) {
272 sockets->failed = 0;
273 }
274
233 -static inline int bind_to_one(LISTEN_SOCKETS *sockets, const char *definition, int default_port, int listen_backlog) {
275 +static inline int bind_to_this(LISTEN_SOCKETS *sockets, const char *definition, int default_port, int listen_backlog) {
276 int added = 0;
277 struct addrinfo hints;
278 struct addrinfo *result = NULL, *rp = NULL;
@@ -258,6 +300,22 @@ static inline int bind_to_one(LISTEN_SOCKETS *sockets, const char *definition, i
300 socktype = SOCK_DGRAM;
301 protocol_str = "udp";
302 }
303 + else if(strncmp(ip, "unix:", 5) == 0) {
304 + char *path = ip + 5;
305 + socktype = SOCK_STREAM;
306 + protocol_str = "unix";
307 +
308 + int fd = create_listen_socket_unix(path, listen_backlog);
309 + if (fd == -1) {
310 + error("LISTENER: Cannot create unix socket '%s'", path);
311 + sockets->failed++;
312 + }
313 + else {
314 + listen_sockets_add(sockets, fd, socktype, protocol_str, path, 0);
315 + added++;
316 + }
317 + return added;
318 + }
319
320 char *e = ip;
321 if(*e == '[') {
@@ -385,7 +443,7 @@ int listen_sockets_setup(LISTEN_SOCKETS *sockets) {
443
444 char buf[e - s + 1];
445 strncpyz(buf, s, e - s);
388 - bind_to_one(sockets, buf, sockets->default_port, sockets->backlog);
446 + bind_to_this(sockets, buf, sockets->default_port, sockets->backlog);
447
448 s = e;
449 }
@@ -403,7 +461,35 @@ int listen_sockets_setup(LISTEN_SOCKETS *sockets) {
461 // --------------------------------------------------------------------------------------------------------------------
462 // connect to another host/port
463
406 -// _connect_to()
464 +// connect_to_this_unix()
465 +// path the path of the unix socket
466 +// timeout the timeout for establishing a connection
467 +
468 +static inline int connect_to_unix(const char *path, struct timeval *timeout) {
469 + int fd = socket(AF_UNIX, SOCK_STREAM, 0);
470 +
471 + if(timeout) {
472 + if(setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *) timeout, sizeof(struct timeval)) < 0)
473 + error("Failed to set timeout on UNIX socket '%s'", path);
474 + }
475 +
476 + struct sockaddr_un addr;
477 + memset(&addr, 0, sizeof(addr));
478 + addr.sun_family = AF_UNIX;
479 + strncpy(addr.sun_path, path, sizeof(addr.sun_path)-1);
480 +
481 + if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
482 + error("Cannot connect to UNIX socket on path '%s'.", path);
483 + close(fd);
484 + return -1;
485 + }
486 +
487 + debug(D_CONNECT_TO, "Connected to UNIX socket on path '%s'.", path);
488 +
489 + return fd;
490 +}
491 +
492 +// connect_to_this_ip46()
493 // protocol IPPROTO_TCP, IPPROTO_UDP
494 // socktype SOCK_STREAM, SOCK_DGRAM
495 // host the destination hostname or IP address (IPv4 or IPv6) to connect to
@@ -413,7 +499,7 @@ int listen_sockets_setup(LISTEN_SOCKETS *sockets) {
499 // service the service name or port to connect to
500 // timeout the timeout for establishing a connection
501
416 -static inline int _connect_to(int protocol, int socktype, const char *host, uint32_t scope_id, const char *service, struct timeval *timeout) {
502 +static inline int connect_to_this_ip46(int protocol, int socktype, const char *host, uint32_t scope_id, const char *service, struct timeval *timeout) {
503 struct addrinfo hints;
504 struct addrinfo *ai_head = NULL, *ai = NULL;
505
@@ -519,7 +605,7 @@ static inline int _connect_to(int protocol, int socktype, const char *host, uint
605 return fd;
606 }
607
522 -// connect_to()
608 +// connect_to_this()
609 //
610 // definition format:
611 //
@@ -530,7 +616,7 @@ static inline int _connect_to(int protocol, int socktype, const char *host, uint
616 // INTERFACE = for IPv6 only, the network interface to use
617 // PORT = port number or service name
618
533 -int connect_to(const char *definition, int default_port, struct timeval *timeout) {
619 +int connect_to_this(const char *definition, int default_port, struct timeval *timeout) {
620 char buffer[strlen(definition) + 1];
621 strcpy(buffer, definition);
622
@@ -551,6 +637,10 @@ int connect_to(const char *definition, int default_port, struct timeval *timeout
637 protocol = IPPROTO_UDP;
638 socktype = SOCK_DGRAM;
639 }
640 + else if(strncmp(host, "unix:", 5) == 0) {
641 + char *path = host + 5;
642 + return connect_to_unix(path, timeout);
643 + }
644
645 char *e = host;
646 if(*e == '[') {
@@ -595,7 +685,7 @@ int connect_to(const char *definition, int default_port, struct timeval *timeout
685 service = default_service;
686
687
598 - return _connect_to(protocol, socktype, host, scope_id, service, timeout);
688 + return connect_to_this_ip46(protocol, socktype, host, scope_id, service, timeout);
689 }
690
691 int connect_to_one_of(const char *destination, int default_port, struct timeval *timeout, size_t *reconnects_counter, char *connected_to, size_t connected_to_size) {
@@ -617,7 +707,7 @@ int connect_to_one_of(const char *destination, int default_port, struct timeval
707 char buf[e - s + 1];
708 strncpyz(buf, s, e - s);
709 if(reconnects_counter) *reconnects_counter += 1;
620 - sock = connect_to(buf, default_port, timeout);
710 + sock = connect_to_this(buf, default_port, timeout);
711 if(sock != -1) {
712 if(connected_to && connected_to_size) {
713 strncpy(connected_to, buf, connected_to_size);
src/socket.h
+1 -1
@@ -21,7 +21,7 @@ typedef struct listen_sockets {
21 extern int listen_sockets_setup(LISTEN_SOCKETS *sockets);
22 extern void listen_sockets_close(LISTEN_SOCKETS *sockets);
23
24 -extern int connect_to(const char *definition, int default_port, struct timeval *timeout);
24 +extern int connect_to_this(const char *definition, int default_port, struct timeval *timeout);
25 extern int connect_to_one_of(const char *destination, int default_port, struct timeval *timeout, size_t *reconnects_counter, char *connected_to, size_t connected_to_size);
26
27 extern ssize_t recv_timeout(int sockfd, void *buf, size_t len, int flags, int timeout);