/*--------------------------------------------------------------------
 * FILE:
 *     pool_auth.c
 *
 * NOTE:
 *     authenticaton stuff
 *
 * Portions Copyright (c) 2003-2006, Atsushi Mitani
 * Portions Copyright (c) 2003-2006, Tatsuo Ishii
 *--------------------------------------------------------------------
 */
/*
 * Permission to use, copy, modify, and distribute this software and
 * its documentation for any purpose and without fee is hereby
 * granted, provided that the above copyright notice appear in all
 * copies and that both that copyright notice and this permission
 * notice appear in supporting documentation, and that the name of the
 * author not be used in advertising or publicity pertaining to
 * distribution of the software without specific, written prior
 * permission. The author makes no representations about the
 * suitability of this software for any purpose.  It is provided "as
 * is" without express or implied warranty.
 *
*/
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/param.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include <sys/time.h>
#include <stdio.h>
#include "replicate_com.h"
#include "pglb.h"

int pool_do_auth(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *cp);
int pool_do_reauth(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *cp);
int pool_read_message_length(POOL_CONNECTION_POOL *cp);
signed char pool_read_kind(POOL_CONNECTION_POOL *cp);

static POOL_STATUS pool_send_auth_ok(POOL_CONNECTION *frontend, int pid, int key, int protoMajor);
static int do_clear_text_password(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, int protoMajor);
static int do_crypt(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, int protoMajor);
static int do_md5(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, int protoMajor);

