/*
 * Copyright (c) 2012 Jakub Zawadzki
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote 
 * products derived from this software without specific prior written 
 * permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <string.h>

#include <time.h>
#include <sys/time.h>

#include <dbus/dbus.h>

#include "pcap-int.h"
#include "pcap-dbus.h"

/*
 * Private data for capturing on D-Bus.
 */
struct pcap_dbus {
	DBusConnection *conn;
	u_int	packets_read;	/* count of packets read */
};

static int
dbus_read(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
{
	struct pcap_dbus *handlep = handle->priv;

	struct pcap_pkthdr pkth;
	DBusMessage *message;

	char *raw_msg;
	int raw_msg_len;

	int count = 0;

	message = dbus_connection_pop_message(handlep->conn);

	while (!message) {
		// XXX handle->opt.timeout = timeout_ms;
		if (!dbus_connection_read_write(handlep->conn, 100)) {
			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Connection closed");
			return -1;
		}

		if (handle->break_loop) {
			handle->break_loop = 0;
			return -2;
		}

		message = dbus_connection_pop_message(handlep->conn);
	}

	if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Disconnected");
		return -1;
	}

	if (dbus_message_marshal(message, &raw_msg, &raw_msg_len)) {
		pkth.caplen = pkth.len = raw_msg_len;
		/* pkth.caplen = min (payload_len, handle->snapshot); */

		gettimeofday(&pkth.ts, NULL);
		if (handle->fcode.bf_insns == NULL ||
		    bpf_filter(handle->fcode.bf_insns, (u_char *)raw_msg, pkth.len, pkth.caplen)) {
			handlep->packets_read++;
			callback(user, &pkth, (u_char *)raw_msg);
			count++;
		}

		dbus_free(raw_msg);
	}
	return count;
}

static int
dbus_write(pcap_t *handle, const void *buf, size_t size)
{
	/* XXX, not tested */
	struct pcap_dbus *handlep = handle->priv;

	DBusError error = DBUS_ERROR_INIT;
	DBusMessage *msg;

	if (!(msg = dbus_message_demarshal(buf, size, &error))) {
		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dbus_message_demarshal() failed: %s", error.message);
		dbus_error_free(&error);
		return -1;
	}

	dbus_connection_send(handlep->conn, msg, NULL);
	dbus_connection_flush(handlep->conn);

	dbus_message_unref(msg);
	return 0;
}                           

static int
dbus_stats(pcap_t *handle, struct pcap_stat *stats)
{
	struct pcap_dbus *handlep = handle->priv;

	stats->ps_recv = handlep->packets_read;
	stats->ps_drop = 0;
	stats->ps_ifdrop = 0;
	return 0;
}

static void
dbus_cleanup(pcap_t *handle)
{
	struct pcap_dbus *handlep = handle->priv;

	dbus_connection_unref(handlep->conn);

	pcap_cleanup_live_common(handle);
}

static int
dbus_activate(pcap_t *handle)
{
#define EAVESDROPPING_RULE "eavesdrop=true,"

	static const char *rules[] = {
		EAVESDROPPING_RULE "type='signal'",
		EAVESDROPPING_RULE "type='method_call'",
		EAVESDROPPING_RULE "type='method_return'",
		EAVESDROPPING_RULE "type='error'",
	};

	#define N_RULES sizeof(rules)/sizeof(rules[0])

	struct pcap_dbus *handlep = handle->priv;
	const char *dev = handle->opt.source;

	DBusError error = DBUS_ERROR_INIT;
	int i;

	if (strcmp(dev, "dbus-system") == 0) {
		if (!(handlep->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to get system bus: %s", error.message);
			dbus_error_free(&error);
			return PCAP_ERROR;
		}

	} else if (strcmp(dev, "dbus-session") == 0) {
		if (!(handlep->conn = dbus_bus_get(DBUS_BUS_SESSION, &error))) {
			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to get session bus: %s", error.message);
			dbus_error_free(&error);
			return PCAP_ERROR;
		}

	} else if (strncmp(dev, "dbus://", 7) == 0) {
		const char *addr = dev + 7;

		if (!(handlep->conn = dbus_connection_open(addr, &error))) {
			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to open connection to: %s: %s", addr, error.message);
			dbus_error_free(&error);
			return PCAP_ERROR;
		}

		if (!dbus_bus_register(handlep->conn, &error)) {
			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to register bus %s: %s\n", addr, error.message);
			dbus_error_free(&error);
			return PCAP_ERROR;
		}

	} else {
		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't get bus address from %s", handle->opt.source);
		return PCAP_ERROR;
	}

	/* Initialize some components of the pcap structure. */
	handle->bufsize = 0;
	handle->offset = 0;
	handle->linktype = DLT_DBUS;
	handle->read_op = dbus_read;
	handle->inject_op = dbus_write;
	handle->setfilter_op = install_bpf_program; /* XXX, later add support for dbus_bus_add_match() */
	handle->setdirection_op = NULL;
	handle->set_datalink_op = NULL;      /* can't change data link type */
	handle->getnonblock_op = pcap_getnonblock_fd;
	handle->setnonblock_op = pcap_setnonblock_fd;
	handle->stats_op = dbus_stats;

	handle->selectable_fd = handle->fd = -1;

	if (handle->opt.rfmon) {
		/*
		 * Monitor mode doesn't apply to dbus connections.
		 */
		dbus_cleanup(handle);
		return PCAP_ERROR_RFMON_NOTSUP;
	}

	/* dbus_connection_set_max_message_size(handlep->conn, handle->snapshot); */
	if (handle->opt.buffer_size != 0)
		dbus_connection_set_max_received_size(handlep->conn, handle->opt.buffer_size);

	for (i = 0; i < N_RULES; i++) {
		dbus_bus_add_match(handlep->conn, rules[i], &error);
		if (dbus_error_is_set(&error)) {
			dbus_error_free(&error);

			/* try without eavesdrop */
			dbus_bus_add_match(handlep->conn, rules[i] + strlen(EAVESDROPPING_RULE), &error);
			if (dbus_error_is_set(&error)) {
				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to add bus match: %s\n", error.message);
				dbus_error_free(&error);
				dbus_cleanup(handle);
				return PCAP_ERROR;
			}
		}
	}

	return 0;
}

pcap_t *
dbus_create(const char *device, char *ebuf, int *is_ours)
{
	pcap_t *p;

	if (strcmp(device, "dbus-system") && 
		strcmp(device, "dbus-session") && 
		strncmp(device, "dbus://", 7))
	{
		*is_ours = 0;
		return NULL;
	}

	*is_ours = 1;
	p = pcap_create_common(device, ebuf, sizeof (struct pcap_dbus));
	if (p == NULL)
		return (NULL);

	p->activate_op = dbus_activate;
	return (p);
}

int 
dbus_findalldevs(pcap_if_t **alldevsp, char *err_str)
{
	if (pcap_add_if(alldevsp, "dbus-system", 0, "D-Bus system bus", err_str) < 0)
		return -1;
	if (pcap_add_if(alldevsp, "dbus-session", 0, "D-Bus session bus", err_str) < 0)
		return -1;
	return 0;
}

