2 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL
12 #include <sys/socket.h>
16 #include <um_malloc.h>
18 int tap_open_common(void *dev
, char *gate_addr
)
22 if (gate_addr
== NULL
)
24 if (sscanf(gate_addr
, "%d.%d.%d.%d", &tap_addr
[0],
25 &tap_addr
[1], &tap_addr
[2], &tap_addr
[3]) != 4) {
26 printk(UM_KERN_ERR
"Invalid tap IP address - '%s'\n",
33 void tap_check_ips(char *gate_addr
, unsigned char *eth_addr
)
37 if ((gate_addr
!= NULL
) &&
38 (sscanf(gate_addr
, "%d.%d.%d.%d", &tap_addr
[0],
39 &tap_addr
[1], &tap_addr
[2], &tap_addr
[3]) == 4) &&
40 (eth_addr
[0] == tap_addr
[0]) &&
41 (eth_addr
[1] == tap_addr
[1]) &&
42 (eth_addr
[2] == tap_addr
[2]) &&
43 (eth_addr
[3] == tap_addr
[3])) {
44 printk(UM_KERN_ERR
"The tap IP address and the UML eth IP "
45 "address must be different\n");
49 /* Do reliable error handling as this fails frequently enough. */
50 void read_output(int fd
, char *output
, int len
)
52 int remain
, ret
, expected
;
62 ret
= read(fd
, &remain
, sizeof(remain
));
64 if (ret
!= sizeof(remain
)) {
67 expected
= sizeof(remain
);
73 expected
= (remain
< len
) ? remain
: len
;
74 ret
= read(fd
, output
, expected
);
75 if (ret
!= expected
) {
88 printk(UM_KERN_ERR
"read_output - read of %s failed, "
89 "errno = %d\n", str
, -ret
);
91 printk(UM_KERN_ERR
"read_output - read of %s failed, read only "
92 "%d of %d bytes\n", str
, ret
, expected
);
95 int net_read(int fd
, void *buf
, int len
)
99 n
= read(fd
, buf
, len
);
101 if ((n
< 0) && (errno
== EAGAIN
))
108 int net_recvfrom(int fd
, void *buf
, int len
)
112 CATCH_EINTR(n
= recvfrom(fd
, buf
, len
, 0, NULL
, NULL
));
123 int net_write(int fd
, void *buf
, int len
)
127 n
= write(fd
, buf
, len
);
129 if ((n
< 0) && (errno
== EAGAIN
))
136 int net_send(int fd
, void *buf
, int len
)
140 CATCH_EINTR(n
= send(fd
, buf
, len
, 0));
151 int net_sendto(int fd
, void *buf
, int len
, void *to
, int sock_len
)
155 CATCH_EINTR(n
= sendto(fd
, buf
, len
, 0, (struct sockaddr
*) to
,
167 struct change_pre_exec_data
{
172 static void change_pre_exec(void *arg
)
174 struct change_pre_exec_data
*data
= arg
;
176 close(data
->close_me
);
177 dup2(data
->stdout_fd
, 1);
180 static int change_tramp(char **argv
, char *output
, int output_len
)
182 int pid
, fds
[2], err
;
183 struct change_pre_exec_data pe_data
;
185 err
= os_pipe(fds
, 1, 0);
187 printk(UM_KERN_ERR
"change_tramp - pipe failed, err = %d\n",
191 pe_data
.close_me
= fds
[0];
192 pe_data
.stdout_fd
= fds
[1];
193 pid
= run_helper(change_pre_exec
, &pe_data
, argv
);
195 if (pid
> 0) /* Avoid hang as we won't get data in failure case. */
196 read_output(fds
[0], output
, output_len
);
206 static void change(char *dev
, char *what
, unsigned char *addr
,
207 unsigned char *netmask
)
209 char addr_buf
[sizeof("255.255.255.255\0")];
210 char netmask_buf
[sizeof("255.255.255.255\0")];
211 char version
[sizeof("nnnnn\0")];
212 char *argv
[] = { "uml_net", version
, what
, dev
, addr_buf
,
217 sprintf(version
, "%d", UML_NET_VERSION
);
218 sprintf(addr_buf
, "%d.%d.%d.%d", addr
[0], addr
[1], addr
[2], addr
[3]);
219 sprintf(netmask_buf
, "%d.%d.%d.%d", netmask
[0], netmask
[1],
220 netmask
[2], netmask
[3]);
222 output_len
= UM_KERN_PAGE_SIZE
;
223 output
= uml_kmalloc(output_len
, UM_GFP_KERNEL
);
225 printk(UM_KERN_ERR
"change : failed to allocate output "
228 pid
= change_tramp(argv
, output
, output_len
);
234 if (output
!= NULL
) {
235 printk("%s", output
);
240 void open_addr(unsigned char *addr
, unsigned char *netmask
, void *arg
)
242 change(arg
, "add", addr
, netmask
);
245 void close_addr(unsigned char *addr
, unsigned char *netmask
, void *arg
)
247 change(arg
, "del", addr
, netmask
);
250 char *split_if_spec(char *str
, ...)
252 char **arg
, *end
, *ret
= NULL
;
256 while ((arg
= va_arg(ap
, char **)) != NULL
) {
259 end
= strchr(str
, ',');