2 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
4 * James Leu (jleu@mindspring.net).
5 * Copyright (C) 2001 by various other people who didn't put their name here.
6 * Licensed under the GPL.
13 #include <sys/socket.h>
18 #include <um_malloc.h>
20 #define MAX_PACKET ETH_MAX_PACKET
22 static int etap_user_init(void *data
, void *dev
)
24 struct ethertap_data
*pri
= data
;
31 enum { ADD_ADDR
, DEL_ADDR
} what
;
32 unsigned char addr
[4];
33 unsigned char netmask
[4];
36 static void etap_change(int op
, unsigned char *addr
, unsigned char *netmask
,
39 struct addr_change change
;
44 memcpy(change
.addr
, addr
, sizeof(change
.addr
));
45 memcpy(change
.netmask
, netmask
, sizeof(change
.netmask
));
46 CATCH_EINTR(n
= write(fd
, &change
, sizeof(change
)));
47 if (n
!= sizeof(change
)) {
48 printk(UM_KERN_ERR
"etap_change - request failed, err = %d\n",
53 output
= uml_kmalloc(UM_KERN_PAGE_SIZE
, UM_GFP_KERNEL
);
55 printk(UM_KERN_ERR
"etap_change : Failed to allocate output "
57 read_output(fd
, output
, UM_KERN_PAGE_SIZE
);
64 static void etap_open_addr(unsigned char *addr
, unsigned char *netmask
,
67 etap_change(ADD_ADDR
, addr
, netmask
, *((int *) arg
));
70 static void etap_close_addr(unsigned char *addr
, unsigned char *netmask
,
73 etap_change(DEL_ADDR
, addr
, netmask
, *((int *) arg
));
76 struct etap_pre_exec_data
{
82 static void etap_pre_exec(void *arg
)
84 struct etap_pre_exec_data
*data
= arg
;
86 dup2(data
->control_remote
, 1);
88 close(data
->control_me
);
91 static int etap_tramp(char *dev
, char *gate
, int control_me
,
92 int control_remote
, int data_me
, int data_remote
)
94 struct etap_pre_exec_data pe_data
;
96 char version_buf
[sizeof("nnnnn\0")];
97 char data_fd_buf
[sizeof("nnnnnn\0")];
98 char gate_buf
[sizeof("nnn.nnn.nnn.nnn\0")];
99 char *setup_args
[] = { "uml_net", version_buf
, "ethertap", dev
,
100 data_fd_buf
, gate_buf
, NULL
};
101 char *nosetup_args
[] = { "uml_net", version_buf
, "ethertap",
102 dev
, data_fd_buf
, NULL
};
105 sprintf(data_fd_buf
, "%d", data_remote
);
106 sprintf(version_buf
, "%d", UML_NET_VERSION
);
108 strncpy(gate_buf
, gate
, 15);
111 else args
= nosetup_args
;
114 pe_data
.control_remote
= control_remote
;
115 pe_data
.control_me
= control_me
;
116 pe_data
.data_me
= data_me
;
117 pid
= run_helper(etap_pre_exec
, &pe_data
, args
);
122 close(control_remote
);
123 CATCH_EINTR(n
= read(control_me
, &c
, sizeof(c
)));
124 if (n
!= sizeof(c
)) {
126 printk(UM_KERN_ERR
"etap_tramp : read of status failed, "
131 printk(UM_KERN_ERR
"etap_tramp : uml_net failed\n");
132 err
= helper_wait(pid
);
137 static int etap_open(void *data
)
139 struct ethertap_data
*pri
= data
;
141 int data_fds
[2], control_fds
[2], err
, output_len
;
143 err
= tap_open_common(pri
->dev
, pri
->gate_addr
);
147 err
= socketpair(AF_UNIX
, SOCK_DGRAM
, 0, data_fds
);
150 printk(UM_KERN_ERR
"etap_open - data socketpair failed - "
151 "err = %d\n", errno
);
155 err
= socketpair(AF_UNIX
, SOCK_STREAM
, 0, control_fds
);
158 printk(UM_KERN_ERR
"etap_open - control socketpair failed - "
159 "err = %d\n", errno
);
163 err
= etap_tramp(pri
->dev_name
, pri
->gate_addr
, control_fds
[0],
164 control_fds
[1], data_fds
[0], data_fds
[1]);
165 output_len
= UM_KERN_PAGE_SIZE
;
166 output
= uml_kmalloc(output_len
, UM_GFP_KERNEL
);
167 read_output(control_fds
[0], output
, output_len
);
170 printk(UM_KERN_ERR
"etap_open : failed to allocate output "
173 printk("%s", output
);
178 printk(UM_KERN_ERR
"etap_tramp failed - err = %d\n", -err
);
179 goto out_close_control
;
182 pri
->data_fd
= data_fds
[0];
183 pri
->control_fd
= control_fds
[0];
184 iter_addresses(pri
->dev
, etap_open_addr
, &pri
->control_fd
);
188 close(control_fds
[0]);
189 close(control_fds
[1]);
196 static void etap_close(int fd
, void *data
)
198 struct ethertap_data
*pri
= data
;
200 iter_addresses(pri
->dev
, etap_close_addr
, &pri
->control_fd
);
203 if (shutdown(pri
->data_fd
, SHUT_RDWR
) < 0)
204 printk(UM_KERN_ERR
"etap_close - shutdown data socket failed, "
205 "errno = %d\n", errno
);
207 if (shutdown(pri
->control_fd
, SHUT_RDWR
) < 0)
208 printk(UM_KERN_ERR
"etap_close - shutdown control socket "
209 "failed, errno = %d\n", errno
);
213 close(pri
->control_fd
);
214 pri
->control_fd
= -1;
217 static void etap_add_addr(unsigned char *addr
, unsigned char *netmask
,
220 struct ethertap_data
*pri
= data
;
222 tap_check_ips(pri
->gate_addr
, addr
);
223 if (pri
->control_fd
== -1)
225 etap_open_addr(addr
, netmask
, &pri
->control_fd
);
228 static void etap_del_addr(unsigned char *addr
, unsigned char *netmask
,
231 struct ethertap_data
*pri
= data
;
233 if (pri
->control_fd
== -1)
236 etap_close_addr(addr
, netmask
, &pri
->control_fd
);
239 const struct net_user_info ethertap_user_info
= {
240 .init
= etap_user_init
,
244 .add_address
= etap_add_addr
,
245 .delete_address
= etap_del_addr
,
246 .mtu
= ETH_MAX_PACKET
,
247 .max_packet
= ETH_MAX_PACKET
+ ETH_HEADER_ETHERTAP
,