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 ...@@ -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 ' SLIP transport' CONFIG_UML_NET_SLIP $CONFIG_UML_NET
dep_bool ' Daemon transport' CONFIG_UML_NET_DAEMON $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 ' 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 # Below are hardware-independent drivers mirrored from
# drivers/net/Config.in. It would be nice if Linux # drivers/net/Config.in. It would be nice if Linux
......
...@@ -86,6 +86,7 @@ CONFIG_UML_NET_TUNTAP=y ...@@ -86,6 +86,7 @@ CONFIG_UML_NET_TUNTAP=y
CONFIG_UML_NET_SLIP=y CONFIG_UML_NET_SLIP=y
CONFIG_UML_NET_DAEMON=y CONFIG_UML_NET_DAEMON=y
CONFIG_UML_NET_MCAST=y CONFIG_UML_NET_MCAST=y
# CONFIG_UML_NET_PCAP is not set
CONFIG_DUMMY=y CONFIG_DUMMY=y
# CONFIG_BONDING is not set # CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set # CONFIG_EQUALIZER is not set
......
...@@ -5,9 +5,23 @@ ...@@ -5,9 +5,23 @@
CHAN_OBJS := chan_kern.o chan_user.o line.o 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 slip-objs := slip_kern.o slip_user.o
daemon-objs := daemon_kern.o daemon_user.o daemon-objs := daemon_kern.o daemon_user.o
mcast-objs := mcast_kern.o mcast_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 net-objs := net_kern.o net_user.o
mconsole-objs := mconsole_kern.o mconsole_user.o mconsole-objs := mconsole_kern.o mconsole_user.o
hostaudio-objs := hostaudio_kern.o hostaudio_user.o hostaudio-objs := hostaudio_kern.o hostaudio_user.o
...@@ -22,6 +36,7 @@ obj-$(CONFIG_SSL) += ssl.o ...@@ -22,6 +36,7 @@ obj-$(CONFIG_SSL) += ssl.o
obj-$(CONFIG_UML_NET_SLIP) += slip.o obj-$(CONFIG_UML_NET_SLIP) += slip.o
obj-$(CONFIG_UML_NET_DAEMON) += daemon.o obj-$(CONFIG_UML_NET_DAEMON) += daemon.o
obj-$(CONFIG_UML_NET_MCAST) += mcast.o obj-$(CONFIG_UML_NET_MCAST) += mcast.o
obj-$(CONFIG_UML_NET_PCAP) += pcap.o $(PCAP)
obj-$(CONFIG_UML_NET) += net.o obj-$(CONFIG_UML_NET) += net.o
obj-$(CONFIG_MCONSOLE) += mconsole.o obj-$(CONFIG_MCONSOLE) += mconsole.o
obj-$(CONFIG_MMAPPER) += mmapper_kern.o obj-$(CONFIG_MMAPPER) += mmapper_kern.o
...@@ -35,6 +50,8 @@ obj-$(CONFIG_TTY_CHAN) += tty.o ...@@ -35,6 +50,8 @@ obj-$(CONFIG_TTY_CHAN) += tty.o
obj-$(CONFIG_XTERM_CHAN) += xterm.o obj-$(CONFIG_XTERM_CHAN) += xterm.o
obj-$(CONFIG_UML_WATCHDOG) += harddog.o obj-$(CONFIG_UML_WATCHDOG) += harddog.o
CFLAGS_pcap_user.o = -I/usr/include/pcap
obj-y += stdio_console.o $(CHAN_OBJS) obj-y += stdio_console.o $(CHAN_OBJS)
USER_SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y) $(obj-m)),$($(f)-objs)) USER_SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y) $(obj-m)),$($(f)-objs))
......
...@@ -12,41 +12,36 @@ ...@@ -12,41 +12,36 @@
#include "net_kern.h" #include "net_kern.h"
#include "net_user.h" #include "net_user.h"
#include "daemon.h" #include "daemon.h"
#include "daemon_kern.h"
struct daemon_data daemon_priv[MAX_UML_NETDEV] = { struct daemon_init {
[ 0 ... MAX_UML_NETDEV - 1 ] = char *sock_type;
{ char *ctl_sock;
sock_type : "unix",
ctl_sock : "/tmp/uml.ctl",
ctl_addr : NULL,
data_addr : NULL,
local_addr : NULL,
fd : -1,
control : -1,
dev : NULL,
}
}; };
void daemon_init(struct net_device *dev, int index) void daemon_init(struct net_device *dev, void *data)
{ {
struct uml_net_private *pri; struct uml_net_private *pri;
struct daemon_data *dpri; struct daemon_data *dpri;
struct daemon_init *init = data;
init_etherdev(dev, 0); init_etherdev(dev, 0);
pri = dev->priv; pri = dev->priv;
dpri = (struct daemon_data *) pri->user; 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", printk("daemon backend (uml_switch version %d) - %s:%s",
SWITCH_VERSION, dpri->sock_type, dpri->ctl_sock); SWITCH_VERSION, dpri->sock_type, dpri->ctl_sock);
printk("\n"); 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, static int daemon_read(int fd, struct sk_buff **skb,
struct uml_net_private *lp) struct uml_net_private *lp)
{ {
...@@ -65,47 +60,37 @@ static int daemon_write(int fd, struct sk_buff **skb, ...@@ -65,47 +60,37 @@ static int daemon_write(int fd, struct sk_buff **skb,
static struct net_kern_info daemon_kern_info = { static struct net_kern_info daemon_kern_info = {
init: daemon_init, init: daemon_init,
protocol: daemon_protocol, protocol: eth_protocol,
read: daemon_read, read: daemon_read,
write: daemon_write, write: daemon_write,
}; };
static int daemon_count = 0; int daemon_setup(char *str, char **mac_out, void *data)
int daemon_setup(char *str, struct uml_net *dev)
{ {
int err, n = daemon_count; struct daemon_init *init = data;
char *remain;
dev->user = &daemon_user_info;
dev->kern = &daemon_kern_info; *init = ((struct daemon_init)
dev->private_size = sizeof(struct daemon_data); { sock_type : "unix",
dev->transport_index = daemon_count++; ctl_sock : "/tmp/uml.ctl" });
if(*str != ',') return(0);
str++; remain = split_if_spec(str, mac_out, &init->sock_type, &init->ctl_sock,
if(*str != ','){ NULL);
err = setup_etheraddr(str, dev->mac); if(remain != NULL)
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';
printk(KERN_WARNING "daemon_setup : Ignoring data socket " printk(KERN_WARNING "daemon_setup : Ignoring data socket "
"specification\n"); "specification\n");
return(0);
return(1);
} }
static struct transport daemon_transport = { static struct transport daemon_transport = {
list : LIST_HEAD_INIT(daemon_transport.list), list : LIST_HEAD_INIT(daemon_transport.list),
name : "daemon", 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) static int register_daemon(void)
...@@ -115,6 +100,7 @@ static int register_daemon(void) ...@@ -115,6 +100,7 @@ static int register_daemon(void)
} }
__initcall(register_daemon); __initcall(register_daemon);
/* /*
* Overrides for Emacs so that we follow Linus's tabbing style. * Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically * 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 { ...@@ -10,8 +10,6 @@ struct mcast_data {
unsigned short port; unsigned short port;
void *mcast_addr; void *mcast_addr;
int ttl; int ttl;
unsigned char hwaddr[ETH_ADDR_LEN];
int hw_setup;
void *dev; void *dev;
}; };
......
...@@ -19,26 +19,28 @@ ...@@ -19,26 +19,28 @@
#include "net_kern.h" #include "net_kern.h"
#include "net_user.h" #include "net_user.h"
#include "mcast.h" #include "mcast.h"
#include "mcast_kern.h"
struct mcast_init {
struct mcast_data mcast_priv[MAX_UML_NETDEV] = { char *addr;
[ 0 ... MAX_UML_NETDEV - 1 ] = int port;
{ int ttl;
addr: "239.192.168.1",
port: 1102,
ttl: 1,
}
}; };
void mcast_init(struct net_device *dev, int index) void mcast_init(struct net_device *dev, void *data)
{ {
struct uml_net_private *pri; struct uml_net_private *pri;
struct mcast_data *dpri; struct mcast_data *dpri;
struct mcast_init *init = data;
init_etherdev(dev, 0); init_etherdev(dev, 0);
pri = dev->priv; pri = dev->priv;
dpri = (struct mcast_data *) pri->user; 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("mcast backend ");
printk("multicast adddress: %s:%u, TTL:%u ", printk("multicast adddress: %s:%u, TTL:%u ",
dpri->addr, dpri->port, dpri->ttl); dpri->addr, dpri->port, dpri->ttl);
...@@ -46,11 +48,6 @@ void mcast_init(struct net_device *dev, int index) ...@@ -46,11 +48,6 @@ void mcast_init(struct net_device *dev, int index)
printk("\n"); 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) static int mcast_read(int fd, struct sk_buff **skb, struct uml_net_private *lp)
{ {
*skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER);
...@@ -68,71 +65,64 @@ static int mcast_write(int fd, struct sk_buff **skb, ...@@ -68,71 +65,64 @@ static int mcast_write(int fd, struct sk_buff **skb,
static struct net_kern_info mcast_kern_info = { static struct net_kern_info mcast_kern_info = {
init: mcast_init, init: mcast_init,
protocol: mcast_protocol, protocol: eth_protocol,
read: mcast_read, read: mcast_read,
write: mcast_write, write: mcast_write,
}; };
static int mcast_count = 0; int mcast_setup(char *str, char **mac_out, void *data)
int mcast_setup(char *str, struct uml_net *dev)
{ {
int err, n = mcast_count; struct mcast_init *init = data;
int num = 0; char *port_str = NULL, *ttl_str = NULL, *remain;
char *p1, *p2; char *last;
int n;
dev->user = &mcast_user_info;
dev->kern = &mcast_kern_info; *init = ((struct mcast_init)
dev->private_size = sizeof(struct mcast_data); { addr : "239.192.168.1",
dev->transport_index = mcast_count++; port : 1102,
ttl : 1 });
/* somewhat more sophisticated parser, needed for in_aton */
remain = split_if_spec(str, mac_out, &init->addr, &port_str, &ttl_str,
p1 = str; NULL);
if (*str == ',') if(remain != NULL){
p1++; printk(KERN_ERR "mcast_setup - Extra garbage on "
while (p1 && *p1) { "specification : '%s'\n", remain);
if ((p2 = strchr(p1, ','))) return(0);
*p2++ = '\0'; }
if (strlen(p1) > 0) {
switch (num) { if(port_str != NULL){
case 0: n = simple_strtoul(port_str, &last, 10);
/* First argument: Ethernet address */ if(*last != '\0'){
err = setup_etheraddr(p1, dev->mac); printk(KERN_ERR "mcast_setup - Bad port : '%s'\n",
if (!err) port_str);
dev->have_mac = 1; return(0);
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;
} }
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", printk(KERN_INFO "Configured mcast device: %s:%u-%u\n", init->addr,
mcast_priv[n].addr, mcast_priv[n].port, init->port, init->ttl);
mcast_priv[n].ttl);
return(0); return(1);
} }
static struct transport mcast_transport = { static struct transport mcast_transport = {
list : LIST_HEAD_INIT(mcast_transport.list), list : LIST_HEAD_INIT(mcast_transport.list),
name : "mcast", 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) static int register_mcast(void)
...@@ -142,6 +132,7 @@ static int register_mcast(void) ...@@ -142,6 +132,7 @@ static int register_mcast(void)
} }
__initcall(register_mcast); __initcall(register_mcast);
/* /*
* Overrides for Emacs so that we follow Linus's tabbing style. * Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically * 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
...@@ -29,16 +29,6 @@ ...@@ -29,16 +29,6 @@
LIST_HEAD(opened); LIST_HEAD(opened);
struct uml_net devices[MAX_UML_NETDEV] = {
[ 0 ... MAX_UML_NETDEV - 1 ] =
{
dev: NULL,
user: NULL,
kern: NULL,
private_size: 0,
}
};
static int uml_net_rx(struct net_device *dev) static int uml_net_rx(struct net_device *dev)
{ {
struct uml_net_private *lp = dev->priv; struct uml_net_private *lp = dev->priv;
...@@ -255,22 +245,38 @@ void uml_net_user_timer_expire(unsigned long _conn) ...@@ -255,22 +245,38 @@ void uml_net_user_timer_expire(unsigned long _conn)
#endif #endif
} }
static int eth_configure(struct uml_net *device, int n) static struct list_head devices = LIST_HEAD_INIT(devices);
static int eth_configure(int n, void *init, char *mac,
struct transport *transport)
{ {
struct uml_net *device;
struct net_device *dev; struct net_device *dev;
struct uml_net_private *lp; struct uml_net_private *lp;
int save, err; int save, err, size;
device = kmalloc(sizeof(*device), GFP_KERNEL);
if(device == NULL){
printk(KERN_ERR "eth_configure failed to allocate uml_net\n");
return(1);
}
list_add(&device->list, &devices);
device->index = n;
device->private_size += sizeof(struct uml_net_private) + size = transport->private_size + sizeof(struct uml_net_private) +
sizeof(((struct uml_net_private *) 0)->user); sizeof(((struct uml_net_private *) 0)->user);
if(setup_etheraddr(mac, device->mac))
device->have_mac = 1;
printk(KERN_INFO "Netdevice %d ", n); printk(KERN_INFO "Netdevice %d ", n);
if(device->have_mac) printk("(%02x:%02x:%02x:%02x:%02x:%02x) ", if(device->have_mac) printk("(%02x:%02x:%02x:%02x:%02x:%02x) ",
device->mac[0], device->mac[1], device->mac[0], device->mac[1],
device->mac[2], device->mac[3], device->mac[2], device->mac[3],
device->mac[4], device->mac[5]); device->mac[4], device->mac[5]);
printk(": "); printk(": ");
dev = kmalloc(sizeof(*dev) + device->private_size, GFP_KERNEL); dev = kmalloc(sizeof(*dev) + size, GFP_KERNEL);
if(dev == NULL){ if(dev == NULL){
printk(KERN_ERR "eth_configure: failed to allocate device\n"); printk(KERN_ERR "eth_configure: failed to allocate device\n");
return(1); return(1);
...@@ -279,14 +285,9 @@ static int eth_configure(struct uml_net *device, int n) ...@@ -279,14 +285,9 @@ static int eth_configure(struct uml_net *device, int n)
dev->priv = (void *) &dev[1]; dev->priv = (void *) &dev[1];
device->dev = dev; device->dev = dev;
(*device->kern->init)(dev, device->transport_index); (*transport->kern->init)(dev, init);
rtnl_lock();
err = register_netdevice(dev);
rtnl_unlock();
if(err)
return(1);
dev->mtu = device->user->max_packet; dev->mtu = transport->user->max_packet;
dev->open = uml_net_open; dev->open = uml_net_open;
dev->hard_start_xmit = uml_net_start_xmit; dev->hard_start_xmit = uml_net_start_xmit;
dev->stop = uml_net_close; dev->stop = uml_net_close;
...@@ -298,7 +299,36 @@ static int eth_configure(struct uml_net *device, int n) ...@@ -298,7 +299,36 @@ static int eth_configure(struct uml_net *device, int n)
dev->do_ioctl = uml_net_ioctl; dev->do_ioctl = uml_net_ioctl;
dev->watchdog_timeo = (HZ >> 1); dev->watchdog_timeo = (HZ >> 1);
dev->irq = UM_ETH_IRQ; dev->irq = UM_ETH_IRQ;
dev->init = NULL;
dev->master = NULL;
dev->neigh_setup = NULL;
dev->owner = NULL;
dev->state = 0;
dev->next_sched = 0;
dev->get_wireless_stats = 0;
dev->wireless_handlers = 0;
dev->gflags = 0;
dev->mc_list = NULL;
dev->mc_count = 0;
dev->promiscuity = 0;
dev->atalk_ptr = NULL;
dev->ip_ptr = NULL;
dev->dn_ptr = NULL;
dev->ip6_ptr = NULL;
dev->ec_ptr = NULL;
atomic_set(&dev->refcnt, 0);
dev->features = 0;
dev->uninit = NULL;
dev->destructor = NULL;
dev->set_config = NULL;
dev->accept_fastpath = 0;
dev->br_port = 0;
rtnl_lock();
err = register_netdevice(dev);
rtnl_unlock();
if(err)
return(1);
lp = dev->priv; lp = dev->priv;
/* lp.user is the first four bytes of the transport data, which /* lp.user is the first four bytes of the transport data, which
...@@ -314,28 +344,41 @@ static int eth_configure(struct uml_net *device, int n) ...@@ -314,28 +344,41 @@ static int eth_configure(struct uml_net *device, int n)
fd : -1, fd : -1,
mac : { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0}, mac : { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0},
have_mac : device->have_mac, have_mac : device->have_mac,
protocol : device->kern->protocol, protocol : transport->kern->protocol,
open : device->user->open, open : transport->user->open,
close : device->user->close, close : transport->user->close,
remove : device->user->remove, remove : transport->user->remove,
read : device->kern->read, read : transport->kern->read,
write : device->kern->write, write : transport->kern->write,
add_address : device->user->add_address, add_address : transport->user->add_address,
delete_address : device->user->delete_address, delete_address : transport->user->delete_address,
set_mtu : device->user->set_mtu, set_mtu : transport->user->set_mtu,
user : { save } }); user : { save } });
init_timer(&lp->tl); init_timer(&lp->tl);
lp->tl.function = uml_net_user_timer_expire; lp->tl.function = uml_net_user_timer_expire;
memset(&lp->stats, 0, sizeof(lp->stats)); memset(&lp->stats, 0, sizeof(lp->stats));
if(lp->have_mac) memcpy(lp->mac, device->mac, sizeof(lp->mac)); if(lp->have_mac) memcpy(lp->mac, device->mac, sizeof(lp->mac));
if(device->user->init) if(transport->user->init)
(*device->user->init)(&lp->user, dev); (*transport->user->init)(&lp->user, dev);
if(device->have_mac) if(device->have_mac)
set_ether_mac(dev, device->mac); set_ether_mac(dev, device->mac);
return(0); return(0);
} }
static struct uml_net *find_device(int n)
{
struct uml_net *device;
struct list_head *ele;
list_for_each(ele, &devices){
device = list_entry(ele, struct uml_net, list);
if(device->index == n)
return(device);
}
return(NULL);
}
static int eth_parse(char *str, int *index_out, char **str_out) static int eth_parse(char *str, int *index_out, char **str_out)
{ {
char *end; char *end;
...@@ -346,8 +389,8 @@ static int eth_parse(char *str, int *index_out, char **str_out) ...@@ -346,8 +389,8 @@ static int eth_parse(char *str, int *index_out, char **str_out)
printk(KERN_ERR "eth_setup: Failed to parse '%s'\n", str); printk(KERN_ERR "eth_setup: Failed to parse '%s'\n", str);
return(1); return(1);
} }
if((n < 0) || (n > sizeof(devices)/sizeof(devices[0]))){ if(n < 0){
printk(KERN_ERR "eth_setup: device %d out of range\n", n); printk(KERN_ERR "eth_setup: device %d is negative\n", n);
return(1); return(1);
} }
str = end; str = end;
...@@ -357,7 +400,7 @@ static int eth_parse(char *str, int *index_out, char **str_out) ...@@ -357,7 +400,7 @@ static int eth_parse(char *str, int *index_out, char **str_out)
return(1); return(1);
} }
str++; str++;
if(devices[n].dev != NULL){ if(find_device(n)){
printk(KERN_ERR "eth_setup: Device %d already configured\n", printk(KERN_ERR "eth_setup: Device %d already configured\n",
n); n);
return(1); return(1);
...@@ -377,24 +420,54 @@ struct list_head transports = LIST_HEAD_INIT(transports); ...@@ -377,24 +420,54 @@ struct list_head transports = LIST_HEAD_INIT(transports);
struct list_head eth_cmd_line = LIST_HEAD_INIT(eth_cmd_line); struct list_head eth_cmd_line = LIST_HEAD_INIT(eth_cmd_line);
static int check_transport(struct transport *transport, char *eth, int n,
void **init_out, char **mac_out)
{
int len;
len = strlen(transport->name);
if(strncmp(eth, transport->name, len))
return(0);
eth += len;
if(*eth == ',')
eth++;
else if(*eth != '\0')
return(0);
*init_out = kmalloc(transport->setup_size, GFP_KERNEL);
if(*init_out == NULL)
return(1);
if(!transport->setup(eth, mac_out, *init_out)){
kfree(*init_out);
*init_out = NULL;
}
return(1);
}
void register_transport(struct transport *new) void register_transport(struct transport *new)
{ {
struct list_head *ele, *next; struct list_head *ele, *next;
struct eth_init *eth; struct eth_init *eth;
char *str; void *init;
int err; char *mac = NULL;
int match;
list_add(&new->list, &transports); list_add(&new->list, &transports);
list_for_each_safe(ele, next, &eth_cmd_line){ list_for_each_safe(ele, next, &eth_cmd_line){
eth = list_entry(ele, struct eth_init, list); eth = list_entry(ele, struct eth_init, list);
if(!strncmp(eth->init, new->name, strlen(new->name))){ match = check_transport(new, eth->init, eth->index, &init,
str = eth->init + strlen(new->name); &mac);
err = new->setup(str, &devices[eth->index]); if(!match)
if(!err) eth_configure(&devices[eth->index], continue;
eth->index); else if(init != NULL){
list_del(&eth->list); eth_configure(eth->index, init, mac, new);
kfree(init);
} }
list_del(&eth->list);
return;
} }
} }
...@@ -402,16 +475,20 @@ static int eth_setup_common(char *str, int index) ...@@ -402,16 +475,20 @@ static int eth_setup_common(char *str, int index)
{ {
struct list_head *ele; struct list_head *ele;
struct transport *transport; struct transport *transport;
void *init;
char *mac = NULL;
list_for_each(ele, &transports){ list_for_each(ele, &transports){
transport = list_entry(ele, struct transport, list); transport = list_entry(ele, struct transport, list);
if(!strncmp(str, transport->name, strlen(transport->name))){ if(!check_transport(transport, str, index, &init, &mac))
str += strlen(transport->name); continue;
return(transport->setup(str, &devices[index])); if(init != NULL){
eth_configure(index, init, mac, transport);
kfree(init);
} }
return(1);
} }
return(0);
return(-1);
} }
static int eth_setup(char *str) static int eth_setup(char *str)
...@@ -446,13 +523,12 @@ static int eth_init(void) ...@@ -446,13 +523,12 @@ static int eth_init(void)
{ {
struct list_head *ele, *next; struct list_head *ele, *next;
struct eth_init *eth; struct eth_init *eth;
int err;
list_for_each_safe(ele, next, &eth_cmd_line){ list_for_each_safe(ele, next, &eth_cmd_line){
eth = list_entry(ele, struct eth_init, list); eth = list_entry(ele, struct eth_init, list);
err = eth_setup_common(eth->init, eth->index);
if(!err) eth_configure(&devices[eth->index], eth->index); if(eth_setup_common(eth->init, eth->index))
if(err >= 0) list_del(&eth->list); list_del(&eth->list);
} }
return(1); return(1);
...@@ -462,7 +538,7 @@ __initcall(eth_init); ...@@ -462,7 +538,7 @@ __initcall(eth_init);
static int net_config(char *str) static int net_config(char *str)
{ {
int err, n; int n, err;
err = eth_parse(str, &n, &str); err = eth_parse(str, &n, &str);
if(err) return(err); if(err) return(err);
...@@ -470,32 +546,38 @@ static int net_config(char *str) ...@@ -470,32 +546,38 @@ static int net_config(char *str)
str = uml_strdup(str); str = uml_strdup(str);
if(str == NULL){ if(str == NULL){
printk(KERN_ERR "net_config failed to strdup string\n"); printk(KERN_ERR "net_config failed to strdup string\n");
return(1); return(-1);
} }
err = eth_setup_common(str, n); err = !eth_setup_common(str, n);
if(err){ if(err)
kfree(str); kfree(str);
return(err); return(err);
}
err = eth_configure(&devices[n], n);
return(err);
} }
static int net_remove(char *str) static int net_remove(char *str)
{ {
struct uml_net *device;
struct net_device *dev; struct net_device *dev;
struct uml_net_private *lp; struct uml_net_private *lp;
char *end;
int n; int n;
if(!isdigit(*str)) return(-1); n = simple_strtoul(str, &end, 0);
n = *str - '0'; if(*end != '\0')
if(devices[n].dev == NULL) return(0); return(-1);
dev = devices[n].dev;
device = find_device(n);
if(device == NULL)
return(0);
dev = device->dev;
lp = dev->priv; lp = dev->priv;
if(lp->fd > 0) return(-1); if(lp->fd > 0) return(-1);
if(lp->remove != NULL) (*lp->remove)(&lp->user); if(lp->remove != NULL) (*lp->remove)(&lp->user);
unregister_netdev(dev); unregister_netdev(dev);
devices[n].dev = NULL;
list_del(&device->list);
kfree(device);
return(0); return(0);
} }
...@@ -596,6 +678,8 @@ int setup_etheraddr(char *str, unsigned char *addr) ...@@ -596,6 +678,8 @@ int setup_etheraddr(char *str, unsigned char *addr)
char *end; char *end;
int i; int i;
if(str == NULL)
return(0);
for(i=0;i<6;i++){ for(i=0;i<6;i++){
addr[i] = simple_strtoul(str, &end, 16); addr[i] = simple_strtoul(str, &end, 16);
if((end == str) || if((end == str) ||
...@@ -603,7 +687,7 @@ int setup_etheraddr(char *str, unsigned char *addr) ...@@ -603,7 +687,7 @@ int setup_etheraddr(char *str, unsigned char *addr)
printk(KERN_ERR printk(KERN_ERR
"setup_etheraddr: failed to parse '%s' " "setup_etheraddr: failed to parse '%s' "
"as an ethernet address\n", str); "as an ethernet address\n", str);
return(-1); return(0);
} }
str = end + 1; str = end + 1;
} }
...@@ -611,9 +695,9 @@ int setup_etheraddr(char *str, unsigned char *addr) ...@@ -611,9 +695,9 @@ int setup_etheraddr(char *str, unsigned char *addr)
printk(KERN_ERR printk(KERN_ERR
"Attempt to assign a broadcast ethernet address to a " "Attempt to assign a broadcast ethernet address to a "
"device disallowed\n"); "device disallowed\n");
return(-1);
}
return(0); return(0);
}
return(1);
} }
void dev_ip_addr(void *d, char *buf, char *bin_buf) void dev_ip_addr(void *d, char *buf, char *bin_buf)
...@@ -684,6 +768,24 @@ void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *, ...@@ -684,6 +768,24 @@ void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *,
} }
} }
int dev_netmask(void *d, void *m)
{
struct net_device *dev = d;
struct in_device *ip = dev->ip_ptr;
struct in_ifaddr *in;
__u32 *mask_out = m;
if(ip == NULL)
return(1);
in = ip->ifa_list;
if(in == NULL)
return(1);
*mask_out = in->ifa_mask;
return(0);
}
void *get_output_buffer(int *len_out) void *get_output_buffer(int *len_out)
{ {
void *ret; void *ret;
...@@ -699,32 +801,26 @@ void free_output_buffer(void *buffer) ...@@ -699,32 +801,26 @@ void free_output_buffer(void *buffer)
free_pages((unsigned long) buffer, 0); free_pages((unsigned long) buffer, 0);
} }
int tap_setup_common(char *str, char *type, char **dev_name, char *mac, int tap_setup_common(char *str, char *type, char **dev_name, char **mac_out,
int *have_mac, char **gate_addr) char **gate_addr)
{ {
int err; char *remain;
if(*str != ','){ remain = split_if_spec(str, dev_name, mac_out, gate_addr, NULL);
printk(KERN_ERR if(remain != NULL){
"ethertap_setup: expected ',' after '%s'\n", type); printk("tap_setup_common - Extra garbage on specification : "
"'%s'\n", remain);
return(1); return(1);
} }
str++;
if(*str != ',') *dev_name = str;
str = strchr(str, ',');
if(str == NULL) return(0);
*str++ = '\0';
if(*str != ','){
err = setup_etheraddr(str, mac);
if(!err) *have_mac = 1;
}
str = strchr(str, ',');
if(str == NULL) return(0);
*str++ = '\0';
if(*str != '\0') *gate_addr = str;
return(0); return(0);
} }
unsigned short eth_protocol(struct sk_buff *skb)
{
return(eth_type_trans(skb, skb->dev));
}
/* /*
* Overrides for Emacs so that we follow Linus's tabbing style. * Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically * Emacs will notice this stuff at the end of the file and automatically
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
*/ */
#include <stddef.h> #include <stddef.h>
#include <stdarg.h>
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
...@@ -220,6 +221,27 @@ void close_addr(unsigned char *addr, unsigned char *netmask, void *arg) ...@@ -220,6 +221,27 @@ void close_addr(unsigned char *addr, unsigned char *netmask, void *arg)
change(arg, "del", addr, netmask); 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. * Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically * 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 * Licensed under the GPL
*/ */
#ifndef __UM_TUNTAP_KERN_H #include "net_user.h"
#define __UM_TUNTAP_KERN_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. * 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) ...@@ -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); fd = os_rcv_fd(conn->socket[0], &conn->helper_pid);
if(fd < 0){ if(fd < 0){
printk("os_accept_connection returned %d\n", -fd); printk("os_rcv_fd returned %d\n", -fd);
os_close_file(conn->fd); os_close_file(conn->fd);
} }
conn->fd = fd; conn->fd = fd;
......
...@@ -7,28 +7,29 @@ ...@@ -7,28 +7,29 @@
#include "net_user.h" #include "net_user.h"
#include "kern.h" #include "kern.h"
#include "slip.h" #include "slip.h"
#include "slip_kern.h"
struct slip_data slip_priv[MAX_UML_NETDEV] = { struct slip_init {
[ 0 ... MAX_UML_NETDEV - 1 ] = char *gate_addr;
{
addr: NULL,
gate_addr: NULL,
slave: -1,
buf: { 0 },
pos: 0,
esc: 0,
}
}; };
void slip_init(struct net_device *dev, int index) void slip_init(struct net_device *dev, void *data)
{ {
struct uml_net_private *private; struct uml_net_private *private;
struct slip_data *spri; struct slip_data *spri;
struct slip_init *init = data;
private = dev->priv; private = dev->priv;
spri = (struct slip_data *) private->user; 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); strncpy(dev->name, "umn", IFNAMSIZ);
dev->init = NULL; dev->init = NULL;
dev->hard_header_len = 0; dev->hard_header_len = 0;
...@@ -67,26 +68,26 @@ struct net_kern_info slip_kern_info = { ...@@ -67,26 +68,26 @@ struct net_kern_info slip_kern_info = {
write: slip_write, write: slip_write,
}; };
static int slip_count = 0; static int slip_setup(char *str, char **mac_out, void *data)
int slip_setup(char *str, struct uml_net *dev)
{ {
int n = slip_count; struct slip_init *init = data;
*init = ((struct slip_init)
{ gate_addr : NULL });
dev->user = &slip_user_info; if(str[0] != '\0')
dev->kern = &slip_kern_info; init->gate_addr = str;
dev->private_size = sizeof(struct slip_data); return(1);
dev->transport_index = slip_count++;
if(*str != ',') return(0);
str++;
if(str[0] != '\0') slip_priv[n].gate_addr = str;
return(0);
} }
static struct transport slip_transport = { static struct transport slip_transport = {
list : LIST_HEAD_INIT(slip_transport.list), list : LIST_HEAD_INIT(slip_transport.list),
name : "slip", 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) 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); ...@@ -25,6 +25,7 @@ extern void *sbrk(int increment);
extern void *malloc(int size); extern void *malloc(int size);
extern void perror(char *err); extern void perror(char *err);
extern int kill(int pid, int sig); extern int kill(int pid, int sig);
extern int getpid(void);
extern int getuid(void); extern int getuid(void);
extern int pause(void); extern int pause(void);
extern int write(int, const void *, int); extern int write(int, const void *, int);
......
...@@ -6,14 +6,10 @@ ...@@ -6,14 +6,10 @@
#include "linux/socket.h" #include "linux/socket.h"
#include "linux/list.h" #include "linux/list.h"
#define MAX_UML_NETDEV (16)
struct uml_net { struct uml_net {
struct list_head list;
struct net_device *dev; struct net_device *dev;
struct net_user_info *user; int index;
struct net_kern_info *kern;
int private_size;
int transport_index;
unsigned char mac[ETH_ALEN]; unsigned char mac[ETH_ALEN];
int have_mac; int have_mac;
}; };
...@@ -41,7 +37,7 @@ struct uml_net_private { ...@@ -41,7 +37,7 @@ struct uml_net_private {
}; };
struct net_kern_info { struct net_kern_info {
void (*init)(struct net_device *, int); void (*init)(struct net_device *, void *);
unsigned short (*protocol)(struct sk_buff *); unsigned short (*protocol)(struct sk_buff *);
int (*read)(int, struct sk_buff **skb, struct uml_net_private *); int (*read)(int, struct sk_buff **skb, struct uml_net_private *);
int (*write)(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 { ...@@ -50,7 +46,11 @@ struct net_kern_info {
struct transport { struct transport {
struct list_head list; struct list_head list;
char *name; 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); extern struct net_device *ether_init(int);
...@@ -58,8 +58,9 @@ extern unsigned short ether_protocol(struct sk_buff *); ...@@ -58,8 +58,9 @@ extern unsigned short ether_protocol(struct sk_buff *);
extern int setup_etheraddr(char *str, unsigned char *addr); extern int setup_etheraddr(char *str, unsigned char *addr);
extern struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra); 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, 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 void register_transport(struct transport *new);
extern unsigned short eth_protocol(struct sk_buff *skb);
#endif #endif
......
...@@ -43,6 +43,10 @@ extern int net_sendto(int fd, void *buf, int len, void *to, int sock_len); ...@@ -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 open_addr(unsigned char *addr, unsigned char *netmask, void *arg);
extern void close_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 #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); ...@@ -64,10 +64,6 @@ extern void signal_init(void);
extern int start_fork_tramp(void *arg, unsigned long temp_stack, extern int start_fork_tramp(void *arg, unsigned long temp_stack,
int clone_flags, int (*tramp)(void *)); int clone_flags, int (*tramp)(void *));
extern void trace_myself(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 clone_and_wait(int (*fn)(void *), void *arg, void *sp, int flags);
extern int input_loop(void); extern int input_loop(void);
extern void continue_execing_proc(int pid); extern void continue_execing_proc(int pid);
...@@ -81,7 +77,6 @@ extern void save_signal_state(int *sig_ptr); ...@@ -81,7 +77,6 @@ extern void save_signal_state(int *sig_ptr);
extern void *um_kmalloc(int size); extern void *um_kmalloc(int size);
extern int raw(int fd, int complain); extern int raw(int fd, int complain);
extern int switcheroo(int fd, int prot, void *from, void *to, int size); 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_machinename(char *machine_out);
extern void setup_hostinfo(void); extern void setup_hostinfo(void);
extern void add_arg(char *cmd_line, char *arg); extern void add_arg(char *cmd_line, char *arg);
...@@ -109,7 +104,6 @@ extern int user_write(int fd, char *buf, int len); ...@@ -109,7 +104,6 @@ extern int user_write(int fd, char *buf, int len);
extern void write_sigio_workaround(void); extern void write_sigio_workaround(void);
extern void arch_check_bugs(void); extern void arch_check_bugs(void);
extern int arch_handle_signal(int sig, struct uml_pt_regs *regs); 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 unsigned long pid_pc(int pid);
extern int arch_fixup(unsigned long address, void *sc_ptr); extern int arch_fixup(unsigned long address, void *sc_ptr);
extern void forward_pending_sigio(int target); extern void forward_pending_sigio(int target);
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "irq_user.h" #include "irq_user.h"
#include "syscall_user.h" #include "syscall_user.h"
#include "ptrace_user.h" #include "ptrace_user.h"
#include "time_user.h"
#include "init.h" #include "init.h"
#include "os.h" #include "os.h"
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "init.h" #include "init.h"
#include "irq_user.h" #include "irq_user.h"
#include "mem_user.h" #include "mem_user.h"
#include "time_user.h"
#include "tlb.h" #include "tlb.h"
#include "frame_kern.h" #include "frame_kern.h"
#include "sigcontext.h" #include "sigcontext.h"
......
...@@ -53,6 +53,28 @@ static void set_interval(int timer_type) ...@@ -53,6 +53,28 @@ static void set_interval(int timer_type)
panic("setitimer failed - errno = %d\n", errno); 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) void idle_timer(void)
{ {
if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR) if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR)
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "asm/current.h" #include "asm/current.h"
#include "kern_util.h" #include "kern_util.h"
#include "user_util.h" #include "user_util.h"
#include "time_user.h"
u64 jiffies_64; u64 jiffies_64;
......
...@@ -99,7 +99,7 @@ void flush_kernel_range(unsigned long start, unsigned long end, int update_seq) ...@@ -99,7 +99,7 @@ void flush_kernel_range(unsigned long start, unsigned long end, int update_seq)
int updated = 0, err; int updated = 0, err;
mm = &init_mm; mm = &init_mm;
for(addr = start_vm; addr < end_vm;){ for(addr = start; addr < end;){
pgd = pgd_offset(mm, addr); pgd = pgd_offset(mm, addr);
pmd = pmd_offset(pgd, addr); pmd = pmd_offset(pgd, addr);
if(pmd_present(*pmd)){ if(pmd_present(*pmd)){
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "frame_user.h" #include "frame_user.h"
#include "syscall_user.h" #include "syscall_user.h"
#include "ptrace_user.h" #include "ptrace_user.h"
#include "time_user.h"
#include "task.h" #include "task.h"
#include "os.h" #include "os.h"
...@@ -517,7 +518,14 @@ void alarm_handler(int sig, struct sigcontext sc) ...@@ -517,7 +518,14 @@ void alarm_handler(int sig, struct sigcontext sc)
user = user_context(SC_SP(&sc)); user = user_context(SC_SP(&sc));
if(!user && !kern_timer_on) return; if(!user && !kern_timer_on) return;
if(!user && jail_timer_off) return; if(!user && jail_timer_off) return;
if(sig == SIGALRM)
switch_timers(0);
sig_handler_common(sig, &sc); sig_handler_common(sig, &sc);
if(sig == SIGALRM)
switch_timers(1);
} }
void do_longjmp(void *p) 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 @@ ...@@ -12,42 +12,32 @@
#include "net_kern.h" #include "net_kern.h"
#include "net_user.h" #include "net_user.h"
#include "etap.h" #include "etap.h"
#include "etap_kern.h"
struct ethertap_setup { struct ethertap_init {
char *dev_name; char *dev_name;
char *gate_addr; char *gate_addr;
}; };
struct ethertap_setup ethertap_priv[MAX_UML_NETDEV] = { static void etap_init(struct net_device *dev, void *data)
[ 0 ... MAX_UML_NETDEV - 1 ] =
{
dev_name: NULL,
gate_addr: NULL,
}
};
static void etap_init(struct net_device *dev, int index)
{ {
struct uml_net_private *pri; struct uml_net_private *pri;
struct ethertap_data *epri; struct ethertap_data *epri;
struct ethertap_init *init = data;
init_etherdev(dev, 0); init_etherdev(dev, 0);
pri = dev->priv; pri = dev->priv;
epri = (struct ethertap_data *) pri->user; epri = (struct ethertap_data *) pri->user;
epri->dev_name = ethertap_priv[index].dev_name; *epri = ((struct ethertap_data)
epri->gate_addr = ethertap_priv[index].gate_addr; { 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); printk("ethertap backend - %s", epri->dev_name);
if(epri->gate_addr != NULL) if(epri->gate_addr != NULL)
printk(", IP = %s", epri->gate_addr); printk(", IP = %s", epri->gate_addr);
printk("\n"); 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) 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) ...@@ -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 = { struct net_kern_info ethertap_kern_info = {
init: etap_init, init: etap_init,
protocol: etap_protocol, protocol: eth_protocol,
read: etap_read, read: etap_read,
write: etap_write, write: etap_write,
}; };
static int ethertap_count = 0; int ethertap_setup(char *str, char **mac_out, void *data)
int ethertap_setup(char *str, struct uml_net *dev)
{ {
struct ethertap_setup *pri; struct ethertap_init *init = data;
int err;
*init = ((struct ethertap_init)
pri = &ethertap_priv[ethertap_count]; { dev_name : NULL,
err = tap_setup_common(str, "ethertap", &pri->dev_name, dev->mac, gate_addr : NULL });
&dev->have_mac, &pri->gate_addr); if(tap_setup_common(str, "ethertap", &init->dev_name, mac_out,
if(err) return(err); &init->gate_addr))
if(pri->dev_name == NULL){ return(0);
if(init->dev_name == NULL){
printk("ethertap_setup : Missing tap device name\n"); printk("ethertap_setup : Missing tap device name\n");
return(1); return(0);
} }
dev->user = &ethertap_user_info; return(1);
dev->kern = &ethertap_kern_info;
dev->private_size = sizeof(struct ethertap_data);
dev->transport_index = ethertap_count++;
return(0);
} }
static struct transport ethertap_transport = { static struct transport ethertap_transport = {
list : LIST_HEAD_INIT(ethertap_transport.list), list : LIST_HEAD_INIT(ethertap_transport.list),
name : "ethertap", 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) static int register_ethertap(void)
......
...@@ -14,8 +14,6 @@ struct tuntap_data { ...@@ -14,8 +14,6 @@ struct tuntap_data {
char *gate_addr; char *gate_addr;
int fd; int fd;
void *dev; void *dev;
unsigned char hw_addr[ETH_ADDR_LEN];
int hw_setup;
}; };
extern struct net_user_info tuntap_user_info; extern struct net_user_info tuntap_user_info;
......
...@@ -13,40 +13,30 @@ ...@@ -13,40 +13,30 @@
#include "net_user.h" #include "net_user.h"
#include "tuntap.h" #include "tuntap.h"
struct tuntap_setup { struct tuntap_init {
char *dev_name; char *dev_name;
char *gate_addr; char *gate_addr;
}; };
struct tuntap_setup tuntap_priv[MAX_UML_NETDEV] = { static void tuntap_init(struct net_device *dev, void *data)
[ 0 ... MAX_UML_NETDEV - 1 ] =
{
dev_name: NULL,
gate_addr: NULL,
}
};
static void tuntap_init(struct net_device *dev, int index)
{ {
struct uml_net_private *pri; struct uml_net_private *pri;
struct tuntap_data *tpri; struct tuntap_data *tpri;
struct tuntap_init *init = data;
init_etherdev(dev, 0); init_etherdev(dev, 0);
pri = dev->priv; pri = dev->priv;
tpri = (struct tuntap_data *) pri->user; tpri = (struct tuntap_data *) pri->user;
tpri->dev_name = tuntap_priv[index].dev_name; *tpri = ((struct tuntap_data)
tpri->fixed_config = (tpri->dev_name != NULL); { dev_name : init->dev_name,
tpri->gate_addr = tuntap_priv[index].gate_addr; fixed_config : (init->dev_name != NULL),
gate_addr : init->gate_addr,
fd : -1,
dev : dev });
printk("TUN/TAP backend - "); printk("TUN/TAP backend - ");
if(tpri->gate_addr != NULL) if(tpri->gate_addr != NULL)
printk("IP = %s", tpri->gate_addr); printk("IP = %s", tpri->gate_addr);
printk("\n"); 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, static int tuntap_read(int fd, struct sk_buff **skb,
...@@ -66,34 +56,33 @@ static int tuntap_write(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 = { struct net_kern_info tuntap_kern_info = {
init: tuntap_init, init: tuntap_init,
protocol: tuntap_protocol, protocol: eth_protocol,
read: tuntap_read, read: tuntap_read,
write: tuntap_write, write: tuntap_write,
}; };
static int tuntap_count = 0; int tuntap_setup(char *str, char **mac_out, void *data)
int tuntap_setup(char *str, struct uml_net *dev)
{ {
struct tuntap_setup *pri; struct tuntap_init *init = data;
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);
dev->user = &tuntap_user_info; *init = ((struct tuntap_init)
dev->kern = &tuntap_kern_info; { dev_name : NULL,
dev->private_size = sizeof(struct tuntap_data); gate_addr : NULL });
dev->transport_index = tuntap_count++; if(tap_setup_common(str, "tuntap", &init->dev_name, mac_out,
&init->gate_addr))
return(0); return(0);
return(1);
} }
static struct transport tuntap_transport = { static struct transport tuntap_transport = {
list : LIST_HEAD_INIT(tuntap_transport.list), list : LIST_HEAD_INIT(tuntap_transport.list),
name : "tuntap", 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) static int register_tuntap(void)
......
...@@ -233,11 +233,25 @@ static inline void set_pte(pte_t *pteptr, pte_t pteval) ...@@ -233,11 +233,25 @@ static inline void set_pte(pte_t *pteptr, pte_t pteval)
* The following only work if pte_present() is true. * The following only work if pte_present() is true.
* Undefined behaviour if not.. * Undefined behaviour if not..
*/ */
static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; } static inline int pte_read(pte_t pte)
static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; } {
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_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_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_newpage(pte_t pte) { return pte_val(pte) & _PAGE_NEWPAGE; }
static inline int pte_newprot(pte_t pte) 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