/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *	http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* NOTICE: This is a clean room re-implementation of libnl */

#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <netlink/genl/ctrl.h>
#include <netlink/genl/family.h>
#include "netlink-types.h"

/* Get head of attribute data. */
struct nlattr *genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen)
{
	return (struct nlattr *) \
		((char *) gnlh + GENL_HDRLEN + NLMSG_ALIGN(hdrlen));

}

/* Get length of attribute data. */
int genlmsg_attrlen(const struct genlmsghdr *gnlh, int hdrlen)
{
	struct nlattr *nla;
	struct nlmsghdr *nlh;

	nla = genlmsg_attrdata(gnlh, hdrlen);
	nlh = (struct nlmsghdr *) ((char *) gnlh - NLMSG_HDRLEN);
	return (char *) nlmsg_tail(nlh) - (char *) nla;
}

/* Add generic netlink header to netlink message. */
void *genlmsg_put(struct nl_msg *msg, uint32_t pid, uint32_t seq, int family,
		int hdrlen, int flags, uint8_t cmd, uint8_t version)
{
	int new_size;
	struct nlmsghdr *nlh;
	struct timeval tv;
	struct genlmsghdr *gmh;

	/* Make sure nl_msg has enough space */
	new_size = NLMSG_HDRLEN + GENL_HDRLEN + hdrlen;
	if ((sizeof(struct nl_msg) + new_size) > msg->nm_size)
		goto fail;

	/* Fill in netlink header */
	nlh = msg->nm_nlh;
	nlh->nlmsg_len = new_size;
	nlh->nlmsg_type = family;
	nlh->nlmsg_pid = getpid();
	nlh->nlmsg_flags = flags | NLM_F_REQUEST | NLM_F_ACK;

	/* Get current time for sequence number */
	if (gettimeofday(&tv, NULL))
		nlh->nlmsg_seq = 1;
	else
		nlh->nlmsg_seq = (int) tv.tv_sec;

	/* Setup genlmsghdr in new message */
	gmh = (struct genlmsghdr *) ((char *)nlh + NLMSG_HDRLEN);
	gmh->cmd = (__u8) cmd;
	gmh->version = version;

	return gmh;
fail:
	return NULL;

}

/* Socket has already been alloced to connect it to kernel? */
int genl_connect(struct nl_sock *sk)
{
	return nl_connect(sk, NETLINK_GENERIC);

}

