aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/os-Linux/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/os-Linux/drivers')
-rw-r--r--arch/um/os-Linux/drivers/Makefile13
-rw-r--r--arch/um/os-Linux/drivers/etap.h27
-rw-r--r--arch/um/os-Linux/drivers/ethertap_kern.c119
-rw-r--r--arch/um/os-Linux/drivers/ethertap_user.c240
-rw-r--r--arch/um/os-Linux/drivers/tuntap.h32
-rw-r--r--arch/um/os-Linux/drivers/tuntap_kern.c104
-rw-r--r--arch/um/os-Linux/drivers/tuntap_user.c225
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 @@
1#
2# Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
3# Licensed under the GPL
4#
5
6ethertap-objs := ethertap_kern.o ethertap_user.o
7tuntap-objs := tuntap_kern.o tuntap_user.o
8
9obj-y =
10obj-$(CONFIG_UML_NET_ETHERTAP) += ethertap.o
11obj-$(CONFIG_UML_NET_TUNTAP) += tuntap.o
12
13include 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 @@
1/*
2 * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include "net_user.h"
7
8struct ethertap_data {
9 char *dev_name;
10 char *gate_addr;
11 int data_fd;
12 int control_fd;
13 void *dev;
14};
15
16extern struct net_user_info ethertap_user_info;
17
18/*
19 * Overrides for Emacs so that we follow Linus's tabbing style.
20 * Emacs will notice this stuff at the end of the file and automatically
21 * adjust the settings for this buffer only. This must remain at the end
22 * of the file.
23 * ---------------------------------------------------------------------------
24 * Local variables:
25 * c-file-style: "linux"
26 * End:
27 */
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 @@
1/*
2 * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
3 * James Leu (jleu@mindspring.net).
4 * Copyright (C) 2001 by various other people who didn't put their name here.
5 * Licensed under the GPL.
6 */
7
8#include "linux/init.h"
9#include "linux/netdevice.h"
10#include "linux/etherdevice.h"
11#include "net_kern.h"
12#include "net_user.h"
13#include "etap.h"
14
15struct ethertap_init {
16 char *dev_name;
17 char *gate_addr;
18};
19
20static void etap_init(struct net_device *dev, void *data)
21{
22 struct uml_net_private *pri;
23 struct ethertap_data *epri;
24 struct ethertap_init *init = data;
25
26 pri = dev->priv;
27 epri = (struct ethertap_data *) pri->user;
28 epri->dev_name = init->dev_name;
29 epri->gate_addr = init->gate_addr;
30 epri->data_fd = -1;
31 epri->control_fd = -1;
32 epri->dev = dev;
33
34 printk("ethertap backend - %s", epri->dev_name);
35 if (epri->gate_addr != NULL)
36 printk(", IP = %s", epri->gate_addr);
37 printk("\n");
38}
39
40static int etap_read(int fd, struct sk_buff **skb, struct uml_net_private *lp)
41{
42 int len;
43
44 *skb = ether_adjust_skb(*skb, ETH_HEADER_ETHERTAP);
45 if(*skb == NULL) return(-ENOMEM);
46 len = net_recvfrom(fd, (*skb)->mac.raw,
47 (*skb)->dev->mtu + 2 * ETH_HEADER_ETHERTAP);
48 if(len <= 0) return(len);
49 skb_pull(*skb, 2);
50 len -= 2;
51 return(len);
52}
53
54static int etap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp)
55{
56 if(skb_headroom(*skb) < 2){
57 struct sk_buff *skb2;
58
59 skb2 = skb_realloc_headroom(*skb, 2);
60 dev_kfree_skb(*skb);
61 if (skb2 == NULL) return(-ENOMEM);
62 *skb = skb2;
63 }
64 skb_push(*skb, 2);
65 return(net_send(fd, (*skb)->data, (*skb)->len));
66}
67
68struct net_kern_info ethertap_kern_info = {
69 .init = etap_init,
70 .protocol = eth_protocol,
71 .read = etap_read,
72 .write = etap_write,
73};
74
75int ethertap_setup(char *str, char **mac_out, void *data)
76{
77 struct ethertap_init *init = data;
78
79 *init = ((struct ethertap_init)
80 { .dev_name = NULL,
81 .gate_addr = NULL });
82 if(tap_setup_common(str, "ethertap", &init->dev_name, mac_out,
83 &init->gate_addr))
84 return(0);
85 if(init->dev_name == NULL){
86 printk("ethertap_setup : Missing tap device name\n");
87 return(0);
88 }
89
90 return(1);
91}
92
93static struct transport ethertap_transport = {
94 .list = LIST_HEAD_INIT(ethertap_transport.list),
95 .name = "ethertap",
96 .setup = ethertap_setup,
97 .user = &ethertap_user_info,
98 .kern = &ethertap_kern_info,
99 .private_size = sizeof(struct ethertap_data),
100};
101
102static int register_ethertap(void)
103{
104 register_transport(&ethertap_transport);
105 return(1);
106}
107
108__initcall(register_ethertap);
109
110/*
111 * Overrides for Emacs so that we follow Linus's tabbing style.
112 * Emacs will notice this stuff at the end of the file and automatically
113 * adjust the settings for this buffer only. This must remain at the end
114 * of the file.
115 * ---------------------------------------------------------------------------
116 * Local variables:
117 * c-file-style: "linux"
118 * End:
119 */
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 @@
1/*
2 * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
3 * James Leu (jleu@mindspring.net).
4 * Copyright (C) 2001 by various other people who didn't put their name here.
5 * Licensed under the GPL.
6 */
7
8#include <stdio.h>
9#include <unistd.h>
10#include <stddef.h>
11#include <stdlib.h>
12#include <sys/errno.h>
13#include <sys/socket.h>
14#include <sys/wait.h>
15#include <sys/un.h>
16#include <net/if.h>
17#include "user.h"
18#include "kern_util.h"
19#include "user_util.h"
20#include "net_user.h"
21#include "etap.h"
22#include "helper.h"
23#include "os.h"
24
25#define MAX_PACKET ETH_MAX_PACKET
26
27void etap_user_init(void *data, void *dev)
28{
29 struct ethertap_data *pri = data;
30
31 pri->dev = dev;
32}
33
34struct addr_change {
35 enum { ADD_ADDR, DEL_ADDR } what;
36 unsigned char addr[4];
37 unsigned char netmask[4];
38};
39
40static void etap_change(int op, unsigned char *addr, unsigned char *netmask,
41 int fd)
42{
43 struct addr_change change;
44 void *output;
45 int n;
46
47 change.what = op;
48 memcpy(change.addr, addr, sizeof(change.addr));
49 memcpy(change.netmask, netmask, sizeof(change.netmask));
50 n = os_write_file(fd, &change, sizeof(change));
51 if(n != sizeof(change))
52 printk("etap_change - request failed, err = %d\n", -n);
53 output = um_kmalloc(page_size());
54 if(output == NULL)
55 printk("etap_change : Failed to allocate output buffer\n");
56 read_output(fd, output, page_size());
57 if(output != NULL){
58 printk("%s", output);
59 kfree(output);
60 }
61}
62
63static void etap_open_addr(unsigned char *addr, unsigned char *netmask,
64 void *arg)
65{
66 etap_change(ADD_ADDR, addr, netmask, *((int *) arg));
67}
68
69static void etap_close_addr(unsigned char *addr, unsigned char *netmask,
70 void *arg)
71{
72 etap_change(DEL_ADDR, addr, netmask, *((int *) arg));
73}
74
75struct etap_pre_exec_data {
76 int control_remote;
77 int control_me;
78 int data_me;
79};
80
81static void etap_pre_exec(void *arg)
82{
83 struct etap_pre_exec_data *data = arg;
84
85 dup2(data->control_remote, 1);
86 os_close_file(data->data_me);
87 os_close_file(data->control_me);
88}
89
90static int etap_tramp(char *dev, char *gate, int control_me,
91 int control_remote, int data_me, int data_remote)
92{
93 struct etap_pre_exec_data pe_data;
94 int pid, status, err, n;
95 char version_buf[sizeof("nnnnn\0")];
96 char data_fd_buf[sizeof("nnnnnn\0")];
97 char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")];
98 char *setup_args[] = { "uml_net", version_buf, "ethertap", dev,
99 data_fd_buf, gate_buf, NULL };
100 char *nosetup_args[] = { "uml_net", version_buf, "ethertap",
101 dev, data_fd_buf, NULL };
102 char **args, c;
103
104 sprintf(data_fd_buf, "%d", data_remote);
105 sprintf(version_buf, "%d", UML_NET_VERSION);
106 if(gate != NULL){
107 strcpy(gate_buf, gate);
108 args = setup_args;
109 }
110 else args = nosetup_args;
111
112 err = 0;
113 pe_data.control_remote = control_remote;
114 pe_data.control_me = control_me;
115 pe_data.data_me = data_me;
116 pid = run_helper(etap_pre_exec, &pe_data, args, NULL);
117
118 if(pid < 0) err = pid;
119 os_close_file(data_remote);
120 os_close_file(control_remote);
121 n = os_read_file(control_me, &c, sizeof(c));
122 if(n != sizeof(c)){
123 printk("etap_tramp : read of status failed, err = %d\n", -n);
124 return(-EINVAL);
125 }
126 if(c != 1){
127 printk("etap_tramp : uml_net failed\n");
128 err = -EINVAL;
129 CATCH_EINTR(n = waitpid(pid, &status, 0));
130 if(n < 0)
131 err = -errno;
132 else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1))
133 printk("uml_net didn't exit with status 1\n");
134 }
135 return(err);
136}
137
138static int etap_open(void *data)
139{
140 struct ethertap_data *pri = data;
141 char *output;
142 int data_fds[2], control_fds[2], err, output_len;
143
144 err = tap_open_common(pri->dev, pri->gate_addr);
145 if(err) return(err);
146
147 err = os_pipe(data_fds, 0, 0);
148 if(err < 0){
149 printk("data os_pipe failed - err = %d\n", -err);
150 return(err);
151 }
152
153 err = os_pipe(control_fds, 1, 0);
154 if(err < 0){
155 printk("control os_pipe failed - err = %d\n", -err);
156 return(err);
157 }
158
159 err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0],
160 control_fds[1], data_fds[0], data_fds[1]);
161 output_len = page_size();
162 output = um_kmalloc(output_len);
163 read_output(control_fds[0], output, output_len);
164
165 if(output == NULL)
166 printk("etap_open : failed to allocate output buffer\n");
167 else {
168 printk("%s", output);
169 kfree(output);
170 }
171
172 if(err < 0){
173 printk("etap_tramp failed - err = %d\n", -err);
174 return(err);
175 }
176
177 pri->data_fd = data_fds[0];
178 pri->control_fd = control_fds[0];
179 iter_addresses(pri->dev, etap_open_addr, &pri->control_fd);
180 return(data_fds[0]);
181}
182
183static void etap_close(int fd, void *data)
184{
185 struct ethertap_data *pri = data;
186
187 iter_addresses(pri->dev, etap_close_addr, &pri->control_fd);
188 os_close_file(fd);
189 os_shutdown_socket(pri->data_fd, 1, 1);
190 os_close_file(pri->data_fd);
191 pri->data_fd = -1;
192 os_close_file(pri->control_fd);
193 pri->control_fd = -1;
194}
195
196static int etap_set_mtu(int mtu, void *data)
197{
198 return(mtu);
199}
200
201static void etap_add_addr(unsigned char *addr, unsigned char *netmask,
202 void *data)
203{
204 struct ethertap_data *pri = data;
205
206 tap_check_ips(pri->gate_addr, addr);
207 if(pri->control_fd == -1) return;
208 etap_open_addr(addr, netmask, &pri->control_fd);
209}
210
211static void etap_del_addr(unsigned char *addr, unsigned char *netmask,
212 void *data)
213{
214 struct ethertap_data *pri = data;
215
216 if(pri->control_fd == -1) return;
217 etap_close_addr(addr, netmask, &pri->control_fd);
218}
219
220struct net_user_info ethertap_user_info = {
221 .init = etap_user_init,
222 .open = etap_open,
223 .close = etap_close,
224 .remove = NULL,
225 .set_mtu = etap_set_mtu,
226 .add_address = etap_add_addr,
227 .delete_address = etap_del_addr,
228 .max_packet = MAX_PACKET - ETH_HEADER_ETHERTAP
229};
230
231/*
232 * Overrides for Emacs so that we follow Linus's tabbing style.
233 * Emacs will notice this stuff at the end of the file and automatically
234 * adjust the settings for this buffer only. This must remain at the end
235 * of the file.
236 * ---------------------------------------------------------------------------
237 * Local variables:
238 * c-file-style: "linux"
239 * End:
240 */
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 @@
1/*
2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __UM_TUNTAP_H
7#define __UM_TUNTAP_H
8
9#include "net_user.h"
10
11struct tuntap_data {
12 char *dev_name;
13 int fixed_config;
14 char *gate_addr;
15 int fd;
16 void *dev;
17};
18
19extern struct net_user_info tuntap_user_info;
20
21#endif
22
23/*
24 * Overrides for Emacs so that we follow Linus's tabbing style.
25 * Emacs will notice this stuff at the end of the file and automatically
26 * adjust the settings for this buffer only. This must remain at the end
27 * of the file.
28 * ---------------------------------------------------------------------------
29 * Local variables:
30 * c-file-style: "linux"
31 * End:
32 */
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 @@
1/*
2 * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include "linux/stddef.h"
7#include "linux/netdevice.h"
8#include "linux/etherdevice.h"
9#include "linux/skbuff.h"
10#include "linux/init.h"
11#include "asm/errno.h"
12#include "net_kern.h"
13#include "net_user.h"
14#include "tuntap.h"
15
16struct tuntap_init {
17 char *dev_name;
18 char *gate_addr;
19};
20
21static void tuntap_init(struct net_device *dev, void *data)
22{
23 struct uml_net_private *pri;
24 struct tuntap_data *tpri;
25 struct tuntap_init *init = data;
26
27 pri = dev->priv;
28 tpri = (struct tuntap_data *) pri->user;
29 tpri->dev_name = init->dev_name;
30 tpri->fixed_config = (init->dev_name != NULL);
31 tpri->gate_addr = init->gate_addr;
32 tpri->fd = -1;
33 tpri->dev = dev;
34
35 printk("TUN/TAP backend - ");
36 if (tpri->gate_addr != NULL)
37 printk("IP = %s", tpri->gate_addr);
38 printk("\n");
39}
40
41static int tuntap_read(int fd, struct sk_buff **skb,
42 struct uml_net_private *lp)
43{
44 *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER);
45 if(*skb == NULL) return(-ENOMEM);
46 return(net_read(fd, (*skb)->mac.raw,
47 (*skb)->dev->mtu + ETH_HEADER_OTHER));
48}
49
50static int tuntap_write(int fd, struct sk_buff **skb,
51 struct uml_net_private *lp)
52{
53 return(net_write(fd, (*skb)->data, (*skb)->len));
54}
55
56struct net_kern_info tuntap_kern_info = {
57 .init = tuntap_init,
58 .protocol = eth_protocol,
59 .read = tuntap_read,
60 .write = tuntap_write,
61};
62
63int tuntap_setup(char *str, char **mac_out, void *data)
64{
65 struct tuntap_init *init = data;
66
67 *init = ((struct tuntap_init)
68 { .dev_name = NULL,
69 .gate_addr = NULL });
70 if(tap_setup_common(str, "tuntap", &init->dev_name, mac_out,
71 &init->gate_addr))
72 return(0);
73
74 return(1);
75}
76
77static struct transport tuntap_transport = {
78 .list = LIST_HEAD_INIT(tuntap_transport.list),
79 .name = "tuntap",
80 .setup = tuntap_setup,
81 .user = &tuntap_user_info,
82 .kern = &tuntap_kern_info,
83 .private_size = sizeof(struct tuntap_data),
84 .setup_size = sizeof(struct tuntap_init),
85};
86
87static int register_tuntap(void)
88{
89 register_transport(&tuntap_transport);
90 return(1);
91}
92
93__initcall(register_tuntap);
94
95/*
96 * Overrides for Emacs so that we follow Linus's tabbing style.
97 * Emacs will notice this stuff at the end of the file and automatically
98 * adjust the settings for this buffer only. This must remain at the end
99 * of the file.
100 * ---------------------------------------------------------------------------
101 * Local variables:
102 * c-file-style: "linux"
103 * End:
104 */
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 @@
1/*
2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include <stdio.h>
7#include <stddef.h>
8#include <stdlib.h>
9#include <unistd.h>
10#include <errno.h>
11#include <sys/wait.h>
12#include <sys/socket.h>
13#include <sys/un.h>
14#include <sys/uio.h>
15#include <sys/ioctl.h>
16#include <net/if.h>
17#include <linux/if_tun.h>
18#include "net_user.h"
19#include "tuntap.h"
20#include "kern_util.h"
21#include "user_util.h"
22#include "user.h"
23#include "helper.h"
24#include "os.h"
25
26#define MAX_PACKET ETH_MAX_PACKET
27
28void tuntap_user_init(void *data, void *dev)
29{
30 struct tuntap_data *pri = data;
31
32 pri->dev = dev;
33}
34
35static void tuntap_add_addr(unsigned char *addr, unsigned char *netmask,
36 void *data)
37{
38 struct tuntap_data *pri = data;
39
40 tap_check_ips(pri->gate_addr, addr);
41 if((pri->fd == -1) || pri->fixed_config) return;
42 open_addr(addr, netmask, pri->dev_name);
43}
44
45static void tuntap_del_addr(unsigned char *addr, unsigned char *netmask,
46 void *data)
47{
48 struct tuntap_data *pri = data;
49
50 if((pri->fd == -1) || pri->fixed_config) return;
51 close_addr(addr, netmask, pri->dev_name);
52}
53
54struct tuntap_pre_exec_data {
55 int stdout;
56 int close_me;
57};
58
59static void tuntap_pre_exec(void *arg)
60{
61 struct tuntap_pre_exec_data *data = arg;
62
63 dup2(data->stdout, 1);
64 os_close_file(data->close_me);
65}
66
67static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
68 char *buffer, int buffer_len, int *used_out)
69{
70 struct tuntap_pre_exec_data data;
71 char version_buf[sizeof("nnnnn\0")];
72 char *argv[] = { "uml_net", version_buf, "tuntap", "up", gate,
73 NULL };
74 char buf[CMSG_SPACE(sizeof(*fd_out))];
75 struct msghdr msg;
76 struct cmsghdr *cmsg;
77 struct iovec iov;
78 int pid, n;
79
80 sprintf(version_buf, "%d", UML_NET_VERSION);
81
82 data.stdout = remote;
83 data.close_me = me;
84
85 pid = run_helper(tuntap_pre_exec, &data, argv, NULL);
86
87 if(pid < 0) return(-pid);
88
89 os_close_file(remote);
90
91 msg.msg_name = NULL;
92 msg.msg_namelen = 0;
93 if(buffer != NULL){
94 iov = ((struct iovec) { buffer, buffer_len });
95 msg.msg_iov = &iov;
96 msg.msg_iovlen = 1;
97 }
98 else {
99 msg.msg_iov = NULL;
100 msg.msg_iovlen = 0;
101 }
102 msg.msg_control = buf;
103 msg.msg_controllen = sizeof(buf);
104 msg.msg_flags = 0;
105 n = recvmsg(me, &msg, 0);
106 *used_out = n;
107 if(n < 0){
108 printk("tuntap_open_tramp : recvmsg failed - errno = %d\n",
109 errno);
110 return(-errno);
111 }
112 CATCH_EINTR(waitpid(pid, NULL, 0));
113
114 cmsg = CMSG_FIRSTHDR(&msg);
115 if(cmsg == NULL){
116 printk("tuntap_open_tramp : didn't receive a message\n");
117 return(-EINVAL);
118 }
119 if((cmsg->cmsg_level != SOL_SOCKET) ||
120 (cmsg->cmsg_type != SCM_RIGHTS)){
121 printk("tuntap_open_tramp : didn't receive a descriptor\n");
122 return(-EINVAL);
123 }
124 *fd_out = ((int *) CMSG_DATA(cmsg))[0];
125 return(0);
126}
127
128static int tuntap_open(void *data)
129{
130 struct ifreq ifr;
131 struct tuntap_data *pri = data;
132 char *output, *buffer;
133 int err, fds[2], len, used;
134
135 err = tap_open_common(pri->dev, pri->gate_addr);
136 if(err < 0)
137 return(err);
138
139 if(pri->fixed_config){
140 pri->fd = os_open_file("/dev/net/tun", of_rdwr(OPENFLAGS()), 0);
141 if(pri->fd < 0){
142 printk("Failed to open /dev/net/tun, err = %d\n",
143 -pri->fd);
144 return(pri->fd);
145 }
146 memset(&ifr, 0, sizeof(ifr));
147 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
148 strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name));
149 if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){
150 printk("TUNSETIFF failed, errno = %d\n", errno);
151 os_close_file(pri->fd);
152 return(-errno);
153 }
154 }
155 else {
156 err = os_pipe(fds, 0, 0);
157 if(err < 0){
158 printk("tuntap_open : os_pipe failed - err = %d\n",
159 -err);
160 return(err);
161 }
162
163 buffer = get_output_buffer(&len);
164 if(buffer != NULL) len--;
165 used = 0;
166
167 err = tuntap_open_tramp(pri->gate_addr, &pri->fd, fds[0],
168 fds[1], buffer, len, &used);
169
170 output = buffer;
171 if(err < 0) {
172 printk("%s", output);
173 free_output_buffer(buffer);
174 printk("tuntap_open_tramp failed - err = %d\n", -err);
175 return(err);
176 }
177
178 pri->dev_name = uml_strdup(buffer);
179 output += IFNAMSIZ;
180 printk("%s", output);
181 free_output_buffer(buffer);
182
183 os_close_file(fds[0]);
184 iter_addresses(pri->dev, open_addr, pri->dev_name);
185 }
186
187 return(pri->fd);
188}
189
190static void tuntap_close(int fd, void *data)
191{
192 struct tuntap_data *pri = data;
193
194 if(!pri->fixed_config)
195 iter_addresses(pri->dev, close_addr, pri->dev_name);
196 os_close_file(fd);
197 pri->fd = -1;
198}
199
200static int tuntap_set_mtu(int mtu, void *data)
201{
202 return(mtu);
203}
204
205struct net_user_info tuntap_user_info = {
206 .init = tuntap_user_init,
207 .open = tuntap_open,
208 .close = tuntap_close,
209 .remove = NULL,
210 .set_mtu = tuntap_set_mtu,
211 .add_address = tuntap_add_addr,
212 .delete_address = tuntap_del_addr,
213 .max_packet = MAX_PACKET
214};
215
216/*
217 * Overrides for Emacs so that we follow Linus's tabbing style.
218 * Emacs will notice this stuff at the end of the file and automatically
219 * adjust the settings for this buffer only. This must remain at the end
220 * of the file.
221 * ---------------------------------------------------------------------------
222 * Local variables:
223 * c-file-style: "linux"
224 * End:
225 */