Commit 2d5fe0e0 authored by Linus Torvalds's avatar Linus Torvalds

Merge http://jdike.stearns.org/net-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents c5e1bfd8 e7568fd6
......@@ -9,6 +9,7 @@ dep_bool ' TUN/TAP transport' CONFIG_UML_NET_TUNTAP $CONFIG_UML_NET
dep_bool ' SLIP transport' CONFIG_UML_NET_SLIP $CONFIG_UML_NET
dep_bool ' Daemon transport' CONFIG_UML_NET_DAEMON $CONFIG_UML_NET
dep_bool ' Multicast transport' CONFIG_UML_NET_MCAST $CONFIG_UML_NET
dep_bool ' pcap transport' CONFIG_UML_NET_PCAP $CONFIG_UML_NET
# Below are hardware-independent drivers mirrored from
# drivers/net/Config.in. It would be nice if Linux
......
......@@ -86,6 +86,7 @@ CONFIG_UML_NET_TUNTAP=y
CONFIG_UML_NET_SLIP=y
CONFIG_UML_NET_DAEMON=y
CONFIG_UML_NET_MCAST=y
# CONFIG_UML_NET_PCAP is not set
CONFIG_DUMMY=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
......
......@@ -5,9 +5,23 @@
CHAN_OBJS := chan_kern.o chan_user.o line.o
# This nonsense is due to kbuild. In the 2.4 build, I stick -lpcap in
# pcap-objs, and that is just included in the link command. The 2.5 kbuild
# filters out everything from pcap-objs which are not in the built-in.o
# dependencies, which are $(obj-y). So, -lpcap must be in $(obj-y), too.
# However, make magically expands -lfoo prerequisites into /usr/lib/libfoo.a
# file names. This causes the kbuild filtering to filter the -lpcap from
# pcap-objs, causing the link to fail.
# So, what this does is figure out by hand (crudely) what file -lpcap really
# is and just use it.
PCAP = $(shell for f in echo {/lib,/usr/lib}/libpcap.{a,so}; do \
[ -f $$f ] && echo $$f ; done | head -1)
slip-objs := slip_kern.o slip_user.o
daemon-objs := daemon_kern.o daemon_user.o
mcast-objs := mcast_kern.o mcast_user.o
pcap-objs := pcap_kern.o pcap_user.o $(PCAP)
net-objs := net_kern.o net_user.o
mconsole-objs := mconsole_kern.o mconsole_user.o
hostaudio-objs := hostaudio_kern.o hostaudio_user.o
......@@ -22,6 +36,7 @@ obj-$(CONFIG_SSL) += ssl.o
obj-$(CONFIG_UML_NET_SLIP) += slip.o
obj-$(CONFIG_UML_NET_DAEMON) += daemon.o
obj-$(CONFIG_UML_NET_MCAST) += mcast.o
obj-$(CONFIG_UML_NET_PCAP) += pcap.o $(PCAP)
obj-$(CONFIG_UML_NET) += net.o
obj-$(CONFIG_MCONSOLE) += mconsole.o
obj-$(CONFIG_MMAPPER) += mmapper_kern.o
......@@ -35,6 +50,8 @@ obj-$(CONFIG_TTY_CHAN) += tty.o
obj-$(CONFIG_XTERM_CHAN) += xterm.o
obj-$(CONFIG_UML_WATCHDOG) += harddog.o
CFLAGS_pcap_user.o = -I/usr/include/pcap
obj-y += stdio_console.o $(CHAN_OBJS)
USER_SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y) $(obj-m)),$($(f)-objs))
......
......@@ -12,41 +12,36 @@
#include "net_kern.h"
#include "net_user.h"
#include "daemon.h"
#include "daemon_kern.h"
struct daemon_data daemon_priv[MAX_UML_NETDEV] = {
[ 0 ... MAX_UML_NETDEV - 1 ] =
{
sock_type : "unix",
ctl_sock : "/tmp/uml.ctl",
ctl_addr : NULL,
data_addr : NULL,
local_addr : NULL,
fd : -1,
control : -1,
dev : NULL,
}
struct daemon_init {
char *sock_type;
char *ctl_sock;
};
void daemon_init(struct net_device *dev, int index)
void daemon_init(struct net_device *dev, void *data)
{
struct uml_net_private *pri;
struct daemon_data *dpri;
struct daemon_init *init = data;
init_etherdev(dev, 0);
pri = dev->priv;
dpri = (struct daemon_data *) pri->user;
*dpri = daemon_priv[index];
*dpri = ((struct daemon_data)
{ sock_type : init->sock_type,
ctl_sock : init->ctl_sock,
ctl_addr : NULL,
data_addr : NULL,
local_addr : NULL,
fd : -1,
control : -1,
dev : dev });
printk("daemon backend (uml_switch version %d) - %s:%s",
SWITCH_VERSION, dpri->sock_type, dpri->ctl_sock);
printk("\n");
}
static unsigned short daemon_protocol(struct sk_buff *skb)
{
return(eth_type_trans(skb, skb->dev));
}
static int daemon_read(int fd, struct sk_buff **skb,
struct uml_net_private *lp)
{
......@@ -65,47 +60,37 @@ static int daemon_write(int fd, struct sk_buff **skb,
static struct net_kern_info daemon_kern_info = {
init: daemon_init,
protocol: daemon_protocol,
protocol: eth_protocol,
read: daemon_read,
write: daemon_write,
};
static int daemon_count = 0;
int daemon_setup(char *str, struct uml_net *dev)
int daemon_setup(char *str, char **mac_out, void *data)
{
int err, n = daemon_count;
dev->user = &daemon_user_info;
dev->kern = &daemon_kern_info;
dev->private_size = sizeof(struct daemon_data);
dev->transport_index = daemon_count++;
if(*str != ',') return(0);
str++;
if(*str != ','){
err = setup_etheraddr(str, dev->mac);
if(!err) dev->have_mac = 1;
}
str = strchr(str, ',');
if(str == NULL) return(0);
*str++ = '\0';
if(*str != ',') daemon_priv[n].sock_type = str;
str = strchr(str, ',');
if(str == NULL) return(0);
*str++ = '\0';
if(*str != ',') daemon_priv[n].ctl_sock = str;
str = strchr(str, ',');
if(str == NULL) return(0);
*str = '\0';
struct daemon_init *init = data;
char *remain;
*init = ((struct daemon_init)
{ sock_type : "unix",
ctl_sock : "/tmp/uml.ctl" });
remain = split_if_spec(str, mac_out, &init->sock_type, &init->ctl_sock,
NULL);
if(remain != NULL)
printk(KERN_WARNING "daemon_setup : Ignoring data socket "
"specification\n");
return(0);
return(1);
}
static struct transport daemon_transport = {
list : LIST_HEAD_INIT(daemon_transport.list),
name : "daemon",
setup : daemon_setup
setup : daemon_setup,
user : &daemon_user_info,
kern : &daemon_kern_info,
private_size : sizeof(struct daemon_data),
setup_size : sizeof(struct daemon_init),
};
static int register_daemon(void)
......@@ -115,6 +100,7 @@ static int register_daemon(void)
}
__initcall(register_daemon);
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
......
#ifndef __UM_DAEMON_KERN_H
#define __UM_DAEMON_KERN_H
#include "net_kern.h"
extern int daemon_setup(char *arg, struct uml_net *dev);
#endif
......@@ -10,8 +10,6 @@ struct mcast_data {
unsigned short port;
void *mcast_addr;
int ttl;
unsigned char hwaddr[ETH_ADDR_LEN];
int hw_setup;
void *dev;
};
......
......@@ -19,26 +19,28 @@
#include "net_kern.h"
#include "net_user.h"
#include "mcast.h"
#include "mcast_kern.h"
struct mcast_data mcast_priv[MAX_UML_NETDEV] = {
[ 0 ... MAX_UML_NETDEV - 1 ] =
{
addr: "239.192.168.1",
port: 1102,
ttl: 1,
}
struct mcast_init {
char *addr;
int port;
int ttl;
};
void mcast_init(struct net_device *dev, int index)
void mcast_init(struct net_device *dev, void *data)
{
struct uml_net_private *pri;
struct mcast_data *dpri;
struct mcast_init *init = data;
init_etherdev(dev, 0);
pri = dev->priv;
dpri = (struct mcast_data *) pri->user;
*dpri = mcast_priv[index];
*dpri = ((struct mcast_data)
{ addr : init->addr,
port : init->port,
ttl : init->ttl,
mcast_addr : NULL,
dev : dev });
printk("mcast backend ");
printk("multicast adddress: %s:%u, TTL:%u ",
dpri->addr, dpri->port, dpri->ttl);
......@@ -46,11 +48,6 @@ void mcast_init(struct net_device *dev, int index)
printk("\n");
}
static unsigned short mcast_protocol(struct sk_buff *skb)
{
return eth_type_trans(skb, skb->dev);
}
static int mcast_read(int fd, struct sk_buff **skb, struct uml_net_private *lp)
{
*skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER);
......@@ -68,71 +65,64 @@ static int mcast_write(int fd, struct sk_buff **skb,
static struct net_kern_info mcast_kern_info = {
init: mcast_init,
protocol: mcast_protocol,
protocol: eth_protocol,
read: mcast_read,
write: mcast_write,
};
static int mcast_count = 0;
int mcast_setup(char *str, struct uml_net *dev)
int mcast_setup(char *str, char **mac_out, void *data)
{
int err, n = mcast_count;
int num = 0;
char *p1, *p2;
dev->user = &mcast_user_info;
dev->kern = &mcast_kern_info;
dev->private_size = sizeof(struct mcast_data);
dev->transport_index = mcast_count++;
/* somewhat more sophisticated parser, needed for in_aton */
p1 = str;
if (*str == ',')
p1++;
while (p1 && *p1) {
if ((p2 = strchr(p1, ',')))
*p2++ = '\0';
if (strlen(p1) > 0) {
switch (num) {
case 0:
/* First argument: Ethernet address */
err = setup_etheraddr(p1, dev->mac);
if (!err)
dev->have_mac = 1;
break;
case 1:
/* Second argument: Multicast group */
mcast_priv[n].addr = p1;
break;
case 2:
/* Third argument: Port number */
mcast_priv[n].port =
htons(simple_strtoul(p1, NULL, 10));
break;
case 3:
/* Fourth argument: TTL */
mcast_priv[n].ttl =
simple_strtoul(p1, NULL, 10);
break;
struct mcast_init *init = data;
char *port_str = NULL, *ttl_str = NULL, *remain;
char *last;
int n;
*init = ((struct mcast_init)
{ addr : "239.192.168.1",
port : 1102,
ttl : 1 });
remain = split_if_spec(str, mac_out, &init->addr, &port_str, &ttl_str,
NULL);
if(remain != NULL){
printk(KERN_ERR "mcast_setup - Extra garbage on "
"specification : '%s'\n", remain);
return(0);
}
if(port_str != NULL){
n = simple_strtoul(port_str, &last, 10);
if(*last != '\0'){
printk(KERN_ERR "mcast_setup - Bad port : '%s'\n",
port_str);
return(0);
}
init->port = htons(n);
}
if(ttl_str != NULL){
init->ttl = simple_strtoul(ttl_str, &last, 10);
if(*last != '\0'){
printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n",
ttl_str);
return(0);
}
p1 = p2;
num++;
}
printk(KERN_INFO "Configured mcast device: %s:%u-%u\n",
mcast_priv[n].addr, mcast_priv[n].port,
mcast_priv[n].ttl);
printk(KERN_INFO "Configured mcast device: %s:%u-%u\n", init->addr,
init->port, init->ttl);
return(0);
return(1);
}
static struct transport mcast_transport = {
list : LIST_HEAD_INIT(mcast_transport.list),
name : "mcast",
setup : mcast_setup
setup : mcast_setup,
user : &mcast_user_info,
kern : &mcast_kern_info,
private_size : sizeof(struct mcast_data),
setup_size : sizeof(struct mcast_init),
};
static int register_mcast(void)
......@@ -142,6 +132,7 @@ static int register_mcast(void)
}
__initcall(register_mcast);
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
......
#ifndef __UM_MCAST_KERN_H
#define __UM_MCAST_KERN_H
#include "net_kern.h"
extern int mcast_setup(char *arg, struct uml_net *dev);
#endif
This diff is collapsed.
......@@ -4,6 +4,7 @@
*/
#include <stddef.h>
#include <stdarg.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
......@@ -220,6 +221,27 @@ void close_addr(unsigned char *addr, unsigned char *netmask, void *arg)
change(arg, "del", addr, netmask);
}
char *split_if_spec(char *str, ...)
{
char **arg, *end;
va_list ap;
va_start(ap, str);
while((arg = va_arg(ap, char **)) != NULL){
if(*str == '\0')
return(NULL);
end = strchr(str, ',');
if(end != str)
*arg = str;
if(end == NULL)
return(NULL);
*end++ = '\0';
str = end;
}
va_end(ap);
return(str);
}
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
......
/*
* Copyright (C) 2002 Jeff Dike <jdike@karaya.com>
* 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 "pcap_user.h"
struct pcap_init {
char *host_if;
int promisc;
int optimize;
char *filter;
};
void pcap_init(struct net_device *dev, void *data)
{
struct uml_net_private *pri;
struct pcap_data *ppri;
struct pcap_init *init = data;
init_etherdev(dev, 0);
pri = dev->priv;
ppri = (struct pcap_data *) pri->user;
*ppri = ((struct pcap_data)
{ host_if : init->host_if,
promisc : init->promisc,
optimize : init->optimize,
filter : init->filter,
compiled : NULL,
pcap : NULL });
}
static int pcap_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(pcap_user_read(fd, (*skb)->mac.raw,
(*skb)->dev->mtu + ETH_HEADER_OTHER,
(struct pcap_data *) &lp->user));
}
static int pcap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp)
{
return(-EPERM);
}
static struct net_kern_info pcap_kern_info = {
init: pcap_init,
protocol: eth_protocol,
read: pcap_read,
write: pcap_write,
};
int pcap_setup(char *str, char **mac_out, void *data)
{
struct pcap_init *init = data;
char *remain, *host_if = NULL, *options[2] = { NULL, NULL };
int i;
*init = ((struct pcap_init)
{ host_if : "eth0",
promisc : 1,
optimize : 0,
filter : NULL });
remain = split_if_spec(str, &host_if, &init->filter,
&options[0], &options[1], NULL);
if(remain != NULL){
printk(KERN_ERR "pcap_setup - Extra garbage on "
"specification : '%s'\n", remain);
return(0);
}
if(host_if != NULL)
init->host_if = host_if;
for(i = 0; i < sizeof(options)/sizeof(options[0]); i++){
if(options[i] == NULL)
continue;
if(!strcmp(options[i], "promisc"))
init->promisc = 1;
else if(!strcmp(options[i], "nopromisc"))
init->promisc = 0;
else if(!strcmp(options[i], "optimize"))
init->optimize = 1;
else if(!strcmp(options[i], "nooptimize"))
init->optimize = 0;
else printk("pcap_setup : bad option - '%s'\n", options[i]);
}
return(1);
}
static struct transport pcap_transport = {
list : LIST_HEAD_INIT(pcap_transport.list),
name : "pcap",
setup : pcap_setup,
user : &pcap_user_info,
kern : &pcap_kern_info,
private_size : sizeof(struct pcap_data),
setup_size : sizeof(struct pcap_init),
};
static int register_pcap(void)
{
register_transport(&pcap_transport);
return(1);
}
__initcall(register_pcap);
/*
* 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:
*/
/*
* Copyright (C) 2002 Jeff Dike <jdike@karaya.com>
* Licensed under the GPL.
*/
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pcap.h>
#include <asm/types.h>
#include "net_user.h"
#include "pcap_user.h"
#include "user.h"
#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER)
#define PCAP_FD(p) (*(int *)(p))
static void pcap_user_init(void *data, void *dev)
{
struct pcap_data *pri = data;
pcap_t *p;
char errors[PCAP_ERRBUF_SIZE];
p = pcap_open_live(pri->host_if, MAX_PACKET, pri->promisc, 0, errors);
if(p == NULL){
printk("pcap_user_init : pcap_open_live failed - '%s'\n",
errors);
return;
}
pri->dev = dev;
pri->pcap = p;
}
static int pcap_open(void *data)
{
struct pcap_data *pri = data;
__u32 netmask;
int err;
if(pri->pcap == NULL)
return(-ENODEV);
if(pri->filter != NULL){
err = dev_netmask(pri->dev, &netmask);
if(err < 0){
printk("pcap_open : dev_netmask failed\n");
return(-EIO);
}
pri->compiled = um_kmalloc(sizeof(struct bpf_program));
if(pri->compiled == NULL){
printk("pcap_open : kmalloc failed\n");
return(-ENOMEM);
}
err = pcap_compile(pri->pcap,
(struct bpf_program *) pri->compiled,
pri->filter, pri->optimize, netmask);
if(err < 0){
printk("pcap_open : pcap_compile failed - '%s'\n",
pcap_geterr(pri->pcap));
return(-EIO);
}
err = pcap_setfilter(pri->pcap, pri->compiled);
if(err < 0){
printk("pcap_open : pcap_setfilter failed - '%s'\n",
pcap_geterr(pri->pcap));
return(-EIO);
}
}
return(PCAP_FD(pri->pcap));
}
static void pcap_remove(void *data)
{
struct pcap_data *pri = data;
if(pri->compiled != NULL)
pcap_freecode(pri->compiled);
pcap_close(pri->pcap);
}
struct pcap_handler_data {
char *buffer;
int len;
};
static void handler(u_char *data, const struct pcap_pkthdr *header,
const u_char *packet)
{
int len;
struct pcap_handler_data *hdata = (struct pcap_handler_data *) data;
len = hdata->len < header->caplen ? hdata->len : header->caplen;
memcpy(hdata->buffer, packet, len);
hdata->len = len;
}
int pcap_user_read(int fd, void *buffer, int len, struct pcap_data *pri)
{
struct pcap_handler_data hdata = ((struct pcap_handler_data)
{ buffer : buffer,
len : len });
int n;
n = pcap_dispatch(pri->pcap, 1, handler, (u_char *) &hdata);
if(n < 0){
printk("pcap_dispatch failed - %s\n", pcap_geterr(pri->pcap));
return(-EIO);
}
else if(n == 0)
return(0);
return(hdata.len);
}
struct net_user_info pcap_user_info = {
init: pcap_user_init,
open: pcap_open,
close: NULL,
remove: pcap_remove,
set_mtu: NULL,
add_address: NULL,
delete_address: NULL,
max_packet: MAX_PACKET - ETH_HEADER_OTHER
};
/*
* 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:
*/
/*
* Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#ifndef __UM_TUNTAP_KERN_H
#define __UM_TUNTAP_KERN_H
#include "net_user.h"
#include "net_kern.h"
struct pcap_data {
char *host_if;
int promisc;
int optimize;
char *filter;
void *compiled;
void *pcap;
void *dev;
};
extern int tuntap_setup(char *arg, struct uml_net *dev);
extern struct net_user_info pcap_user_info;
#endif
extern int pcap_user_read(int fd, void *buf, int len, struct pcap_data *pri);
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
......
......@@ -53,7 +53,7 @@ static void pipe_interrupt(int irq, void *data, struct pt_regs *regs)
fd = os_rcv_fd(conn->socket[0], &conn->helper_pid);
if(fd < 0){
printk("os_accept_connection returned %d\n", -fd);
printk("os_rcv_fd returned %d\n", -fd);
os_close_file(conn->fd);
}
conn->fd = fd;
......
......@@ -7,28 +7,29 @@
#include "net_user.h"
#include "kern.h"
#include "slip.h"
#include "slip_kern.h"
struct slip_data slip_priv[MAX_UML_NETDEV] = {
[ 0 ... MAX_UML_NETDEV - 1 ] =
{
addr: NULL,
gate_addr: NULL,
slave: -1,
buf: { 0 },
pos: 0,
esc: 0,
}
struct slip_init {
char *gate_addr;
};
void slip_init(struct net_device *dev, int index)
void slip_init(struct net_device *dev, void *data)
{
struct uml_net_private *private;
struct slip_data *spri;
struct slip_init *init = data;
private = dev->priv;
spri = (struct slip_data *) private->user;
*spri = slip_priv[index];
*spri = ((struct slip_data)
{ name : { '\0' },
addr: NULL,
gate_addr : init->gate_addr,
slave : 0,
buf : { '\0' },
pos : 0,
esc : 0,
dev : dev });
strncpy(dev->name, "umn", IFNAMSIZ);
dev->init = NULL;
dev->hard_header_len = 0;
......@@ -67,26 +68,26 @@ struct net_kern_info slip_kern_info = {
write: slip_write,
};
static int slip_count = 0;
int slip_setup(char *str, struct uml_net *dev)
static int slip_setup(char *str, char **mac_out, void *data)
{
int n = slip_count;
struct slip_init *init = data;
*init = ((struct slip_init)
{ gate_addr : NULL });
dev->user = &slip_user_info;
dev->kern = &slip_kern_info;
dev->private_size = sizeof(struct slip_data);
dev->transport_index = slip_count++;
if(*str != ',') return(0);
str++;
if(str[0] != '\0') slip_priv[n].gate_addr = str;
return(0);
if(str[0] != '\0')
init->gate_addr = str;
return(1);
}
static struct transport slip_transport = {
list : LIST_HEAD_INIT(slip_transport.list),
name : "slip",
setup : slip_setup
setup : slip_setup,
user : &slip_user_info,
kern : &slip_kern_info,
private_size : sizeof(struct slip_data),
setup_size : sizeof(struct slip_init),
};
static int register_slip(void)
......
#ifndef __UM_SLIP_KERN_H
#define __UM_SLIP_KERN_H
#include "net_kern.h"
extern int slip_setup(char *arg, struct uml_net *dev);
#endif
......@@ -25,6 +25,7 @@ extern void *sbrk(int increment);
extern void *malloc(int size);
extern void perror(char *err);
extern int kill(int pid, int sig);
extern int getpid(void);
extern int getuid(void);
extern int pause(void);
extern int write(int, const void *, int);
......
......@@ -6,14 +6,10 @@
#include "linux/socket.h"
#include "linux/list.h"
#define MAX_UML_NETDEV (16)
struct uml_net {
struct list_head list;
struct net_device *dev;
struct net_user_info *user;
struct net_kern_info *kern;
int private_size;
int transport_index;
int index;
unsigned char mac[ETH_ALEN];
int have_mac;
};
......@@ -41,7 +37,7 @@ struct uml_net_private {
};
struct net_kern_info {
void (*init)(struct net_device *, int);
void (*init)(struct net_device *, void *);
unsigned short (*protocol)(struct sk_buff *);
int (*read)(int, struct sk_buff **skb, struct uml_net_private *);
int (*write)(int, struct sk_buff **skb, struct uml_net_private *);
......@@ -50,7 +46,11 @@ struct net_kern_info {
struct transport {
struct list_head list;
char *name;
int (*setup)(char *, struct uml_net *);
int (*setup)(char *, char **, void *);
struct net_user_info *user;
struct net_kern_info *kern;
int private_size;
int setup_size;
};
extern struct net_device *ether_init(int);
......@@ -58,8 +58,9 @@ extern unsigned short ether_protocol(struct sk_buff *);
extern int setup_etheraddr(char *str, unsigned char *addr);
extern struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra);
extern int tap_setup_common(char *str, char *type, char **dev_name,
char *hw_addr, int *hw_setup, char **gate_addr);
char **mac_out, char **gate_addr);
extern void register_transport(struct transport *new);
extern unsigned short eth_protocol(struct sk_buff *skb);
#endif
......
......@@ -43,6 +43,10 @@ extern int net_sendto(int fd, void *buf, int len, void *to, int sock_len);
extern void open_addr(unsigned char *addr, unsigned char *netmask, void *arg);
extern void close_addr(unsigned char *addr, unsigned char *netmask, void *arg);
extern char *split_if_spec(char *str, ...);
extern int dev_netmask(void *d, void *m);
#endif
/*
......
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#ifndef __TIME_USER_H__
#define __TIME_USER_H__
extern void timer(void);
extern void get_profile_timer(void);
extern void disable_profile_timer(void);
extern void switch_timers(int to_real);
extern void user_time_init(void);
extern void set_timers(int set_signal);
extern void idle_sleep(int secs);
#endif
......@@ -64,10 +64,6 @@ extern void signal_init(void);
extern int start_fork_tramp(void *arg, unsigned long temp_stack,
int clone_flags, int (*tramp)(void *));
extern void trace_myself(void);
extern void timer(void);
extern void get_profile_timer(void);
extern void disable_profile_timer(void);
extern void set_timers(int set_signal);
extern int clone_and_wait(int (*fn)(void *), void *arg, void *sp, int flags);
extern int input_loop(void);
extern void continue_execing_proc(int pid);
......@@ -81,7 +77,6 @@ extern void save_signal_state(int *sig_ptr);
extern void *um_kmalloc(int size);
extern int raw(int fd, int complain);
extern int switcheroo(int fd, int prot, void *from, void *to, int size);
extern void idle_sleep(int secs);
extern void setup_machinename(char *machine_out);
extern void setup_hostinfo(void);
extern void add_arg(char *cmd_line, char *arg);
......@@ -109,7 +104,6 @@ extern int user_write(int fd, char *buf, int len);
extern void write_sigio_workaround(void);
extern void arch_check_bugs(void);
extern int arch_handle_signal(int sig, struct uml_pt_regs *regs);
extern void user_time_init(void);
extern unsigned long pid_pc(int pid);
extern int arch_fixup(unsigned long address, void *sc_ptr);
extern void forward_pending_sigio(int target);
......
......@@ -35,6 +35,7 @@
#include "irq_user.h"
#include "syscall_user.h"
#include "ptrace_user.h"
#include "time_user.h"
#include "init.h"
#include "os.h"
......
......@@ -34,6 +34,7 @@
#include "init.h"
#include "irq_user.h"
#include "mem_user.h"
#include "time_user.h"
#include "tlb.h"
#include "frame_kern.h"
#include "sigcontext.h"
......
......@@ -53,6 +53,28 @@ static void set_interval(int timer_type)
panic("setitimer failed - errno = %d\n", errno);
}
void switch_timers(int to_real)
{
struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
struct itimerval enable = ((struct itimerval) { { 0, 1000000/hz() },
{ 0, 1000000/hz() }});
int old, new;
if(to_real){
old = ITIMER_VIRTUAL;
new = ITIMER_REAL;
}
else {
old = ITIMER_REAL;
new = ITIMER_VIRTUAL;
}
if((setitimer(old, &disable, NULL) < 0) ||
(setitimer(new, &enable, NULL)))
printk("switch_timers - setitimer failed, errno = %d\n",
errno);
}
void idle_timer(void)
{
if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR)
......
......@@ -16,6 +16,7 @@
#include "asm/current.h"
#include "kern_util.h"
#include "user_util.h"
#include "time_user.h"
u64 jiffies_64;
......
......@@ -99,7 +99,7 @@ void flush_kernel_range(unsigned long start, unsigned long end, int update_seq)
int updated = 0, err;
mm = &init_mm;
for(addr = start_vm; addr < end_vm;){
for(addr = start; addr < end;){
pgd = pgd_offset(mm, addr);
pmd = pmd_offset(pgd, addr);
if(pmd_present(*pmd)){
......
......@@ -34,6 +34,7 @@
#include "frame_user.h"
#include "syscall_user.h"
#include "ptrace_user.h"
#include "time_user.h"
#include "task.h"
#include "os.h"
......@@ -517,7 +518,14 @@ void alarm_handler(int sig, struct sigcontext sc)
user = user_context(SC_SP(&sc));
if(!user && !kern_timer_on) return;
if(!user && jail_timer_off) return;
if(sig == SIGALRM)
switch_timers(0);
sig_handler_common(sig, &sc);
if(sig == SIGALRM)
switch_timers(1);
}
void do_longjmp(void *p)
......
/*
* Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#ifndef __UM_ETHERTAP_KERN_H
#define __UM_ETHERTAP_KERN_H
#include "net_kern.h"
extern int ethertap_setup(char *arg, struct uml_net *dev);
#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:
*/
......@@ -12,42 +12,32 @@
#include "net_kern.h"
#include "net_user.h"
#include "etap.h"
#include "etap_kern.h"
struct ethertap_setup {
struct ethertap_init {
char *dev_name;
char *gate_addr;
};
struct ethertap_setup ethertap_priv[MAX_UML_NETDEV] = {
[ 0 ... MAX_UML_NETDEV - 1 ] =
{
dev_name: NULL,
gate_addr: NULL,
}
};
static void etap_init(struct net_device *dev, int index)
static void etap_init(struct net_device *dev, void *data)
{
struct uml_net_private *pri;
struct ethertap_data *epri;
struct ethertap_init *init = data;
init_etherdev(dev, 0);
pri = dev->priv;
epri = (struct ethertap_data *) pri->user;
epri->dev_name = ethertap_priv[index].dev_name;
epri->gate_addr = ethertap_priv[index].gate_addr;
*epri = ((struct ethertap_data)
{ dev_name : init->dev_name,
gate_addr : init->gate_addr,
data_fd : -1,
control_fd : -1,
dev : dev });
printk("ethertap backend - %s", epri->dev_name);
if(epri->gate_addr != NULL)
printk(", IP = %s", epri->gate_addr);
printk("\n");
epri->data_fd = -1;
epri->control_fd = -1;
}
static unsigned short etap_protocol(struct sk_buff *skb)
{
return(eth_type_trans(skb, skb->dev));
}
static int etap_read(int fd, struct sk_buff **skb, struct uml_net_private *lp)
......@@ -80,38 +70,36 @@ static int etap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp)
struct net_kern_info ethertap_kern_info = {
init: etap_init,
protocol: etap_protocol,
protocol: eth_protocol,
read: etap_read,
write: etap_write,
};
static int ethertap_count = 0;
int ethertap_setup(char *str, struct uml_net *dev)
int ethertap_setup(char *str, char **mac_out, void *data)
{
struct ethertap_setup *pri;
int err;
pri = &ethertap_priv[ethertap_count];
err = tap_setup_common(str, "ethertap", &pri->dev_name, dev->mac,
&dev->have_mac, &pri->gate_addr);
if(err) return(err);
if(pri->dev_name == NULL){
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(1);
return(0);
}
dev->user = &ethertap_user_info;
dev->kern = &ethertap_kern_info;
dev->private_size = sizeof(struct ethertap_data);
dev->transport_index = ethertap_count++;
return(0);
return(1);
}
static struct transport ethertap_transport = {
list : LIST_HEAD_INIT(ethertap_transport.list),
name : "ethertap",
setup : ethertap_setup
setup : ethertap_setup,
user : &ethertap_user_info,
kern : &ethertap_kern_info,
private_size : sizeof(struct ethertap_data),
};
static int register_ethertap(void)
......
......@@ -14,8 +14,6 @@ struct tuntap_data {
char *gate_addr;
int fd;
void *dev;
unsigned char hw_addr[ETH_ADDR_LEN];
int hw_setup;
};
extern struct net_user_info tuntap_user_info;
......
......@@ -13,40 +13,30 @@
#include "net_user.h"
#include "tuntap.h"
struct tuntap_setup {
struct tuntap_init {
char *dev_name;
char *gate_addr;
};
struct tuntap_setup tuntap_priv[MAX_UML_NETDEV] = {
[ 0 ... MAX_UML_NETDEV - 1 ] =
{
dev_name: NULL,
gate_addr: NULL,
}
};
static void tuntap_init(struct net_device *dev, int index)
static void tuntap_init(struct net_device *dev, void *data)
{
struct uml_net_private *pri;
struct tuntap_data *tpri;
struct tuntap_init *init = data;
init_etherdev(dev, 0);
pri = dev->priv;
tpri = (struct tuntap_data *) pri->user;
tpri->dev_name = tuntap_priv[index].dev_name;
tpri->fixed_config = (tpri->dev_name != NULL);
tpri->gate_addr = tuntap_priv[index].gate_addr;
*tpri = ((struct tuntap_data)
{ dev_name : init->dev_name,
fixed_config : (init->dev_name != NULL),
gate_addr : init->gate_addr,
fd : -1,
dev : dev });
printk("TUN/TAP backend - ");
if(tpri->gate_addr != NULL)
printk("IP = %s", tpri->gate_addr);
printk("\n");
tpri->fd = -1;
}
static unsigned short tuntap_protocol(struct sk_buff *skb)
{
return(eth_type_trans(skb, skb->dev));
}
static int tuntap_read(int fd, struct sk_buff **skb,
......@@ -66,34 +56,33 @@ static int tuntap_write(int fd, struct sk_buff **skb,
struct net_kern_info tuntap_kern_info = {
init: tuntap_init,
protocol: tuntap_protocol,
protocol: eth_protocol,
read: tuntap_read,
write: tuntap_write,
};
static int tuntap_count = 0;
int tuntap_setup(char *str, struct uml_net *dev)
int tuntap_setup(char *str, char **mac_out, void *data)
{
struct tuntap_setup *pri;
int err;
pri = &tuntap_priv[tuntap_count];
err = tap_setup_common(str, "tuntap", &pri->dev_name, dev->mac,
&dev->have_mac, &pri->gate_addr);
if(err) return(err);
struct tuntap_init *init = data;
dev->user = &tuntap_user_info;
dev->kern = &tuntap_kern_info;
dev->private_size = sizeof(struct tuntap_data);
dev->transport_index = tuntap_count++;
*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
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)
......
......@@ -233,11 +233,25 @@ static inline void set_pte(pte_t *pteptr, pte_t pteval)
* The following only work if pte_present() is true.
* Undefined behaviour if not..
*/
static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
static inline int pte_read(pte_t pte)
{
return((pte_val(pte) & _PAGE_USER) &&
!(pte_val(pte) & _PAGE_PROTNONE));
}
static inline int pte_exec(pte_t pte){
return((pte_val(pte) & _PAGE_USER) &&
!(pte_val(pte) & _PAGE_PROTNONE));
}
static inline int pte_write(pte_t pte)
{
return((pte_val(pte) & _PAGE_RW) &&
!(pte_val(pte) & _PAGE_PROTNONE));
}
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
static inline int pte_newpage(pte_t pte) { return pte_val(pte) & _PAGE_NEWPAGE; }
static inline int pte_newprot(pte_t pte)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment