Просмотр исходного кода

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 лет назад
Родитель
Сommit
c652ee0df8
6 измененных файлов с 132 добавлено и 1 удалено
  1. 55 0
      exec/totemconfig.c
  2. 27 0
      exec/totemip.c
  3. 37 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

+ 55 - 0
exec/totemconfig.c

@@ -77,6 +77,7 @@
 #define RRP_PROBLEM_COUNT_THRESHOLD_DEFAULT	10
 #define RRP_PROBLEM_COUNT_THRESHOLD_MIN		2
 #define RRP_AUTORECOVERY_CHECK_TIMEOUT		1000
+#define BLOCK_UNLISTED_IPS			1
 
 #define DEFAULT_PORT				5405
 
@@ -130,6 +131,8 @@ static uint32_t *totem_get_param_by_name(struct totem_config *totem_config, cons
 		return &totem_config->max_messages;
 	if (strcmp(param_name, "totem.miss_count_const") == 0)
 		return &totem_config->miss_count_const;
+	if (strcmp(param_name, "totem.block_unlisted_ips") == 0)
+		return &totem_config->block_unlisted_ips;
 
 	return NULL;
 }
@@ -166,6 +169,55 @@ static void totem_volatile_config_set_value (struct totem_config *totem_config,
 	icmap_set_uint32(runtime_key_name, *totem_get_param_by_name(totem_config, key_name));
 }
 
+/*
+ * 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);
+
+	*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,
@@ -238,6 +290,9 @@ static void totem_volatile_config_read (struct totem_config *totem_config, const
 	    RRP_AUTORECOVERY_CHECK_TIMEOUT, 0);
 
 	totem_volatile_config_set_value(totem_config, "totem.heartbeat_failures_allowed", deleted_key, 0, 1);
+
+	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

@@ -91,6 +91,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)

+ 37 - 0
exec/totemudpu.c

@@ -497,6 +497,35 @@ int totemudpu_finalize (
 	return (res);
 }
 
+static struct totemudpu_member *find_member_by_sockaddr(
+	const void *udpu_context,
+	const struct sockaddr *sa)
+{
+	struct 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;
+
+	for (list = instance->member_list.next;
+		list != &instance->member_list;
+		list = list->next) {
+
+		member = 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,
@@ -567,6 +596,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);
+	}
+
 	/*
 	 * Authenticate and if authenticated, decrypt datagram
 	 */

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

@@ -191,6 +191,8 @@ struct totem_config {
 
 	int ip_version;
 
+	unsigned int block_unlisted_ips;
+
 	void (*totem_memb_ring_id_create_or_load) (
 	    struct memb_ring_id *memb_ring_id,
 	    const struct totem_ip_address *addr);

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

@@ -79,6 +79,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 2012-10-10 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
+.TH COROSYNC_CONF 5 2019-05-23 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
 .SH NAME
 corosync.conf - corosync executive configuration file
 
@@ -513,6 +513,14 @@ auto-recovered.
 
 The default is 1000 milliseconds.
 
+.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