#include "ceph_debug.h"

#include <linux/module.h>
#include <linux/err.h>

#include "types.h"
#include "auth_none.h"
#include "decode.h"
#include "super.h"

#include "messenger.h"

/*
 * get protocol handler
 */
static u32 supported_protocols[] = {
	CEPH_AUTH_NONE
};

int ceph_auth_init_protocol(struct ceph_auth_client *ac, int protocol)
{
	switch (protocol) {
	case CEPH_AUTH_NONE:
		return ceph_auth_none_init(ac);
	default:
		return -ENOENT;
	}
}

/*
 * setup, teardown.
 */
struct ceph_auth_client *ceph_auth_init(const char *name, const char *secret)
{
	struct ceph_auth_client *ac;
	int ret;

	dout("auth_init name '%s' secret '%s'\n", name, secret);

	ret = -ENOMEM;
	ac = kzalloc(sizeof(*ac), GFP_NOFS);
	if (!ac)
		goto out;

	ac->negotiating = true;
	if (name)
		ac->name = name;
	else
		ac->name = CEPH_AUTH_NAME_DEFAULT;
	dout("auth_init name %s secret %s\n", ac->name, secret);
	ac->secret = secret;
	return ac;

out:
	return ERR_PTR(ret);
}

void ceph_auth_destroy(struct ceph_auth_client *ac)
{
	dout("auth_destroy %p\n", ac);
	if (ac->ops)
		ac->ops->destroy(ac);
	kfree(ac);
}

/*
 * Reset occurs when reconnecting to the monitor.
 */
void ceph_auth_reset(struct ceph_auth_client *ac)
{
	dout("auth_reset %p\n", ac);
	if (ac->ops && !ac->negotiating)
		ac->ops->reset(ac);
	ac->negotiating = true;
}

int ceph_entity_name_encode(const char *name, void **p, void *end)
{
	int len = strlen(name);

	if (*p + 2*sizeof(u32) + len > end)
		return -ERANGE;
	ceph_encode_32(p, CEPH_ENTITY_TYPE_CLIENT);
	ceph_encode_32(p, len);
	ceph_encode_copy(p, name, len);
	return 0;
}

/*
 * Initiate protocol negotiation with monitor.  Include entity name
 * and list supported protocols.
 */
int ceph_auth_build_hello(struct ceph_auth_client *ac, void *buf, size_t len)
{
	struct ceph_mon_request_header *monhdr = buf;
	void *p = monhdr + 1, *end = buf + len, *lenp;
	int i, num;
	int ret;

	dout("auth_build_hello\n");
	monhdr->have_version = 0;
	monhdr->session_mon = cpu_to_le16(-1);
	monhdr->session_mon_tid = 0;

	ceph_encode_32(&p, 0);  /* no protocol, yet */

	lenp = p;
	p += sizeof(u32);

	num = ARRAY_SIZE(supported_protocols);
	ceph_encode_32(&p, num);
	for (i = 0; i < num; i++)
		ceph_encode_32(&p, supported_protocols[i]);

	ret = ceph_entity_name_encode(ac->name, &p, end);
	if (ret < 0)
		return ret;
	ceph_decode_need(&p, end, sizeof(u64), bad);
	ceph_encode_64(&p, ac->global_id);

	ceph_encode_32(&lenp, p - lenp - sizeof(u32));
	return p - buf;

bad:
	return -ERANGE;
}

/*
 * Handle auth message from monitor.
 */
int ceph_handle_auth_reply(struct ceph_auth_client *ac,
			   void *buf, size_t len,
			   void *reply_buf, size_t reply_len)
{
	void *p = buf;
	void *end = buf + len;
	int protocol;
	s32 result;
	u64 global_id;
	void *payload, *payload_end;
	int payload_len;
	char *result_msg;
	int result_msg_len;
	int ret = -EINVAL;

	dout("handle_auth_reply %p %p\n", p, end);
	ceph_decode_need(&p, end, sizeof(u32) * 3 + sizeof(u64), bad);
	protocol = ceph_decode_32(&p);
	result = ceph_decode_32(&p);
	global_id = ceph_decode_64(&p);
	payload_len = ceph_decode_32(&p);
	payload = p;
	p += payload_len;
	ceph_decode_need(&p, end, sizeof(u32), bad);
	result_msg_len = ceph_decode_32(&p);
	result_msg = p;
	p += result_msg_len;
	if (p != end)
		goto bad;

	dout(" result %d '%.*s' gid %llu len %d\n", result, result_msg_len,
	     result_msg, global_id, payload_len);

	payload_end = payload + payload_len;

	if (global_id && ac->global_id != global_id) {
		dout(" set global_id %lld -> %lld\n", ac->global_id, global_id);
		ac->global_id = global_id;
	}

	if (ac->negotiating) {
		/* set up (new) protocol handler? */
		if (ac->protocol && ac->protocol != protocol) {
			ac->ops->destroy(ac);
			ac->protocol = 0;
			ac->ops = NULL;
		}
		if (ac->protocol != protocol) {
			ret = ceph_auth_init_protocol(ac, protocol);
			if (ret) {
				pr_err("error %d on auth protocol %d init\n",
				       ret, protocol);
				goto out;
			}
		}
	}

	ret = ac->ops->handle_reply(ac, result, payload, payload_end);
	if (ret == -EAGAIN) {
		struct ceph_mon_request_header *monhdr = reply_buf;
		void *p = reply_buf + 1;
		void *end = reply_buf + reply_len;

		monhdr->have_version = 0;
		monhdr->session_mon = cpu_to_le16(-1);
		monhdr->session_mon_tid = 0;

		ceph_encode_32(&p, ac->protocol);

		ret = ac->ops->build_request(ac, p + sizeof(u32), end);
		if (ret < 0) {
			pr_err("error %d building request\n", ret);
			goto out;
		}
		dout(" built request %d bytes\n", ret);
		ceph_encode_32(&p, ret);
		return p + ret - reply_buf;
	} else if (ret) {
		pr_err("authentication error %d\n", ret);
		return ret;
	}
	return 0;

bad:
	pr_err("failed to decode auth msg\n");
out:
	return ret;
}


