Commit 7e04f253 authored by Jeff Dike's avatar Jeff Dike

A bunch of network updates from 2.4.19.

Added the pcap transport, which makes a pcap packet stream look
like a network interface inside UML.
Lifted the limit on the number of network interfaces.
Cleaned up and simplified the transport interface.
parent 7570df54
...@@ -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
......
...@@ -8,6 +8,7 @@ CHAN_OBJS := chan_kern.o chan_user.o line.o ...@@ -8,6 +8,7 @@ CHAN_OBJS := chan_kern.o chan_user.o line.o
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
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 +23,7 @@ obj-$(CONFIG_SSL) += ssl.o ...@@ -22,6 +23,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
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 +37,8 @@ obj-$(CONFIG_TTY_CHAN) += tty.o ...@@ -35,6 +37,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; *init = ((struct daemon_init)
dev->kern = &daemon_kern_info; { sock_type : "unix",
dev->private_size = sizeof(struct daemon_data); ctl_sock : "/tmp/uml.ctl" });
dev->transport_index = daemon_count++;
if(*str != ',') return(0); remain = split_if_spec(str, mac_out, &init->sock_type, &init->ctl_sock,
str++; NULL);
if(*str != ','){ if(remain != NULL)
err = setup_etheraddr(str, dev->mac); printk(KERN_WARNING "daemon_setup : Ignoring data socket "
if(!err) dev->have_mac = 1; "specification\n");
}
str = strchr(str, ','); return(1);
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 "
"specification\n");
return(0);
} }
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: init->port = htons(n);
/* Second argument: Multicast group */ }
mcast_priv[n].addr = p1;
break; if(ttl_str != NULL){
case 2: init->ttl = simple_strtoul(ttl_str, &last, 10);
/* Third argument: Port number */ if(*last != '\0'){
mcast_priv[n].port = printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n",
htons(simple_strtoul(p1, NULL, 10)); ttl_str);
break; return(0);
case 3:
/* Fourth argument: TTL */
mcast_priv[n].ttl =
simple_strtoul(p1, NULL, 10);
break;
}
} }
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
This diff is collapsed.
...@@ -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.
......
...@@ -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;
dev->user = &slip_user_info; *init = ((struct slip_init)
dev->kern = &slip_kern_info; { gate_addr : NULL });
dev->private_size = sizeof(struct slip_data);
dev->transport_index = slip_count++; if(str[0] != '\0')
if(*str != ',') return(0); init->gate_addr = str;
str++; return(1);
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
...@@ -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) 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]; *init = ((struct tuntap_init)
err = tap_setup_common(str, "tuntap", &pri->dev_name, dev->mac, { dev_name : NULL,
&dev->have_mac, &pri->gate_addr); gate_addr : NULL });
if(err) return(err); if(tap_setup_common(str, "tuntap", &init->dev_name, mac_out,
&init->gate_addr))
return(0);
dev->user = &tuntap_user_info; return(1);
dev->kern = &tuntap_kern_info;
dev->private_size = sizeof(struct tuntap_data);
dev->transport_index = tuntap_count++;
return(0);
} }
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)
......
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