/*
 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
 * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
 * James Leu (jleu@mindspring.net).
 * Copyright (C) 2001 by various other people who didn't put their name here.
 * Licensed under the GPL.
 */

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include "etap.h"
#include "kern_constants.h"
#include "os.h"
#include "net_user.h"
#include "um_malloc.h"
#include "user.h"

#define MAX_PACKET ETH_MAX_PACKET

static int etap_user_init(void *data, void *dev)
{
	struct ethertap_data *pri = data;

	pri->dev = dev;
	return 0;
}

struct addr_change {
	enum { ADD_ADDR, DEL_ADDR } what;
	unsigned char addr[4];
	unsigned char netmask[4];
};

static void etap_change(int op, unsigned char *addr, unsigned char *netmask,
			int fd)
{
	struct addr_change change;
	char *output;
	int n;

	change.what = op;
	memcpy(change.addr, addr, sizeof(change.addr));
	memcpy(change.netmask, netmask, sizeof(change.netmask));
	CATCH_EINTR(n = write(fd, &change, sizeof(change)));
	if (n != sizeof(change)) {
		printk(UM_KERN_ERR "etap_change - request failed, err = %d\n",
		       errno);
		return;
	}

	output = kmalloc(UM_KERN_PAGE_SIZE, UM_GFP_KERNEL);
	if (output == NULL)
		printk(UM_KERN_ERR "etap_change : Failed to allocate output "
		       "buffer\n");
	read_output(fd, output, UM_KERN_PAGE_SIZE);
	if (output != NULL) {
		printk("%s", output);
		kfree(output);
	}
}

static void etap_open_addr(unsigned char *addr, unsigned char *netmask,
			   void *arg)
{
	etap_change(ADD_ADDR, addr, netmask, *((int *) arg));
}

static void etap_close_addr(unsigned char *addr, unsigned char *netmask,
			    void *arg)
{
	etap_change(DEL_ADDR, addr, netmask, *((int *) arg));
}

struct etap_pre_exec_data {
	int control_remote;
	int control_me;
	int data_me;
};

static void etap_pre_exec(void *arg)
{
	struct etap_pre_exec_data *data = arg;

	dup2(data->control_remote, 1);
	close(data->data_me);
	close(data->control_me);
}

static int etap_tramp(char *dev, char *gate, int control_me,
		      int control_remote, int data_me, int data_remote)
{
	struct etap_pre_exec_data pe_data;
	int pid, status, err, n;
	char version_buf[sizeof("nnnnn\0")];
	char data_fd_buf[sizeof("nnnnnn\0")];
	char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")];
	char *setup_args[] = { "uml_net", version_buf, "ethertap", dev,
			       data_fd_buf, gate_buf, NULL };
	char *nosetup_args[] = { "uml_net", version_buf, "ethertap",
				 dev, data_fd_buf, NULL };
	char **args, c;

	sprintf(data_fd_buf, "%d", data_remote);
	sprintf(version_buf, "%d", UML_NET_VERSION);
	if (gate != NULL) {
		strcpy(gate_buf, gate);
		args = setup_args;
	}
	else args = nosetup_args;

	err = 0;
	pe_data.control_remote = control_remote;
	pe_data.control_me = control_me;
	pe_data.data_me = data_me;
	pid = run_helper(etap_pre_exec, &pe_data, args);

	if (pid < 0)
		err = pid;
	close(data_remote);
	close(control_remote);
	CATCH_EINTR(n = read(control_me, &c, sizeof(c)));
	if (n != sizeof(c)) {
		err = -errno;
		printk(UM_KERN_ERR "etap_tramp : read of status failed, "
		       "err = %d\n", -err);
		return err;
	}
	if (c != 1) {
		printk(UM_KERN_ERR "etap_tramp : uml_net failed\n");
		err = -EINVAL;
		CATCH_EINTR(n = waitpid(pid, &status, 0));
		if (n < 0)
			err = -errno;
		else if (!WIFEXITED(status) || (WEXITSTATUS(status) != 1))
			printk(UM_KERN_ERR "uml_net didn't exit with "
			       "status 1\n");
	}
	return err;
}

static int etap_open(void *data)
{
	struct ethertap_data *pri = data;
	char *output;
	int data_fds[2], control_fds[2], err, output_len;

	err = tap_open_common(pri->dev, pri->gate_addr);
	if (err)
		return err;

	err = socketpair(AF_UNIX, SOCK_DGRAM, 0, data_fds);
	if (err) {
		err = -errno;
		printk(UM_KERN_ERR "etap_open - data socketpair failed - "
		       "err = %d\n", errno);
		return err;
	}

	err = socketpair(AF_UNIX, SOCK_STREAM, 0, control_fds);
	if (err) {
		err = -errno;
		printk(UM_KERN_ERR "etap_open - control socketpair failed - "
		       "err = %d\n", errno);
		goto out_close_data;
	}

	err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0],
			 control_fds[1], data_fds[0], data_fds[1]);
	output_len = UM_KERN_PAGE_SIZE;
	output = kmalloc(output_len, UM_GFP_KERNEL);
	read_output(control_fds[0], output, output_len);

	if (output == NULL)
		printk(UM_KERN_ERR "etap_open : failed to allocate output "
		       "buffer\n");
	else {
		printk("%s", output);
		kfree(output);
	}

	if (err < 0) {
		printk(UM_KERN_ERR "etap_tramp failed - err = %d\n", -err);
		goto out_close_control;
	}

	pri->data_fd = data_fds[0];
	pri->control_fd = control_fds[0];
	iter_addresses(pri->dev, etap_open_addr, &pri->control_fd);
	return data_fds[0];

out_close_control:
	close(control_fds[0]);
	close(control_fds[1]);
out_close_data:
	close(data_fds[0]);
	close(data_fds[1]);
	return err;
}

static void etap_close(int fd, void *data)
{
	struct ethertap_data *pri = data;

	iter_addresses(pri->dev, etap_close_addr, &pri->control_fd);
	close(fd);

	if (shutdown(pri->data_fd, SHUT_RDWR) < 0)
		printk(UM_KERN_ERR "etap_close - shutdown data socket failed, "
		       "errno = %d\n", errno);

	if (shutdown(pri->control_fd, SHUT_RDWR) < 0)
		printk(UM_KERN_ERR "etap_close - shutdown control socket "
		       "failed, errno = %d\n", errno);

	close(pri->data_fd);
	pri->data_fd = -1;
	close(pri->control_fd);
	pri->control_fd = -1;
}

static void etap_add_addr(unsigned char *addr, unsigned char *netmask,
			  void *data)
{
	struct ethertap_data *pri = data;

	tap_check_ips(pri->gate_addr, addr);
	if (pri->control_fd == -1)
		return;
	etap_open_addr(addr, netmask, &pri->control_fd);
}

static void etap_del_addr(unsigned char *addr, unsigned char *netmask,
			  void *data)
{
	struct ethertap_data *pri = data;

	if (pri->control_fd == -1)
		return;

	etap_close_addr(addr, netmask, &pri->control_fd);
}

const struct net_user_info ethertap_user_info = {
	.init		= etap_user_init,
	.open		= etap_open,
	.close	 	= etap_close,
	.remove	 	= NULL,
	.add_address	= etap_add_addr,
	.delete_address = etap_del_addr,
	.mtu		= ETH_MAX_PACKET,
	.max_packet	= ETH_MAX_PACKET + ETH_HEADER_ETHERTAP,
};
