2 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL
12 #include <sys/socket.h>
15 #include "kern_constants.h"
17 #include "um_malloc.h"
20 int tap_open_common(void *dev
, char *gate_addr
)
24 if (gate_addr
== NULL
)
26 if (sscanf(gate_addr
, "%d.%d.%d.%d", &tap_addr
[0],
27 &tap_addr
[1], &tap_addr
[2], &tap_addr
[3]) != 4) {
28 printk(UM_KERN_ERR
"Invalid tap IP address - '%s'\n",
35 void tap_check_ips(char *gate_addr
, unsigned char *eth_addr
)
39 if ((gate_addr
!= NULL
) &&
40 (sscanf(gate_addr
, "%d.%d.%d.%d", &tap_addr
[0],
41 &tap_addr
[1], &tap_addr
[2], &tap_addr
[3]) == 4) &&
42 (eth_addr
[0] == tap_addr
[0]) &&
43 (eth_addr
[1] == tap_addr
[1]) &&
44 (eth_addr
[2] == tap_addr
[2]) &&
45 (eth_addr
[3] == tap_addr
[3])) {
46 printk(UM_KERN_ERR
"The tap IP address and the UML eth IP "
47 "address must be different\n");
51 /* Do reliable error handling as this fails frequently enough. */
52 void read_output(int fd
, char *output
, int len
)
54 int remain
, ret
, expected
;
64 ret
= read(fd
, &remain
, sizeof(remain
));
66 if (ret
!= sizeof(remain
)) {
69 expected
= sizeof(remain
);
75 expected
= (remain
< len
) ? remain
: len
;
76 ret
= read(fd
, output
, expected
);
77 if (ret
!= expected
) {
90 printk(UM_KERN_ERR
"read_output - read of %s failed, "
91 "errno = %d\n", str
, -ret
);
93 printk(UM_KERN_ERR
"read_output - read of %s failed, read only "
94 "%d of %d bytes\n", str
, ret
, expected
);
97 int net_read(int fd
, void *buf
, int len
)
101 n
= read(fd
, buf
, len
);
103 if ((n
< 0) && (errno
== EAGAIN
))
110 int net_recvfrom(int fd
, void *buf
, int len
)
114 CATCH_EINTR(n
= recvfrom(fd
, buf
, len
, 0, NULL
, NULL
));
125 int net_write(int fd
, void *buf
, int len
)
129 n
= write(fd
, buf
, len
);
131 if ((n
< 0) && (errno
== EAGAIN
))
138 int net_send(int fd
, void *buf
, int len
)
142 CATCH_EINTR(n
= send(fd
, buf
, len
, 0));
153 int net_sendto(int fd
, void *buf
, int len
, void *to
, int sock_len
)
157 CATCH_EINTR(n
= sendto(fd
, buf
, len
, 0, (struct sockaddr
*) to
,
169 struct change_pre_exec_data
{
174 static void change_pre_exec(void *arg
)
176 struct change_pre_exec_data
*data
= arg
;
178 close(data
->close_me
);
179 dup2(data
->stdout
, 1);
182 static int change_tramp(char **argv
, char *output
, int output_len
)
184 int pid
, fds
[2], err
;
185 struct change_pre_exec_data pe_data
;
187 err
= os_pipe(fds
, 1, 0);
189 printk(UM_KERN_ERR
"change_tramp - pipe failed, err = %d\n",
193 pe_data
.close_me
= fds
[0];
194 pe_data
.stdout
= fds
[1];
195 pid
= run_helper(change_pre_exec
, &pe_data
, argv
);
197 if (pid
> 0) /* Avoid hang as we won't get data in failure case. */
198 read_output(fds
[0], output
, output_len
);
208 static void change(char *dev
, char *what
, unsigned char *addr
,
209 unsigned char *netmask
)
211 char addr_buf
[sizeof("255.255.255.255\0")];
212 char netmask_buf
[sizeof("255.255.255.255\0")];
213 char version
[sizeof("nnnnn\0")];
214 char *argv
[] = { "uml_net", version
, what
, dev
, addr_buf
,
219 sprintf(version
, "%d", UML_NET_VERSION
);
220 sprintf(addr_buf
, "%d.%d.%d.%d", addr
[0], addr
[1], addr
[2], addr
[3]);
221 sprintf(netmask_buf
, "%d.%d.%d.%d", netmask
[0], netmask
[1],
222 netmask
[2], netmask
[3]);
224 output_len
= UM_KERN_PAGE_SIZE
;
225 output
= kmalloc(output_len
, UM_GFP_KERNEL
);
227 printk(UM_KERN_ERR
"change : failed to allocate output "
230 pid
= change_tramp(argv
, output
, output_len
);
233 if (output
!= NULL
) {
234 printk("%s", output
);
239 void open_addr(unsigned char *addr
, unsigned char *netmask
, void *arg
)
241 change(arg
, "add", addr
, netmask
);
244 void close_addr(unsigned char *addr
, unsigned char *netmask
, void *arg
)
246 change(arg
, "del", addr
, netmask
);
249 char *split_if_spec(char *str
, ...)
255 while ((arg
= va_arg(ap
, char **)) != NULL
) {
258 end
= strchr(str
, ',');