From b6a1268714671904e96a49b88680dc3ff07aaa1c Mon Sep 17 00:00:00 2001 From: Kozlov Dmitry Date: Wed, 6 Oct 2010 16:43:14 +0400 Subject: project cleanup and prepare to release --- driver/gre.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 driver/gre.c (limited to 'driver/gre.c') diff --git a/driver/gre.c b/driver/gre.c new file mode 100644 index 0000000..cda0576 --- /dev/null +++ b/driver/gre.c @@ -0,0 +1,140 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gre.h" + + +struct gre_protocol *gre_proto[GREPROTO_MAX] ____cacheline_aligned_in_smp; +static DEFINE_RWLOCK(gre_proto_lock); + +int gre_add_protocol(struct gre_protocol *proto, u8 version) +{ + int ret; + + if (version >= GREPROTO_MAX) + return -1; + + write_lock_bh(&gre_proto_lock); + if (gre_proto[version]) { + ret = -1; + } else { + gre_proto[version]=proto; + ret = 0; + } + write_unlock_bh(&gre_proto_lock); + + return ret; +} +int gre_del_protocol(struct gre_protocol *proto, u8 version) +{ + int ret; + + if (version >= GREPROTO_MAX) + return -1; + + write_lock_bh(&gre_proto_lock); + if (gre_proto[version] == proto) { + gre_proto[version] = NULL; + ret = 0; + } else { + ret = -1; + } + write_unlock_bh(&gre_proto_lock); + + return ret; +} +static int gre_rcv(struct sk_buff *skb) +{ + u8 ver; + int ret; + + if (!pskb_may_pull(skb, 12)) + goto drop_nolock; + + ver = skb->data[1]&0x7f; + if (ver >= GREPROTO_MAX) + goto drop_nolock; + + read_lock(&gre_proto_lock); + if (!gre_proto[ver] || !gre_proto[ver]->handler) + goto drop; + + ret = gre_proto[ver]->handler(skb); + read_unlock(&gre_proto_lock); + + return ret; + +drop: + read_unlock(&gre_proto_lock); +drop_nolock: + kfree_skb(skb); + return NET_RX_DROP; +} +static void gre_err(struct sk_buff *skb, u32 info) +{ + u8 ver; + + printk("err\n"); + + if (!pskb_may_pull(skb, 12)) + goto drop_nolock; + + ver=skb->data[1]; + if (ver>=GREPROTO_MAX) + goto drop_nolock; + + read_lock(&gre_proto_lock); + if (!gre_proto[ver] || !gre_proto[ver]->err_handler) + goto drop; + + gre_proto[ver]->err_handler(skb,info); + read_unlock(&gre_proto_lock); + + return; + +drop: + read_unlock(&gre_proto_lock); +drop_nolock: + kfree_skb(skb); +} + + +static struct net_protocol net_gre_protocol = { + .handler = gre_rcv, + .err_handler = gre_err, +// .netns_ok=1, +}; + +static int __init gre_init(void) +{ + printk(KERN_INFO "GRE over IPv4 demultiplexor driver"); + + if (inet_add_protocol(&net_gre_protocol, IPPROTO_GRE) < 0) { + printk(KERN_INFO "gre: can't add protocol\n"); + return -EAGAIN; + } + + return 0; +} + +static void __exit gre_exit(void) +{ + inet_del_protocol(&net_gre_protocol, IPPROTO_GRE); +} + +module_init(gre_init); +module_exit(gre_exit); + +MODULE_DESCRIPTION("GRE over IPv4 demultiplexor driver"); +MODULE_AUTHOR("Kozlov D. (xeb@mail.ru)"); +MODULE_LICENSE("GPL"); +EXPORT_SYMBOL_GPL(gre_add_protocol); +EXPORT_SYMBOL_GPL(gre_del_protocol); + -- cgit v1.2.3