2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
13 #include <sys/socket.h>
16 #include "user_util.h"
17 #include "kern_util.h"
21 int tap_open_common(void *dev
, char *gate_addr
)
25 if(gate_addr
== NULL
) return(0);
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("Invalid tap IP address - '%s'\n", gate_addr
);
34 void tap_check_ips(char *gate_addr
, unsigned char *eth_addr
)
38 if((gate_addr
!= NULL
) &&
39 (sscanf(gate_addr
, "%d.%d.%d.%d", &tap_addr
[0],
40 &tap_addr
[1], &tap_addr
[2], &tap_addr
[3]) == 4) &&
41 (eth_addr
[0] == tap_addr
[0]) &&
42 (eth_addr
[1] == tap_addr
[1]) &&
43 (eth_addr
[2] == tap_addr
[2]) &&
44 (eth_addr
[3] == tap_addr
[3])){
45 printk("The tap IP address and the UML eth IP address"
46 " must be different\n");
50 /* Do reliable error handling as this fails frequently enough. */
51 void read_output(int fd
, char *output
, int len
)
53 int remain
, ret
, expected
;
63 ret
= os_read_file(fd
, &remain
, sizeof(remain
));
65 if (ret
!= sizeof(remain
)) {
66 expected
= sizeof(remain
);
72 expected
= (remain
< len
) ? remain
: len
;
73 ret
= os_read_file(fd
, output
, expected
);
74 if (ret
!= expected
) {
85 printk("read_output - read of %s failed, errno = %d\n", str
, -ret
);
87 printk("read_output - read of %s failed, read only %d of %d bytes\n", str
, ret
, expected
);
90 int net_read(int fd
, void *buf
, int len
)
94 n
= os_read_file(fd
, buf
, len
);
103 int net_recvfrom(int fd
, void *buf
, int len
)
107 while(((n
= recvfrom(fd
, buf
, len
, 0, NULL
, NULL
)) < 0) &&
111 if(errno
== EAGAIN
) return(0);
114 else if(n
== 0) return(-ENOTCONN
);
118 int net_write(int fd
, void *buf
, int len
)
122 n
= os_write_file(fd
, buf
, len
);
131 int net_send(int fd
, void *buf
, int len
)
135 while(((n
= send(fd
, buf
, len
, 0)) < 0) && (errno
== EINTR
)) ;
137 if(errno
== EAGAIN
) return(0);
140 else if(n
== 0) return(-ENOTCONN
);
144 int net_sendto(int fd
, void *buf
, int len
, void *to
, int sock_len
)
148 while(((n
= sendto(fd
, buf
, len
, 0, (struct sockaddr
*) to
,
149 sock_len
)) < 0) && (errno
== EINTR
)) ;
151 if(errno
== EAGAIN
) return(0);
154 else if(n
== 0) return(-ENOTCONN
);
158 struct change_pre_exec_data
{
163 static void change_pre_exec(void *arg
)
165 struct change_pre_exec_data
*data
= arg
;
167 os_close_file(data
->close_me
);
168 dup2(data
->stdout
, 1);
171 static int change_tramp(char **argv
, char *output
, int output_len
)
173 int pid
, fds
[2], err
;
174 struct change_pre_exec_data pe_data
;
176 err
= os_pipe(fds
, 1, 0);
178 printk("change_tramp - pipe failed, err = %d\n", -err
);
181 pe_data
.close_me
= fds
[0];
182 pe_data
.stdout
= fds
[1];
183 pid
= run_helper(change_pre_exec
, &pe_data
, argv
, NULL
);
185 if (pid
> 0) /* Avoid hang as we won't get data in failure case. */
186 read_output(fds
[0], output
, output_len
);
188 os_close_file(fds
[0]);
189 os_close_file(fds
[1]);
192 CATCH_EINTR(err
= waitpid(pid
, NULL
, 0));
196 static void change(char *dev
, char *what
, unsigned char *addr
,
197 unsigned char *netmask
)
199 char addr_buf
[sizeof("255.255.255.255\0")];
200 char netmask_buf
[sizeof("255.255.255.255\0")];
201 char version
[sizeof("nnnnn\0")];
202 char *argv
[] = { "uml_net", version
, what
, dev
, addr_buf
,
207 sprintf(version
, "%d", UML_NET_VERSION
);
208 sprintf(addr_buf
, "%d.%d.%d.%d", addr
[0], addr
[1], addr
[2], addr
[3]);
209 sprintf(netmask_buf
, "%d.%d.%d.%d", netmask
[0], netmask
[1],
210 netmask
[2], netmask
[3]);
212 output_len
= page_size();
213 output
= um_kmalloc(output_len
);
215 printk("change : failed to allocate output buffer\n");
217 pid
= change_tramp(argv
, output
, output_len
);
221 printk("%s", output
);
226 void open_addr(unsigned char *addr
, unsigned char *netmask
, void *arg
)
228 change(arg
, "add", addr
, netmask
);
231 void close_addr(unsigned char *addr
, unsigned char *netmask
, void *arg
)
233 change(arg
, "del", addr
, netmask
);
236 char *split_if_spec(char *str
, ...)
242 while((arg
= va_arg(ap
, char **)) != NULL
){
245 end
= strchr(str
, ',');
258 * Overrides for Emacs so that we follow Linus's tabbing style.
259 * Emacs will notice this stuff at the end of the file and automatically
260 * adjust the settings for this buffer only. This must remain at the end
262 * ---------------------------------------------------------------------------
264 * c-file-style: "linux"