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>
16 #include "kern_constants.h"
19 #include "um_malloc.h"
22 #define MAX_PACKET ETH_MAX_PACKET
24 static int etap_user_init(void *data
, void *dev
)
26 struct ethertap_data
*pri
= data
;
33 enum { ADD_ADDR
, DEL_ADDR
} what
;
34 unsigned char addr
[4];
35 unsigned char netmask
[4];
38 static void etap_change(int op
, unsigned char *addr
, unsigned char *netmask
,
41 struct addr_change change
;
46 memcpy(change
.addr
, addr
, sizeof(change
.addr
));
47 memcpy(change
.netmask
, netmask
, sizeof(change
.netmask
));
48 CATCH_EINTR(n
= write(fd
, &change
, sizeof(change
)));
49 if (n
!= sizeof(change
)) {
50 printk(UM_KERN_ERR
"etap_change - request failed, err = %d\n",
55 output
= kmalloc(UM_KERN_PAGE_SIZE
, UM_GFP_KERNEL
);
57 printk(UM_KERN_ERR
"etap_change : Failed to allocate output "
59 read_output(fd
, output
, UM_KERN_PAGE_SIZE
);
66 static void etap_open_addr(unsigned char *addr
, unsigned char *netmask
,
69 etap_change(ADD_ADDR
, addr
, netmask
, *((int *) arg
));
72 static void etap_close_addr(unsigned char *addr
, unsigned char *netmask
,
75 etap_change(DEL_ADDR
, addr
, netmask
, *((int *) arg
));
78 struct etap_pre_exec_data
{
84 static void etap_pre_exec(void *arg
)
86 struct etap_pre_exec_data
*data
= arg
;
88 dup2(data
->control_remote
, 1);
90 close(data
->control_me
);
93 static int etap_tramp(char *dev
, char *gate
, int control_me
,
94 int control_remote
, int data_me
, int data_remote
)
96 struct etap_pre_exec_data pe_data
;
98 char version_buf
[sizeof("nnnnn\0")];
99 char data_fd_buf
[sizeof("nnnnnn\0")];
100 char gate_buf
[sizeof("nnn.nnn.nnn.nnn\0")];
101 char *setup_args
[] = { "uml_net", version_buf
, "ethertap", dev
,
102 data_fd_buf
, gate_buf
, NULL
};
103 char *nosetup_args
[] = { "uml_net", version_buf
, "ethertap",
104 dev
, data_fd_buf
, NULL
};
107 sprintf(data_fd_buf
, "%d", data_remote
);
108 sprintf(version_buf
, "%d", UML_NET_VERSION
);
110 strcpy(gate_buf
, gate
);
113 else args
= nosetup_args
;
116 pe_data
.control_remote
= control_remote
;
117 pe_data
.control_me
= control_me
;
118 pe_data
.data_me
= data_me
;
119 pid
= run_helper(etap_pre_exec
, &pe_data
, args
);
124 close(control_remote
);
125 CATCH_EINTR(n
= read(control_me
, &c
, sizeof(c
)));
126 if (n
!= sizeof(c
)) {
128 printk(UM_KERN_ERR
"etap_tramp : read of status failed, "
133 printk(UM_KERN_ERR
"etap_tramp : uml_net failed\n");
134 err
= helper_wait(pid
);
139 static int etap_open(void *data
)
141 struct ethertap_data
*pri
= data
;
143 int data_fds
[2], control_fds
[2], err
, output_len
;
145 err
= tap_open_common(pri
->dev
, pri
->gate_addr
);
149 err
= socketpair(AF_UNIX
, SOCK_DGRAM
, 0, data_fds
);
152 printk(UM_KERN_ERR
"etap_open - data socketpair failed - "
153 "err = %d\n", errno
);
157 err
= socketpair(AF_UNIX
, SOCK_STREAM
, 0, control_fds
);
160 printk(UM_KERN_ERR
"etap_open - control socketpair failed - "
161 "err = %d\n", errno
);
165 err
= etap_tramp(pri
->dev_name
, pri
->gate_addr
, control_fds
[0],
166 control_fds
[1], data_fds
[0], data_fds
[1]);
167 output_len
= UM_KERN_PAGE_SIZE
;
168 output
= kmalloc(output_len
, UM_GFP_KERNEL
);
169 read_output(control_fds
[0], output
, output_len
);
172 printk(UM_KERN_ERR
"etap_open : failed to allocate output "
175 printk("%s", output
);
180 printk(UM_KERN_ERR
"etap_tramp failed - err = %d\n", -err
);
181 goto out_close_control
;
184 pri
->data_fd
= data_fds
[0];
185 pri
->control_fd
= control_fds
[0];
186 iter_addresses(pri
->dev
, etap_open_addr
, &pri
->control_fd
);
190 close(control_fds
[0]);
191 close(control_fds
[1]);
198 static void etap_close(int fd
, void *data
)
200 struct ethertap_data
*pri
= data
;
202 iter_addresses(pri
->dev
, etap_close_addr
, &pri
->control_fd
);
205 if (shutdown(pri
->data_fd
, SHUT_RDWR
) < 0)
206 printk(UM_KERN_ERR
"etap_close - shutdown data socket failed, "
207 "errno = %d\n", errno
);
209 if (shutdown(pri
->control_fd
, SHUT_RDWR
) < 0)
210 printk(UM_KERN_ERR
"etap_close - shutdown control socket "
211 "failed, errno = %d\n", errno
);
215 close(pri
->control_fd
);
216 pri
->control_fd
= -1;
219 static void etap_add_addr(unsigned char *addr
, unsigned char *netmask
,
222 struct ethertap_data
*pri
= data
;
224 tap_check_ips(pri
->gate_addr
, addr
);
225 if (pri
->control_fd
== -1)
227 etap_open_addr(addr
, netmask
, &pri
->control_fd
);
230 static void etap_del_addr(unsigned char *addr
, unsigned char *netmask
,
233 struct ethertap_data
*pri
= data
;
235 if (pri
->control_fd
== -1)
238 etap_close_addr(addr
, netmask
, &pri
->control_fd
);
241 const struct net_user_info ethertap_user_info
= {
242 .init
= etap_user_init
,
246 .add_address
= etap_add_addr
,
247 .delete_address
= etap_del_addr
,
248 .mtu
= ETH_MAX_PACKET
,
249 .max_packet
= ETH_MAX_PACKET
+ ETH_HEADER_ETHERTAP
,