/*
* do authentication against backend. if success return 0 otherwise non 0.
*/
int pool_do_auth(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *cp)
{
	char * func = "pool_do_auth()";
	int status;
	signed char kind;
	int pid, pid1;
	int key, key1;
	int protoMajor;
	int length;

	protoMajor = MAJOR(cp);

	kind = pool_read_kind(cp);
	if (kind < 0)
	{
		return -1;
	}

	/* error response? */
	if (kind == 'E')
	{
		/* we assume error response at this stage is likely version
		 * protocol mismatch (v3 frontend vs. v2 backend). So we throw
		 * a V2 protocol error response in the hope that v3 frontend
		 * will negotiate again using v2 protocol.
		 */
		show_error("%s:pool_do_auth: maybe protocol version mismatch (current version %d)",func, protoMajor);
		ErrorResponse(frontend, cp);
		return -1;
	}
	else if (kind != 'R')
	{
		show_error("%s:pool_do_auth: expect \"R\" got %c",func, kind);
		return -1;
	}

	/*
	 * message length (v3 only) */
	if (protoMajor == PROTO_MAJOR_V3 && pool_read_message_length(cp) < 0)
	{
		return -1;
	}

	/*
	 * read authentication request kind.
	 *
	 * 0: authentication ok
	 * 1: kerberos v4
	 * 2: kerberos v5
	 * 3: clear text password
	 * 4: crypt password
	 * 5: md5 password
	 * 6: scm credential
	 *
	 * in replication mode, we only supports  kind = 0, 3. this is because to "salt"
	 * cannot be replicated among master and secondary.
	 * in non replication mode, we supports  kind = 0, 3, 4, 5
	 */

	status = pool_read(MASTER(cp), &pid, sizeof(pid));
	if (status < 0)
	{
		show_error("%s:pool_do_auth: read authentication kind failed",func);
		return -1;
	}

	if (REPLICATION)
	{
		status = pool_read(SECONDARY(cp), &pid1, sizeof(pid1));

		if (status < 0)
		{
			show_error("%s:pool_do_auth: read authentication kind from secondary failed",func);
			return -1;
		}
	}

	pid = ntohl(pid);

	/* trust? */
	if (pid == 0)
	{
		if (protoMajor == PROTO_MAJOR_V3)
		{
			int msglen;

			pool_write(frontend, "R", 1);
			msglen = htonl(8);
			pool_write(frontend, &msglen, sizeof(msglen));
			msglen = htonl(0);
			if (pool_write_and_flush(frontend, &msglen, sizeof(msglen)) < 0)
			{
				return -1;
			}
		}
		MASTER(cp)->auth_kind = 0;
	}

	/* clear text password authentication? */
	else if (pid == 3)
	{
#ifdef PRINT_DEBUG
		show_debug("%s:trying clear text password authentication",func);
#endif			

		pid = do_clear_text_password(MASTER(cp), frontend, 0, protoMajor);

		if (pid >= 0 && REPLICATION)
		{
			pid = do_clear_text_password(SECONDARY(cp), frontend, 0, protoMajor);
		}
	}

	/* crypt authentication? */
	else if (pid == 4)
	{
#ifdef PRINT_DEBUG
		show_debug("%s:trying crypt authentication",func);
#endif			

		pid = do_crypt(MASTER(cp), frontend, 0, protoMajor);

		if (pid >= 0 && REPLICATION)
		{
			pid = do_crypt(SECONDARY(cp), frontend, 0, protoMajor);
		}
	}

	/* md5 authentication? */
	else if (pid == 5)
	{
#ifdef PRINT_DEBUG
		show_debug("%s:trying md5 authentication",func);
#endif			

		pid = do_md5(MASTER(cp), frontend, 0, protoMajor);

		if (pid >= 0 && REPLICATION)
		{
			pid = do_md5(SECONDARY(cp), frontend, 0, protoMajor);
		}
	}

	if (pid != 0)
	{
		show_error("%s:pool_do_auth: backend does not return authenticaton ok",func);
		return -1;
	} 

	/*
	 * authentication ok. now read pid and secret key from the
	 * backend
	 */
	kind = pool_read_kind(cp);
	if (kind < 0)
	{
		return -1;
	}

	/* error response? */
	if (kind == 'E')
	{
		if (protoMajor == PROTO_MAJOR_V2)
			ErrorResponse(frontend, cp);
		else
			SimpleForwardToFrontend(kind, frontend, cp);
		return -1;
	}
	else if (kind != 'K')
	{
		if (protoMajor == PROTO_MAJOR_V3)
		{
			/* process parameter status */
			while (kind == 'S')
			{
				if (ParameterStatus(frontend, cp) != POOL_CONTINUE)
						return -1;

				pool_flush(frontend);

				kind = pool_read_kind(cp);
				if (kind < 0)
				{
					show_error("%s:pool_do_auth: failed to read kind while processing ParamterStatus",func);
					return -1;
				}
			}
		}
		else
		{
			show_error("%s:pool_do_auth: expect \"K\" got %c",func, kind);
			return -1;
		}
	}

	/*
	 * message length (V3 only)
	 */
	if (protoMajor == PROTO_MAJOR_V3 && (length = pool_read_message_length(cp)) != 12)
	{
		show_error("%s:pool_do_auth: invalid messages length(%d) for BackendKeyData",func, length);
		return -1;
	}

	/*
	 * OK, read pid and secret key
	 */

	/* pid */
	pool_read(MASTER(cp), &pid, sizeof(pid));
	MASTER_CONNECTION(cp)->pid = pid;

	/* key */
	pool_read(MASTER(cp), &key, sizeof(key));
	MASTER_CONNECTION(cp)->key = key;

	if (REPLICATION)
	{
		pool_read(SECONDARY(cp), &pid1, sizeof(pid1));
		SECONDARY_CONNECTION(cp)->pid = pid;

		/* key */
		pool_read(SECONDARY(cp), &key1, sizeof(key1));
		SECONDARY_CONNECTION(cp)->key = key;
	}

	return (pool_send_auth_ok(frontend, pid, key, protoMajor));
}

/*
* do re-authentication for reused connection. if success return 0 otherwise non 0.
*/
int pool_do_reauth(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *cp)
{
	char * func = "pool_do_reauth()";
	int status;
	int protoMajor;

	protoMajor = MAJOR(cp);

	switch(MASTER(cp)->auth_kind)
	{
		case 0:
			/* trust */
			status = 0;
			break;

		case 3:
			/* clear text password */
			status = do_clear_text_password(MASTER(cp), frontend, 1, protoMajor);
			break;
			
		case 4:
			/* crypt password */
			status = do_crypt(MASTER(cp), frontend, 1, protoMajor);
			break;

		case 5:
			/* md5 password */
			status = do_md5(MASTER(cp), frontend, 1, protoMajor);
			break;

		default:
			show_error("%s: unknown authentication request code %d", 
					   func,MASTER(cp)->auth_kind);
			return -1;
	}

	if (status == 0)
	{
		if (protoMajor == PROTO_MAJOR_V3)
		{
			int msglen;

			pool_write(frontend, "R", 1);
			msglen = htonl(8);
			pool_write(frontend, &msglen, sizeof(msglen));
			msglen = htonl(0);
			if (pool_write_and_flush(frontend, &msglen, sizeof(msglen)) < 0)
			{
				return -1;
			}
		}
	}
	else
	{
#ifdef PRINT_DEBUG
		show_debug("%s: authentication failed",func);
#endif			
		return -1;
	}

	return (pool_send_auth_ok(frontend, MASTER_CONNECTION(cp)->pid, MASTER_CONNECTION(cp)->key, protoMajor) != POOL_CONTINUE);
}

/*
* send authentication ok to frontend. if success return 0 otherwise non 0.
*/
static POOL_STATUS pool_send_auth_ok(POOL_CONNECTION *frontend, int pid, int key, int protoMajor)
{
	char kind;
	int len;

	if (protoMajor == PROTO_MAJOR_V2)
	{
		/* return "Authentication OK" to the frontend */
		kind = 'R';
		pool_write(frontend, &kind, 1);
		len = htonl(0);
		if (pool_write_and_flush(frontend, &len, sizeof(len)) < 0)
		{
			return -1;
		}
	}

	/* send backend key data */
	kind = 'K';
	pool_write(frontend, &kind, 1);
	if (protoMajor == PROTO_MAJOR_V3)
	{
		len = htonl(12);
		pool_write(frontend, &len, sizeof(len));
	}
	pool_write(frontend, &pid, sizeof(pid));
	if (pool_write_and_flush(frontend, &key, sizeof(key)) < 0)
	{
		return -1;
	}

	return 0;
}

/*
 * perform clear text password authetication
 */
static int do_clear_text_password(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, int protoMajor)
{
	char * func = "do_clear_text_password()";
	static int size;
	static char password[MAX_PASSWORD_SIZE];
	char response;
	int kind;
	int len;

	/* master? */
	if (!backend->issecondary_backend)
	{
		pool_write(frontend, "R", 1);	/* authenticaton */
		if (protoMajor == PROTO_MAJOR_V3)
		{
			len = htonl(8);
			pool_write(frontend, &len, sizeof(len));
		}
		kind = htonl(3);		/* clear text password authentication */
		pool_write_and_flush(frontend, &kind, sizeof(kind));	/* indicating clear text password authentication */

		/* read password packet */
		if (protoMajor == PROTO_MAJOR_V2)
		{
			if (pool_read(frontend, &size, sizeof(size)))
			{
				show_error("%s: failed to read password packet size",func);
				return -1;
			}
		}
		else
		{
			char k;

			if (pool_read(frontend, &k, sizeof(k)))
			{
				show_error("%s: failed to read password packet \"p\"",func);
				return -1;
			}
			if (k != 'p')
			{
				show_error("%s:packet does not start with \"p\"",func);
				return -1;
			}
			if (pool_read(frontend, &size, sizeof(size)))
			{
				show_error("%s: failed to read password packet size",func);
				return -1;
			}
		}

		if ((ntohl(size) - 4) > sizeof(password))
		{
			show_error("%s: password is too long (size: %d)",func, ntohl(size) - 4);
			return -1;
		}

		if (pool_read(frontend, password, ntohl(size) - 4))
		{
			show_error("%s: failed to read password (size: %d)",func, ntohl(size) - 4);
			return -1;
		}
	}

	/* connection reusing? */
	if (reauth)
	{
		if ((ntohl(size) - 4) != backend->pwd_size)
		{
#ifdef PRINT_DEBUG
			show_debug("%s; password size does not match in re-authetication",func);
#endif			
			return -1;
		}

		if (memcmp(password, backend->password, backend->pwd_size) != 0)
		{
#ifdef PRINT_DEBUG
			show_debug("%s; password does not match in re-authetication",func);
#endif			
			return -1;
		}

		return 0;
	}

	/* send password packet to backend */
	if (protoMajor == PROTO_MAJOR_V3)
		pool_write(backend, "p", 1);
	pool_write(backend, &size, sizeof(size));
	pool_write_and_flush(backend, password, ntohl(size) -4);
	if (pool_read(backend, &response, sizeof(response)))
	{
		show_error("%s: failed to read authentication response",func);
		return -1;
	}

	if (response != 'R')
	{
#ifdef PRINT_DEBUG
		show_debug("%s: backend does not return R while processing clear text password authentication",func);
#endif			
		return -1;
	}

	if (protoMajor == PROTO_MAJOR_V3)
	{
		if (pool_read(backend, &len, sizeof(len)))
		{
			show_error("%s: failed to read authentication packet size",func);
			return -1;
		}

		if (ntohl(len) != 8)
		{
			show_error("%s: incorrect authentication packet size (%d)",func, ntohl(len));
			return -1;
		}
	}

	/* expect to read "Authentication OK" response. kind should be 0... */
	if (pool_read(backend, &kind, sizeof(kind)))
	{
#ifdef PRINT_DEBUG
		show_debug("%s: failed to read Authentication OK response",func);
#endif			
		return -1;
	}

	/* if authenticated, save info */
	if (!reauth && kind == 0)
	{
		if (!backend->issecondary_backend && protoMajor == PROTO_MAJOR_V3)
		{
			int msglen;

			pool_write(frontend, "R", 1);
			msglen = htonl(8);
			pool_write(frontend, &msglen, sizeof(msglen));
			msglen = htonl(0);
			if (pool_write_and_flush(frontend, &msglen, sizeof(msglen)) < 0)
			{
				return -1;
			}
		}

		backend->auth_kind = 3;
		backend->pwd_size = ntohl(size) - 4;
		memcpy(backend->password, password, backend->pwd_size);
	}
	return kind;
}

