mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
bitkeeper revision 1.3 (3ddba75cRdjLs2ie8aQo_VuXG8i-Kw)
Dom0 proc interface to vfr rules. Rules stored in liked list in kernel. Vif lookup table.
This commit is contained in:
1 parent
4676bbf96d
commit
9d5293906a
9 files changed
+478
-108
No files matched your search
@@ -248,6 +248,7 @@
|
||||
3ddb79b75eo4PRXkT6Th9popt_SJhg xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/Makefile
|
||||
3ddb79b7Xyaoep6U0kLvx6Kx7OauDw xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/dom0_core.c
|
||||
3ddb79b7PulSkF9m3c7K5MkxHRf4hA xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/dom0_ops.h
|
||||
3ddba759XOjcl_OF-52dOYq7sgMykQ xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/vfr.c
|
||||
3ddb79b7s7yYBioHidSkIoHtQxYmOw xenolinux-2.4.16-sparse/arch/xeno/drivers/network/Makefile
|
||||
3ddb79b7CpLL98ScdpbKkVBktlbCtQ xenolinux-2.4.16-sparse/arch/xeno/drivers/network/network.c
|
||||
3ddb79b7hqi9krq6h98lnpONHGzvEA xenolinux-2.4.16-sparse/arch/xeno/kernel/Makefile
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
akw27@boulderdash.cl.cam.ac.uk
|
||||
smh22@boulderdash.cl.cam.ac.uk
|
||||
+103
-5
@@ -10,10 +10,19 @@
|
||||
#include <xeno/errno.h>
|
||||
#include <xeno/init.h>
|
||||
#include <xeno/slab.h>
|
||||
#include <xeno/spinlock.h>
|
||||
|
||||
/* vif globals
|
||||
* sys_vif_list is a lookup table for vifs, used in packet forwarding.
|
||||
* it should be replaced later by something a little more flexible.
|
||||
*/
|
||||
|
||||
/* vif globals */
|
||||
int sys_vif_count;
|
||||
net_vif_t *sys_vif_list[MAX_SYSTEM_VIFS];
|
||||
net_rule_ent_t *net_rule_list;
|
||||
kmem_cache_t *net_vif_cache;
|
||||
kmem_cache_t *net_rule_cache;
|
||||
static rwlock_t net_rule_lock = RW_LOCK_UNLOCKED;
|
||||
|
||||
net_ring_t *create_net_vif(int domain)
|
||||
{
|
||||
@@ -63,6 +72,84 @@ void destroy_net_vif(struct task_struct *p)
|
||||
}
|
||||
|
||||
|
||||
int add_net_rule(net_rule_t *rule)
|
||||
{
|
||||
net_rule_ent_t *new_ent;
|
||||
|
||||
if ( (new_ent = kmem_cache_alloc(net_rule_cache, GFP_KERNEL)) == NULL )
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(&new_ent->r, rule, sizeof(net_rule_t));
|
||||
|
||||
write_lock(&net_rule_lock);
|
||||
new_ent->next = net_rule_list;
|
||||
net_rule_list = new_ent;
|
||||
write_unlock(&net_rule_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int delete_net_rule(net_rule_t *rule)
|
||||
{
|
||||
net_rule_ent_t *ent = net_rule_list, *prev = NULL;
|
||||
|
||||
while ( (ent) && (!(memcmp(rule, &ent->r, sizeof(net_rule_t)))) )
|
||||
{
|
||||
prev = ent;
|
||||
ent = ent->next;
|
||||
}
|
||||
|
||||
if (ent)
|
||||
{
|
||||
write_lock(&net_rule_lock);
|
||||
if (prev)
|
||||
{
|
||||
prev->next = ent->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
net_rule_list = ent->next;
|
||||
}
|
||||
kmem_cache_free(net_rule_cache, ent);
|
||||
write_unlock(&net_rule_lock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void print_net_rule(net_rule_t *r)
|
||||
{
|
||||
printk("===] NET RULE:\n");
|
||||
printk("=] src_addr : %lu\n", (unsigned long) r->src_addr);
|
||||
printk("=] src_addr_mask : %lu\n", (unsigned long) r->src_addr_mask);
|
||||
printk("=] dst_addr : %lu\n", (unsigned long) r->dst_addr);
|
||||
printk("=] dst_addr_mask : %lu\n", (unsigned long) r->dst_addr_mask);
|
||||
printk("=] src_port : %u\n", r->src_port);
|
||||
printk("=] src_port_mask : %u\n", r->src_port_mask);
|
||||
printk("=] dst_port : %u\n", r->dst_port);
|
||||
printk("=] dst_port_mask : %u\n", r->dst_port_mask);
|
||||
printk("=] dst_proto : %u\n", r->proto);
|
||||
printk("=] src_interface : %u\n", r->src_interface);
|
||||
printk("=] dst_interface : %u\n", r->dst_interface);
|
||||
printk("=] action : %u\n", r->action);
|
||||
}
|
||||
|
||||
void print_net_rule_list()
|
||||
{
|
||||
net_rule_ent_t *ent = net_rule_list;
|
||||
int count = 0;
|
||||
|
||||
while (ent)
|
||||
{
|
||||
print_net_rule(&ent->r);
|
||||
ent = ent->next;
|
||||
count++;
|
||||
}
|
||||
printk("\nTotal of %d rules.\n", count);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the hook function to handle guest-invoked traps requesting
|
||||
* changes to the network system.
|
||||
@@ -78,22 +165,30 @@ long do_network_op(network_op_t *u_network_op)
|
||||
|
||||
if ( copy_from_user(&op, u_network_op, sizeof(op)) )
|
||||
return -EFAULT;
|
||||
|
||||
switch ( op.cmd )
|
||||
{
|
||||
|
||||
case NETWORK_OP_ADDRULE:
|
||||
{
|
||||
printk("received addrule request from guestos!\n");
|
||||
add_net_rule(&op.u.net_rule);
|
||||
}
|
||||
break;
|
||||
|
||||
case NETWORK_OP_DELETERULE:
|
||||
{
|
||||
printk("received deleterule request from guestos!\n");
|
||||
delete_net_rule(&op.u.net_rule);
|
||||
}
|
||||
break;
|
||||
|
||||
case NETWORK_OP_GETRULELIST:
|
||||
{
|
||||
// This should eventually ship a rule list up to the VM
|
||||
// to be printed in its procfs. For now, we just print the rules.
|
||||
|
||||
print_net_rule_list();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -ENOSYS;
|
||||
}
|
||||
@@ -104,6 +199,9 @@ long do_network_op(network_op_t *u_network_op)
|
||||
void __init net_init (void)
|
||||
{
|
||||
sys_vif_count = 0;
|
||||
net_rule_list = NULL;
|
||||
net_vif_cache = kmem_cache_create("net_vif_cache", sizeof(net_vif_t),
|
||||
0, SLAB_HWCACHE_ALIGN, NULL, NULL);
|
||||
0, SLAB_HWCACHE_ALIGN, NULL, NULL);
|
||||
net_rule_cache = kmem_cache_create("net_rule_cache", sizeof(net_rule_ent_t),
|
||||
0, SLAB_HWCACHE_ALIGN, NULL, NULL);
|
||||
}
|
||||
@@ -51,22 +51,19 @@ typedef struct net_ring_st {
|
||||
unsigned int rx_ring_size;
|
||||
} net_ring_t;
|
||||
|
||||
/* This is here for consideration: Having a global lookup for vifs
|
||||
* may make the guest /proc stuff more straight forward, and could
|
||||
* be used in the routing code. I don't know if it warrants the
|
||||
* overhead yet.
|
||||
*/
|
||||
|
||||
/* net_vif_t sys_vif_list[MAX_SYSTEM_VIFS]; */
|
||||
|
||||
/* Specify base of per-domain array. Get returned free slot in the array. */
|
||||
net_ring_t *create_net_vif(int domain);
|
||||
|
||||
/* Packet routing/filtering code follows:
|
||||
*/
|
||||
|
||||
#define NETWORK_ACTION_DROP 0
|
||||
#define NETWORK_ACTION_PASS 1
|
||||
#define NETWORK_ACTION_ACCEPT 0
|
||||
#define NETWORK_ACTION_COUNT 1
|
||||
|
||||
#define NETWORK_PROTO_IP 0
|
||||
#define NETWORK_PROTO_TCP 1
|
||||
#define NETWORK_PROTO_UDP 2
|
||||
#define NETWORK_PROTO_ARP 3
|
||||
|
||||
typedef struct net_rule_st
|
||||
{
|
||||
@@ -78,10 +75,11 @@ typedef struct net_rule_st
|
||||
u32 dst_addr_mask;
|
||||
u16 src_port_mask;
|
||||
u16 dst_port_mask;
|
||||
|
||||
int src_interface;
|
||||
int dst_interface;
|
||||
int action;
|
||||
u16 proto;
|
||||
|
||||
u16 src_interface;
|
||||
u16 dst_interface;
|
||||
u16 action;
|
||||
} net_rule_t;
|
||||
|
||||
/* Network trap operations and associated structure.
|
||||
@@ -91,6 +89,7 @@ typedef struct net_rule_st
|
||||
|
||||
#define NETWORK_OP_ADDRULE 0
|
||||
#define NETWORK_OP_DELETERULE 1
|
||||
#define NETWORK_OP_GETRULELIST 2
|
||||
|
||||
typedef struct network_op_st
|
||||
{
|
||||
@@ -101,7 +100,13 @@ typedef struct network_op_st
|
||||
}
|
||||
u;
|
||||
} network_op_t;
|
||||
|
||||
|
||||
typedef struct net_rule_ent_st
|
||||
{
|
||||
net_rule_t r;
|
||||
struct net_rule_ent_st *next;
|
||||
} net_rule_ent_t;
|
||||
|
||||
/* Drop a new rule down to the network tables. */
|
||||
int add_net_rule(net_rule_t *rule);
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ typedef struct net_vif_st {
|
||||
|
||||
/* vif globals */
|
||||
extern int sys_vif_count;
|
||||
extern net_vif_t *sys_vif_list[];
|
||||
|
||||
/* vif prototypes */
|
||||
net_ring_t *create_net_vif(int domain);
|
||||
|
||||
+54
-51
@@ -1912,72 +1912,75 @@ long do_net_update(void)
|
||||
{
|
||||
shared_info_t *shared = current->shared_info;
|
||||
net_ring_t *net_ring = current->net_ring_base;
|
||||
unsigned int i;
|
||||
unsigned int i, j;
|
||||
struct sk_buff *skb;
|
||||
tx_entry_t tx;
|
||||
|
||||
for ( i = net_ring->tx_cons; i != net_ring->tx_prod; i = TX_RING_INC(i) )
|
||||
for ( j = 0; j < current->num_net_vifs; j++)
|
||||
{
|
||||
if ( copy_from_user(&tx, net_ring->tx_ring+i, sizeof(tx)) )
|
||||
continue;
|
||||
|
||||
if ( TX_RING_INC(i) == net_ring->tx_event )
|
||||
set_bit(_EVENT_NET_TX, &shared->events);
|
||||
|
||||
skb = alloc_skb(tx.size, GFP_KERNEL);
|
||||
if ( skb == NULL ) continue;
|
||||
skb_put(skb, tx.size);
|
||||
if ( copy_from_user(skb->data, (void *)tx.addr, tx.size) )
|
||||
net_ring = current->net_vif_list[j]->net_ring;
|
||||
for ( i = net_ring->tx_cons; i != net_ring->tx_prod; i = TX_RING_INC(i) )
|
||||
{
|
||||
kfree_skb(skb);
|
||||
continue;
|
||||
}
|
||||
skb->dev = the_dev;
|
||||
if ( copy_from_user(&tx, net_ring->tx_ring+i, sizeof(tx)) )
|
||||
continue;
|
||||
|
||||
if ( skb->len < 16 )
|
||||
{
|
||||
kfree_skb(skb);
|
||||
continue;
|
||||
}
|
||||
if ( TX_RING_INC(i) == net_ring->tx_event )
|
||||
set_bit(_EVENT_NET_TX, &shared->events);
|
||||
|
||||
memcpy(skb->data + ETH_ALEN, skb->dev->dev_addr, ETH_ALEN);
|
||||
|
||||
switch ( ntohs(*(unsigned short *)(skb->data + 12)) )
|
||||
{
|
||||
case ETH_P_ARP:
|
||||
skb->protocol = __constant_htons(ETH_P_ARP);
|
||||
if ( skb->len < 42 ) break;
|
||||
memcpy(skb->data + 22, skb->dev->dev_addr, 6);
|
||||
break;
|
||||
case ETH_P_IP:
|
||||
skb->protocol = __constant_htons(ETH_P_IP);
|
||||
break;
|
||||
default:
|
||||
kfree_skb(skb);
|
||||
skb = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( skb != NULL )
|
||||
{
|
||||
skb_get(skb); /* get a reference for non-local delivery */
|
||||
skb->protocol = eth_type_trans(skb, skb->dev);
|
||||
if ( netif_rx(skb) == 0 )
|
||||
skb = alloc_skb(tx.size, GFP_KERNEL);
|
||||
if ( skb == NULL ) continue;
|
||||
skb_put(skb, tx.size);
|
||||
if ( copy_from_user(skb->data, (void *)tx.addr, tx.size) )
|
||||
{
|
||||
/* Give up non-local reference. Packet delivered locally. */
|
||||
kfree_skb(skb);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
skb->dev = the_dev;
|
||||
|
||||
if ( skb->len < 16 )
|
||||
{
|
||||
/* Pass the non-local reference to the net device. */
|
||||
skb_push(skb, skb->dev->hard_header_len);
|
||||
dev_queue_xmit(skb);
|
||||
kfree_skb(skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(skb->data + ETH_ALEN, skb->dev->dev_addr, ETH_ALEN);
|
||||
|
||||
switch ( ntohs(*(unsigned short *)(skb->data + 12)) )
|
||||
{
|
||||
case ETH_P_ARP:
|
||||
skb->protocol = __constant_htons(ETH_P_ARP);
|
||||
if ( skb->len < 42 ) break;
|
||||
memcpy(skb->data + 22, skb->dev->dev_addr, 6);
|
||||
break;
|
||||
case ETH_P_IP:
|
||||
skb->protocol = __constant_htons(ETH_P_IP);
|
||||
break;
|
||||
default:
|
||||
kfree_skb(skb);
|
||||
skb = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( skb != NULL )
|
||||
{
|
||||
skb_get(skb); /* get a reference for non-local delivery */
|
||||
skb->protocol = eth_type_trans(skb, skb->dev);
|
||||
if ( netif_rx(skb) == 0 )
|
||||
{
|
||||
/* Give up non-local reference. Packet delivered locally. */
|
||||
kfree_skb(skb);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Pass the non-local reference to the net device. */
|
||||
skb_push(skb, skb->dev->hard_header_len);
|
||||
dev_queue_xmit(skb);
|
||||
}
|
||||
}
|
||||
}
|
||||
net_ring->tx_cons = i;
|
||||
}
|
||||
|
||||
net_ring->tx_cons = i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
O_TARGET := dom0.o
|
||||
obj-y := dom0_core.o
|
||||
obj-y := dom0_core.o vfr.o
|
||||
include $(TOPDIR)/Rules.make
|
||||
@@ -0,0 +1,277 @@
|
||||
/******************************************************************************
|
||||
* vfr.c
|
||||
*
|
||||
* Interface to the virtual firewall/router.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/proc_fs.h>
|
||||
|
||||
#include <asm/hypervisor-ifs/network.h>
|
||||
|
||||
static struct proc_dir_entry *proc_vfr;
|
||||
|
||||
static unsigned char readbuf[1024];
|
||||
|
||||
/* Helpers, implemented at the bottom. */
|
||||
u32 getipaddr(const char *buff, unsigned int len);
|
||||
u16 antous(const char *buff, int len);
|
||||
|
||||
static int vfr_read_proc(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
strcpy(page, readbuf);
|
||||
*readbuf = '\0';
|
||||
*eof = 1;
|
||||
*start = page;
|
||||
return strlen(page);
|
||||
}
|
||||
|
||||
/* The format for the vfr interface is as follows:
|
||||
*
|
||||
* COMMAND <field>=<val> [<field>=<val> [...]]
|
||||
*
|
||||
* where:
|
||||
*
|
||||
* COMMAND = { ACCEPT | COUNT }
|
||||
*
|
||||
* field=val pairs are as follows:
|
||||
*
|
||||
* field = { srcaddr | dstaddr }
|
||||
* val is a dot seperated, numeric IP address.
|
||||
*
|
||||
* field = { srcport | dstport }
|
||||
* val is a (16-bit) unsigned int
|
||||
*
|
||||
* field = { proto }
|
||||
* val = { IP | TCP | UDP | ARP }
|
||||
*
|
||||
*/
|
||||
|
||||
static int vfr_write_proc(struct file *file, const char *buffer,
|
||||
u_long count, void *data)
|
||||
{
|
||||
network_op_t op;
|
||||
int ret, len;
|
||||
int ts, te, tl; // token start, end, and length
|
||||
int fs, fe, fl; // field.
|
||||
|
||||
len = count;
|
||||
ts = te = 0;
|
||||
|
||||
memset(&op, 0, sizeof(network_op_t));
|
||||
|
||||
// get the command:
|
||||
while ( count && (buffer[ts] == ' ') ) { ts++; count--; } // skip spaces.
|
||||
te = ts;
|
||||
while ( count && (buffer[te] != ' ') ) { te++; count--; } // command end
|
||||
if ( te <= ts ) goto bad;
|
||||
tl = te - ts;
|
||||
|
||||
if ( strncmp(&buffer[ts], "ADD", tl) == 0 )
|
||||
{
|
||||
op.cmd = NETWORK_OP_ADDRULE;
|
||||
}
|
||||
else if ( strncmp(&buffer[ts], "DELETE", tl) == 0 )
|
||||
{
|
||||
op.cmd = NETWORK_OP_DELETERULE;
|
||||
}
|
||||
else if ( strncmp(&buffer[ts], "PRINT", tl) == 0 )
|
||||
{
|
||||
op.cmd = NETWORK_OP_GETRULELIST;
|
||||
goto doneparsing;
|
||||
}
|
||||
|
||||
ts = te;
|
||||
|
||||
// get the action
|
||||
while ( count && (buffer[ts] == ' ') ) { ts++; count--; } // skip spaces.
|
||||
te = ts;
|
||||
while ( count && (buffer[te] != ' ') ) { te++; count--; } // command end
|
||||
if ( te <= ts ) goto bad;
|
||||
tl = te - ts;
|
||||
|
||||
if ( strncmp(&buffer[ts], "ACCEPT", tl) == 0 )
|
||||
{
|
||||
op.u.net_rule.action = NETWORK_ACTION_ACCEPT;
|
||||
goto keyval;
|
||||
}
|
||||
if ( strncmp(&buffer[ts], "COUNT", tl) == 0 )
|
||||
{
|
||||
op.u.net_rule.action = NETWORK_ACTION_COUNT;
|
||||
goto keyval;
|
||||
}
|
||||
|
||||
// default case;
|
||||
return (len);
|
||||
|
||||
|
||||
// get the key=val pairs.
|
||||
keyval:
|
||||
while (count)
|
||||
{
|
||||
//get field
|
||||
ts = te; while ( count && (buffer[ts] == ' ') ) { ts++; count--; }
|
||||
te = ts;
|
||||
while ( count && (buffer[te] != ' ') && (buffer[te] != '=') )
|
||||
{ te++; count--; }
|
||||
if ( te <= ts ) goto bad;
|
||||
tl = te - ts;
|
||||
fs = ts; fe = te; fl = tl; // save the field markers.
|
||||
// skip " = " (ignores extra equals.)
|
||||
while ( count && ((buffer[te] == ' ') || (buffer[te] == '=')) )
|
||||
{ te++; count--; }
|
||||
ts = te;
|
||||
while ( count && (buffer[te] != ' ') ) { te++; count--; }
|
||||
tl = te - ts;
|
||||
|
||||
if ( (fl <= 0) || (tl <= 0) ) goto bad;
|
||||
|
||||
if (strncmp(&buffer[fs], "srcaddr", fl) == 0)
|
||||
{
|
||||
op.u.net_rule.src_addr = getipaddr(&buffer[ts], tl-1);
|
||||
}
|
||||
else if (strncmp(&buffer[fs], "dstaddr", fl) == 0)
|
||||
{
|
||||
op.u.net_rule.dst_addr = getipaddr(&buffer[ts], tl-1);
|
||||
}
|
||||
else if (strncmp(&buffer[fs], "srcaddrmask", fl) == 0)
|
||||
{
|
||||
op.u.net_rule.src_addr_mask = getipaddr(&buffer[ts], tl-1);
|
||||
}
|
||||
else if (strncmp(&buffer[fs], "dstaddrmask", fl) == 0)
|
||||
{
|
||||
op.u.net_rule.dst_addr_mask = getipaddr(&buffer[ts], tl-1);
|
||||
}
|
||||
else if (strncmp(&buffer[fs], "srcport", fl) == 0)
|
||||
{
|
||||
op.u.net_rule.src_port = antous(&buffer[ts], tl-1);
|
||||
}
|
||||
else if (strncmp(&buffer[fs], "dstport", fl) == 0)
|
||||
{
|
||||
op.u.net_rule.dst_port = antous(&buffer[ts], tl-1);
|
||||
}
|
||||
else if (strncmp(&buffer[fs], "srcportmask", fl) == 0)
|
||||
{
|
||||
op.u.net_rule.src_port_mask = antous(&buffer[ts], tl-1);
|
||||
}
|
||||
else if (strncmp(&buffer[fs], "dstportmask", fl) == 0)
|
||||
{
|
||||
op.u.net_rule.dst_port_mask = antous(&buffer[ts], tl-1);
|
||||
}
|
||||
else if (strncmp(&buffer[fs], "srcint", fl) == 0)
|
||||
{
|
||||
op.u.net_rule.src_interface = antous(&buffer[ts], tl-1);
|
||||
}
|
||||
else if (strncmp(&buffer[fs], "dstint", fl) == 0)
|
||||
{
|
||||
op.u.net_rule.dst_interface = antous(&buffer[ts], tl-1);
|
||||
}
|
||||
else if ( (strncmp(&buffer[fs], "proto", fl) == 0))
|
||||
{
|
||||
if (strncmp(&buffer[ts], "ip", tl))
|
||||
op.u.net_rule.proto = NETWORK_PROTO_IP;
|
||||
if (strncmp(&buffer[ts], "tcp", tl))
|
||||
op.u.net_rule.proto = NETWORK_PROTO_TCP;
|
||||
if (strncmp(&buffer[ts], "udp", tl))
|
||||
op.u.net_rule.proto = NETWORK_PROTO_UDP;
|
||||
if (strncmp(&buffer[ts], "arp", tl))
|
||||
op.u.net_rule.proto = NETWORK_PROTO_ARP;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
doneparsing:
|
||||
ret = HYPERVISOR_network_op(&op);
|
||||
return(len);
|
||||
|
||||
bad:
|
||||
return(len);
|
||||
|
||||
|
||||
}
|
||||
|
||||
static int __init init_module(void)
|
||||
{
|
||||
*readbuf = '\0';
|
||||
proc_vfr = create_proc_entry ("vfr", 0600, &proc_root);
|
||||
if ( proc_vfr != NULL )
|
||||
{
|
||||
proc_vfr->owner = THIS_MODULE;
|
||||
proc_vfr->nlink = 1;
|
||||
proc_vfr->read_proc = vfr_read_proc;
|
||||
proc_vfr->write_proc = vfr_write_proc;
|
||||
printk("Successfully installed virtual firewall/router interface\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit cleanup_module(void)
|
||||
{
|
||||
if ( proc_vfr == NULL ) return;
|
||||
remove_proc_entry("vfr", &proc_root);
|
||||
proc_vfr = NULL;
|
||||
}
|
||||
|
||||
module_init(init_module);
|
||||
module_exit(cleanup_module);
|
||||
|
||||
/* Helper functions start here: */
|
||||
|
||||
u16 antous(const char *buff, int len)
|
||||
{
|
||||
int ret;
|
||||
char c;
|
||||
|
||||
ret = 0;
|
||||
|
||||
while ( (len) && ((c = *buff) >= '0') && (c <= '9') )
|
||||
{
|
||||
ret *= 10;
|
||||
ret += c - '0';
|
||||
buff++; len--;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 getipaddr(const char *buff, unsigned int len)
|
||||
{
|
||||
int i;
|
||||
char c;
|
||||
u32 ret, val;
|
||||
|
||||
ret = 0; val = 0;
|
||||
|
||||
while ( len )
|
||||
{
|
||||
if (!((((c = *buff) >= '0') && ( c <= '9')) || ( c == '.' ) ) )
|
||||
{
|
||||
return(0); // malformed.
|
||||
}
|
||||
|
||||
if ( c == '.' ) {
|
||||
if (val > 255) return (0); //malformed.
|
||||
ret = ret << 8;
|
||||
ret += val;
|
||||
val = 0;
|
||||
len--; buff++;
|
||||
continue;
|
||||
}
|
||||
val *= 10;
|
||||
val += c - '0';
|
||||
buff++; len--;
|
||||
}
|
||||
ret = ret << 8;
|
||||
ret += val;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@@ -51,43 +51,19 @@ typedef struct net_ring_st {
|
||||
unsigned int rx_ring_size;
|
||||
} net_ring_t;
|
||||
|
||||
/* net_vif_st is the larger struct that describes a virtual network interface
|
||||
* it contains a pointer to the net_ring_t structure that needs to be on a
|
||||
* shared page between the hypervisor and guest. The vif struct is private
|
||||
* to the hypervisor and is used primarily as a container to allow routing
|
||||
* and interface administration. This define should eventually be moved to
|
||||
* a non-shared interface file, as it is of no relevance to the guest.
|
||||
*/
|
||||
|
||||
typedef struct net_vif_st {
|
||||
net_ring_t *net_ring;
|
||||
int id;
|
||||
// rules table goes here in next revision.
|
||||
} net_vif_t;
|
||||
|
||||
/* VIF-related defines. */
|
||||
#define MAX_GUEST_VIFS 2 // each VIF is a small overhead in task_struct
|
||||
#define MAX_SYSTEM_VIFS 256 // trying to avoid dynamic allocation
|
||||
|
||||
/* vif globals */
|
||||
extern int sys_vif_count;
|
||||
|
||||
/* This is here for consideration: Having a global lookup for vifs
|
||||
* may make the guest /proc stuff more straight forward, and could
|
||||
* be used in the routing code. I don't know if it warrants the
|
||||
* overhead yet.
|
||||
*/
|
||||
|
||||
/* net_vif_t sys_vif_list[MAX_SYSTEM_VIFS]; */
|
||||
|
||||
/* Specify base of per-domain array. Get returned free slot in the array. */
|
||||
net_ring_t *create_net_vif(int domain);
|
||||
|
||||
/* Packet routing/filtering code follows:
|
||||
*/
|
||||
|
||||
#define NETWORK_ACTION_DROP 0
|
||||
#define NETWORK_ACTION_PASS 1
|
||||
#define NETWORK_ACTION_ACCEPT 0
|
||||
#define NETWORK_ACTION_COUNT 1
|
||||
|
||||
#define NETWORK_PROTO_IP 0
|
||||
#define NETWORK_PROTO_TCP 1
|
||||
#define NETWORK_PROTO_UDP 2
|
||||
#define NETWORK_PROTO_ARP 3
|
||||
|
||||
typedef struct net_rule_st
|
||||
{
|
||||
@@ -99,10 +75,11 @@ typedef struct net_rule_st
|
||||
u32 dst_addr_mask;
|
||||
u16 src_port_mask;
|
||||
u16 dst_port_mask;
|
||||
|
||||
int src_interface;
|
||||
int dst_interface;
|
||||
int action;
|
||||
u16 proto;
|
||||
|
||||
u16 src_interface;
|
||||
u16 dst_interface;
|
||||
u16 action;
|
||||
} net_rule_t;
|
||||
|
||||
/* Network trap operations and associated structure.
|
||||
@@ -112,6 +89,7 @@ typedef struct net_rule_st
|
||||
|
||||
#define NETWORK_OP_ADDRULE 0
|
||||
#define NETWORK_OP_DELETERULE 1
|
||||
#define NETWORK_OP_GETRULELIST 2
|
||||
|
||||
typedef struct network_op_st
|
||||
{
|
||||
@@ -122,7 +100,13 @@ typedef struct network_op_st
|
||||
}
|
||||
u;
|
||||
} network_op_t;
|
||||
|
||||
|
||||
typedef struct net_rule_ent_st
|
||||
{
|
||||
net_rule_t r;
|
||||
struct net_rule_ent_st *next;
|
||||
} net_rule_ent_t;
|
||||
|
||||
/* Drop a new rule down to the network tables. */
|
||||
int add_net_rule(net_rule_t *rule);
|
||||
|
||||
|
||||