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"
25 #define MAX_PACKET ETH_MAX_PACKET
27 void etap_user_init(void *data
, void *dev
)
29 struct ethertap_data
*pri
= data
;
35 enum { ADD_ADDR
, DEL_ADDR
} what
;
36 unsigned char addr
[4];
37 unsigned char netmask
[4];
40 static void etap_change(int op
, unsigned char *addr
, unsigned char *netmask
,
43 struct addr_change change
;
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());
55 printk("etap_change : Failed to allocate output buffer\n");
56 read_output(fd
, output
, page_size());
63 static void etap_open_addr(unsigned char *addr
, unsigned char *netmask
,
66 etap_change(ADD_ADDR
, addr
, netmask
, *((int *) arg
));
69 static void etap_close_addr(unsigned char *addr
, unsigned char *netmask
,
72 etap_change(DEL_ADDR
, addr
, netmask
, *((int *) arg
));
75 struct etap_pre_exec_data
{
81 static void etap_pre_exec(void *arg
)
83 struct etap_pre_exec_data
*data
= arg
;
85 dup2(data
->control_remote
, 1);
86 os_close_file(data
->data_me
);
87 os_close_file(data
->control_me
);
90 static int etap_tramp(char *dev
, char *gate
, int control_me
,
91 int control_remote
, int data_me
, int data_remote
)
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
};
104 sprintf(data_fd_buf
, "%d", data_remote
);
105 sprintf(version_buf
, "%d", UML_NET_VERSION
);
107 strcpy(gate_buf
, gate
);
110 else args
= nosetup_args
;
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
);
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
));
123 printk("etap_tramp : read of status failed, err = %d\n", -n
);
127 printk("etap_tramp : uml_net failed\n");
129 CATCH_EINTR(n
= waitpid(pid
, &status
, 0));
132 else if(!WIFEXITED(status
) || (WEXITSTATUS(status
) != 1))
133 printk("uml_net didn't exit with status 1\n");
138 static int etap_open(void *data
)
140 struct ethertap_data
*pri
= data
;
142 int data_fds
[2], control_fds
[2], err
, output_len
;
144 err
= tap_open_common(pri
->dev
, pri
->gate_addr
);
147 err
= os_pipe(data_fds
, 0, 0);
149 printk("data os_pipe failed - err = %d\n", -err
);
153 err
= os_pipe(control_fds
, 1, 0);
155 printk("control os_pipe failed - err = %d\n", -err
);
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
);
166 printk("etap_open : failed to allocate output buffer\n");
168 printk("%s", output
);
173 printk("etap_tramp failed - err = %d\n", -err
);
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
);
183 static void etap_close(int fd
, void *data
)
185 struct ethertap_data
*pri
= data
;
187 iter_addresses(pri
->dev
, etap_close_addr
, &pri
->control_fd
);
189 os_shutdown_socket(pri
->data_fd
, 1, 1);
190 os_close_file(pri
->data_fd
);
192 os_close_file(pri
->control_fd
);
193 pri
->control_fd
= -1;
196 static int etap_set_mtu(int mtu
, void *data
)
201 static void etap_add_addr(unsigned char *addr
, unsigned char *netmask
,
204 struct ethertap_data
*pri
= data
;
206 tap_check_ips(pri
->gate_addr
, addr
);
207 if(pri
->control_fd
== -1) return;
208 etap_open_addr(addr
, netmask
, &pri
->control_fd
);
211 static void etap_del_addr(unsigned char *addr
, unsigned char *netmask
,
214 struct ethertap_data
*pri
= data
;
216 if(pri
->control_fd
== -1) return;
217 etap_close_addr(addr
, netmask
, &pri
->control_fd
);
220 struct net_user_info ethertap_user_info
= {
221 .init
= etap_user_init
,
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
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
236 * ---------------------------------------------------------------------------
238 * c-file-style: "linux"