int genl_ctrl_alloc_cache(struct nl_sock *sock, struct nl_cache **result)
{
	int rc = -1;
	int nl80211_genl_id = -1;
	char sendbuf[sizeof(struct nlmsghdr)+sizeof(struct genlmsghdr)];
	struct nlmsghdr nlmhdr;
	struct genlmsghdr gmhhdr;
	struct iovec sendmsg_iov;
	struct msghdr msg;
	int num_char;
	const int RECV_BUF_SIZE = getpagesize();
	char *recvbuf;
	struct iovec recvmsg_iov;
	int nl80211_flag = 0, nlm_f_multi = 0, nlmsg_done = 0;
	struct nlmsghdr *nlh;

	/* REQUEST GENERIC NETLINK FAMILY ID */
	/* Message buffer */
	nlmhdr.nlmsg_len = sizeof(sendbuf);
	nlmhdr.nlmsg_type = NETLINK_GENERIC;
	nlmhdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP;
	nlmhdr.nlmsg_seq = sock->s_seq_next;
	nlmhdr.nlmsg_pid = sock->s_local.nl_pid;

	/* Generic netlink header */
	memset(&gmhhdr, 0, sizeof(gmhhdr));
	gmhhdr.cmd = CTRL_CMD_GETFAMILY;
	gmhhdr.version = CTRL_ATTR_FAMILY_ID;

	/* Combine netlink and generic netlink headers */
	memcpy(&sendbuf[0], &nlmhdr, sizeof(nlmhdr));
	memcpy(&sendbuf[0]+sizeof(nlmhdr), &gmhhdr, sizeof(gmhhdr));

	/* Create IO vector with Netlink message */
	sendmsg_iov.iov_base = &sendbuf;
	sendmsg_iov.iov_len = sizeof(sendbuf);

	/* Socket message */
	msg.msg_name = (void *) &sock->s_peer;
	msg.msg_namelen = sizeof(sock->s_peer);
	msg.msg_iov = &sendmsg_iov;
	msg.msg_iovlen = 1; /* Only sending one iov */
	msg.msg_control = NULL;
	msg.msg_controllen = 0;
	msg.msg_flags = 0;

	/* Send message and verify sent */
	num_char = sendmsg(sock->s_fd, &msg, 0);
	if (num_char == -1)
		return -errno;

	/* RECEIVE GENL CMD RESPONSE */

	/* Create receive iov buffer */
	recvbuf = (char *) malloc(RECV_BUF_SIZE);

	/* Attach to iov */
	recvmsg_iov.iov_base = recvbuf;
	recvmsg_iov.iov_len = RECV_BUF_SIZE;

	msg.msg_iov = &recvmsg_iov;
	msg.msg_iovlen = 1;

	/***************************************************************/
	/* Receive message. If multipart message, keep receiving until */
	/* message type is NLMSG_DONE				       */
	/***************************************************************/

	do {

		int recvmsg_len, nlmsg_rem;

		/* Receive message */
		memset(recvbuf, 0, RECV_BUF_SIZE);
		recvmsg_len = recvmsg(sock->s_fd, &msg, 0);

		/* Make sure receive successful */
		if (recvmsg_len < 0) {
			rc = -errno;
			goto error_recvbuf;
		}

		/* Parse nlmsghdr */
		nlmsg_for_each_msg(nlh, (struct nlmsghdr *) recvbuf, \
				recvmsg_len, nlmsg_rem) {
			struct nlattr *nla;
			int nla_rem;

			/* Check type */
			switch (nlh->nlmsg_type) {
			case NLMSG_DONE:
				goto return_genl_id;
				break;
			case NLMSG_ERROR:

				/* Should check nlmsgerr struct received */
				fprintf(stderr, "Receive message error\n");
				goto error_recvbuf;
			case NLMSG_OVERRUN:
				fprintf(stderr, "Receive data partly lost\n");
				goto error_recvbuf;
			case NLMSG_MIN_TYPE:
			case NLMSG_NOOP:
				break;
			default:
				break;
			}



			/* Check flags */
			if (nlh->nlmsg_flags & NLM_F_MULTI)
				nlm_f_multi = 1;
			else
				nlm_f_multi = 0;

			if (nlh->nlmsg_type & NLMSG_DONE)
				nlmsg_done = 1;
			else
				nlmsg_done = 0;

			/* Iteratve over attributes */
			nla_for_each_attr(nla,
					nlmsg_attrdata(nlh, GENL_HDRLEN),
					nlmsg_attrlen(nlh, GENL_HDRLEN),
					nla_rem){

				/* If this family is nl80211 */
				if (nla->nla_type == CTRL_ATTR_FAMILY_NAME &&
					!strcmp((char *)nla_data(nla),
						"nl80211"))
					nl80211_flag = 1;

				/* Save the family id */
				else if (nl80211_flag &&
					nla->nla_type == CTRL_ATTR_FAMILY_ID) {
					nl80211_genl_id =
						*((int *)nla_data(nla));
					nl80211_flag = 0;
				}

			}

		}

	} while (nlm_f_multi && !nlmsg_done);

return_genl_id:
	/* Return family id as cache pointer */
	*result = (struct nl_cache *) nl80211_genl_id;
	rc = 0;
error_recvbuf:
	free(recvbuf);
error:
	return rc;
}

/* Checks the netlink cache to find family reference by name string */
/* NOTE: Caller needs to call genl_family_put() when done with *
 * returned object */
struct genl_family *genl_ctrl_search_by_name(struct nl_cache *cache, \
					const char *name)
{
	struct genl_family *gf = (struct genl_family *) \
		malloc(sizeof(struct genl_family));
	if (!gf)
		goto fail;
	memset(gf, 0, sizeof(*gf));

	/* Add ref */
	gf->ce_refcnt++;

	/* Overriding cache pointer as family id for now */
	gf->gf_id = (uint16_t) ((uint32_t) cache);
	strncpy(gf->gf_name, name, GENL_NAMSIZ);

	return gf;
fail:
	return NULL;

}

int genl_ctrl_resolve(struct nl_sock *sk, const char *name)
{
	struct nl_cache *cache = NULL;
	struct genl_family *gf = NULL;
	int id = -1;

	/* Hack to support wpa_supplicant */
	if (strcmp(name, "nlctrl") == 0)
		return NETLINK_GENERIC;

	if (strcmp(name, "nl80211") != 0) {
		fprintf(stderr, "%s is not supported\n", name);
		return id;
	}

	if (!genl_ctrl_alloc_cache(sk, &cache)) {
		gf = genl_ctrl_search_by_name(cache, name);
		if (gf)
			id = genl_family_get_id(gf);
	}

	if (gf)
		genl_family_put(gf);
	if (cache)
		nl_cache_free(cache);

	return id;
}
