diff options
Diffstat (limited to 'arch/um/os-Linux/drivers/ethertap_user.c')
| -rw-r--r-- | arch/um/os-Linux/drivers/ethertap_user.c | 191 |
1 files changed, 100 insertions, 91 deletions
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c index 901b85e8a1c..b39b6696ac5 100644 --- a/arch/um/os-Linux/drivers/ethertap_user.c +++ b/arch/um/os-Linux/drivers/ethertap_user.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and * James Leu (jleu@mindspring.net). * Copyright (C) 2001 by various other people who didn't put their name here. * Licensed under the GPL. @@ -7,27 +8,23 @@ #include <stdio.h> #include <unistd.h> -#include <stddef.h> -#include <stdlib.h> -#include <sys/errno.h> +#include <errno.h> +#include <string.h> #include <sys/socket.h> #include <sys/wait.h> -#include <sys/un.h> -#include <net/if.h> -#include "user.h" -#include "kern_util.h" -#include "user_util.h" -#include "net_user.h" #include "etap.h" -#include "os.h" +#include <os.h> +#include <net_user.h> +#include <um_malloc.h> #define MAX_PACKET ETH_MAX_PACKET -void etap_user_init(void *data, void *dev) +static int etap_user_init(void *data, void *dev) { struct ethertap_data *pri = data; pri->dev = dev; + return 0; } struct addr_change { @@ -40,20 +37,25 @@ static void etap_change(int op, unsigned char *addr, unsigned char *netmask, int fd) { struct addr_change change; - void *output; + char *output; int n; change.what = op; memcpy(change.addr, addr, sizeof(change.addr)); memcpy(change.netmask, netmask, sizeof(change.netmask)); - n = os_write_file(fd, &change, sizeof(change)); - if(n != sizeof(change)) - printk("etap_change - request failed, err = %d\n", -n); - output = um_kmalloc(page_size()); - if(output == NULL) - printk("etap_change : Failed to allocate output buffer\n"); - read_output(fd, output, page_size()); - if(output != NULL){ + CATCH_EINTR(n = write(fd, &change, sizeof(change))); + if (n != sizeof(change)) { + printk(UM_KERN_ERR "etap_change - request failed, err = %d\n", + errno); + return; + } + + output = uml_kmalloc(UM_KERN_PAGE_SIZE, UM_GFP_KERNEL); + if (output == NULL) + printk(UM_KERN_ERR "etap_change : Failed to allocate output " + "buffer\n"); + read_output(fd, output, UM_KERN_PAGE_SIZE); + if (output != NULL) { printk("%s", output); kfree(output); } @@ -82,27 +84,27 @@ static void etap_pre_exec(void *arg) struct etap_pre_exec_data *data = arg; dup2(data->control_remote, 1); - os_close_file(data->data_me); - os_close_file(data->control_me); + close(data->data_me); + close(data->control_me); } -static int etap_tramp(char *dev, char *gate, int control_me, +static int etap_tramp(char *dev, char *gate, int control_me, int control_remote, int data_me, int data_remote) { struct etap_pre_exec_data pe_data; - int pid, status, err, n; + int pid, err, n; char version_buf[sizeof("nnnnn\0")]; char data_fd_buf[sizeof("nnnnnn\0")]; char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")]; char *setup_args[] = { "uml_net", version_buf, "ethertap", dev, data_fd_buf, gate_buf, NULL }; - char *nosetup_args[] = { "uml_net", version_buf, "ethertap", + char *nosetup_args[] = { "uml_net", version_buf, "ethertap", dev, data_fd_buf, NULL }; char **args, c; sprintf(data_fd_buf, "%d", data_remote); sprintf(version_buf, "%d", UML_NET_VERSION); - if(gate != NULL){ + if (gate != NULL) { strcpy(gate_buf, gate); args = setup_args; } @@ -112,26 +114,24 @@ static int etap_tramp(char *dev, char *gate, int control_me, pe_data.control_remote = control_remote; pe_data.control_me = control_me; pe_data.data_me = data_me; - pid = run_helper(etap_pre_exec, &pe_data, args, NULL); - - if(pid < 0) err = pid; - os_close_file(data_remote); - os_close_file(control_remote); - n = os_read_file(control_me, &c, sizeof(c)); - if(n != sizeof(c)){ - printk("etap_tramp : read of status failed, err = %d\n", -n); - return(-EINVAL); + pid = run_helper(etap_pre_exec, &pe_data, args); + + if (pid < 0) + err = pid; + close(data_remote); + close(control_remote); + CATCH_EINTR(n = read(control_me, &c, sizeof(c))); + if (n != sizeof(c)) { + err = -errno; + printk(UM_KERN_ERR "etap_tramp : read of status failed, " + "err = %d\n", -err); + return err; } - if(c != 1){ - printk("etap_tramp : uml_net failed\n"); - err = -EINVAL; - CATCH_EINTR(n = waitpid(pid, &status, 0)); - if(n < 0) - err = -errno; - else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1)) - printk("uml_net didn't exit with status 1\n"); + if (c != 1) { + printk(UM_KERN_ERR "etap_tramp : uml_net failed\n"); + err = helper_wait(pid); } - return(err); + return err; } static int etap_open(void *data) @@ -141,42 +141,56 @@ static int etap_open(void *data) int data_fds[2], control_fds[2], err, output_len; err = tap_open_common(pri->dev, pri->gate_addr); - if(err) return(err); - - err = os_pipe(data_fds, 0, 0); - if(err < 0){ - printk("data os_pipe failed - err = %d\n", -err); - return(err); + if (err) + return err; + + err = socketpair(AF_UNIX, SOCK_DGRAM, 0, data_fds); + if (err) { + err = -errno; + printk(UM_KERN_ERR "etap_open - data socketpair failed - " + "err = %d\n", errno); + return err; } - err = os_pipe(control_fds, 1, 0); - if(err < 0){ - printk("control os_pipe failed - err = %d\n", -err); - return(err); + err = socketpair(AF_UNIX, SOCK_STREAM, 0, control_fds); + if (err) { + err = -errno; + printk(UM_KERN_ERR "etap_open - control socketpair failed - " + "err = %d\n", errno); + goto out_close_data; } - - err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0], + + err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0], control_fds[1], data_fds[0], data_fds[1]); - output_len = page_size(); - output = um_kmalloc(output_len); + output_len = UM_KERN_PAGE_SIZE; + output = uml_kmalloc(output_len, UM_GFP_KERNEL); read_output(control_fds[0], output, output_len); - if(output == NULL) - printk("etap_open : failed to allocate output buffer\n"); + if (output == NULL) + printk(UM_KERN_ERR "etap_open : failed to allocate output " + "buffer\n"); else { printk("%s", output); kfree(output); } - if(err < 0){ - printk("etap_tramp failed - err = %d\n", -err); - return(err); + if (err < 0) { + printk(UM_KERN_ERR "etap_tramp failed - err = %d\n", -err); + goto out_close_control; } pri->data_fd = data_fds[0]; pri->control_fd = control_fds[0]; iter_addresses(pri->dev, etap_open_addr, &pri->control_fd); - return(data_fds[0]); + return data_fds[0]; + +out_close_control: + close(control_fds[0]); + close(control_fds[1]); +out_close_data: + close(data_fds[0]); + close(data_fds[1]); + return err; } static void etap_close(int fd, void *data) @@ -184,56 +198,51 @@ static void etap_close(int fd, void *data) struct ethertap_data *pri = data; iter_addresses(pri->dev, etap_close_addr, &pri->control_fd); - os_close_file(fd); - os_shutdown_socket(pri->data_fd, 1, 1); - os_close_file(pri->data_fd); + close(fd); + + if (shutdown(pri->data_fd, SHUT_RDWR) < 0) + printk(UM_KERN_ERR "etap_close - shutdown data socket failed, " + "errno = %d\n", errno); + + if (shutdown(pri->control_fd, SHUT_RDWR) < 0) + printk(UM_KERN_ERR "etap_close - shutdown control socket " + "failed, errno = %d\n", errno); + + close(pri->data_fd); pri->data_fd = -1; - os_close_file(pri->control_fd); + close(pri->control_fd); pri->control_fd = -1; } -static int etap_set_mtu(int mtu, void *data) -{ - return(mtu); -} - static void etap_add_addr(unsigned char *addr, unsigned char *netmask, void *data) { struct ethertap_data *pri = data; tap_check_ips(pri->gate_addr, addr); - if(pri->control_fd == -1) return; + if (pri->control_fd == -1) + return; etap_open_addr(addr, netmask, &pri->control_fd); } -static void etap_del_addr(unsigned char *addr, unsigned char *netmask, +static void etap_del_addr(unsigned char *addr, unsigned char *netmask, void *data) { struct ethertap_data *pri = data; - if(pri->control_fd == -1) return; + if (pri->control_fd == -1) + return; + etap_close_addr(addr, netmask, &pri->control_fd); } -struct net_user_info ethertap_user_info = { +const struct net_user_info ethertap_user_info = { .init = etap_user_init, .open = etap_open, .close = etap_close, .remove = NULL, - .set_mtu = etap_set_mtu, .add_address = etap_add_addr, .delete_address = etap_del_addr, - .max_packet = MAX_PACKET - ETH_HEADER_ETHERTAP + .mtu = ETH_MAX_PACKET, + .max_packet = ETH_MAX_PACKET + ETH_HEADER_ETHERTAP, }; - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ |
