Преглед изворни кода

udpu: Drop packets from unlisted IPs

This feature allows corosync to block packets received from unknown
nodes (nodes with IP address which is not in the nodelist). This is
mainly for situations when "forgotten" node is booted and tries to join
cluster which already removed such node from configuration. Another use
case is to allow atomic reconfiguration and rejoin of two separate
clusters.

Signed-off-by: Jan Friesse <jfriesse@redhat.com>
Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
Jan Friesse пре 6 година
родитељ
комит
72737d3929
6 измењених фајлова са 128 додато и 2 уклоњено
  1. 54 1
      exec/totemconfig.c
  2. 27 0
      exec/totemip.c
  3. 34 0
      exec/totemudpu.c
  4. 2 0
      include/corosync/totem/totem.h
  5. 2 0
      include/corosync/totem/totemip.h
  6. 9 1
      man/corosync.conf.5

+ 54 - 1
exec/totemconfig.c

@@ -79,6 +79,7 @@
 #define WINDOW_SIZE				50
 #define MAX_MESSAGES				17
 #define MISS_COUNT_CONST			5
+#define BLOCK_UNLISTED_IPS			1
 
 /* These currently match the defaults in libknet.h */
 #define KNET_PING_INTERVAL                      1000
@@ -138,6 +139,8 @@ static void *totem_get_param_by_name(struct totem_config *totem_config, const ch
 		return &totem_config->knet_compression_level;
 	if (strcmp(param_name, "totem.knet_compression_model") == 0)
 		return &totem_config->knet_compression_model;
+	if (strcmp(param_name, "totem.block_unlisted_ips") == 0)
+		return &totem_config->block_unlisted_ips;
 
 	return NULL;
 }
@@ -235,6 +238,55 @@ static void totem_volatile_config_set_string_value (struct totem_config *totem_c
 	icmap_set_string(runtime_key_name, (char *)*config_value);
 }
 
+/*
+ * Read string value stored in key_name from icmap, use it as a boolean (yes/no) type, convert it
+ * to integer value (1/0) and store into totem_config.
+ *
+ * If key is not found or key_name == delete_key default value is used
+ * and stored into totem_config.
+ */
+static void totem_volatile_config_set_boolean_value (struct totem_config *totem_config,
+	const char *key_name, const char *deleted_key, unsigned int default_value)
+{
+	char runtime_key_name[ICMAP_KEYNAME_MAXLEN];
+	char *str;
+	int val;
+
+	str = NULL;
+	val = default_value;
+
+	if ((deleted_key != NULL && strcmp(deleted_key, key_name) == 0) ||
+	    (icmap_get_string(key_name, &str) != CS_OK)) {
+		/*
+		 * Do nothing. str is NULL (icmap_get_string ether not called or
+		 * not changed str).
+		 */
+	} else {
+		if (strcmp(str, "yes") == 0) {
+			val = 1;
+		} else if (strcmp(str, "no") == 0) {
+			val = 0;
+		}
+		free(str);
+	}
+
+	/*
+	 * Store totem_config value to cmap runtime section
+	 */
+	if (strlen("runtime.config.") + strlen(key_name) >= ICMAP_KEYNAME_MAXLEN) {
+		/*
+		 * This shouldn't happen
+		 */
+		return ;
+	}
+
+	strcpy(runtime_key_name, "runtime.config.");
+	strcat(runtime_key_name, key_name);
+
+	*(uint32_t *)totem_get_param_by_name(totem_config, key_name) = val;
+
+	icmap_set_uint32(runtime_key_name, val);
+}
 
 /*
  * Read and validate config values from cmap and store them into totem_config. If key doesn't exists,
@@ -302,7 +354,8 @@ static void totem_volatile_config_read (struct totem_config *totem_config, const
 
 	totem_volatile_config_set_string_value(totem_config, "totem.knet_compression_model", deleted_key, "none");
 
-
+	totem_volatile_config_set_boolean_value(totem_config, "totem.block_unlisted_ips", deleted_key,
+	    BLOCK_UNLISTED_IPS);
 }
 
 static int totem_volatile_config_validate (

+ 27 - 0
exec/totemip.c

@@ -92,6 +92,33 @@ int totemip_equal(const struct totem_ip_address *addr1,
 
 }
 
+int totemip_sa_equal(const struct totem_ip_address *totem_ip,
+	const struct sockaddr *sa)
+{
+	int res;
+
+	res = -1;
+
+	if (totem_ip->family != sa->sa_family) {
+		return 0;
+	}
+
+	switch (totem_ip->family) {
+	case AF_INET:
+		res = (memcmp(totem_ip->addr,
+		    &((const struct sockaddr_in *)sa)->sin_addr, sizeof(struct in_addr)) == 0);
+		break;
+	case AF_INET6:
+		res =  (memcmp(totem_ip->addr,
+		    &((const struct sockaddr_in6 *)sa)->sin6_addr, sizeof(struct in6_addr)) == 0);
+		break;
+	default:
+		assert(0);
+	}
+
+	return (res);
+}
+
 /* Copy a totem_ip_address */
 void totemip_copy(struct totem_ip_address *addr1,
 		  const struct totem_ip_address *addr2)

+ 34 - 0
exec/totemudpu.c

@@ -444,6 +444,32 @@ int totemudpu_finalize (
 	return (res);
 }
 
+static struct totemudpu_member *find_member_by_sockaddr(
+	const void *udpu_context,
+	const struct sockaddr *sa)
+{
+	struct qb_list_head *list;
+	struct totemudpu_member *member;
+	struct totemudpu_member *res_member;
+	const struct totemudpu_instance *instance = (const struct totemudpu_instance *)udpu_context;
+
+	res_member = NULL;
+
+	qb_list_for_each(list, &(instance->member_list)) {
+		member = qb_list_entry (list,
+			struct totemudpu_member,
+			list);
+
+		if (totemip_sa_equal(&member->member, sa)) {
+			res_member = member;
+			break ;
+		}
+	}
+
+	return (res_member);
+}
+
+
 static int net_deliver_fn (
 	int fd,
 	int revents,
@@ -513,6 +539,14 @@ static int net_deliver_fn (
 		return (0);
 	}
 
+	if (instance->totem_config->block_unlisted_ips &&
+	    find_member_by_sockaddr(instance, (const struct sockaddr *)&system_from) == NULL) {
+		log_printf(instance->totemudpu_log_level_debug, "Packet rejected from %s",
+		    totemip_sa_print((const struct sockaddr *)&system_from));
+
+		return (0);
+	}
+
 	iovec->iov_len = bytes_received;
 
 	/*

+ 2 - 0
include/corosync/totem/totem.h

@@ -233,6 +233,8 @@ struct totem_config {
 
 	enum totem_ip_version_enum ip_version;
 
+	unsigned int block_unlisted_ips;
+
 	void (*totem_memb_ring_id_create_or_load) (
 	    struct memb_ring_id *memb_ring_id,
 	    unsigned int nodeid);

+ 2 - 0
include/corosync/totem/totemip.h

@@ -86,6 +86,8 @@ struct totem_ip_if_address
 
 extern int totemip_equal(const struct totem_ip_address *addr1,
 			 const struct totem_ip_address *addr2);
+extern int totemip_sa_equal(const struct totem_ip_address *totem_ip,
+			const struct sockaddr *sa);
 extern int totemip_compare(const void *a, const void *b);
 extern int totemip_is_mcast(struct totem_ip_address *addr);
 extern void totemip_copy(struct totem_ip_address *addr1,

+ 9 - 1
man/corosync.conf.5

@@ -32,7 +32,7 @@
 .\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 .\" * THE POSSIBILITY OF SUCH DAMAGE.
 .\" */
-.TH COROSYNC_CONF 5 2019-04-11 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
+.TH COROSYNC_CONF 5 2019-05-24 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
 .SH NAME
 corosync.conf - corosync executive configuration file
 
@@ -571,6 +571,14 @@ knet_enable_access_lists
 Allow knet to drop packets from IP addresses that are not known to corosync.
 Value is 0 (off) and 1 (on). Default: 0.
 
+.TP
+block_unlisted_ips
+Allow UDPU to drop packets from IP addresses that are not known
+(nodes which don't exist in the nodelist) to corosync.
+Value is yes or no.
+
+The default value is yes.
+
 .PP
 Within the
 .B logging