/*
 * Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
 *
 * 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 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.
 */

#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <ipxe/linux_api.h>
#include <ipxe/list.h>
#include <ipxe/linux.h>
#include <ipxe/malloc.h>
#include <ipxe/device.h>
#include <ipxe/netdevice.h>
#include <ipxe/iobuf.h>
#include <ipxe/ethernet.h>
#include <ipxe/settings.h>
#include <ipxe/socket.h>

/* This hack prevents pre-2.6.32 headers from redefining struct sockaddr */
#define _SYS_SOCKET_H
#define __GLIBC__ 2
#include <linux/socket.h>
#undef __GLIBC__
#include <linux/if.h>
#include <linux/if_ether.h>
#include <linux/if_tun.h>

#define RX_BUF_SIZE 1536
#define RX_QUOTA 4

/** @file
 *
 * The TAP driver.
 *
 * The TAP is a Virtual Ethernet network device.
 */

struct tap_nic {
	/** Tap interface name */
	char * interface;
	/** File descriptor of the opened tap device */
	int fd;
};

/** Default MAC address */
static const uint8_t tap_default_mac[ETH_ALEN] =
	{ 0x52, 0x54, 0x00, 0x12, 0x34, 0x56 };

/** Open the TAP device */
static int tap_open(struct net_device * netdev)
{
	struct tap_nic * nic = netdev->priv;
	struct ifreq ifr;
	int ret;

	nic->fd = linux_open("/dev/net/tun", O_RDWR);
	if (nic->fd < 0) {
		DBGC(nic, "tap %p open('/dev/net/tun') = %d (%s)\n", nic, nic->fd, linux_strerror(linux_errno));
		return nic->fd;
	}

	memset(&ifr, 0, sizeof(ifr));
	/* IFF_NO_PI for no extra packet information */
	ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
	strncpy(ifr.ifr_name, nic->interface, IFNAMSIZ);
	DBGC(nic, "tap %p interface = '%s'\n", nic, nic->interface);

	ret = linux_ioctl(nic->fd, TUNSETIFF, &ifr);

	if (ret != 0) {
		DBGC(nic, "tap %p ioctl(%d, ...) = %d (%s)\n", nic, nic->fd, ret, linux_strerror(linux_errno));
		linux_close(nic->fd);
		return ret;
	}

	/* Set nonblocking mode to make tap_poll easier */
	ret = linux_fcntl(nic->fd, F_SETFL, O_NONBLOCK);

	if (ret != 0) {
		DBGC(nic, "tap %p fcntl(%d, ...) = %d (%s)\n", nic, nic->fd, ret, linux_strerror(linux_errno));
		linux_close(nic->fd);
		return ret;
	}

	return 0;
}

/** Close the TAP device */
static void tap_close(struct net_device *netdev)
{
	struct tap_nic * nic = netdev->priv;
	linux_close(nic->fd);
}

/**
 * Transmit an ethernet packet.
 *
 * The packet can be written to the TAP device and marked as complete immediately.
 */
static int tap_transmit(struct net_device *netdev, struct io_buffer *iobuf)
{
	struct tap_nic * nic = netdev->priv;
	int rc;

	/* Pad and align packet */
	iob_pad(iobuf, ETH_ZLEN);

	rc = linux_write(nic->fd, iobuf->data, iobuf->tail - iobuf->data);
	DBGC2(nic, "tap %p wrote %d bytes\n", nic, rc);
	netdev_tx_complete(netdev, iobuf);

	return 0;
}

/** Poll for new packets */
static void tap_poll(struct net_device *netdev)
{
	struct tap_nic * nic = netdev->priv;
	struct pollfd pfd;
	struct io_buffer * iobuf;
	unsigned int quota = RX_QUOTA;
	int r;

	pfd.fd = nic->fd;
	pfd.events = POLLIN;
	if (linux_poll(&pfd, 1, 0) == -1) {
		DBGC(nic, "tap %p poll failed (%s)\n", nic, linux_strerror(linux_errno));
		return;
	}
	if ((pfd.revents & POLLIN) == 0)
		return;

	/* At this point we know there is at least one new packet to be read */

	iobuf = alloc_iob(RX_BUF_SIZE);
	if (! iobuf)
		goto allocfail;

	while (quota-- &&
	       ((r = linux_read(nic->fd, iobuf->data, RX_BUF_SIZE)) > 0)) {
		DBGC2(nic, "tap %p read %d bytes\n", nic, r);

		iob_put(iobuf, r);
		netdev_rx(netdev, iobuf);

		iobuf = alloc_iob(RX_BUF_SIZE);
		if (! iobuf)
			goto allocfail;
	}

	free_iob(iobuf);
	return;

allocfail:
	DBGC(nic, "tap %p alloc_iob failed\n", nic);
}

/**
 * Set irq.
 *
 * Not used on linux, provide a dummy implementation.
 */
static void tap_irq(struct net_device *netdev, int enable)
{
	struct tap_nic *nic = netdev->priv;

	DBGC(nic, "tap %p irq enable = %d\n", nic, enable);
}

/** Tap operations */
static struct net_device_operations tap_operations = {
	.open		= tap_open,
	.close		= tap_close,
	.transmit	= tap_transmit,
	.poll		= tap_poll,
	.irq		= tap_irq,
};

/** Handle a device request for the tap driver */
static int tap_probe(struct linux_device *device, struct linux_device_request *request)
{
	struct linux_setting *if_setting;
	struct net_device *netdev;
	struct tap_nic *nic;
	int rc;

	netdev = alloc_etherdev(sizeof(*nic));
	if (! netdev)
		return -ENOMEM;

	netdev_init(netdev, &tap_operations);
	nic = netdev->priv;
	linux_set_drvdata(device, netdev);
	netdev->dev = &device->dev;
	memcpy ( netdev->hw_addr, tap_default_mac, ETH_ALEN );
	memset(nic, 0, sizeof(*nic));

	/* Look for the mandatory if setting */
	if_setting = linux_find_setting("if", &request->settings);

	/* No if setting */
	if (! if_setting) {
		printf("tap missing a mandatory if setting\n");
		rc = -EINVAL;
		goto err_settings;
	}

	nic->interface = if_setting->value;
	snprintf ( device->dev.name, sizeof ( device->dev.name ), "%s",
		   nic->interface );
	device->dev.desc.bus_type = BUS_TYPE_TAP;
	if_setting->applied = 1;

	/* Apply rest of the settings */
	linux_apply_settings(&request->settings, &netdev->settings.settings);

	/* Register network device */
	if ((rc = register_netdev(netdev)) != 0)
		goto err_register;

	netdev_link_up(netdev);

	return 0;

	unregister_netdev(netdev);
err_register:
err_settings:
	netdev_nullify(netdev);
	netdev_put(netdev);
	return rc;
}

/** Remove the device */
static void tap_remove(struct linux_device *device)
{
	struct net_device *netdev = linux_get_drvdata(device);
	unregister_netdev(netdev);
	netdev_nullify(netdev);
	netdev_put(netdev);
}

/** Tap linux_driver */
struct linux_driver tap_driver __linux_driver = {
	.name = "tap",
	.probe = tap_probe,
	.remove = tap_remove,
	.can_probe = 1,
};
