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.
12 #include <sys/errno.h>
13 #include <sys/socket.h>
18 #include "kern_util.h"
19 #include "user_util.h"
24 #define MAX_PACKET ETH_MAX_PACKET
26 void etap_user_init(void *data
, void *dev
)
28 struct ethertap_data
*pri
= data
;
34 enum { ADD_ADDR
, DEL_ADDR
} what
;
35 unsigned char addr
[4];
36 unsigned char netmask
[4];
39 static void etap_change(int op
, unsigned char *addr
, unsigned char *netmask
,
42 struct addr_change change
;
47 memcpy(change
.addr
, addr
, sizeof(change
.addr
));
48 memcpy(change
.netmask
, netmask
, sizeof(change
.netmask
));
49 n
= os_write_file(fd
, &change
, sizeof(change
));
50 if(n
!= sizeof(change
))
51 printk("etap_change - request failed, err = %d\n", -n
);
52 output
= um_kmalloc(page_size());
54 printk("etap_change : Failed to allocate output buffer\n");
55 read_output(fd
, output
, page_size());
62 static void etap_open_addr(unsigned char *addr
, unsigned char *netmask
,
65 etap_change(ADD_ADDR
, addr
, netmask
, *((int *) arg
));
68 static void etap_close_addr(unsigned char *addr
, unsigned char *netmask
,
71 etap_change(DEL_ADDR
, addr
, netmask
, *((int *) arg
));
74 struct etap_pre_exec_data
{
80 static void etap_pre_exec(void *arg
)
82 struct etap_pre_exec_data
*data
= arg
;
84 dup2(data
->control_remote
, 1);
85 os_close_file(data
->data_me
);
86 os_close_file(data
->control_me
);
89 static int etap_tramp(char *dev
, char *gate
, int control_me
,
90 int control_remote
, int data_me
, int data_remote
)
92 struct etap_pre_exec_data pe_data
;
93 int pid
, status
, err
, n
;
94 char version_buf
[sizeof("nnnnn\0")];
95 char data_fd_buf
[sizeof("nnnnnn\0")];
96 char gate_buf
[sizeof("nnn.nnn.nnn.nnn\0")];
97 char *setup_args
[] = { "uml_net", version_buf
, "ethertap", dev
,
98 data_fd_buf
, gate_buf
, NULL
};
99 char *nosetup_args
[] = { "uml_net", version_buf
, "ethertap",
100 dev
, data_fd_buf
, NULL
};
103 sprintf(data_fd_buf
, "%d", data_remote
);
104 sprintf(version_buf
, "%d", UML_NET_VERSION
);
106 strcpy(gate_buf
, gate
);
109 else args
= nosetup_args
;
112 pe_data
.control_remote
= control_remote
;
113 pe_data
.control_me
= control_me
;
114 pe_data
.data_me
= data_me
;
115 pid
= run_helper(etap_pre_exec
, &pe_data
, args
, NULL
);
117 if(pid
< 0) err
= pid
;
118 os_close_file(data_remote
);
119 os_close_file(control_remote
);
120 n
= os_read_file(control_me
, &c
, sizeof(c
));
122 printk("etap_tramp : read of status failed, err = %d\n", -n
);
126 printk("etap_tramp : uml_net failed\n");
128 CATCH_EINTR(n
= waitpid(pid
, &status
, 0));
131 else if(!WIFEXITED(status
) || (WEXITSTATUS(status
) != 1))
132 printk("uml_net didn't exit with status 1\n");
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
);
146 err
= os_pipe(data_fds
, 0, 0);
148 printk("data os_pipe failed - err = %d\n", -err
);
152 err
= os_pipe(control_fds
, 1, 0);
154 printk("control os_pipe failed - err = %d\n", -err
);
158 err
= etap_tramp(pri
->dev_name
, pri
->gate_addr
, control_fds
[0],
159 control_fds
[1], data_fds
[0], data_fds
[1]);
160 output_len
= page_size();
161 output
= um_kmalloc(output_len
);
162 read_output(control_fds
[0], output
, output_len
);
165 printk("etap_open : failed to allocate output buffer\n");
167 printk("%s", output
);
172 printk("etap_tramp failed - err = %d\n", -err
);
176 pri
->data_fd
= data_fds
[0];
177 pri
->control_fd
= control_fds
[0];
178 iter_addresses(pri
->dev
, etap_open_addr
, &pri
->control_fd
);
182 static void etap_close(int fd
, void *data
)
184 struct ethertap_data
*pri
= data
;
186 iter_addresses(pri
->dev
, etap_close_addr
, &pri
->control_fd
);
188 os_shutdown_socket(pri
->data_fd
, 1, 1);
189 os_close_file(pri
->data_fd
);
191 os_close_file(pri
->control_fd
);
192 pri
->control_fd
= -1;
195 static int etap_set_mtu(int mtu
, void *data
)
200 static void etap_add_addr(unsigned char *addr
, unsigned char *netmask
,
203 struct ethertap_data
*pri
= data
;
205 tap_check_ips(pri
->gate_addr
, addr
);
206 if(pri
->control_fd
== -1) return;
207 etap_open_addr(addr
, netmask
, &pri
->control_fd
);
210 static void etap_del_addr(unsigned char *addr
, unsigned char *netmask
,
213 struct ethertap_data
*pri
= data
;
215 if(pri
->control_fd
== -1) return;
216 etap_close_addr(addr
, netmask
, &pri
->control_fd
);
219 struct net_user_info ethertap_user_info
= {
220 .init
= etap_user_init
,
224 .set_mtu
= etap_set_mtu
,
225 .add_address
= etap_add_addr
,
226 .delete_address
= etap_del_addr
,
227 .max_packet
= MAX_PACKET
- ETH_HEADER_ETHERTAP
231 * Overrides for Emacs so that we follow Linus's tabbing style.
232 * Emacs will notice this stuff at the end of the file and automatically
233 * adjust the settings for this buffer only. This must remain at the end
235 * ---------------------------------------------------------------------------
237 * c-file-style: "linux"