diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /net/decnet/netfilter |
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'net/decnet/netfilter')
-rw-r--r-- | net/decnet/netfilter/Kconfig | 15 | ||||
-rw-r--r-- | net/decnet/netfilter/Makefile | 6 | ||||
-rw-r--r-- | net/decnet/netfilter/dn_rtmsg.c | 167 |
3 files changed, 188 insertions, 0 deletions
diff --git a/net/decnet/netfilter/Kconfig b/net/decnet/netfilter/Kconfig new file mode 100644 index 00000000000..ecdb3f9f14c --- /dev/null +++ b/net/decnet/netfilter/Kconfig @@ -0,0 +1,15 @@ +# +# DECnet netfilter configuration +# + +menu "DECnet: Netfilter Configuration" + depends on DECNET && NETFILTER && EXPERIMENTAL + +config DECNET_NF_GRABULATOR + tristate "Routing message grabulator (for userland routing daemon)" + help + Enable this module if you want to use the userland DECnet routing + daemon. You will also need to enable routing support for DECnet + unless you just want to monitor routing messages from other nodes. + +endmenu diff --git a/net/decnet/netfilter/Makefile b/net/decnet/netfilter/Makefile new file mode 100644 index 00000000000..255c1ae9dae --- /dev/null +++ b/net/decnet/netfilter/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for DECnet netfilter modules +# + +obj-$(CONFIG_DECNET_NF_GRABULATOR) += dn_rtmsg.o + diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c new file mode 100644 index 00000000000..f86a6259fd1 --- /dev/null +++ b/net/decnet/netfilter/dn_rtmsg.c @@ -0,0 +1,167 @@ +/* + * DECnet An implementation of the DECnet protocol suite for the LINUX + * operating system. DECnet is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * DECnet Routing Message Grabulator + * + * (C) 2000 ChyGwyn Limited - http://www.chygwyn.com/ + * This code may be copied under the GPL v.2 or at your option + * any later version. + * + * Author: Steven Whitehouse <steve@chygwyn.com> + * + */ +#include <linux/module.h> +#include <linux/skbuff.h> +#include <linux/init.h> +#include <linux/netdevice.h> +#include <linux/netfilter.h> +#include <linux/spinlock.h> +#include <linux/netlink.h> + +#include <net/sock.h> +#include <net/flow.h> +#include <net/dn.h> +#include <net/dn_route.h> + +#include <linux/netfilter_decnet.h> + +static struct sock *dnrmg = NULL; + + +static struct sk_buff *dnrmg_build_message(struct sk_buff *rt_skb, int *errp) +{ + struct sk_buff *skb = NULL; + size_t size; + unsigned char *old_tail; + struct nlmsghdr *nlh; + unsigned char *ptr; + struct nf_dn_rtmsg *rtm; + + size = NLMSG_SPACE(rt_skb->len); + size += NLMSG_ALIGN(sizeof(struct nf_dn_rtmsg)); + skb = alloc_skb(size, GFP_ATOMIC); + if (!skb) + goto nlmsg_failure; + old_tail = skb->tail; + nlh = NLMSG_PUT(skb, 0, 0, 0, size - sizeof(*nlh)); + rtm = (struct nf_dn_rtmsg *)NLMSG_DATA(nlh); + rtm->nfdn_ifindex = rt_skb->dev->ifindex; + ptr = NFDN_RTMSG(rtm); + memcpy(ptr, rt_skb->data, rt_skb->len); + nlh->nlmsg_len = skb->tail - old_tail; + return skb; + +nlmsg_failure: + if (skb) + kfree_skb(skb); + *errp = -ENOMEM; + if (net_ratelimit()) + printk(KERN_ERR "dn_rtmsg: error creating netlink message\n"); + return NULL; +} + +static void dnrmg_send_peer(struct sk_buff *skb) +{ + struct sk_buff *skb2; + int status = 0; + int group = 0; + unsigned char flags = *skb->data; + + switch(flags & DN_RT_CNTL_MSK) { + case DN_RT_PKT_L1RT: + group = DNRMG_L1_GROUP; + break; + case DN_RT_PKT_L2RT: + group = DNRMG_L2_GROUP; + break; + default: + return; + } + + skb2 = dnrmg_build_message(skb, &status); + if (skb2 == NULL) + return; + NETLINK_CB(skb2).dst_groups = group; + netlink_broadcast(dnrmg, skb2, 0, group, GFP_ATOMIC); +} + + +static unsigned int dnrmg_hook(unsigned int hook, + struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ + dnrmg_send_peer(*pskb); + return NF_ACCEPT; +} + + +#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0) + +static inline void dnrmg_receive_user_skb(struct sk_buff *skb) +{ + struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data; + + if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) + return; + + if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) + RCV_SKB_FAIL(-EPERM); + + /* Eventually we might send routing messages too */ + + RCV_SKB_FAIL(-EINVAL); +} + +static void dnrmg_receive_user_sk(struct sock *sk, int len) +{ + struct sk_buff *skb; + + while((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { + dnrmg_receive_user_skb(skb); + kfree_skb(skb); + } +} + +static struct nf_hook_ops dnrmg_ops = { + .hook = dnrmg_hook, + .pf = PF_DECnet, + .hooknum = NF_DN_ROUTE, + .priority = NF_DN_PRI_DNRTMSG, +}; + +static int __init init(void) +{ + int rv = 0; + + dnrmg = netlink_kernel_create(NETLINK_DNRTMSG, dnrmg_receive_user_sk); + if (dnrmg == NULL) { + printk(KERN_ERR "dn_rtmsg: Cannot create netlink socket"); + return -ENOMEM; + } + + rv = nf_register_hook(&dnrmg_ops); + if (rv) { + sock_release(dnrmg->sk_socket); + } + + return rv; +} + +static void __exit fini(void) +{ + nf_unregister_hook(&dnrmg_ops); + sock_release(dnrmg->sk_socket); +} + + +MODULE_DESCRIPTION("DECnet Routing Message Grabulator"); +MODULE_AUTHOR("Steven Whitehouse <steve@chygwyn.com>"); +MODULE_LICENSE("GPL"); + +module_init(init); +module_exit(fini); + |