Kaynağa Gözat

qnetd: Some small improvements

Signed-off-by: Jan Friesse <jfriesse@redhat.com>
Jan Friesse 10 yıl önce
ebeveyn
işleme
21911d3906

+ 2 - 2
qdevices/Makefile.am

@@ -43,14 +43,14 @@ corosync_qnetd_SOURCES	= corosync-qnetd.c dynar.c msg.c msgio.c nss-sock.c  \
 			    qnetd-poll-array.c timer-list.c tlv.c send-buffer-list.c \
 			    node-list.c qnetd-algo-test.c qnetd-algorithm.c \
 			    qnetd-algo-ffsplit.c qnetd-cluster-list.c qnetd-client-send.c \
-			    qnetd-algo-2nodelms.c qnetd-algo-lms.c
+			    qnetd-algo-2nodelms.c qnetd-algo-lms.c utils.c
 
 corosync_qdevice_net_SOURCES	= corosync-qdevice-net.c dynar.c msg.c msgio.c nss-sock.c  \
 			    qnetd-client.c qnetd-client-list.c qnetd-log.c \
 			    qnetd-poll-array.c timer-list.c tlv.c send-buffer-list.c \
 			    node-list.c qdevice-net-send.c qdevice-net-cmap.c \
 			    qdevice-net-votequorum.c qdevice-net-instance.c \
-			    qdevice-net-cast-vote-timer.c
+			    qdevice-net-cast-vote-timer.c utils.c
 
 corosync_qnetd_CFLAGS		= $(nss_CFLAGS)
 corosync_qnetd_LDADD		= $(nss_LIBS)

+ 2 - 23
qdevices/corosync-qdevice-net.c

@@ -71,6 +71,7 @@
 #include "qdevice-net-send.h"
 #include "qdevice-net-votequorum.h"
 #include "qdevice-net-cast-vote-timer.h"
+#include "utils.h"
 
 static SECStatus
 qdevice_net_nss_bad_cert_hook(void *arg, PRFileDesc *fd) {
@@ -1018,28 +1019,6 @@ qdevice_net_poll(struct qdevice_net_instance *instance)
 	return (0);
 }
 
-
-/*
- * Check string to value on, off, yes, no, 0, 1. Return 1 if value is on, yes or 1, 0 if
- * value is off, no or 0 and -1 otherwise.
- */
-static int
-qdevice_net_parse_bool_str(const char *str)
-{
-
-	if (strcasecmp(str, "yes") == 0 ||
-	    strcasecmp(str, "on") == 0 ||
-	    strcasecmp(str, "1") == 0) {
-		return (1);
-	} else if (strcasecmp(str, "no") == 0 ||
-	    strcasecmp(str, "off") == 0 ||
-	    strcasecmp(str, "0") == 0) {
-		return (0);
-	}
-
-	return (-1);
-}
-
 static void
 qdevice_net_instance_init_from_cmap(struct qdevice_net_instance *instance,
     cmap_handle_t cmap_handle)
