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:
akw27@boulderdash.cl.cam.ac.uk committed 2002-11-20 15:16:44 +00:00
1 parent 4676bbf96d
commit 9d5293906a
9 files changed
+478 -108

No files matched your search

+1
View File
@@ -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
View File
@@ -1 +1,2 @@
akw27@boulderdash.cl.cam.ac.uk
smh22@boulderdash.cl.cam.ac.uk
+103 -5
View File
@@ -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);
}
+20 -15
View File
@@ -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);
+1
View File
@@ -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
View File
@@ -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);
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.