/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
 *  Copyright (C) 2002-2009  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 <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <syslog.h>
#include <dirent.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>

#include <netinet/in.h>

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

#include "dund.h"
#include "lib.h"

#define PROC_BASE  "/proc"

static int for_each_port(int (*func)(struct rfcomm_dev_info *, unsigned long), unsigned long arg)
{
	struct rfcomm_dev_list_req *dl;
	struct rfcomm_dev_info *di;
	long r = 0;
	int  sk, i;

	sk = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM);
	if (sk < 0 ) {
		perror("Can't open RFCOMM control socket");
		exit(1);
	}

	dl = malloc(sizeof(*dl) + RFCOMM_MAX_DEV * sizeof(*di));
	if (!dl) {
		perror("Can't allocate request memory");
		close(sk);
		exit(1);
	}

	dl->dev_num = RFCOMM_MAX_DEV;
	di = dl->dev_info;

	if (ioctl(sk, RFCOMMGETDEVLIST, (void *) dl) < 0) {
		perror("Can't get device list");
		exit(1);
	}

	for (i = 0; i < dl->dev_num; i++) {
		r = func(di + i, arg);
		if (r) break;
	}

	close(sk);
	return r;
}

static int uses_rfcomm(char *path, char *dev)
{
	struct dirent *de;
	DIR   *dir;

	dir = opendir(path);
	if (!dir)
		return 0;

	if (chdir(path) < 0)
		return 0;

	while ((de = readdir(dir)) != NULL) {
		char link[PATH_MAX + 1];
		int  len = readlink(de->d_name, link, sizeof(link));
		if (len > 0) {
			link[len] = 0;
			if (strstr(link, dev))
				return 1;
		}
	}

	closedir(dir);

	return 0;
}

static int find_pppd(int id, pid_t *pid)
{
	struct dirent *de;
	char  path[PATH_MAX + 1];
	char  dev[10];
	int   empty = 1;
	DIR   *dir;

	dir = opendir(PROC_BASE);
	if (!dir) {
		perror(PROC_BASE);
		return -1;
	}

	sprintf(dev, "rfcomm%d", id);

	*pid = 0;
	while ((de = readdir(dir)) != NULL) {
		empty = 0;
		if (isdigit(de->d_name[0])) {
			sprintf(path, "%s/%s/fd", PROC_BASE, de->d_name);
			if (uses_rfcomm(path, dev)) {
				*pid = atoi(de->d_name);
				break;
			}
		}
	}
	closedir(dir);

	if (empty)
		fprintf(stderr, "%s is empty (not mounted ?)\n", PROC_BASE);

	return *pid != 0;
}

static int dun_exec(char *tty, char *prog, char **args)
{
	int pid = fork();
	int fd;
	
	switch (pid) {
	case -1:
		return -1;

	case 0:
		break;

	default:
		return pid;
	}

	setsid();

	/* Close all FDs */
	for (fd = 3; fd < 20; fd++)
		close(fd);

	execvp(prog, args);

	syslog(LOG_ERR, "Error while executing %s", prog);

	exit(1);
}

static int dun_create_tty(int sk, char *tty, int size)
{
	struct sockaddr_rc sa;
	struct stat st;
	socklen_t alen;
	int id, try = 30;

	struct rfcomm_dev_req req = {
		flags:   (1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP),
		dev_id:  -1
	};

	alen = sizeof(sa);
	if (getpeername(sk, (struct sockaddr *) &sa, &alen) < 0)
		return -1;
	bacpy(&req.dst, &sa.rc_bdaddr);

	alen = sizeof(sa);
	if (getsockname(sk, (struct sockaddr *) &sa, &alen) < 0)
		return -1;
	bacpy(&req.src, &sa.rc_bdaddr);
	req.channel = sa.rc_channel;

	id = ioctl(sk, RFCOMMCREATEDEV, &req);
	if (id < 0)
		return id;

	snprintf(tty, size, "/dev/rfcomm%d", id);
	while (stat(tty, &st) < 0) {
		snprintf(tty, size, "/dev/bluetooth/rfcomm/%d", id);
		if (stat(tty, &st) < 0) {
			snprintf(tty, size, "/dev/rfcomm%d", id);
			if (try--) {
				usleep(100 * 1000);
				continue;
			}

			memset(&req, 0, sizeof(req));
			req.dev_id = id;
			ioctl(sk, RFCOMMRELEASEDEV, &req);

			return -1;
		}
	}

	return id;
}

int dun_init(void)
{
	return 0;
}

int dun_cleanup(void)
{
	return 0;
}

static int show_conn(struct rfcomm_dev_info *di, unsigned long arg)
{
	pid_t pid;
	
	if (di->state == BT_CONNECTED &&
		(di->flags & (1<<RFCOMM_REUSE_DLC)) &&
		(di->flags & (1<<RFCOMM_TTY_ATTACHED)) &&
		(di->flags & (1<<RFCOMM_RELEASE_ONHUP))) {

		if (find_pppd(di->id, &pid)) {
			char dst[18];
			ba2str(&di->dst, dst);

			printf("rfcomm%d: %s channel %d pppd pid %d\n",
					di->id, dst, di->channel, pid);
		}
	}
	return 0;
}

static int kill_conn(struct rfcomm_dev_info *di, unsigned long arg)
{
	bdaddr_t *dst = (bdaddr_t *) arg;
	pid_t pid;

	if (di->state == BT_CONNECTED &&
		(di->flags & (1<<RFCOMM_REUSE_DLC)) &&
		(di->flags & (1<<RFCOMM_TTY_ATTACHED)) &&
		(di->flags & (1<<RFCOMM_RELEASE_ONHUP))) {

		if (dst && bacmp(&di->dst, dst))
			return 0;

		if (find_pppd(di->id, &pid)) {
			if (kill(pid, SIGINT) < 0)
				perror("Kill");

			if (!dst)
				return 0;
			return 1;
		}
	}
	return 0;
}

int dun_show_connections(void)
{
	for_each_port(show_conn, 0);
	return 0;
}

int dun_kill_connection(uint8_t *dst)
{
	for_each_port(kill_conn, (unsigned long) dst);
	return 0;
}

int dun_kill_all_connections(void)
{
	for_each_port(kill_conn, 0);
	return 0;
}

int dun_open_connection(int sk, char *pppd, char **args, int wait)
{
	char tty[100];
	int  pid;

	if (dun_create_tty(sk, tty, sizeof(tty) - 1) < 0) {
		syslog(LOG_ERR, "RFCOMM TTY creation failed. %s(%d)", strerror(errno), errno);
		return -1;
	}

	args[0] = "pppd";
	args[1] = tty;
	args[2] = "nodetach";

	pid = dun_exec(tty, pppd, args);
	if (pid < 0) {
		syslog(LOG_ERR, "Exec failed. %s(%d)", strerror(errno), errno);
		return -1;
	}

	if (wait) {
		int status;
		waitpid(pid, &status, 0);
		/* FIXME: Check for waitpid errors */
	}

	return 0;
}
