/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
 *  Copyright (C) 2002-2010  Marcel Holtmann <marcel@holtmann.org>
 *
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/ioctl.h>

#include <bluetooth/bluetooth.h>
#include <bluetooth/bnep.h>

#include <netinet/in.h>

#include "pand.h"

static int ctl;

/* Compatibility with old ioctls */
#define OLD_BNEPCONADD      1
#define OLD_BNEPCONDEL      2
#define OLD_BNEPGETCONLIST  3
#define OLD_BNEPGETCONINFO  4

static unsigned long bnepconnadd;
static unsigned long bnepconndel;
static unsigned long bnepgetconnlist;
static unsigned long bnepgetconninfo;

static struct {
	char     *str;
	uint16_t uuid;
} __svc[] = {
	{ "PANU", BNEP_SVC_PANU },
	{ "NAP",  BNEP_SVC_NAP  },
	{ "GN",   BNEP_SVC_GN   },
	{ NULL }
};

int bnep_str2svc(char *svc, uint16_t *uuid)
{
	int i;
	for (i = 0; __svc[i].str; i++)
		if (!strcasecmp(svc, __svc[i].str)) {
			*uuid = __svc[i].uuid;
			return 0;
		}
	return -1;
}

char *bnep_svc2str(uint16_t uuid)
{
	int i;
	for (i = 0; __svc[i].str; i++)
		if (__svc[i].uuid == uuid)
			return __svc[i].str;
	return NULL;
}

int bnep_init(void)
{
	ctl = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_BNEP);
	if (ctl < 0) {
		perror("Failed to open control socket");
		return 1;
	}

	/* Temporary ioctl compatibility hack */
	{
		struct bnep_connlist_req req;
		struct bnep_conninfo ci[1];

		req.cnum = 1;
		req.ci   = ci;

		if (!ioctl(ctl, BNEPGETCONNLIST, &req)) {
			/* New ioctls */
			bnepconnadd     = BNEPCONNADD;
			bnepconndel     = BNEPCONNDEL;
			bnepgetconnlist = BNEPGETCONNLIST;
			bnepgetconninfo = BNEPGETCONNINFO;
		} else {
			/* Old ioctls */
			bnepconnadd     = OLD_BNEPCONADD;
			bnepconndel     = OLD_BNEPCONDEL;
			bnepgetconnlist = OLD_BNEPGETCONLIST;
			bnepgetconninfo = OLD_BNEPGETCONINFO;
		}
	}

	return 0;
}

int bnep_cleanup(void)
{
	close(ctl);
	return 0;
}

int bnep_show_connections(void)
{
	struct bnep_connlist_req req;
	struct bnep_conninfo ci[48];
	unsigned int i;

	req.cnum = 48;
	req.ci   = ci;
	if (ioctl(ctl, bnepgetconnlist, &req)) {
		perror("Failed to get connection list");
		return -1;
	}

	for (i = 0; i < req.cnum; i++) {
		char addr[18];
		ba2str((bdaddr_t *) ci[i].dst, addr);
		printf("%s %s %s\n", ci[i].device,
			addr, bnep_svc2str(ci[i].role));
	}
	return 0;
}

int bnep_kill_connection(uint8_t *dst)
{
	struct bnep_conndel_req req;

	memcpy(req.dst, dst, ETH_ALEN);
	req.flags = 0;
	if (ioctl(ctl, bnepconndel, &req)) {
		perror("Failed to kill connection");
		return -1;
	}
	return 0;
}

int bnep_kill_all_connections(void)
{
	struct bnep_connlist_req req;
	struct bnep_conninfo ci[48];
	unsigned int i;

	req.cnum = 48;
	req.ci   = ci;
	if (ioctl(ctl, bnepgetconnlist, &req)) {
		perror("Failed to get connection list");
		return -1;
	}

	for (i = 0; i < req.cnum; i++) {
		struct bnep_conndel_req req;
		memcpy(req.dst, ci[i].dst, ETH_ALEN);
		req.flags = 0;
		ioctl(ctl, bnepconndel, &req);
	}
	return 0;
}

