From ea7611a9ddde2aaeceda60731d4aee6a2ae7f9a5 Mon Sep 17 00:00:00 2001 From: Jan Friesse Date: Thu, 24 Mar 2016 16:07:28 +0100 Subject: [PATCH] qdevice: Add support for daemonize Also local unix socket is now created. In future this is going to be used for qdevice-tool, for now it's used only for handling SIGINT and SIGTERM. Signed-off-by: Jan Friesse --- qdevices/Makefile.am | 2 +- qdevices/corosync-qdevice.c | 108 ++++++++++++++++++++++- qdevices/corosync-qnetd.c | 20 +++-- qdevices/qdevice-config.h | 6 +- qdevices/qdevice-instance.h | 2 + qdevices/qdevice-local-socket.c | 73 +++++++++++++++ qdevices/qdevice-local-socket.h | 55 ++++++++++++ qdevices/qdevice-log.c | 10 ++- qdevices/qdevice-log.h | 5 +- qdevices/qdevice-model-net.c | 7 +- qdevices/qdevice-net-disconnect-reason.h | 3 + qdevices/qdevice-net-instance.c | 14 ++- qdevices/qdevice-net-instance.h | 3 +- qdevices/qdevice-net-poll.c | 27 ++++++ qdevices/qnet-config.h | 2 + qdevices/qnetd-log.h | 3 + qdevices/unix-socket.c | 104 ++++++++++++++++++++++ qdevices/unix-socket.h | 51 +++++++++++ qdevices/utils.c | 17 +--- qdevices/utils.h | 3 +- 20 files changed, 479 insertions(+), 36 deletions(-) create mode 100644 qdevices/qdevice-local-socket.c create mode 100644 qdevices/qdevice-local-socket.h create mode 100644 qdevices/unix-socket.c create mode 100644 qdevices/unix-socket.h diff --git a/qdevices/Makefile.am b/qdevices/Makefile.am index 3033dc20..f33b1b66 100644 --- a/qdevices/Makefile.am +++ b/qdevices/Makefile.am @@ -53,7 +53,7 @@ corosync_qdevice_SOURCES = corosync-qdevice.c qdevice-cmap.c qdevice-instance.c qdevice-model.c \ qdevice-model-net.c \ qdevice-net-instance.c dynar.c send-buffer-list.c timer-list.c \ - msg.c msgio.c nss-sock.c tlv.c \ + msg.c msgio.c nss-sock.c tlv.c unix-socket.c qdevice-local-socket.c \ qdevice-net-poll.c qdevice-net-send.c qdevice-net-votequorum.c \ qdevice-net-socket.c qdevice-net-nss.c qdevice-net-msg-received.c \ qdevice-net-cast-vote-timer.c qdevice-net-echo-request-timer.c \ diff --git a/qdevices/corosync-qdevice.c b/qdevices/corosync-qdevice.c index c25dd85a..1bb088e7 100644 --- a/qdevices/corosync-qdevice.c +++ b/qdevices/corosync-qdevice.c @@ -32,25 +32,126 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include #include "qdevice-config.h" #include "qdevice-cmap.h" #include "qdevice-log.h" #include "qdevice-model.h" #include "qdevice-votequorum.h" +#include "qdevice-local-socket.h" #include "utils.h" +struct qdevice_instance *global_instance; + +static void +signal_int_handler(int sig) +{ + qdevice_log(LOG_DEBUG, "SIGINT received - closing local unix socket"); + qdevice_local_socket_destroy(global_instance); +} + +static void +signal_term_handler(int sig) +{ + qdevice_log(LOG_DEBUG, "SIGTERM received - closing server socket"); + qdevice_local_socket_destroy(global_instance); +} + +static void +signal_handlers_register(void) +{ + struct sigaction act; + + act.sa_handler = signal_int_handler; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_RESTART; + + sigaction(SIGINT, &act, NULL); + + act.sa_handler = signal_term_handler; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_RESTART; + + sigaction(SIGTERM, &act, NULL); +} + +static void +usage(void) +{ + + printf("usage: %s [-dfh]\n", QDEVICE_PROGRAM_NAME); +} + +static void +cli_parse(int argc, char * const argv[], int *foreground, int *force_debug) +{ + int ch; + + *foreground = 0; + *force_debug = 0; + + while ((ch = getopt(argc, argv, "dfh")) != -1) { + switch (ch) { + case 'd': + *force_debug = 1; + break; + case 'f': + *foreground = 1; + break; + case 'h': + case '?': + usage(); + exit(1); + break; + } + } +} + int -main(void) +main(int argc, char * const argv[]) { struct qdevice_instance instance; + int foreground; + int force_debug; + int lock_file; + int another_instance_running; + + cli_parse(argc, argv, &foreground, &force_debug); qdevice_instance_init(&instance); + global_instance = &instance; + qdevice_cmap_init(&instance); - qdevice_log_init(&instance); + qdevice_log_init(&instance, force_debug); + + /* + * Daemonize + */ + if (!foreground) { + utils_tty_detach(); + } + + if ((lock_file = utils_flock(QDEVICE_LOCK_FILE, getpid(), &another_instance_running)) == -1) { + if (another_instance_running) { + qdevice_log(LOG_ERR, "Another instance is running"); + } else { + qdevice_log_err(LOG_ERR, "Can't aquire lock"); + } + + exit(1); + } + + qdevice_log(LOG_DEBUG, "Initializing votequorum"); qdevice_votequorum_init(&instance); + qdevice_log(LOG_DEBUG, "Initializing local socket"); + if (qdevice_local_socket_init(&instance) != 0) { + return (1); + } + + signal_handlers_register(); + qdevice_log(LOG_DEBUG, "Registering qdevice models"); qdevice_model_register_all(); @@ -87,6 +188,7 @@ main(void) qdevice_log(LOG_DEBUG, "Destorying qdevice model"); qdevice_model_destroy(&instance); + qdevice_local_socket_destroy(&instance); qdevice_votequorum_destroy(&instance); qdevice_cmap_destroy(&instance); qdevice_log_close(&instance); diff --git a/qdevices/corosync-qnetd.c b/qdevices/corosync-qnetd.c index fadac081..2c03c64c 100644 --- a/qdevices/corosync-qnetd.c +++ b/qdevices/corosync-qnetd.c @@ -32,14 +32,14 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#include - #include #include #include #include #include +#include "qnet-config.h" + #include "nss-sock.h" #include "qnetd-algorithm.h" #include "qnetd-instance.h" @@ -224,7 +224,7 @@ static void usage(void) { - printf("usage: %s [-46df] [-l listen_addr] [-p listen_port] [-s tls]\n", QNETD_PROGRAM_NAME); + printf("usage: %s [-46dfh] [-l listen_addr] [-p listen_port] [-s tls]\n", QNETD_PROGRAM_NAME); printf("%14s[-c client_cert_required] [-m max_clients]\n", ""); } @@ -247,7 +247,7 @@ cli_parse(int argc, char * const argv[], char **host_addr, uint16_t *host_port, *max_clients = QNETD_DEFAULT_MAX_CLIENTS; *address_family = PR_AF_UNSPEC; - while ((ch = getopt(argc, argv, "46fdc:l:m:p:s:")) != -1) { + while ((ch = getopt(argc, argv, "46dfhc:l:m:p:s:")) != -1) { switch (ch) { case '4': *address_family = PR_AF_INET; @@ -298,6 +298,7 @@ cli_parse(int argc, char * const argv[], char **host_addr, uint16_t *host_port, errx(1, "tls must be one of on, off, req"); } break; + case 'h': case '?': usage(); exit(1); @@ -307,7 +308,7 @@ cli_parse(int argc, char * const argv[], char **host_addr, uint16_t *host_port, } int -main(int argc, char *argv[]) +main(int argc, char * const argv[]) { struct qnetd_instance instance; char *host_addr; @@ -320,6 +321,7 @@ main(int argc, char *argv[]) size_t max_clients; PRIntn address_family; int lock_file; + int another_instance_running; cli_parse(argc, argv, &host_addr, &host_port, &foreground, &debug_log, &bump_log_priority, &tls_supported, &client_cert_required, &max_clients, &address_family); @@ -340,7 +342,13 @@ main(int argc, char *argv[]) utils_tty_detach(); } - if ((lock_file = utils_flock(QNETD_LOCK_FILE, getpid(), qnetd_log_printf)) == -1) { + if ((lock_file = utils_flock(QNETD_LOCK_FILE, getpid(), &another_instance_running)) == -1) { + if (another_instance_running) { + qnetd_log(LOG_ERR, "Another instance is running"); + } else { + qnetd_log_err(LOG_ERR, "Can't acquire lock"); + } + exit(1); } diff --git a/qdevices/qdevice-config.h b/qdevices/qdevice-config.h index 85816a26..d1435153 100644 --- a/qdevices/qdevice-config.h +++ b/qdevices/qdevice-config.h @@ -35,6 +35,8 @@ #ifndef _QDEVICE_CONFIG_H_ #define _QDEVICE_CONFIG_H_ +#include + #include #include @@ -47,10 +49,12 @@ extern "C" { * idea to change them as long as you are not 100% sure what you are doing. */ #define QDEVICE_LOCK_FILE LOCALSTATEDIR"/run/corosync-qdevice.pid" +#define QDEVICE_LOCAL_SOCKET_FILE LOCALSTATEDIR"/run/corosync-qdevice.sock" +#define QDEVICE_LOCAL_SOCKET_BACKLOG 10 #define QDEVICE_MAX_CS_TRY_AGAIN 10 -#define QDEVICE_PROGRAM_NAME "qdevice-net" +#define QDEVICE_PROGRAM_NAME "corosync-qdevice" #define QDEVICE_LOG_SUBSYS "QDEVICE" #define QDEVICE_LOG_DEFAULT_TO_STDERR 1 #define QDEVICE_LOG_DEFAULT_TO_SYSLOG 1 diff --git a/qdevices/qdevice-instance.h b/qdevices/qdevice-instance.h index 35e336f6..f3aa13c2 100644 --- a/qdevices/qdevice-instance.h +++ b/qdevices/qdevice-instance.h @@ -61,6 +61,8 @@ struct qdevice_instance { votequorum_handle_t votequorum_handle; int votequorum_poll_fd; + int local_socket_fd; + enum qdevice_model_type model_type; uint32_t node_id; diff --git a/qdevices/qdevice-local-socket.c b/qdevices/qdevice-local-socket.c new file mode 100644 index 00000000..0b228928 --- /dev/null +++ b/qdevices/qdevice-local-socket.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2015-2016 Red Hat, Inc. + * + * All rights reserved. + * + * Author: Jan Friesse (jfriesse@redhat.com) + * + * This software licensed under BSD license, the text of which follows: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the Red Hat, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "qdevice-config.h" +#include "qdevice-log.h" +#include "qdevice-local-socket.h" +#include "unix-socket.h" + +int +qdevice_local_socket_init(struct qdevice_instance *instance) +{ + int local_socket; + + local_socket = unix_socket_server_create(QDEVICE_LOCAL_SOCKET_FILE, 1, + QDEVICE_LOCAL_SOCKET_BACKLOG); + if (local_socket < 0) { + qdevice_log_err(LOG_ERR, "Can't create unix socket"); + return (-1); + } + + instance->local_socket_fd = local_socket; + + return (0); +} + +void +qdevice_local_socket_destroy(struct qdevice_instance *instance) +{ + + if (instance->local_socket_fd < 0) { + return ; + } + + if (close(instance->local_socket_fd) != 0) { + qdevice_log_err(LOG_WARNING, "Can't close unix socket"); + } + + instance->local_socket_fd = -1; + if (unlink(QDEVICE_LOCAL_SOCKET_FILE) != 0) { + qdevice_log_err(LOG_WARNING, "Can't unlink unix socket"); + } +} diff --git a/qdevices/qdevice-local-socket.h b/qdevices/qdevice-local-socket.h new file mode 100644 index 00000000..663d1b90 --- /dev/null +++ b/qdevices/qdevice-local-socket.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015-2016 Red Hat, Inc. + * + * All rights reserved. + * + * Author: Jan Friesse (jfriesse@redhat.com) + * + * This software licensed under BSD license, the text of which follows: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the Red Hat, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _QDEVICE_LOCAL_SOCKET_H_ +#define _QDEVICE_LOCAL_SOCKET_H_ + +#include "qdevice-instance.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct qdevice_local_socket { +}; + +extern int qdevice_local_socket_init(struct qdevice_instance *instance); + +extern void qdevice_local_socket_destroy(struct qdevice_instance *instance); + +#ifdef __cplusplus +} +#endif + +#endif /* _QDEVICE_LOCAL_SOCKET_H_ */ diff --git a/qdevices/qdevice-log.c b/qdevices/qdevice-log.c index 392fb42b..44fbe589 100644 --- a/qdevices/qdevice-log.c +++ b/qdevices/qdevice-log.c @@ -36,6 +36,8 @@ #include "qdevice-config.h" #include "utils.h" +static int qdevice_log_global_force_debug; + struct qdevice_log_syslog_names { const char *prio_name; int priority; @@ -271,6 +273,10 @@ qdevice_log_configure(struct qdevice_instance *instance) } strcat(log_format_stderr, log_format_syslog); + if (qdevice_log_global_force_debug) { + debug = 1; + } + /* * Finally reconfigure log system */ @@ -289,8 +295,10 @@ qdevice_log_configure(struct qdevice_instance *instance) } void -qdevice_log_init(struct qdevice_instance *instance) +qdevice_log_init(struct qdevice_instance *instance, int force_debug) { + qdevice_log_global_force_debug = force_debug; + qb_log_init(QDEVICE_PROGRAM_NAME, QDEVICE_LOG_DEFAULT_SYSLOG_FACILITY, QDEVICE_LOG_DEFAULT_SYSLOG_PRIORITY); diff --git a/qdevices/qdevice-log.h b/qdevices/qdevice-log.h index 5fe93b32..f1674249 100644 --- a/qdevices/qdevice-log.h +++ b/qdevices/qdevice-log.h @@ -49,7 +49,10 @@ extern "C" { #define qdevice_log_nss(priority, str) qdevice_log(priority, "%s (%d): %s", \ str, PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); -extern void qdevice_log_init(struct qdevice_instance *instance); +#define qdevice_log_err(priority, str) qdevice_log(priority, "%s (%d): %s", \ + str, errno, strerror(errno)); + +extern void qdevice_log_init(struct qdevice_instance *instance, int force_debug); extern void qdevice_log_configure(struct qdevice_instance *instance); diff --git a/qdevices/qdevice-model-net.c b/qdevices/qdevice-model-net.c index 896bf1e3..90b20218 100644 --- a/qdevices/qdevice-model-net.c +++ b/qdevices/qdevice-model-net.c @@ -32,9 +32,6 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ - -#include - #include #include "qdevice-model.h" @@ -225,8 +222,8 @@ qdevice_model_net_run(struct qdevice_instance *instance) " Can't update cast vote timer vote"); } - if (net_instance->disconnect_reason == - QDEVICE_NET_DISCONNECT_REASON_COROSYNC_CONNECTION_CLOSED) { + if (net_instance->disconnect_reason == QDEVICE_NET_DISCONNECT_REASON_COROSYNC_CONNECTION_CLOSED || + net_instance->disconnect_reason == QDEVICE_NET_DISCONNECT_REASON_LOCAL_SOCKET_CLOSED) { try_connect = 0; } diff --git a/qdevices/qdevice-net-disconnect-reason.h b/qdevices/qdevice-net-disconnect-reason.h index b387c75f..03ec296b 100644 --- a/qdevices/qdevice-net-disconnect-reason.h +++ b/qdevices/qdevice-net-disconnect-reason.h @@ -85,6 +85,9 @@ enum qdevice_net_disconnect_reason { /* Can't dispatch cmap or votequroum. This cannot be overwritten and always means end of qdevice-net */ QDEVICE_NET_DISCONNECT_REASON_COROSYNC_CONNECTION_CLOSED, + /* Local socket closed is reasult of sigint */ + QDEVICE_NET_DISCONNECT_REASON_LOCAL_SOCKET_CLOSED, + /* It was not possible to establish connection with qnetd */ QDEVICE_NET_DISCONNECT_REASON_CANT_CONNECT_TO_THE_SERVER, diff --git a/qdevices/qdevice-net-instance.c b/qdevices/qdevice-net-instance.c index 8a1acc8c..2db02f34 100644 --- a/qdevices/qdevice-net-instance.c +++ b/qdevices/qdevice-net-instance.c @@ -51,7 +51,7 @@ qdevice_net_instance_init(struct qdevice_net_instance *instance, size_t initial_ uint32_t sync_heartbeat_interval, uint32_t cast_vote_timer_interval, const char *host_addr, uint16_t host_port, const char *cluster_name, const struct tlv_tie_breaker *tie_breaker, uint32_t connect_timeout, - int force_ip_version, int cmap_fd, int votequorum_fd) + int force_ip_version, int cmap_fd, int votequorum_fd, int local_socket_fd) { memset(instance, 0, sizeof(*instance)); @@ -94,6 +94,11 @@ qdevice_net_instance_init(struct qdevice_net_instance *instance, size_t initial_ return (-1); } + if ((instance->local_socket_poll_fd = PR_CreateSocketPollFd(local_socket_fd)) == NULL) { + qdevice_log_nss(LOG_CRIT, "Can't create NSPR local socket poll fd"); + return (-1); + } + return (0); } @@ -136,6 +141,10 @@ qdevice_net_instance_destroy(struct qdevice_net_instance *instance) qdevice_log_nss(LOG_WARNING, "Unable to close votequorum connection fd"); } + if (PR_DestroySocketPollFd(instance->local_socket_poll_fd) != PR_SUCCESS) { + qdevice_log_nss(LOG_WARNING, "Unable to close local socket poll fd"); + } + return (0); } @@ -337,7 +346,8 @@ qdevice_net_instance_init_from_cmap(struct qdevice_instance *instance) heartbeat_interval, sync_heartbeat_interval, cast_vote_timer_interval, host_addr, host_port, cluster_name, &tie_breaker, connect_timeout, force_ip_version, - instance->cmap_poll_fd, instance->votequorum_poll_fd) == -1) { + instance->cmap_poll_fd, instance->votequorum_poll_fd, + instance->local_socket_fd) == -1) { qdevice_log(LOG_ERR, "Can't initialize qdevice-net instance"); goto error_free_instance; } diff --git a/qdevices/qdevice-net-instance.h b/qdevices/qdevice-net-instance.h index 4a0989d1..3a8194c2 100644 --- a/qdevices/qdevice-net-instance.h +++ b/qdevices/qdevice-net-instance.h @@ -94,6 +94,7 @@ struct qdevice_net_instance { int schedule_disconnect; PRFileDesc *votequorum_poll_fd; PRFileDesc *cmap_poll_fd; + PRFileDesc *local_socket_poll_fd; struct tlv_ring_id last_sent_ring_id; struct tlv_tie_breaker tie_breaker; void *algorithm_data; @@ -112,7 +113,7 @@ extern int qdevice_net_instance_init(struct qdevice_net_instance *instance, uint32_t sync_heartbeat_interval, uint32_t cast_vote_timer_interval, const char *host_addr, uint16_t host_port, const char *cluster_name, const struct tlv_tie_breaker *tie_breaker, uint32_t connect_timeout, int force_ip_version, - int cmap_fd, int votequorum_fd); + int cmap_fd, int votequorum_fd, int local_socket_fd); extern void qdevice_net_instance_clean(struct qdevice_net_instance *instance); diff --git a/qdevices/qdevice-net-poll.c b/qdevices/qdevice-net-poll.c index f7ac6325..b757b32c 100644 --- a/qdevices/qdevice-net-poll.c +++ b/qdevices/qdevice-net-poll.c @@ -42,6 +42,7 @@ enum qdevice_net_poll_pfd { QDEVICE_NET_POLL_VOTEQUORUM, QDEVICE_NET_POLL_CMAP, + QDEVICE_NET_POLL_LOCAL_SOCKET, QDEVICE_NET_POLL_SOCKET, QDEVICE_NET_POLL_MAX_PFDS }; @@ -142,6 +143,13 @@ qdevice_net_poll_err_socket(struct qdevice_net_instance *instance, const PRPollD } } +static void +qdevice_net_poll_read_local_socket(struct qdevice_net_instance *instance) +{ + +// qdevice_log(LOG_DEBUG, "READ ON LOCAL SOCKET"); +} + int qdevice_net_poll(struct qdevice_net_instance *instance) { @@ -160,6 +168,10 @@ qdevice_net_poll(struct qdevice_net_instance *instance) pfds[QDEVICE_NET_POLL_CMAP].in_flags = PR_POLL_READ; no_pfds++; + pfds[QDEVICE_NET_POLL_LOCAL_SOCKET].fd = instance->local_socket_poll_fd; + pfds[QDEVICE_NET_POLL_LOCAL_SOCKET].in_flags = PR_POLL_READ; + no_pfds++; + if (instance->state == QDEVICE_NET_INSTANCE_STATE_WAITING_CONNECT && !instance->non_blocking_client.destroyed) { pfds[QDEVICE_NET_POLL_SOCKET].fd = instance->non_blocking_client.socket; @@ -190,6 +202,9 @@ qdevice_net_poll(struct qdevice_net_instance *instance) case QDEVICE_NET_POLL_CMAP: qdevice_net_poll_read_cmap(instance); break; + case QDEVICE_NET_POLL_LOCAL_SOCKET: + qdevice_net_poll_read_local_socket(instance); + break; default: qdevice_log(LOG_CRIT, "Unhandled read on poll descriptor %u", i); exit(1); @@ -216,6 +231,18 @@ qdevice_net_poll(struct qdevice_net_instance *instance) case QDEVICE_NET_POLL_SOCKET: qdevice_net_poll_err_socket(instance, &pfds[i]); break; + case QDEVICE_NET_POLL_LOCAL_SOCKET: + if (pfds[i].out_flags != PR_POLL_NVAL) { + qdevice_log(LOG_CRIT, "POLLERR (%u) on local socket", + pfds[i].out_flags); + exit(1); + } else { + qdevice_log(LOG_DEBUG, "Local socket is closed"); + instance->schedule_disconnect = 1; + instance->disconnect_reason = + QDEVICE_NET_DISCONNECT_REASON_LOCAL_SOCKET_CLOSED; + } + break; default: qdevice_log(LOG_CRIT, "Unhandled error on poll descriptor %u", i); exit(1); diff --git a/qdevices/qnet-config.h b/qdevices/qnet-config.h index c23d48bb..f47e3f39 100644 --- a/qdevices/qnet-config.h +++ b/qdevices/qnet-config.h @@ -35,6 +35,8 @@ #ifndef _QNET_CONFIG_H_ #define _QNET_CONFIG_H_ +#include + #include "tlv.h" #ifdef __cplusplus diff --git a/qdevices/qnetd-log.h b/qdevices/qnetd-log.h index d5610d65..1121414d 100644 --- a/qdevices/qnetd-log.h +++ b/qdevices/qnetd-log.h @@ -49,6 +49,9 @@ extern "C" { #define qnetd_log_nss(priority, str) qnetd_log_printf(priority, "%s (%d): %s", \ str, PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); +#define qnetd_log_err(priority, str) qnetd_log_printf(priority, "%s (%d): %s", \ + str, errno, strerror(errno)) + extern void qnetd_log_init(int target); extern void qnetd_log_printf(int priority, const char *format, ...) diff --git a/qdevices/unix-socket.c b/qdevices/unix-socket.c new file mode 100644 index 00000000..e7535af3 --- /dev/null +++ b/qdevices/unix-socket.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2015-2016 Red Hat, Inc. + * + * All rights reserved. + * + * Author: Jan Friesse (jfriesse@redhat.com) + * + * This software licensed under BSD license, the text of which follows: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the Red Hat, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include +#include +#include + +#include "unix-socket.h" + +static int +unix_socket_set_non_blocking(int fd) +{ + int flags; + + flags = fcntl(fd, F_GETFL, NULL); + + if (flags < 0) { + return (-1); + } + + flags |= O_NONBLOCK; + if (fcntl(fd, F_SETFL, flags) < 0) { + return (-1); + } + + return (0); +} + +int +unix_socket_server_create(const char *path, int non_blocking, int backlog) +{ + int s; + struct sockaddr_un sun; + + if (strlen(path) >= sizeof(sun.sun_path)) { + errno = ENAMETOOLONG; + return (-1); + } + + if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { + return (-1); + } + + memset(&sun, 0, sizeof(sun)); + sun.sun_family = AF_UNIX; + + strncpy(sun.sun_path, path, sizeof(sun.sun_path)); + unlink(path); + if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) != 0) { + close(s); + + return (-1); + } + + if (non_blocking) { + if (unix_socket_set_non_blocking(s) != 0) { + close(s); + + return (-1); + } + } + + if (listen(s, backlog) != 0) { + close(s); + + return (-1); + } + + return (s); +} diff --git a/qdevices/unix-socket.h b/qdevices/unix-socket.h new file mode 100644 index 00000000..2e71e450 --- /dev/null +++ b/qdevices/unix-socket.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015-2016 Red Hat, Inc. + * + * All rights reserved. + * + * Author: Jan Friesse (jfriesse@redhat.com) + * + * This software licensed under BSD license, the text of which follows: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the Red Hat, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _UNIX_SOCKET_H_ +#define _UNIX_SOCKET_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int unix_socket_server_create(const char *path, int non_blocking, int backlog); + +#ifdef __cplusplus +} +#endif + +#endif /* _UNIX_SOCKET_H_ */ diff --git a/qdevices/utils.c b/qdevices/utils.c index 00205260..0fec7183 100644 --- a/qdevices/utils.c +++ b/qdevices/utils.c @@ -69,18 +69,17 @@ utils_parse_bool_str(const char *str) } int -utils_flock(const char *lockfile, pid_t pid, - void (*log_printf)(int priority, const char *format, ...)) +utils_flock(const char *lockfile, pid_t pid, int *another_instance_running) { struct flock lock; char pid_s[17]; int fd_flag; int lf; + *another_instance_running = 0; + lf = open(lockfile, O_WRONLY | O_CREAT, 0640); if (lf == -1) { - log_printf(LOG_ERR, "Cannot create lock file. Error was %s", strerror(errno)); - return (-1); } @@ -96,18 +95,16 @@ retry_fcntl: break; case EAGAIN: case EACCES: - log_printf(LOG_ERR, "Another instance is already running."); + *another_instance_running = 1; goto error_close; break; default: - log_printf(LOG_ERR, "Cannot aquire lock. Error was %s", strerror(errno)); goto error_close; break; } } if (ftruncate(lf, 0) == -1) { - log_printf(LOG_ERR, "Cannot truncate lock file. Error was %s", strerror(errno)); goto error_close_unlink; } @@ -119,21 +116,15 @@ retry_write: if (errno == EINTR) { goto retry_write; } else { - log_printf(LOG_ERR, "Cannot write pid to lock file. Error was %s", - strerror(errno)); goto error_close_unlink; } } if ((fd_flag = fcntl(lf, F_GETFD, 0)) == -1) { - log_printf(LOG_ERR, "Cannot get close-on exec flag for lock file. Error was %s", - strerror(errno)); goto error_close_unlink; } fd_flag |= FD_CLOEXEC; if (fcntl(lf, F_SETFD, fd_flag) == -1) { - log_printf(LOG_ERR, "Cannot set close-on-exec flag for lock file. Error was %s", - strerror(errno)); goto error_close_unlink; } diff --git a/qdevices/utils.h b/qdevices/utils.h index b1959d08..1a243db2 100644 --- a/qdevices/utils.h +++ b/qdevices/utils.h @@ -45,8 +45,7 @@ extern "C" { extern int utils_parse_bool_str(const char *str); extern int utils_flock(const char *lockfile, pid_t pid, - void (*log_printf)(int priority, const char *format, ...) - __attribute__((__format__(__printf__, 2, 3)))); + int *another_instance_running); extern void utils_tty_detach(void);