diff options
| author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 | 
| commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
| tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/um/os-Linux/drivers | |
| download | linux-1da177e4c3f41524e886b7f1b8a0c1fc7321cac2.tar.bz2 | |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/um/os-Linux/drivers')
| -rw-r--r-- | arch/um/os-Linux/drivers/Makefile | 13 | ||||
| -rw-r--r-- | arch/um/os-Linux/drivers/etap.h | 27 | ||||
| -rw-r--r-- | arch/um/os-Linux/drivers/ethertap_kern.c | 119 | ||||
| -rw-r--r-- | arch/um/os-Linux/drivers/ethertap_user.c | 240 | ||||
| -rw-r--r-- | arch/um/os-Linux/drivers/tuntap.h | 32 | ||||
| -rw-r--r-- | arch/um/os-Linux/drivers/tuntap_kern.c | 104 | ||||
| -rw-r--r-- | arch/um/os-Linux/drivers/tuntap_user.c | 225 | 
7 files changed, 760 insertions, 0 deletions
| diff --git a/arch/um/os-Linux/drivers/Makefile b/arch/um/os-Linux/drivers/Makefile new file mode 100644 index 000000000000..6c546dc9222b --- /dev/null +++ b/arch/um/os-Linux/drivers/Makefile @@ -0,0 +1,13 @@ +#  +# Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) +# Licensed under the GPL +# + +ethertap-objs := ethertap_kern.o ethertap_user.o +tuntap-objs := tuntap_kern.o tuntap_user.o + +obj-y =  +obj-$(CONFIG_UML_NET_ETHERTAP) += ethertap.o +obj-$(CONFIG_UML_NET_TUNTAP) += tuntap.o + +include arch/um/scripts/Makefile.rules diff --git a/arch/um/os-Linux/drivers/etap.h b/arch/um/os-Linux/drivers/etap.h new file mode 100644 index 000000000000..b84f6c4740f7 --- /dev/null +++ b/arch/um/os-Linux/drivers/etap.h @@ -0,0 +1,27 @@ +/*  + * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include "net_user.h" + +struct ethertap_data { +	char *dev_name; +	char *gate_addr; +	int data_fd; +	int control_fd; +	void *dev; +}; + +extern struct net_user_info ethertap_user_info; + +/* + * 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: + */ diff --git a/arch/um/os-Linux/drivers/ethertap_kern.c b/arch/um/os-Linux/drivers/ethertap_kern.c new file mode 100644 index 000000000000..6ae4b19d9f50 --- /dev/null +++ b/arch/um/os-Linux/drivers/ethertap_kern.c @@ -0,0 +1,119 @@ +/* + * 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 "linux/init.h" +#include "linux/netdevice.h" +#include "linux/etherdevice.h" +#include "net_kern.h" +#include "net_user.h" +#include "etap.h" + +struct ethertap_init { +	char *dev_name; +	char *gate_addr; +}; + +static void etap_init(struct net_device *dev, void *data) +{ +	struct uml_net_private *pri; +	struct ethertap_data *epri; +	struct ethertap_init *init = data; + +	pri = dev->priv; +	epri = (struct ethertap_data *) pri->user; +	epri->dev_name = init->dev_name; +	epri->gate_addr = init->gate_addr; +	epri->data_fd = -1; +	epri->control_fd = -1; +	epri->dev = dev; + +	printk("ethertap backend - %s", epri->dev_name); +	if (epri->gate_addr != NULL) +		printk(", IP = %s", epri->gate_addr); +	printk("\n"); +} + +static int etap_read(int fd, struct sk_buff **skb, struct uml_net_private *lp) +{ +	int len; + +	*skb = ether_adjust_skb(*skb, ETH_HEADER_ETHERTAP); +	if(*skb == NULL) return(-ENOMEM); +	len = net_recvfrom(fd, (*skb)->mac.raw,  +			   (*skb)->dev->mtu + 2 * ETH_HEADER_ETHERTAP); +	if(len <= 0) return(len); +	skb_pull(*skb, 2); +	len -= 2; +	return(len); +} + +static int etap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) +{ +	if(skb_headroom(*skb) < 2){ +	  	struct sk_buff *skb2; + +		skb2 = skb_realloc_headroom(*skb, 2); +		dev_kfree_skb(*skb); +		if (skb2 == NULL) return(-ENOMEM); +		*skb = skb2; +	} +	skb_push(*skb, 2); +	return(net_send(fd, (*skb)->data, (*skb)->len)); +} + +struct net_kern_info ethertap_kern_info = { +	.init			= etap_init, +	.protocol		= eth_protocol, +	.read			= etap_read, +	.write 			= etap_write, +}; + +int ethertap_setup(char *str, char **mac_out, void *data) +{ +	struct ethertap_init *init = data; + +	*init = ((struct ethertap_init) +		{ .dev_name 	= NULL, +		  .gate_addr 	= NULL }); +	if(tap_setup_common(str, "ethertap", &init->dev_name, mac_out, +			    &init->gate_addr)) +		return(0); +	if(init->dev_name == NULL){ +		printk("ethertap_setup : Missing tap device name\n"); +		return(0); +	} + +	return(1); +} + +static struct transport ethertap_transport = { +	.list 		= LIST_HEAD_INIT(ethertap_transport.list), +	.name 		= "ethertap", +	.setup  	= ethertap_setup, +	.user 		= ðertap_user_info, +	.kern 		= ðertap_kern_info, +	.private_size 	= sizeof(struct ethertap_data), +}; + +static int register_ethertap(void) +{ +	register_transport(ðertap_transport); +	return(1); +} + +__initcall(register_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: + */ diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c new file mode 100644 index 000000000000..cd4d6544da71 --- /dev/null +++ b/arch/um/os-Linux/drivers/ethertap_user.c @@ -0,0 +1,240 @@ +/* + * 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 "helper.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; +	void *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: + */ diff --git a/arch/um/os-Linux/drivers/tuntap.h b/arch/um/os-Linux/drivers/tuntap.h new file mode 100644 index 000000000000..25d4a2868814 --- /dev/null +++ b/arch/um/os-Linux/drivers/tuntap.h @@ -0,0 +1,32 @@ +/*  + * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __UM_TUNTAP_H +#define __UM_TUNTAP_H + +#include "net_user.h" + +struct tuntap_data { +	char *dev_name; +	int fixed_config; +	char *gate_addr; +	int fd; +	void *dev; +}; + +extern struct net_user_info tuntap_user_info; + +#endif + +/* + * 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: + */ diff --git a/arch/um/os-Linux/drivers/tuntap_kern.c b/arch/um/os-Linux/drivers/tuntap_kern.c new file mode 100644 index 000000000000..4202b9ebad4c --- /dev/null +++ b/arch/um/os-Linux/drivers/tuntap_kern.c @@ -0,0 +1,104 @@ +/*  + * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include "linux/stddef.h" +#include "linux/netdevice.h" +#include "linux/etherdevice.h" +#include "linux/skbuff.h" +#include "linux/init.h" +#include "asm/errno.h" +#include "net_kern.h" +#include "net_user.h" +#include "tuntap.h" + +struct tuntap_init { +	char *dev_name; +	char *gate_addr; +}; + +static void tuntap_init(struct net_device *dev, void *data) +{ +	struct uml_net_private *pri; +	struct tuntap_data *tpri; +	struct tuntap_init *init = data; + +	pri = dev->priv; +	tpri = (struct tuntap_data *) pri->user; +	tpri->dev_name = init->dev_name; +	tpri->fixed_config = (init->dev_name != NULL); +	tpri->gate_addr = init->gate_addr; +	tpri->fd = -1; +	tpri->dev = dev; + +	printk("TUN/TAP backend - "); +	if (tpri->gate_addr != NULL) +		printk("IP = %s", tpri->gate_addr); +	printk("\n"); +} + +static int tuntap_read(int fd, struct sk_buff **skb,  +		       struct uml_net_private *lp) +{ +	*skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); +	if(*skb == NULL) return(-ENOMEM); +	return(net_read(fd, (*skb)->mac.raw,  +			(*skb)->dev->mtu + ETH_HEADER_OTHER)); +} + +static int tuntap_write(int fd, struct sk_buff **skb,  +			struct uml_net_private *lp) +{ +	return(net_write(fd, (*skb)->data, (*skb)->len)); +} + +struct net_kern_info tuntap_kern_info = { +	.init			= tuntap_init, +	.protocol		= eth_protocol, +	.read			= tuntap_read, +	.write 			= tuntap_write, +}; + +int tuntap_setup(char *str, char **mac_out, void *data) +{ +	struct tuntap_init *init = data; + +	*init = ((struct tuntap_init) +		{ .dev_name 	= NULL, +		  .gate_addr 	= NULL }); +	if(tap_setup_common(str, "tuntap", &init->dev_name, mac_out, +			    &init->gate_addr)) +		return(0); + +	return(1); +} + +static struct transport tuntap_transport = { +	.list 		= LIST_HEAD_INIT(tuntap_transport.list), +	.name 		= "tuntap", +	.setup  	= tuntap_setup, +	.user 		= &tuntap_user_info, +	.kern 		= &tuntap_kern_info, +	.private_size 	= sizeof(struct tuntap_data), +	.setup_size 	= sizeof(struct tuntap_init), +}; + +static int register_tuntap(void) +{ +	register_transport(&tuntap_transport); +	return(1); +} + +__initcall(register_tuntap); + +/* + * 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: + */ diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c new file mode 100644 index 000000000000..4b83c6c3f48d --- /dev/null +++ b/arch/um/os-Linux/drivers/tuntap_user.c @@ -0,0 +1,225 @@ +/*  + * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include <stdio.h> +#include <stddef.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <sys/wait.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <sys/uio.h> +#include <sys/ioctl.h> +#include <net/if.h> +#include <linux/if_tun.h> +#include "net_user.h" +#include "tuntap.h" +#include "kern_util.h" +#include "user_util.h" +#include "user.h" +#include "helper.h" +#include "os.h" + +#define MAX_PACKET ETH_MAX_PACKET + +void tuntap_user_init(void *data, void *dev) +{ +	struct tuntap_data *pri = data; + +	pri->dev = dev; +} + +static void tuntap_add_addr(unsigned char *addr, unsigned char *netmask, +			    void *data) +{ +	struct tuntap_data *pri = data; + +	tap_check_ips(pri->gate_addr, addr); +	if((pri->fd == -1) || pri->fixed_config) return; +	open_addr(addr, netmask, pri->dev_name); +} + +static void tuntap_del_addr(unsigned char *addr, unsigned char *netmask, +			    void *data) +{ +	struct tuntap_data *pri = data; + +	if((pri->fd == -1) || pri->fixed_config) return; +	close_addr(addr, netmask, pri->dev_name); +} + +struct tuntap_pre_exec_data { +	int stdout; +	int close_me; +}; + +static void tuntap_pre_exec(void *arg) +{ +	struct tuntap_pre_exec_data *data = arg; +	 +	dup2(data->stdout, 1); +	os_close_file(data->close_me); +} + +static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, +			     char *buffer, int buffer_len, int *used_out) +{ +	struct tuntap_pre_exec_data data; +	char version_buf[sizeof("nnnnn\0")]; +	char *argv[] = { "uml_net", version_buf, "tuntap", "up", gate, +			 NULL }; +	char buf[CMSG_SPACE(sizeof(*fd_out))]; +	struct msghdr msg; +	struct cmsghdr *cmsg; +	struct iovec iov; +	int pid, n; + +	sprintf(version_buf, "%d", UML_NET_VERSION); + +	data.stdout = remote; +	data.close_me = me; + +	pid = run_helper(tuntap_pre_exec, &data, argv, NULL); + +	if(pid < 0) return(-pid); + +	os_close_file(remote); + +	msg.msg_name = NULL; +	msg.msg_namelen = 0; +	if(buffer != NULL){ +		iov = ((struct iovec) { buffer, buffer_len }); +		msg.msg_iov = &iov; +		msg.msg_iovlen = 1; +	} +	else { +		msg.msg_iov = NULL; +		msg.msg_iovlen = 0; +	} +	msg.msg_control = buf; +	msg.msg_controllen = sizeof(buf); +	msg.msg_flags = 0; +	n = recvmsg(me, &msg, 0); +	*used_out = n; +	if(n < 0){ +		printk("tuntap_open_tramp : recvmsg failed - errno = %d\n",  +		       errno); +		return(-errno); +	} +	CATCH_EINTR(waitpid(pid, NULL, 0)); + +	cmsg = CMSG_FIRSTHDR(&msg); +	if(cmsg == NULL){ +		printk("tuntap_open_tramp : didn't receive a message\n"); +		return(-EINVAL); +	} +	if((cmsg->cmsg_level != SOL_SOCKET) ||  +	   (cmsg->cmsg_type != SCM_RIGHTS)){ +		printk("tuntap_open_tramp : didn't receive a descriptor\n"); +		return(-EINVAL); +	} +	*fd_out = ((int *) CMSG_DATA(cmsg))[0]; +	return(0); +} + +static int tuntap_open(void *data) +{ +	struct ifreq ifr; +	struct tuntap_data *pri = data; +	char *output, *buffer; +	int err, fds[2], len, used; + +	err = tap_open_common(pri->dev, pri->gate_addr); +	if(err < 0) +		return(err); + +	if(pri->fixed_config){ +		pri->fd = os_open_file("/dev/net/tun", of_rdwr(OPENFLAGS()), 0); +		if(pri->fd < 0){ +			printk("Failed to open /dev/net/tun, err = %d\n", +			       -pri->fd); +			return(pri->fd); +		} +		memset(&ifr, 0, sizeof(ifr)); +		ifr.ifr_flags = IFF_TAP | IFF_NO_PI; +		strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name)); +		if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){ +			printk("TUNSETIFF failed, errno = %d\n", errno); +			os_close_file(pri->fd); +			return(-errno); +		} +	} +	else { +		err = os_pipe(fds, 0, 0); +		if(err < 0){ +			printk("tuntap_open : os_pipe failed - err = %d\n", +			       -err); +			return(err); +		} + +		buffer = get_output_buffer(&len); +		if(buffer != NULL) len--; +		used = 0; + +		err = tuntap_open_tramp(pri->gate_addr, &pri->fd, fds[0], +					fds[1], buffer, len, &used); + +		output = buffer; +		if(err < 0) { +			printk("%s", output); +			free_output_buffer(buffer); +			printk("tuntap_open_tramp failed - err = %d\n", -err); +			return(err); +		} + +		pri->dev_name = uml_strdup(buffer); +		output += IFNAMSIZ; +		printk("%s", output); +		free_output_buffer(buffer); + +		os_close_file(fds[0]); +		iter_addresses(pri->dev, open_addr, pri->dev_name); +	} + +	return(pri->fd); +} + +static void tuntap_close(int fd, void *data) +{ +	struct tuntap_data *pri = data; + +	if(!pri->fixed_config)  +		iter_addresses(pri->dev, close_addr, pri->dev_name); +	os_close_file(fd); +	pri->fd = -1; +} + +static int tuntap_set_mtu(int mtu, void *data) +{ +	return(mtu); +} + +struct net_user_info tuntap_user_info = { +	.init		= tuntap_user_init, +	.open		= tuntap_open, +	.close	 	= tuntap_close, +	.remove	 	= NULL, +	.set_mtu	= tuntap_set_mtu, +	.add_address	= tuntap_add_addr, +	.delete_address = tuntap_del_addr, +	.max_packet	= MAX_PACKET +}; + +/* + * 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: + */ |