Creation of Cybook 2416 (actually Gen4) repository
This commit is contained in:
13
arch/um/os-Linux/drivers/Makefile
Normal file
13
arch/um/os-Linux/drivers/Makefile
Normal file
@@ -0,0 +1,13 @@
|
||||
#
|
||||
# Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
|
||||
# Licensed under the GPL
|
||||
#
|
||||
|
||||
ethertap-objs := ethertap_kern.o ethertap_user.o
|
||||
tuntap-objs := tuntap_kern.o tuntap_user.o
|
||||
|
||||
obj-y =
|
||||
obj-$(CONFIG_UML_NET_ETHERTAP) += ethertap.o
|
||||
obj-$(CONFIG_UML_NET_TUNTAP) += tuntap.o
|
||||
|
||||
include arch/um/scripts/Makefile.rules
|
||||
27
arch/um/os-Linux/drivers/etap.h
Normal file
27
arch/um/os-Linux/drivers/etap.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#include "net_user.h"
|
||||
|
||||
struct ethertap_data {
|
||||
char *dev_name;
|
||||
char *gate_addr;
|
||||
int data_fd;
|
||||
int control_fd;
|
||||
void *dev;
|
||||
};
|
||||
|
||||
extern const struct net_user_info ethertap_user_info;
|
||||
|
||||
/*
|
||||
* 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:
|
||||
*/
|
||||
108
arch/um/os-Linux/drivers/ethertap_kern.c
Normal file
108
arch/um/os-Linux/drivers/ethertap_kern.c
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "linux/init.h"
|
||||
#include "linux/netdevice.h"
|
||||
#include "linux/etherdevice.h"
|
||||
#include "net_kern.h"
|
||||
#include "net_user.h"
|
||||
#include "etap.h"
|
||||
|
||||
struct ethertap_init {
|
||||
char *dev_name;
|
||||
char *gate_addr;
|
||||
};
|
||||
|
||||
static void etap_init(struct net_device *dev, void *data)
|
||||
{
|
||||
struct uml_net_private *pri;
|
||||
struct ethertap_data *epri;
|
||||
struct ethertap_init *init = data;
|
||||
|
||||
pri = dev->priv;
|
||||
epri = (struct ethertap_data *) pri->user;
|
||||
epri->dev_name = init->dev_name;
|
||||
epri->gate_addr = init->gate_addr;
|
||||
epri->data_fd = -1;
|
||||
epri->control_fd = -1;
|
||||
epri->dev = dev;
|
||||
|
||||
printk("ethertap backend - %s", epri->dev_name);
|
||||
if (epri->gate_addr != NULL)
|
||||
printk(", IP = %s", epri->gate_addr);
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
static int etap_read(int fd, struct sk_buff **skb, struct uml_net_private *lp)
|
||||
{
|
||||
int len;
|
||||
|
||||
*skb = ether_adjust_skb(*skb, ETH_HEADER_ETHERTAP);
|
||||
if(*skb == NULL) return(-ENOMEM);
|
||||
len = net_recvfrom(fd, (*skb)->mac.raw,
|
||||
(*skb)->dev->mtu + 2 * ETH_HEADER_ETHERTAP);
|
||||
if(len <= 0) return(len);
|
||||
skb_pull(*skb, 2);
|
||||
len -= 2;
|
||||
return(len);
|
||||
}
|
||||
|
||||
static int etap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp)
|
||||
{
|
||||
if(skb_headroom(*skb) < 2){
|
||||
struct sk_buff *skb2;
|
||||
|
||||
skb2 = skb_realloc_headroom(*skb, 2);
|
||||
dev_kfree_skb(*skb);
|
||||
if (skb2 == NULL) return(-ENOMEM);
|
||||
*skb = skb2;
|
||||
}
|
||||
skb_push(*skb, 2);
|
||||
return(net_send(fd, (*skb)->data, (*skb)->len));
|
||||
}
|
||||
|
||||
const struct net_kern_info ethertap_kern_info = {
|
||||
.init = etap_init,
|
||||
.protocol = eth_protocol,
|
||||
.read = etap_read,
|
||||
.write = etap_write,
|
||||
};
|
||||
|
||||
int ethertap_setup(char *str, char **mac_out, void *data)
|
||||
{
|
||||
struct ethertap_init *init = data;
|
||||
|
||||
*init = ((struct ethertap_init)
|
||||
{ .dev_name = NULL,
|
||||
.gate_addr = NULL });
|
||||
if(tap_setup_common(str, "ethertap", &init->dev_name, mac_out,
|
||||
&init->gate_addr))
|
||||
return(0);
|
||||
if(init->dev_name == NULL){
|
||||
printk("ethertap_setup : Missing tap device name\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
static struct transport ethertap_transport = {
|
||||
.list = LIST_HEAD_INIT(ethertap_transport.list),
|
||||
.name = "ethertap",
|
||||
.setup = ethertap_setup,
|
||||
.user = ðertap_user_info,
|
||||
.kern = ðertap_kern_info,
|
||||
.private_size = sizeof(struct ethertap_data),
|
||||
};
|
||||
|
||||
static int register_ethertap(void)
|
||||
{
|
||||
register_transport(ðertap_transport);
|
||||
return 0;
|
||||
}
|
||||
|
||||
late_initcall(register_ethertap);
|
||||
240
arch/um/os-Linux/drivers/ethertap_user.c
Normal file
240
arch/um/os-Linux/drivers/ethertap_user.c
Normal file
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/errno.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 "um_malloc.h"
|
||||
|
||||
#define MAX_PACKET ETH_MAX_PACKET
|
||||
|
||||
void etap_user_init(void *data, void *dev)
|
||||
{
|
||||
struct ethertap_data *pri = data;
|
||||
|
||||
pri->dev = dev;
|
||||
}
|
||||
|
||||
struct addr_change {
|
||||
enum { ADD_ADDR, DEL_ADDR } what;
|
||||
unsigned char addr[4];
|
||||
unsigned char netmask[4];
|
||||
};
|
||||
|
||||
static void etap_change(int op, unsigned char *addr, unsigned char *netmask,
|
||||
int fd)
|
||||
{
|
||||
struct addr_change change;
|
||||
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){
|
||||
printk("%s", output);
|
||||
kfree(output);
|
||||
}
|
||||
}
|
||||
|
||||
static void etap_open_addr(unsigned char *addr, unsigned char *netmask,
|
||||
void *arg)
|
||||
{
|
||||
etap_change(ADD_ADDR, addr, netmask, *((int *) arg));
|
||||
}
|
||||
|
||||
static void etap_close_addr(unsigned char *addr, unsigned char *netmask,
|
||||
void *arg)
|
||||
{
|
||||
etap_change(DEL_ADDR, addr, netmask, *((int *) arg));
|
||||
}
|
||||
|
||||
struct etap_pre_exec_data {
|
||||
int control_remote;
|
||||
int control_me;
|
||||
int data_me;
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
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",
|
||||
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){
|
||||
strcpy(gate_buf, gate);
|
||||
args = setup_args;
|
||||
}
|
||||
else args = nosetup_args;
|
||||
|
||||
err = 0;
|
||||
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);
|
||||
}
|
||||
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");
|
||||
}
|
||||
return(err);
|
||||
}
|
||||
|
||||
static int etap_open(void *data)
|
||||
{
|
||||
struct ethertap_data *pri = data;
|
||||
char *output;
|
||||
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);
|
||||
}
|
||||
|
||||
err = os_pipe(control_fds, 1, 0);
|
||||
if(err < 0){
|
||||
printk("control os_pipe failed - err = %d\n", -err);
|
||||
return(err);
|
||||
}
|
||||
|
||||
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);
|
||||
read_output(control_fds[0], output, output_len);
|
||||
|
||||
if(output == NULL)
|
||||
printk("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);
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
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);
|
||||
pri->data_fd = -1;
|
||||
os_close_file(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;
|
||||
etap_open_addr(addr, netmask, &pri->control_fd);
|
||||
}
|
||||
|
||||
static void etap_del_addr(unsigned char *addr, unsigned char *netmask,
|
||||
void *data)
|
||||
{
|
||||
struct ethertap_data *pri = data;
|
||||
|
||||
if(pri->control_fd == -1) return;
|
||||
etap_close_addr(addr, netmask, &pri->control_fd);
|
||||
}
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
/*
|
||||
* 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:
|
||||
*/
|
||||
32
arch/um/os-Linux/drivers/tuntap.h
Normal file
32
arch/um/os-Linux/drivers/tuntap.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#ifndef __UM_TUNTAP_H
|
||||
#define __UM_TUNTAP_H
|
||||
|
||||
#include "net_user.h"
|
||||
|
||||
struct tuntap_data {
|
||||
char *dev_name;
|
||||
int fixed_config;
|
||||
char *gate_addr;
|
||||
int fd;
|
||||
void *dev;
|
||||
};
|
||||
|
||||
extern const struct net_user_info tuntap_user_info;
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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:
|
||||
*/
|
||||
93
arch/um/os-Linux/drivers/tuntap_kern.c
Normal file
93
arch/um/os-Linux/drivers/tuntap_kern.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#include "linux/stddef.h"
|
||||
#include "linux/netdevice.h"
|
||||
#include "linux/etherdevice.h"
|
||||
#include "linux/skbuff.h"
|
||||
#include "linux/init.h"
|
||||
#include "asm/errno.h"
|
||||
#include "net_kern.h"
|
||||
#include "net_user.h"
|
||||
#include "tuntap.h"
|
||||
|
||||
struct tuntap_init {
|
||||
char *dev_name;
|
||||
char *gate_addr;
|
||||
};
|
||||
|
||||
static void tuntap_init(struct net_device *dev, void *data)
|
||||
{
|
||||
struct uml_net_private *pri;
|
||||
struct tuntap_data *tpri;
|
||||
struct tuntap_init *init = data;
|
||||
|
||||
pri = dev->priv;
|
||||
tpri = (struct tuntap_data *) pri->user;
|
||||
tpri->dev_name = init->dev_name;
|
||||
tpri->fixed_config = (init->dev_name != NULL);
|
||||
tpri->gate_addr = init->gate_addr;
|
||||
tpri->fd = -1;
|
||||
tpri->dev = dev;
|
||||
|
||||
printk("TUN/TAP backend - ");
|
||||
if (tpri->gate_addr != NULL)
|
||||
printk("IP = %s", tpri->gate_addr);
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
static int tuntap_read(int fd, struct sk_buff **skb,
|
||||
struct uml_net_private *lp)
|
||||
{
|
||||
*skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER);
|
||||
if(*skb == NULL) return(-ENOMEM);
|
||||
return(net_read(fd, (*skb)->mac.raw,
|
||||
(*skb)->dev->mtu + ETH_HEADER_OTHER));
|
||||
}
|
||||
|
||||
static int tuntap_write(int fd, struct sk_buff **skb,
|
||||
struct uml_net_private *lp)
|
||||
{
|
||||
return(net_write(fd, (*skb)->data, (*skb)->len));
|
||||
}
|
||||
|
||||
const struct net_kern_info tuntap_kern_info = {
|
||||
.init = tuntap_init,
|
||||
.protocol = eth_protocol,
|
||||
.read = tuntap_read,
|
||||
.write = tuntap_write,
|
||||
};
|
||||
|
||||
int tuntap_setup(char *str, char **mac_out, void *data)
|
||||
{
|
||||
struct tuntap_init *init = data;
|
||||
|
||||
*init = ((struct tuntap_init)
|
||||
{ .dev_name = NULL,
|
||||
.gate_addr = NULL });
|
||||
if(tap_setup_common(str, "tuntap", &init->dev_name, mac_out,
|
||||
&init->gate_addr))
|
||||
return(0);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
static struct transport tuntap_transport = {
|
||||
.list = LIST_HEAD_INIT(tuntap_transport.list),
|
||||
.name = "tuntap",
|
||||
.setup = tuntap_setup,
|
||||
.user = &tuntap_user_info,
|
||||
.kern = &tuntap_kern_info,
|
||||
.private_size = sizeof(struct tuntap_data),
|
||||
.setup_size = sizeof(struct tuntap_init),
|
||||
};
|
||||
|
||||
static int register_tuntap(void)
|
||||
{
|
||||
register_transport(&tuntap_transport);
|
||||
return 0;
|
||||
}
|
||||
|
||||
late_initcall(register_tuntap);
|
||||
228
arch/um/os-Linux/drivers/tuntap_user.c
Normal file
228
arch/um/os-Linux/drivers/tuntap_user.c
Normal file
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
|
||||
* Licensed under the GPL
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h>
|
||||
#include <linux/if_tun.h>
|
||||
#include "net_user.h"
|
||||
#include "tuntap.h"
|
||||
#include "kern_util.h"
|
||||
#include "user_util.h"
|
||||
#include "user.h"
|
||||
#include "os.h"
|
||||
|
||||
#define MAX_PACKET ETH_MAX_PACKET
|
||||
|
||||
void tuntap_user_init(void *data, void *dev)
|
||||
{
|
||||
struct tuntap_data *pri = data;
|
||||
|
||||
pri->dev = dev;
|
||||
}
|
||||
|
||||
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);
|
||||
os_close_file(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, NULL);
|
||||
|
||||
if(pid < 0) return(-pid);
|
||||
|
||||
os_close_file(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("tuntap_open_tramp : recvmsg failed - errno = %d\n",
|
||||
errno);
|
||||
return err;
|
||||
}
|
||||
CATCH_EINTR(waitpid(pid, NULL, 0));
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
if(cmsg == NULL){
|
||||
printk("tuntap_open_tramp : didn't receive a message\n");
|
||||
return(-EINVAL);
|
||||
}
|
||||
if((cmsg->cmsg_level != SOL_SOCKET) ||
|
||||
(cmsg->cmsg_type != SCM_RIGHTS)){
|
||||
printk("tuntap_open_tramp : didn't receive a descriptor\n");
|
||||
return(-EINVAL);
|
||||
}
|
||||
*fd_out = ((int *) CMSG_DATA(cmsg))[0];
|
||||
os_set_exec_close(*fd_out, 1);
|
||||
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("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, (void *) &ifr) < 0){
|
||||
err = -errno;
|
||||
printk("TUNSETIFF failed, errno = %d\n", errno);
|
||||
os_close_file(pri->fd);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
else {
|
||||
err = os_pipe(fds, 0, 0);
|
||||
if(err < 0){
|
||||
printk("tuntap_open : os_pipe failed - err = %d\n",
|
||||
-err);
|
||||
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("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);
|
||||
|
||||
os_close_file(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);
|
||||
os_close_file(fd);
|
||||
pri->fd = -1;
|
||||
}
|
||||
|
||||
static int tuntap_set_mtu(int mtu, void *data)
|
||||
{
|
||||
return(mtu);
|
||||
}
|
||||
|
||||
const struct net_user_info tuntap_user_info = {
|
||||
.init = tuntap_user_init,
|
||||
.open = tuntap_open,
|
||||
.close = tuntap_close,
|
||||
.remove = NULL,
|
||||
.set_mtu = tuntap_set_mtu,
|
||||
.add_address = tuntap_add_addr,
|
||||
.delete_address = tuntap_del_addr,
|
||||
.max_packet = MAX_PACKET
|
||||
};
|
||||
|
||||
/*
|
||||
* 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:
|
||||
*/
|
||||
Reference in New Issue
Block a user