summaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-06-19 22:45:37 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-06-19 22:45:37 +0000
commit6d403070f28cd44860fdb3a53be5da0275c65cf4 (patch)
tree0d0e7fe7b5fb7568d19e11d7d862b77a866ce081 /net/ipv6
parentecf1bf5f6c2e668d03b0a9fb026db7aa41e292e1 (diff)
Merge with 2.4.0-test1-ac21 + pile of MIPS cleanups to make merging
possible. Chainsawed RM200 kernel to compile again. Jazz machine status unknown.
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/netfilter/ip6_tables.c11
-rw-r--r--net/ipv6/netfilter/ip6t_mac.c62
-rw-r--r--net/ipv6/netfilter/ip6t_multiport.c101
3 files changed, 168 insertions, 6 deletions
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 2d9c356e9..dea475feb 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -736,7 +736,7 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
target = find_target_lock(t->u.user.name, &ret, &ip6t_mutex);
if (!target) {
// duprintf("check_entry: `%s' not found\n", t->u.name);
- return ret;
+ goto cleanup_matches;
}
if (target->me)
__MOD_INC_USE_COUNT(target->me);
@@ -1342,9 +1342,10 @@ ip6t_register_target(struct ip6t_target *target)
MOD_INC_USE_COUNT;
ret = down_interruptible(&ip6t_mutex);
- if (ret != 0)
+ if (ret != 0) {
+ MOD_DEC_USE_COUNT;
return ret;
-
+ }
if (!list_named_insert(&ip6t_target, target)) {
duprintf("ip6t_register_target: `%s' already in list!\n",
target->name);
@@ -1375,9 +1376,7 @@ ip6t_register_match(struct ip6t_match *match)
MOD_DEC_USE_COUNT;
return ret;
}
- if (list_named_insert(&ip6t_match, match)) {
- ret = 0;
- } else {
+ if (!list_named_insert(&ip6t_match, match)) {
duprintf("ip6t_register_match: `%s' already in list!\n",
match->name);
MOD_DEC_USE_COUNT;
diff --git a/net/ipv6/netfilter/ip6t_mac.c b/net/ipv6/netfilter/ip6t_mac.c
new file mode 100644
index 000000000..c0e403b50
--- /dev/null
+++ b/net/ipv6/netfilter/ip6t_mac.c
@@ -0,0 +1,62 @@
+/* Kernel module to match MAC address parameters. */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/if_ether.h>
+
+#include <linux/netfilter_ipv6/ip6t_mac.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+
+static int
+match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+ const void *hdr,
+ u_int16_t datalen,
+ int *hotdrop)
+{
+ const struct ip6t_mac_info *info = matchinfo;
+
+ /* Is mac pointer valid? */
+ return (skb->mac.raw >= skb->head
+ && skb->mac.raw < skb->head + skb->len - ETH_HLEN
+ /* If so, compare... */
+ && ((memcmp(skb->mac.ethernet->h_source, info->srcaddr, ETH_ALEN)
+ == 0) ^ info->invert));
+}
+
+static int
+ipt_mac_checkentry(const char *tablename,
+ const struct ip6t_ip6 *ip,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ if (hook_mask
+ & ~((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_IN))) {
+ printk("ipt_mac: only valid for PRE_ROUTING or LOCAL_IN.\n");
+ return 0;
+ }
+
+ if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_mac_info)))
+ return 0;
+
+ return 1;
+}
+
+static struct ip6t_match mac_match
+= { { NULL, NULL }, "mac", &match, &ipt_mac_checkentry, NULL, THIS_MODULE };
+
+static int __init init(void)
+{
+ return ip6t_register_match(&mac_match);
+}
+
+static void __exit fini(void)
+{
+ ip6t_unregister_match(&mac_match);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_multiport.c b/net/ipv6/netfilter/ip6t_multiport.c
new file mode 100644
index 000000000..5f2902e3b
--- /dev/null
+++ b/net/ipv6/netfilter/ip6t_multiport.c
@@ -0,0 +1,101 @@
+/* Kernel module to match one of a list of TCP/UDP ports: ports are in
+ the same place so we can treat them as equal. */
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/udp.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+
+#include <linux/netfilter_ipv6/ip6t_multiport.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+
+#if 0
+#define duprintf(format, args...) printk(format , ## args)
+#else
+#define duprintf(format, args...)
+#endif
+
+/* Returns 1 if the port is matched by the test, 0 otherwise. */
+static inline int
+ports_match(const u_int16_t *portlist, enum ip6t_multiport_flags flags,
+ u_int8_t count, u_int16_t src, u_int16_t dst)
+{
+ unsigned int i;
+ for (i=0; i<count; i++) {
+ if (flags != IP6T_MULTIPORT_DESTINATION
+ && portlist[i] == src)
+ return 1;
+
+ if (flags != IP6T_MULTIPORT_SOURCE
+ && portlist[i] == dst)
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+ const void *hdr,
+ u_int16_t datalen,
+ int *hotdrop)
+{
+ const struct udphdr *udp = hdr;
+ const struct ip6t_multiport *multiinfo = matchinfo;
+
+ /* Must be big enough to read ports. */
+ if (offset == 0 && datalen < sizeof(struct udphdr)) {
+ /* We've been asked to examine this packet, and we
+ can't. Hence, no choice but to drop. */
+ duprintf("ipt_multiport:"
+ " Dropping evil offset=0 tinygram.\n");
+ *hotdrop = 1;
+ return 0;
+ }
+
+ /* Must not be a fragment. */
+ return !offset
+ && ports_match(multiinfo->ports,
+ multiinfo->flags, multiinfo->count,
+ ntohs(udp->source), ntohs(udp->dest));
+}
+
+/* Called when user tries to insert an entry of this type. */
+static int
+checkentry(const char *tablename,
+ const struct ip6t_ip6 *ip,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ const struct ip6t_multiport *multiinfo = matchinfo;
+
+ /* Must specify proto == TCP/UDP, no unknown flags or bad count */
+ return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
+ && !(ip->flags & IP6T_INV_PROTO)
+ && matchsize == IP6T_ALIGN(sizeof(struct ip6t_multiport))
+ && (multiinfo->flags == IP6T_MULTIPORT_SOURCE
+ || multiinfo->flags == IP6T_MULTIPORT_DESTINATION
+ || multiinfo->flags == IP6T_MULTIPORT_EITHER)
+ && multiinfo->count <= IP6T_MULTI_PORTS;
+}
+
+static struct ip6t_match multiport_match
+= { { NULL, NULL }, "multiport", &match, &checkentry, NULL, THIS_MODULE };
+
+static int __init init(void)
+{
+ return ip6t_register_match(&multiport_match);
+}
+
+static void __exit fini(void)
+{
+ ip6t_unregister_match(&multiport_match);
+}
+
+module_init(init);
+module_exit(fini);