forked from Minki/linux
edea138584
Tidy kern_util.h. It turns out that most of the function declarations aren't used, so they can go away. os.h no longer includes kern_util.h, so files which got it through os.h now need to include it directly. A number of other files never needed it, so these includes are deleted. The structure which was used to pass signal handlers from the kernel side to the userspace side is gone. Instead, the handlers are declared here, and used directly from libc code. This allows arch/um/os-Linux/trap.c to be deleted, with its remnants being moved to arch/um/os-Linux/skas/trap.c. arch/um/os-Linux/tty.c had its inclusions changed, and it needed some style attention, so it got tidied. Signed-off-by: Jeff Dike <jdike@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
218 lines
4.7 KiB
C
218 lines
4.7 KiB
C
/*
|
|
* Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
|
|
* Licensed under the GPL
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <linux/if_tun.h>
|
|
#include <net/if.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/uio.h>
|
|
#include "kern_constants.h"
|
|
#include "kern_util.h"
|
|
#include "os.h"
|
|
#include "tuntap.h"
|
|
#include "user.h"
|
|
|
|
static int tuntap_user_init(void *data, void *dev)
|
|
{
|
|
struct tuntap_data *pri = data;
|
|
|
|
pri->dev = dev;
|
|
return 0;
|
|
}
|
|
|
|
static void tuntap_add_addr(unsigned char *addr, unsigned char *netmask,
|
|
void *data)
|
|
{
|
|
struct tuntap_data *pri = data;
|
|
|
|
tap_check_ips(pri->gate_addr, addr);
|
|
if ((pri->fd == -1) || pri->fixed_config)
|
|
return;
|
|
open_addr(addr, netmask, pri->dev_name);
|
|
}
|
|
|
|
static void tuntap_del_addr(unsigned char *addr, unsigned char *netmask,
|
|
void *data)
|
|
{
|
|
struct tuntap_data *pri = data;
|
|
|
|
if ((pri->fd == -1) || pri->fixed_config)
|
|
return;
|
|
close_addr(addr, netmask, pri->dev_name);
|
|
}
|
|
|
|
struct tuntap_pre_exec_data {
|
|
int stdout;
|
|
int close_me;
|
|
};
|
|
|
|
static void tuntap_pre_exec(void *arg)
|
|
{
|
|
struct tuntap_pre_exec_data *data = arg;
|
|
|
|
dup2(data->stdout, 1);
|
|
close(data->close_me);
|
|
}
|
|
|
|
static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
|
|
char *buffer, int buffer_len, int *used_out)
|
|
{
|
|
struct tuntap_pre_exec_data data;
|
|
char version_buf[sizeof("nnnnn\0")];
|
|
char *argv[] = { "uml_net", version_buf, "tuntap", "up", gate,
|
|
NULL };
|
|
char buf[CMSG_SPACE(sizeof(*fd_out))];
|
|
struct msghdr msg;
|
|
struct cmsghdr *cmsg;
|
|
struct iovec iov;
|
|
int pid, n, err;
|
|
|
|
sprintf(version_buf, "%d", UML_NET_VERSION);
|
|
|
|
data.stdout = remote;
|
|
data.close_me = me;
|
|
|
|
pid = run_helper(tuntap_pre_exec, &data, argv);
|
|
|
|
if (pid < 0)
|
|
return -pid;
|
|
|
|
close(remote);
|
|
|
|
msg.msg_name = NULL;
|
|
msg.msg_namelen = 0;
|
|
if (buffer != NULL) {
|
|
iov = ((struct iovec) { buffer, buffer_len });
|
|
msg.msg_iov = &iov;
|
|
msg.msg_iovlen = 1;
|
|
}
|
|
else {
|
|
msg.msg_iov = NULL;
|
|
msg.msg_iovlen = 0;
|
|
}
|
|
msg.msg_control = buf;
|
|
msg.msg_controllen = sizeof(buf);
|
|
msg.msg_flags = 0;
|
|
n = recvmsg(me, &msg, 0);
|
|
*used_out = n;
|
|
if (n < 0) {
|
|
err = -errno;
|
|
printk(UM_KERN_ERR "tuntap_open_tramp : recvmsg failed - "
|
|
"errno = %d\n", errno);
|
|
return err;
|
|
}
|
|
helper_wait(pid, 0, "tuntap_open_tramp");
|
|
|
|
cmsg = CMSG_FIRSTHDR(&msg);
|
|
if (cmsg == NULL) {
|
|
printk(UM_KERN_ERR "tuntap_open_tramp : didn't receive a "
|
|
"message\n");
|
|
return -EINVAL;
|
|
}
|
|
if ((cmsg->cmsg_level != SOL_SOCKET) ||
|
|
(cmsg->cmsg_type != SCM_RIGHTS)) {
|
|
printk(UM_KERN_ERR "tuntap_open_tramp : didn't receive a "
|
|
"descriptor\n");
|
|
return -EINVAL;
|
|
}
|
|
*fd_out = ((int *) CMSG_DATA(cmsg))[0];
|
|
os_set_exec_close(*fd_out);
|
|
return 0;
|
|
}
|
|
|
|
static int tuntap_open(void *data)
|
|
{
|
|
struct ifreq ifr;
|
|
struct tuntap_data *pri = data;
|
|
char *output, *buffer;
|
|
int err, fds[2], len, used;
|
|
|
|
err = tap_open_common(pri->dev, pri->gate_addr);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
if (pri->fixed_config) {
|
|
pri->fd = os_open_file("/dev/net/tun",
|
|
of_cloexec(of_rdwr(OPENFLAGS())), 0);
|
|
if (pri->fd < 0) {
|
|
printk(UM_KERN_ERR "Failed to open /dev/net/tun, "
|
|
"err = %d\n", -pri->fd);
|
|
return pri->fd;
|
|
}
|
|
memset(&ifr, 0, sizeof(ifr));
|
|
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
|
|
strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name));
|
|
if (ioctl(pri->fd, TUNSETIFF, &ifr) < 0) {
|
|
err = -errno;
|
|
printk(UM_KERN_ERR "TUNSETIFF failed, errno = %d\n",
|
|
errno);
|
|
close(pri->fd);
|
|
return err;
|
|
}
|
|
}
|
|
else {
|
|
err = socketpair(AF_UNIX, SOCK_DGRAM, 0, fds);
|
|
if (err) {
|
|
err = -errno;
|
|
printk(UM_KERN_ERR "tuntap_open : socketpair failed - "
|
|
"errno = %d\n", errno);
|
|
return err;
|
|
}
|
|
|
|
buffer = get_output_buffer(&len);
|
|
if (buffer != NULL)
|
|
len--;
|
|
used = 0;
|
|
|
|
err = tuntap_open_tramp(pri->gate_addr, &pri->fd, fds[0],
|
|
fds[1], buffer, len, &used);
|
|
|
|
output = buffer;
|
|
if (err < 0) {
|
|
printk("%s", output);
|
|
free_output_buffer(buffer);
|
|
printk(UM_KERN_ERR "tuntap_open_tramp failed - "
|
|
"err = %d\n", -err);
|
|
return err;
|
|
}
|
|
|
|
pri->dev_name = uml_strdup(buffer);
|
|
output += IFNAMSIZ;
|
|
printk("%s", output);
|
|
free_output_buffer(buffer);
|
|
|
|
close(fds[0]);
|
|
iter_addresses(pri->dev, open_addr, pri->dev_name);
|
|
}
|
|
|
|
return pri->fd;
|
|
}
|
|
|
|
static void tuntap_close(int fd, void *data)
|
|
{
|
|
struct tuntap_data *pri = data;
|
|
|
|
if (!pri->fixed_config)
|
|
iter_addresses(pri->dev, close_addr, pri->dev_name);
|
|
close(fd);
|
|
pri->fd = -1;
|
|
}
|
|
|
|
const struct net_user_info tuntap_user_info = {
|
|
.init = tuntap_user_init,
|
|
.open = tuntap_open,
|
|
.close = tuntap_close,
|
|
.remove = NULL,
|
|
.add_address = tuntap_add_addr,
|
|
.delete_address = tuntap_del_addr,
|
|
.mtu = ETH_MAX_PACKET,
|
|
.max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER,
|
|
};
|