2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
13 #include <sys/socket.h>
17 #include "kern_util.h"
20 #include "um_malloc.h"
21 #include "kern_constants.h"
23 int tap_open_common(void *dev
, char *gate_addr
)
29 if(sscanf(gate_addr
, "%d.%d.%d.%d", &tap_addr
[0],
30 &tap_addr
[1], &tap_addr
[2], &tap_addr
[3]) != 4){
31 printk("Invalid tap IP address - '%s'\n", gate_addr
);
37 void tap_check_ips(char *gate_addr
, unsigned char *eth_addr
)
41 if((gate_addr
!= NULL
) &&
42 (sscanf(gate_addr
, "%d.%d.%d.%d", &tap_addr
[0],
43 &tap_addr
[1], &tap_addr
[2], &tap_addr
[3]) == 4) &&
44 (eth_addr
[0] == tap_addr
[0]) &&
45 (eth_addr
[1] == tap_addr
[1]) &&
46 (eth_addr
[2] == tap_addr
[2]) &&
47 (eth_addr
[3] == tap_addr
[3])){
48 printk("The tap IP address and the UML eth IP address"
49 " must be different\n");
53 /* Do reliable error handling as this fails frequently enough. */
54 void read_output(int fd
, char *output
, int len
)
56 int remain
, ret
, expected
;
66 ret
= os_read_file(fd
, &remain
, sizeof(remain
));
68 if (ret
!= sizeof(remain
)) {
69 expected
= sizeof(remain
);
75 expected
= (remain
< len
) ? remain
: len
;
76 ret
= os_read_file(fd
, output
, expected
);
77 if (ret
!= expected
) {
88 printk("read_output - read of %s failed, errno = %d\n", str
, -ret
);
90 printk("read_output - read of %s failed, read only %d of %d bytes\n", str
, ret
, expected
);
93 int net_read(int fd
, void *buf
, int len
)
97 n
= os_read_file(fd
, buf
, len
);
106 int net_recvfrom(int fd
, void *buf
, int len
)
110 CATCH_EINTR(n
= recvfrom(fd
, buf
, len
, 0, NULL
, NULL
));
121 int net_write(int fd
, void *buf
, int len
)
125 n
= os_write_file(fd
, buf
, len
);
134 int net_send(int fd
, void *buf
, int len
)
138 CATCH_EINTR(n
= send(fd
, buf
, len
, 0));
149 int net_sendto(int fd
, void *buf
, int len
, void *to
, int sock_len
)
153 CATCH_EINTR(n
= sendto(fd
, buf
, len
, 0, (struct sockaddr
*) to
,
165 struct change_pre_exec_data
{
170 static void change_pre_exec(void *arg
)
172 struct change_pre_exec_data
*data
= arg
;
174 os_close_file(data
->close_me
);
175 dup2(data
->stdout
, 1);
178 static int change_tramp(char **argv
, char *output
, int output_len
)
180 int pid
, fds
[2], err
;
181 struct change_pre_exec_data pe_data
;
183 err
= os_pipe(fds
, 1, 0);
185 printk("change_tramp - pipe failed, err = %d\n", -err
);
188 pe_data
.close_me
= fds
[0];
189 pe_data
.stdout
= fds
[1];
190 pid
= run_helper(change_pre_exec
, &pe_data
, argv
, NULL
);
192 if (pid
> 0) /* Avoid hang as we won't get data in failure case. */
193 read_output(fds
[0], output
, output_len
);
195 os_close_file(fds
[0]);
196 os_close_file(fds
[1]);
199 CATCH_EINTR(err
= waitpid(pid
, NULL
, 0));
203 static void change(char *dev
, char *what
, unsigned char *addr
,
204 unsigned char *netmask
)
206 char addr_buf
[sizeof("255.255.255.255\0")];
207 char netmask_buf
[sizeof("255.255.255.255\0")];
208 char version
[sizeof("nnnnn\0")];
209 char *argv
[] = { "uml_net", version
, what
, dev
, addr_buf
,
214 sprintf(version
, "%d", UML_NET_VERSION
);
215 sprintf(addr_buf
, "%d.%d.%d.%d", addr
[0], addr
[1], addr
[2], addr
[3]);
216 sprintf(netmask_buf
, "%d.%d.%d.%d", netmask
[0], netmask
[1],
217 netmask
[2], netmask
[3]);
219 output_len
= UM_KERN_PAGE_SIZE
;
220 output
= um_kmalloc(output_len
);
222 printk("change : failed to allocate output buffer\n");
224 pid
= change_tramp(argv
, output
, output_len
);
228 printk("%s", output
);
233 void open_addr(unsigned char *addr
, unsigned char *netmask
, void *arg
)
235 change(arg
, "add", addr
, netmask
);
238 void close_addr(unsigned char *addr
, unsigned char *netmask
, void *arg
)
240 change(arg
, "del", addr
, netmask
);
243 char *split_if_spec(char *str
, ...)
249 while((arg
= va_arg(ap
, char **)) != NULL
){
252 end
= strchr(str
, ',');