@@ -1082,7 +1061,7 @@ qdevice_net_instance_init_from_cmap(struct qdevice_net_instance *instance,
 	 * Check tls
 	 */
 	if (cmap_get_string(cmap_handle, "quorum.device.net.tls", &str) == CS_OK) {
-		if ((i = qdevice_net_parse_bool_str(str)) == -1) {
+		if ((i = utils_parse_bool_str(str)) == -1) {
 			free(str);
 			errx(1, "quorum.device.net.tls value is not valid.");
 		}

+ 73 - 8
qdevices/corosync-qnetd.c

@@ -48,6 +48,7 @@
 #include <keyhi.h>
 #include <syslog.h>
 #include <signal.h>
+#include <errno.h>
 
 #include "qnet-config.h"
 #include "msg.h"
@@ -63,6 +64,7 @@
 #include "qnetd-algorithm.h"
 #include "qnetd-cluster-list.h"
 #include "qnetd-client-send.h"
+#include "utils.h"
 
 struct qnetd_instance {
 	struct {
@@ -73,6 +75,7 @@ struct qnetd_instance {
 	size_t max_client_receive_size;
 	size_t max_client_send_buffers;
 	size_t max_client_send_size;
+	size_t max_clients;
 	struct qnetd_client_list clients;
 	struct qnetd_cluster_list clusters;
 	struct qnetd_poll_array poll_array;
@@ -1180,6 +1183,15 @@ qnetd_client_accept(struct qnetd_instance *instance)
 		return (-1);
 	}
 
+	if (instance->max_clients != 0 &&
+	    qnetd_client_list_no_clients(&instance->clients) >= instance->max_clients) {
+		qnetd_log(LOG_ERR, "Maximum clients reached. Not accepting connection");
+
+		PR_Close(client_socket);
+
+		return (-1);
+	}
+
 	client = qnetd_client_list_add(&instance->clients, client_socket, &client_addr,
 	    instance->max_client_receive_size, instance->max_client_send_buffers,
 	    instance->max_client_send_size);
@@ -1282,7 +1294,7 @@ qnetd_poll(struct qnetd_instance *instance)
 						 * Poll ERR on listening socket is fatal error.
 						 * POLL_NVAL is used as a signal to quit poll loop.
 						 */
-						qnetd_log(LOG_CRIT, "POLL_ERR (%u) on listening "
+						 qnetd_log(LOG_CRIT, "POLL_ERR (%u) on listening "
 						    "socket", pfds[i].out_flags);
 					} else {
 						qnetd_log(LOG_DEBUG, "Listening socket is closed");
@@ -1330,7 +1342,7 @@ qnetd_instance_init_certs(struct qnetd_instance *instance)
 static int
 qnetd_instance_init(struct qnetd_instance *instance, size_t max_client_receive_size,
     size_t max_client_send_buffers, size_t max_client_send_size,
-    enum tlv_tls_supported tls_supported, int tls_client_cert_required)
+    enum tlv_tls_supported tls_supported, int tls_client_cert_required, size_t max_clients)
 {
 
 	memset(instance, 0, sizeof(*instance));
@@ -1346,6 +1358,8 @@ qnetd_instance_init(struct qnetd_instance *instance, size_t max_client_receive_s
 	instance->tls_supported = tls_supported;
 	instance->tls_client_cert_required = tls_client_cert_required;
 
+	instance->max_clients = max_clients;
+
 	return (0);
 }
 
@@ -1380,6 +1394,15 @@ signal_int_handler(int sig)
 	PR_Close(global_server_socket);
 }
 
+static void
+signal_term_handler(int sig)
+{
+
+	qnetd_log(LOG_DEBUG, "SIGTERM received - closing server socket");
+
+	PR_Close(global_server_socket);
+}
+
 static void
 signal_handlers_register(void)
 {
@@ -1390,28 +1413,40 @@ signal_handlers_register(void)
 	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 [-df] [-l listen_addr] [-p listen_port]\n", QNETD_PROGRAM_NAME);
+	printf("usage: %s [-df] [-l listen_addr] [-p listen_port] [-s tls]\n", QNETD_PROGRAM_NAME);
+	printf("%14s[-c client_cert_required] [-m max_clients]\n", "");
 }
 
 static void
 cli_parse(int argc, char * const argv[], char **host_addr, uint16_t *host_port, int *foreground,
-    int *debug_log)
+    int *debug_log, enum tlv_tls_supported *tls_supported, int *client_cert_required,
+    size_t *max_clients)
 {
 	int ch;
 	char *ep;
+	long long int tmpll;
 
 	*host_addr = NULL;
 	*host_port = QNETD_DEFAULT_HOST_PORT;
 	*foreground = 0;
 	*debug_log = 0;
+	*tls_supported = QNETD_DEFAULT_TLS_SUPPORTED;
+	*client_cert_required = QNETD_DEFAULT_TLS_CLIENT_CERT_REQUIRED;
+	*max_clients = QNETD_DEFAULT_MAX_CLIENTS;
 
-	while ((ch = getopt(argc, argv, "fdl:p:")) != -1) {
+	while ((ch = getopt(argc, argv, "fdc:l:m:p:s:")) != -1) {
 		switch (ch) {
 		case 'f':
 			*foreground = 1;
@@ -1419,15 +1454,40 @@ cli_parse(int argc, char * const argv[], char **host_addr, uint16_t *host_port,
 		case 'd':
 			*debug_log = 1;
 			break;
+		case 'c':
+			if ((*client_cert_required = utils_parse_bool_str(optarg)) == -1) {
+				errx(1, "client_cert_required should be on/yes/1, off/no/0");
+			}
+			break;
 		case 'l':
 			*host_addr = strdup(optarg);
 			break;
+		case 'm':
+			errno = 0;
+
+			tmpll = strtoll(optarg, &ep, 10);
+			if (tmpll < 0 || errno != 0 || *ep != '\0') {
+				errx(1, "max clients value %s is invalid", optarg);
+			}
+			*max_clients = (size_t)tmpll;
+			break;
 		case 'p':
 			*host_port = strtol(optarg, &ep, 10);
 			if (*host_port <= 0 || *host_port > ((uint16_t)~0) || *ep != '\0') {
 				errx(1, "host port must be in range 0-65535");
 			}
 			break;
+		case 's':
+			if (strcasecmp(optarg, "on") == 0) {
+				*tls_supported = QNETD_DEFAULT_TLS_SUPPORTED;
+			} else if (strcasecmp(optarg, "off") == 0) {
+				*tls_supported = TLV_TLS_UNSUPPORTED;
+			} else if (strcasecmp(optarg, "req") == 0) {
+				*tls_supported = TLV_TLS_REQUIRED;
+			} else {
+				errx(1, "tls must be one of on, off, req");
+			}
+			break;
 		case '?':
 			usage();
 			exit(1);
@@ -1444,8 +1504,12 @@ main(int argc, char *argv[])
 	uint16_t host_port;
 	int foreground;
 	int debug_log;
+	enum tlv_tls_supported tls_supported;
+	int client_cert_required;
+	size_t max_clients;
 
-	cli_parse(argc, argv, &host_addr, &host_port, &foreground, &debug_log);
+	cli_parse(argc, argv, &host_addr, &host_port, &foreground, &debug_log, &tls_supported,
+	    &client_cert_required, &max_clients);
 
 	if (foreground) {
 		qnetd_log_init(QNETD_LOG_TARGET_STDERR);
@@ -1455,7 +1519,8 @@ main(int argc, char *argv[])
 
 	qnetd_log_set_debug(debug_log);
 
-	if (nss_sock_init_nss((char *)QNETD_NSS_DB_DIR) != 0) {
+	if (nss_sock_init_nss((tls_supported != TLV_TLS_UNSUPPORTED ?
+	    (char *)QNETD_NSS_DB_DIR : NULL)) != 0) {
 		qnetd_err_nss();
 	}
 
@@ -1466,7 +1531,7 @@ main(int argc, char *argv[])
 
 	if (qnetd_instance_init(&instance, QNETD_MAX_CLIENT_RECEIVE_SIZE,
 	    QNETD_MAX_CLIENT_SEND_BUFFERS, QNETD_MAX_CLIENT_SEND_SIZE,
-	    QNETD_TLS_SUPPORTED, QNETD_TLS_CLIENT_CERT_REQUIRED) == -1) {
+	    tls_supported, client_cert_required, max_clients) == -1) {
 		errx(1, "Can't initialize qnetd");
 	}
 	instance.host_addr = host_addr;

+ 3 - 2
qdevices/qnet-config.h

@@ -50,12 +50,13 @@ extern "C" {
 #define QNETD_MAX_CLIENT_SEND_BUFFERS		10
 #define QNETD_MAX_CLIENT_SEND_SIZE		(1 << 15)
 #define QNETD_MAX_CLIENT_RECEIVE_SIZE		(1 << 15)
+#define QNETD_DEFAULT_MAX_CLIENTS		0
 
 #define QNETD_NSS_DB_DIR			COROSYSCONFDIR "/qdevice/net/qnetd/nssdb"
 #define QNETD_CERT_NICKNAME			"QNetd Cert"
 
-#define QNETD_TLS_SUPPORTED			TLV_TLS_SUPPORTED
-#define QNETD_TLS_CLIENT_CERT_REQUIRED		1
+#define QNETD_DEFAULT_TLS_SUPPORTED		TLV_TLS_SUPPORTED
+#define QNETD_DEFAULT_TLS_CLIENT_CERT_REQUIRED	1
 
 #define QNETD_HEARTBEAT_INTERVAL_MIN		1000
 #define QNETD_HEARTBEAT_INTERVAL_MAX		200000

+ 15 - 0
qdevices/qnetd-client-list.c

@@ -93,3 +93,18 @@ qnetd_client_list_del(struct qnetd_client_list *client_list, struct qnetd_client
 	qnetd_client_destroy(client);
 	free(client);
 }
+
+size_t
+qnetd_client_list_no_clients(struct qnetd_client_list *client_list)
+{
+	size_t res;
+	struct qnetd_client *client;
+
+	res = 0;
+
+	TAILQ_FOREACH(client, client_list, entries) {
+		res++;
+	}
+
+	return (res);
+}

+ 2 - 0
qdevices/qnetd-client-list.h

@@ -57,6 +57,8 @@ extern void			 qnetd_client_list_free(struct qnetd_client_list *client_list);
 extern void			 qnetd_client_list_del(struct qnetd_client_list *client_list,
     struct qnetd_client *client);
 
+extern size_t			 qnetd_client_list_no_clients(struct qnetd_client_list *client_list);
+
 #ifdef __cplusplus
 }
 #endif

+ 63 - 0
qdevices/utils.c

@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015 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 <sys/types.h>
+#include <arpa/inet.h>
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "utils.h"
+
+/*
+ * Check string to value on, off, yes, no, 0, 1. Return 1 if value is on, yes or 1, 0 if
+ * value is off, no or 0 and -1 otherwise.
+ */
+int
+utils_parse_bool_str(const char *str)
+{
+
+	if (strcasecmp(str, "yes") == 0 ||
+	    strcasecmp(str, "on") == 0 ||
+	    strcasecmp(str, "1") == 0) {
+		return (1);
+	} else if (strcasecmp(str, "no") == 0 ||
+	    strcasecmp(str, "off") == 0 ||
+	    strcasecmp(str, "0") == 0) {
+		return (0);
+	}
+
+	return (-1);
+}

+ 51 - 0
qdevices/utils.h

@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015 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 _UTILS_H_
+#define _UTILS_H_
+
+#include <sys/types.h>
+#include <inttypes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int		utils_parse_bool_str(const char *str);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UTILS_H_ */