/*
 * perform crypt authetication
 */
static int do_crypt(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, int protoMajor)
{
	char * func = "do_crypt()";
	char salt[2];
	static int size;
	static char password[MAX_PASSWORD_SIZE];
	char response;
	int kind;
	int len;

	if (!reauth)
	{
		/* read salt */
		if (pool_read(backend, salt, sizeof(salt)))
		{
			show_error("%s: failed to read salt",func);
			return -1;
		}
	}
	else
	{
		memcpy(salt, backend->salt, sizeof(salt));
	}

	/* master? */
	if (!backend->issecondary_backend)
	{
		pool_write(frontend, "R", 1);	/* authenticaton */
		if (protoMajor == PROTO_MAJOR_V3)
		{
			len = htonl(10);
			pool_write(frontend, &len, sizeof(len));
		}
		kind = htonl(4);		/* crypt authentication */
		pool_write(frontend, &kind, sizeof(kind));	/* indicating crypt authentication */
		pool_write_and_flush(frontend, salt, sizeof(salt));		/* salt */

		/* read password packet */
		if (protoMajor == PROTO_MAJOR_V2)
		{
			if (pool_read(frontend, &size, sizeof(size)))
			{
				show_error("%s: failed to read password packet size",func);
				return -1;
			}
		}
		else
		{
			char k;

			if (pool_read(frontend, &k, sizeof(k)))
			{
				show_error("%s: failed to read password packet",func);
				return -1;
			}
			if (k != 'p')
			{
				show_error("%s: password packet does not start with \"p\"",func);
				return -1;
			}
			if (pool_read(frontend, &size, sizeof(size)))
			{
				show_error("%s: failed to read password packet size",func);
				return -1;
			}
		}

		if ((ntohl(size) - 4) > sizeof(password))
		{
			show_error("%s: password is too long(size: %d)", func,ntohl(size) - 4);
			return -1;
		}

		if (pool_read(frontend, password, ntohl(size) - 4))
		{
			show_error("%s: failed to read password (size: %d)", func,ntohl(size) - 4);
			return -1;
		}
	}

	/* connection reusing? */
	if (reauth)
	{
#ifdef PRINT_DEBUG
		show_debug("%s:size: %d saved_size: %d",func, (ntohl(size) - 4), backend->pwd_size);
#endif			
		if ((ntohl(size) - 4) != backend->pwd_size)
		{
#ifdef PRINT_DEBUG
			show_debug("%s: password size does not match in re-authetication",func);
#endif			
			return -1;
		}

		if (memcmp(password, backend->password, backend->pwd_size) != 0)
		{
#ifdef PRINT_DEBUG
			show_debug("%s: password does not match in re-authetication",func);
#endif			
			return -1;
		}

		return 0;
	}

	/* send password packet to backend */
	if (protoMajor == PROTO_MAJOR_V3)
		pool_write(backend, "p", 1);
	pool_write(backend, &size, sizeof(size));
	pool_write_and_flush(backend, password, ntohl(size) -4);
	if (pool_read(backend, &response, sizeof(response)))
	{
		show_error("%s: failed to read authentication response",func);
		return -1;
	}

	if (response != 'R')
	{
#ifdef PRINT_DEBUG
		show_debug("%s: backend does not return R while processing crypt authentication(%02x) secondary: %d",func, response, backend->issecondary_backend);
#endif			
		return -1;
	}

	if (protoMajor == PROTO_MAJOR_V3)
	{
		if (pool_read(backend, &len, sizeof(len)))
		{
			show_error("%s: failed to read authentication packet size",func);
			return -1;
		}

		if (ntohl(len) != 8)
		{
			show_error("%s: incorrect authentication packet size (%d)",func, ntohl(len));
			return -1;
		}
	}

	/* expect to read "Authentication OK" response. kind should be 0... */
	if (pool_read(backend, &kind, sizeof(kind)))
	{
#ifdef PRINT_DEBUG
		show_debug("%s: failed to read Authentication OK response",func);
#endif			
		return -1;
	}

	/* if authenticated, save info */
	if (!reauth && kind == 0)
	{
		if (protoMajor == PROTO_MAJOR_V3)
		{
			int msglen;

			pool_write(frontend, "R", 1);
			msglen = htonl(8);
			pool_write(frontend, &msglen, sizeof(msglen));
			msglen = htonl(0);
			if (pool_write_and_flush(frontend, &msglen, sizeof(msglen)) < 0)
			{
				return -1;
			}
		}
		backend->auth_kind = 4;
		backend->pwd_size = ntohl(size) - 4;
		memcpy(backend->password, password, backend->pwd_size);
		memcpy(backend->salt, salt, sizeof(salt));
	}
	return kind;
}

