/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
 *  Copyright (C) 2002-2006  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/poll.h>
#include <sys/wait.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;
	chdir(path);

	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 = 3;

	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--) {
				sleep(1);
				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;
}
