/*
 * 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 <stddef.h>
#include <stdlib.h>
#include <sys/errno.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/un.h>
#include <net/if.h>
#include "user.h"
#include "kern_util.h"
#include "user_util.h"
#include "net_user.h"
#include "etap.h"
#include "os.h"

#define MAX_PACKET ETH_MAX_PACKET

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

	pri->dev = dev;
}

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));
	n = os_write_file(fd, &change, sizeof(change));
	if(n != sizeof(change))
		printk("etap_change - request failed, err = %d\n", -n);
	output = um_kmalloc(page_size());
	if(output == NULL)
		printk("etap_change : Failed to allocate output buffer\n");
	read_output(fd, output, 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);
	os_close_file(data->data_me);
	os_close_file(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, NULL);

	if(pid < 0) err = pid;
	os_close_file(data_remote);
	os_close_file(control_remote);
	n = os_read_file(control_me, &c, sizeof(c));
	if(n != sizeof(c)){
		printk("etap_tramp : read of status failed, err = %d\n", -n);
		return(-EINVAL);
	}
	if(c != 1){
		printk("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("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 = os_pipe(data_fds, 0, 0);
	if(err < 0){
		printk("data os_pipe failed - err = %d\n", -err);
		return(err);
	}

	err = os_pipe(control_fds, 1, 0);
	if(err < 0){
		printk("control os_pipe failed - err = %d\n", -err);
		return(err);
	}
	
	err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0], 
			 control_fds[1], data_fds[0], data_fds[1]);
	output_len = page_size();
	output = um_kmalloc(output_len);
	read_output(control_fds[0], output, output_len);

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

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

	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]);
}

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

	iter_addresses(pri->dev, etap_close_addr, &pri->control_fd);
	os_close_file(fd);
	os_shutdown_socket(pri->data_fd, 1, 1);
	os_close_file(pri->data_fd);
	pri->data_fd = -1;
	os_close_file(pri->control_fd);
	pri->control_fd = -1;
}

static int etap_set_mtu(int mtu, void *data)
{
	return(mtu);
}

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);
}

struct net_user_info ethertap_user_info = {
	.init		= etap_user_init,
	.open		= etap_open,
	.close	 	= etap_close,
	.remove	 	= NULL,
	.set_mtu	= etap_set_mtu,
	.add_address	= etap_add_addr,
	.delete_address = etap_del_addr,
	.max_packet	= MAX_PACKET - ETH_HEADER_ETHERTAP
};

/*
 * Overrides for Emacs so that we follow Linus's tabbing style.
 * Emacs will notice this stuff at the end of the file and automatically
 * adjust the settings for this buffer only.  This must remain at the end
 * of the file.
 * ---------------------------------------------------------------------------
 * Local variables:
 * c-file-style: "linux"
 * End:
 */