/*
 * perform MD5 authetication
 */
static int do_md5(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, int protoMajor)
{
	char * func = "do_md5()";
	char salt[4];
	static int size;
	static char password[MAX_PASSWORD_SIZE];
	char response;
	int kind;
	int len;

	if (!reauth)
	{
		/* read salt */
		if (pool_read(backend, salt, sizeof(salt)))
		{
			show_error("%s: failed to read salt",func);
			return -1;
		}
	}
	else
	{
		memcpy(salt, backend->salt, sizeof(salt));
	}

	/* master? */
	if (!backend->issecondary_backend)
	{
		pool_write(frontend, "R", 1);	/* authenticaton */
		if (protoMajor == PROTO_MAJOR_V3)
		{
			len = htonl(12);
			pool_write(frontend, &len, sizeof(len));
		}
		kind = htonl(5);
		pool_write(frontend, &kind, sizeof(kind));	/* indicating MD5 */
		pool_write_and_flush(frontend, salt, sizeof(salt));		/* salt */

		/* read password packet */
		if (protoMajor == PROTO_MAJOR_V2)
		{
			if (pool_read(frontend, &size, sizeof(size)))
			{
				show_error("%s: failed to read password packet size",func);
				return -1;
			}
		}
		else
		{
			char k;

			if (pool_read(frontend, &k, sizeof(k)))
			{
				show_error("%s: failed to read password packet \"p\"",func);
				return -1;
			}
			if (k != 'p')
			{
				show_error("%s: password packet does not start with \"p\"",func);
				return -1;
			}
			if (pool_read(frontend, &size, sizeof(size)))
			{
				show_error("%s: failed to read password packet size",func);
				return -1;
			}
		}

		if ((ntohl(size) - 4) > sizeof(password))
		{
			show_error("%s: password is too long(size: %d)",func, ntohl(size) - 4);
			return -1;
		}

		if (pool_read(frontend, password, ntohl(size) - 4))
		{
			show_error("%s: failed to read password (size: %d)",func, ntohl(size) - 4);
			return -1;
		}
	}

	/* connection reusing? */
	if (reauth)
	{
		if ((ntohl(size) - 4) != backend->pwd_size)
		{
#ifdef PRINT_DEBUG
			show_debug("%s; password size does not match in re-authetication",func);
#endif			
			return -1;
		}

		if (memcmp(password, backend->password, backend->pwd_size) != 0)
		{
#ifdef PRINT_DEBUG
			show_debug("%s; password does not match in re-authetication",func);
#endif			
			return -1;
		}

		return 0;
	}

	/* send password packet to backend */
	if (protoMajor == PROTO_MAJOR_V3)
		pool_write(backend, "p", 1);
	pool_write(backend, &size, sizeof(size));
	pool_write_and_flush(backend, password, ntohl(size) -4);
	if (pool_read(backend, &response, sizeof(response)))
	{
		show_error("%s: failed to read authentication response",func);
		return -1;
	}

	if (response != 'R')
	{
#ifdef PRINT_DEBUG
		show_debug("%s: backend does not return R while processing MD5 authentication %c", func,response);
#endif			
		return -1;
	}

	if (protoMajor == PROTO_MAJOR_V3)
	{
		if (pool_read(backend, &len, sizeof(len)))
		{
			show_error("%s: failed to read authentication packet size",func);
			return -1;
		}

		if (ntohl(len) != 8)
		{
			show_error("%s: incorrect authentication packet size (%d)",func, ntohl(len));
			return -1;
		}
	}

	/* expect to read "Authentication OK" response. kind should be 0... */
	if (pool_read(backend, &kind, sizeof(kind)))
	{
#ifdef PRINT_DEBUG
		show_debug("%s: failed to read Authentication OK response",func);
#endif			
		return -1;
	}

	/* if authenticated, save info */
	if (!reauth && kind == 0)
	{
		if (protoMajor == PROTO_MAJOR_V3)
		{
			int msglen;

			pool_write(frontend, "R", 1);
			msglen = htonl(8);
			pool_write(frontend, &msglen, sizeof(msglen));
			msglen = htonl(0);
			if (pool_write_and_flush(frontend, &msglen, sizeof(msglen)) < 0)
			{
				return -1;
			}
		}
		backend->auth_kind = 5;
		backend->pwd_size = ntohl(size) - 4;
		memcpy(backend->password, password, backend->pwd_size);
		memcpy(backend->salt, salt, sizeof(salt));
	}
	return kind;
}