static int bnep_connadd(int sk, uint16_t role, char *dev)
{
	struct bnep_connadd_req req;

	strncpy(req.device, dev, 16);
	req.device[15] = '\0';
	req.sock = sk;
	req.role = role;
	if (ioctl(ctl, bnepconnadd, &req))
		return -1;
	strncpy(dev, req.device, 16);
	return 0;
}

struct __service_16 {
	uint16_t dst;
	uint16_t src;
} __attribute__ ((packed));

struct __service_32 {
	uint16_t unused1;
	uint16_t dst;
	uint16_t unused2;
	uint16_t src;
} __attribute__ ((packed));

struct __service_128 {
	uint16_t unused1;
	uint16_t dst;
	uint16_t unused2[8];
	uint16_t src;
	uint16_t unused3[7];
} __attribute__ ((packed));

int bnep_accept_connection(int sk, uint16_t role, char *dev)
{
	struct bnep_setup_conn_req *req;
	struct bnep_control_rsp *rsp;
	unsigned char pkt[BNEP_MTU];
	ssize_t r;

	r = recv(sk, pkt, BNEP_MTU, 0);
	if (r <= 0)
		return -1;

	errno = EPROTO;

	if ((size_t) r < sizeof(*req))
		return -1;

	req = (void *) pkt;

	/* Highest known Control command ID
	 * is BNEP_FILTER_MULT_ADDR_RSP = 0x06 */
	if (req->type == BNEP_CONTROL &&
				req->ctrl > BNEP_FILTER_MULT_ADDR_RSP) {
		uint8_t pkt[3];

		pkt[0] = BNEP_CONTROL;
		pkt[1] = BNEP_CMD_NOT_UNDERSTOOD;
		pkt[2] = req->ctrl;

		send(sk, pkt, sizeof(pkt), 0);

		return -1;
	}

	if (req->type != BNEP_CONTROL || req->ctrl != BNEP_SETUP_CONN_REQ)
		return -1;

	/* FIXME: Check role UUIDs */

	rsp = (void *) pkt;
	rsp->type = BNEP_CONTROL;
	rsp->ctrl = BNEP_SETUP_CONN_RSP;
	rsp->resp = htons(BNEP_SUCCESS);
	if (send(sk, rsp, sizeof(*rsp), 0) < 0)
		return -1;

	return bnep_connadd(sk, role, dev);
}

/* Create BNEP connection
 * sk      - Connect L2CAP socket
 * role    - Local role
 * service - Remote service
 * dev     - Network device (contains actual dev name on return)
 */
int bnep_create_connection(int sk, uint16_t role, uint16_t svc, char *dev)
{
	struct bnep_setup_conn_req *req;
	struct bnep_control_rsp *rsp;
	struct __service_16 *s;
	struct timeval timeo;
	unsigned char pkt[BNEP_MTU];
	ssize_t r;

	/* Send request */
	req = (void *) pkt;
	req->type = BNEP_CONTROL;
	req->ctrl = BNEP_SETUP_CONN_REQ;
	req->uuid_size = 2;	/* 16bit UUID */

	s = (void *) req->service;
	s->dst = htons(svc);
	s->src = htons(role);

	memset(&timeo, 0, sizeof(timeo));
	timeo.tv_sec = 30;

	setsockopt(sk, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo));

	if (send(sk, pkt, sizeof(*req) + sizeof(*s), 0) < 0)
		return -1;

receive:
	/* Get response */
	r = recv(sk, pkt, BNEP_MTU, 0);
	if (r <= 0)
		return -1;

	memset(&timeo, 0, sizeof(timeo));
	timeo.tv_sec = 0;

	setsockopt(sk, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo));

	errno = EPROTO;

	if ((size_t) r < sizeof(*rsp))
		return -1;

	rsp = (void *) pkt;
	if (rsp->type != BNEP_CONTROL)
		return -1;

	if (rsp->ctrl != BNEP_SETUP_CONN_RSP)
		goto receive;

	r = ntohs(rsp->resp);

	switch (r) {
	case BNEP_SUCCESS:
		break;

	case BNEP_CONN_INVALID_DST:
	case BNEP_CONN_INVALID_SRC:
	case BNEP_CONN_INVALID_SVC:
		errno = EPROTO;
		return -1;

	case BNEP_CONN_NOT_ALLOWED:
		errno = EACCES;
		return -1;
	}

	return bnep_connadd(sk, role, dev);
}