/*
 * read message length (V3 only)
 */
int pool_read_message_length(POOL_CONNECTION_POOL *cp)
{
	char * func = "pool_read_message_length()";
	int status;
	int length, length1;

	status = pool_read(MASTER(cp), &length, sizeof(length));
	if (status < 0)
	{
		show_error("%s: error while reading message length",func);
		return -1;
	}
	length = ntohl(length);

	if (REPLICATION)
	{
		status = pool_read(SECONDARY(cp), &length1, sizeof(length1));
		if (status < 0)
		{
			show_error("%s: error while reading message length from secondary backend",func);
			return -1;
		}
		length1 = ntohl(length1);

		if (length != length1)
		{
			show_error("%s: length does not match between backends master(%d) secondary(%d)",
					   func,length, length1);
			return -1;
		}
	}

	if (length < 0)
	{
		show_error("%s:read_message_length: invalid message length (%d)", func, length);
		return -1;
	}

	return length;
}

signed char pool_read_kind(POOL_CONNECTION_POOL *cp)
{
	char * func = "pool_read_kind()";
	int status;
	char kind, kind1;

	status = pool_read(MASTER(cp), &kind, sizeof(kind));
	if (status < 0)
	{
		show_error("%s:read_message_kind: error while reading message kind",func);
		return -1;
	}

	if (REPLICATION)
	{
		status = pool_read(SECONDARY(cp), &kind1, sizeof(kind1));
		if (status < 0)
		{
			show_error("%s: error while reading message kind from secondary backend",func);
			return -1;
		}

		if (kind != kind1)
		{
			show_error("%s: kind does not match between backends master(%d) secondary(%d)",
			   func, kind, kind1);
			return -1;
		}
	}

	return kind;
}
