From 8f3864732f38c72c018138269b3e2109c3b3cd40 Mon Sep 17 00:00:00 2001 From: Bart De Schuymer Date: Sat, 3 May 2003 18:13:34 +0000 Subject: update to 2.5.68+pkttype --- kernel/linux2.5/net/bridge/netfilter/Kconfig | 20 ++++++-- kernel/linux2.5/net/bridge/netfilter/Makefile | 9 ++-- kernel/linux2.5/net/bridge/netfilter/ebt_arp.c | 45 +++++++++++++++++ kernel/linux2.5/net/bridge/netfilter/ebt_ip.c | 2 +- kernel/linux2.5/net/bridge/netfilter/ebt_pkttype.c | 59 ++++++++++++++++++++++ .../linux2.5/net/bridge/netfilter/ebtable_broute.c | 15 +++--- .../linux2.5/net/bridge/netfilter/ebtable_filter.c | 19 +++---- kernel/linux2.5/net/bridge/netfilter/ebtable_nat.c | 21 ++++---- kernel/linux2.5/net/bridge/netfilter/ebtables.c | 21 ++++++-- 9 files changed, 171 insertions(+), 40 deletions(-) create mode 100644 kernel/linux2.5/net/bridge/netfilter/ebt_pkttype.c (limited to 'kernel/linux2.5/net/bridge/netfilter') diff --git a/kernel/linux2.5/net/bridge/netfilter/Kconfig b/kernel/linux2.5/net/bridge/netfilter/Kconfig index 0f34466..4b6a1ed 100644 --- a/kernel/linux2.5/net/bridge/netfilter/Kconfig +++ b/kernel/linux2.5/net/bridge/netfilter/Kconfig @@ -49,7 +49,7 @@ config BRIDGE_EBT_LOG If you want to compile it as a module, say M here and read . If unsure, say `N'. -config BRIDGE_EBT_IPF +config BRIDGE_EBT_IP tristate "ebt: IP filter support" depends on BRIDGE_NF_EBTABLES help @@ -59,7 +59,7 @@ config BRIDGE_EBT_IPF If you want to compile it as a module, say M here and read . If unsure, say `N'. -config BRIDGE_EBT_ARPF +config BRIDGE_EBT_ARP tristate "ebt: ARP filter support" depends on BRIDGE_NF_EBTABLES help @@ -69,7 +69,7 @@ config BRIDGE_EBT_ARPF If you want to compile it as a module, say M here and read . If unsure, say `N'. -config BRIDGE_EBT_VLANF +config BRIDGE_EBT_VLAN tristate "ebt: 802.1Q VLAN filter support" depends on BRIDGE_NF_EBTABLES help @@ -79,7 +79,7 @@ config BRIDGE_EBT_VLANF If you want to compile it as a module, say M here and read . If unsure, say `N'. -config BRIDGE_EBT_MARKF +config BRIDGE_EBT_MARK tristate "ebt: mark filter support" depends on BRIDGE_NF_EBTABLES help @@ -91,6 +91,18 @@ config BRIDGE_EBT_MARKF If you want to compile it as a module, say M here and read . If unsure, say `N'. +config BRIDGE_EBT_PKTTYPE + tristate "ebt: packet type filter support" + depends on BRIDGE_NF_EBTABLES + help + This option adds the packet type match, which allows matching on the + type of packet based on its Ethernet "class" (as determined by + the generic networking code): broadcast, multicast, + for this host alone or for another host. + + If you want to compile it as a module, say M here and read + . If unsure, say `N'. + config BRIDGE_EBT_SNAT tristate "ebt: snat target support" depends on BRIDGE_NF_EBTABLES diff --git a/kernel/linux2.5/net/bridge/netfilter/Makefile b/kernel/linux2.5/net/bridge/netfilter/Makefile index 0989ba8..871252b 100644 --- a/kernel/linux2.5/net/bridge/netfilter/Makefile +++ b/kernel/linux2.5/net/bridge/netfilter/Makefile @@ -6,10 +6,11 @@ obj-$(CONFIG_BRIDGE_NF_EBTABLES) += ebtables.o obj-$(CONFIG_BRIDGE_EBT_T_FILTER) += ebtable_filter.o obj-$(CONFIG_BRIDGE_EBT_T_NAT) += ebtable_nat.o obj-$(CONFIG_BRIDGE_EBT_BROUTE) += ebtable_broute.o -obj-$(CONFIG_BRIDGE_EBT_IPF) += ebt_ip.o -obj-$(CONFIG_BRIDGE_EBT_ARPF) += ebt_arp.o -obj-$(CONFIG_BRIDGE_EBT_VLANF) += ebt_vlan.o -obj-$(CONFIG_BRIDGE_EBT_MARKF) += ebt_mark_m.o +obj-$(CONFIG_BRIDGE_EBT_IP) += ebt_ip.o +obj-$(CONFIG_BRIDGE_EBT_ARP) += ebt_arp.o +obj-$(CONFIG_BRIDGE_EBT_VLAN) += ebt_vlan.o +obj-$(CONFIG_BRIDGE_EBT_MARK) += ebt_mark_m.o +obj-$(CONFIG_BRIDGE_EBT_PKTTYPE) += ebt_pkttype.o obj-$(CONFIG_BRIDGE_EBT_LOG) += ebt_log.o obj-$(CONFIG_BRIDGE_EBT_SNAT) += ebt_snat.o obj-$(CONFIG_BRIDGE_EBT_DNAT) += ebt_dnat.o diff --git a/kernel/linux2.5/net/bridge/netfilter/ebt_arp.c b/kernel/linux2.5/net/bridge/netfilter/ebt_arp.c index 35d2608..0d1650b 100644 --- a/kernel/linux2.5/net/bridge/netfilter/ebt_arp.c +++ b/kernel/linux2.5/net/bridge/netfilter/ebt_arp.c @@ -13,6 +13,7 @@ #include #include #include +#include static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *data, unsigned int datalen) @@ -61,6 +62,50 @@ static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in return EBT_NOMATCH; } } + + if (info->bitmask & (EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC)) + { + uint32_t arp_len = sizeof(struct arphdr) + + (2 * (((*skb).nh.arph)->ar_hln)) + + (2 * (((*skb).nh.arph)->ar_pln)); + unsigned char dst[ETH_ALEN]; + unsigned char src[ETH_ALEN]; + + /* Make sure the packet is long enough */ + if ((((*skb).nh.raw) + arp_len) > (*skb).tail) + return EBT_NOMATCH; + /* MAC addresses are 6 bytes */ + if (((*skb).nh.arph)->ar_hln != ETH_ALEN) + return EBT_NOMATCH; + if (info->bitmask & EBT_ARP_SRC_MAC) { + uint8_t verdict, i; + memcpy(&src, ((*skb).nh.raw) + + sizeof(struct arphdr), + ETH_ALEN); + verdict = 0; + for (i = 0; i < 6; i++) + verdict |= (src[i] ^ info->smaddr[i]) & + info->smmsk[i]; + if (FWINV(verdict != 0, EBT_ARP_SRC_MAC)) + return EBT_NOMATCH; + } + + if (info->bitmask & EBT_ARP_DST_MAC) { + uint8_t verdict, i; + memcpy(&dst, ((*skb).nh.raw) + + sizeof(struct arphdr) + + (((*skb).nh.arph)->ar_hln) + + (((*skb).nh.arph)->ar_pln), + ETH_ALEN); + verdict = 0; + for (i = 0; i < 6; i++) + verdict |= (dst[i] ^ info->dmaddr[i]) & + info->dmmsk[i]; + if (FWINV(verdict != 0, EBT_ARP_DST_MAC)) + return EBT_NOMATCH; + } + } + return EBT_MATCH; } diff --git a/kernel/linux2.5/net/bridge/netfilter/ebt_ip.c b/kernel/linux2.5/net/bridge/netfilter/ebt_ip.c index 9f7f6cf..e61899b 100644 --- a/kernel/linux2.5/net/bridge/netfilter/ebt_ip.c +++ b/kernel/linux2.5/net/bridge/netfilter/ebt_ip.c @@ -86,7 +86,7 @@ static int ebt_ip_check(const char *tablename, unsigned int hookmask, if (info->bitmask & ~EBT_IP_MASK || info->invflags & ~EBT_IP_MASK) return -EINVAL; if (info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT)) { - if (!(info->bitmask & EBT_IPROTO)) + if (info->bitmask & EBT_IPROTO) return -EINVAL; if (info->protocol != IPPROTO_TCP && info->protocol != IPPROTO_UDP) diff --git a/kernel/linux2.5/net/bridge/netfilter/ebt_pkttype.c b/kernel/linux2.5/net/bridge/netfilter/ebt_pkttype.c new file mode 100644 index 0000000..f6458ad --- /dev/null +++ b/kernel/linux2.5/net/bridge/netfilter/ebt_pkttype.c @@ -0,0 +1,59 @@ +/* + * ebt_pkttype + * + * Authors: + * Bart De Schuymer + * + * April, 2003 + * + */ + +#include +#include +#include + +static int ebt_filter_pkttype(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const void *data, + unsigned int datalen) +{ + struct ebt_pkttype_info *info = (struct ebt_pkttype_info *)data; + + return (skb->pkt_type != info->pkt_type) ^ info->invert; +} + +static int ebt_pkttype_check(const char *tablename, unsigned int hookmask, + const struct ebt_entry *e, void *data, unsigned int datalen) +{ + struct ebt_pkttype_info *info = (struct ebt_pkttype_info *)data; + + if (datalen != sizeof(struct ebt_pkttype_info)) + return -EINVAL; + if (info->invert != 0 && info->invert != 1) + return -EINVAL; + /* Allow any pkt_type value */ + return 0; +} + +static struct ebt_match filter_pkttype = +{ + .name = EBT_PKTTYPE_MATCH, + .match = ebt_filter_pkttype, + .check = ebt_pkttype_check, + .me = THIS_MODULE, +}; + +static int __init init(void) +{ + return ebt_register_match(&filter_pkttype); +} + +static void __exit fini(void) +{ + ebt_unregister_match(&filter_pkttype); +} + +module_init(init); +module_exit(fini); +MODULE_LICENSE("GPL"); diff --git a/kernel/linux2.5/net/bridge/netfilter/ebtable_broute.c b/kernel/linux2.5/net/bridge/netfilter/ebtable_broute.c index c1fb15b..1767c94 100644 --- a/kernel/linux2.5/net/bridge/netfilter/ebtable_broute.c +++ b/kernel/linux2.5/net/bridge/netfilter/ebtable_broute.c @@ -14,14 +14,13 @@ #include #include #include -#include /* EBT_ACCEPT means the frame will be bridged * EBT_DROP means the frame will be routed */ static struct ebt_entries initial_chain = { - .name = "BROUTING", - .policy = EBT_ACCEPT, + .name = "BROUTING", + .policy = EBT_ACCEPT, }; static struct ebt_replace initial_table = @@ -30,9 +29,9 @@ static struct ebt_replace initial_table = .valid_hooks = 1 << NF_BR_BROUTING, .entries_size = sizeof(struct ebt_entries), .hook_entry = { - [NF_BR_BROUTING] = &initial_chain + [NF_BR_BROUTING] = &initial_chain, }, - .entries = (char *)&initial_chain + .entries = (char *)&initial_chain, }; static int check(const struct ebt_table_info *info, unsigned int valid_hooks) @@ -49,6 +48,7 @@ static struct ebt_table broute_table = .valid_hooks = 1 << NF_BR_BROUTING, .lock = RW_LOCK_UNLOCKED, .check = check, + .me = THIS_MODULE, }; static int ebt_broute(struct sk_buff **pskb) @@ -69,18 +69,15 @@ static int __init init(void) ret = ebt_register_table(&broute_table); if (ret < 0) return ret; - br_write_lock_bh(BR_NETPROTO_LOCK); /* see br_input.c */ br_should_route_hook = ebt_broute; - br_write_unlock_bh(BR_NETPROTO_LOCK); return ret; } static void __exit fini(void) { - br_write_lock_bh(BR_NETPROTO_LOCK); br_should_route_hook = NULL; - br_write_unlock_bh(BR_NETPROTO_LOCK); + synchronize_net(); ebt_unregister_table(&broute_table); } diff --git a/kernel/linux2.5/net/bridge/netfilter/ebtable_filter.c b/kernel/linux2.5/net/bridge/netfilter/ebtable_filter.c index ba6de32..ce60c4e 100644 --- a/kernel/linux2.5/net/bridge/netfilter/ebtable_filter.c +++ b/kernel/linux2.5/net/bridge/netfilter/ebtable_filter.c @@ -18,16 +18,16 @@ static struct ebt_entries initial_chains[] = { { .name = "INPUT", - .policy = EBT_ACCEPT + .policy = EBT_ACCEPT, }, { .name = "FORWARD", - .policy = EBT_ACCEPT + .policy = EBT_ACCEPT, }, { .name = "OUTPUT", - .policy = EBT_ACCEPT - } + .policy = EBT_ACCEPT, + }, }; static struct ebt_replace initial_table = @@ -40,7 +40,7 @@ static struct ebt_replace initial_table = [NF_BR_FORWARD] = &initial_chains[1], [NF_BR_LOCAL_OUT] = &initial_chains[2], }, - .entries = (char *)initial_chains + .entries = (char *)initial_chains, }; static int check(const struct ebt_table_info *info, unsigned int valid_hooks) @@ -56,7 +56,8 @@ static struct ebt_table frame_filter = .table = &initial_table, .valid_hooks = FILTER_VALID_HOOKS, .lock = RW_LOCK_UNLOCKED, - .check = check + .check = check, + .me = THIS_MODULE, }; static unsigned int @@ -77,14 +78,14 @@ static struct nf_hook_ops ebt_ops_filter[] = { .hook = ebt_hook, .pf = PF_BRIDGE, .hooknum = NF_BR_FORWARD, - .priority = NF_BR_PRI_FILTER_BRIDGED + .priority = NF_BR_PRI_FILTER_BRIDGED, }, { .hook = ebt_hook, .pf = PF_BRIDGE, .hooknum = NF_BR_LOCAL_OUT, - .priority = NF_BR_PRI_FILTER_OTHER - } + .priority = NF_BR_PRI_FILTER_OTHER, + }, }; static int __init init(void) diff --git a/kernel/linux2.5/net/bridge/netfilter/ebtable_nat.c b/kernel/linux2.5/net/bridge/netfilter/ebtable_nat.c index 184d802..8dcf545 100644 --- a/kernel/linux2.5/net/bridge/netfilter/ebtable_nat.c +++ b/kernel/linux2.5/net/bridge/netfilter/ebtable_nat.c @@ -17,15 +17,15 @@ static struct ebt_entries initial_chains[] = { { .name = "PREROUTING", - .policy = EBT_ACCEPT + .policy = EBT_ACCEPT, }, { .name = "OUTPUT", - .policy = EBT_ACCEPT + .policy = EBT_ACCEPT, }, { .name = "POSTROUTING", - .policy = EBT_ACCEPT + .policy = EBT_ACCEPT, } }; @@ -37,9 +37,9 @@ static struct ebt_replace initial_table = .hook_entry = { [NF_BR_PRE_ROUTING] = &initial_chains[0], [NF_BR_LOCAL_OUT] = &initial_chains[1], - [NF_BR_POST_ROUTING] = &initial_chains[2] + [NF_BR_POST_ROUTING] = &initial_chains[2], }, - .entries = (char *)initial_chains + .entries = (char *)initial_chains, }; static int check(const struct ebt_table_info *info, unsigned int valid_hooks) @@ -55,7 +55,8 @@ static struct ebt_table frame_nat = .table = &initial_table, .valid_hooks = NAT_VALID_HOOKS, .lock = RW_LOCK_UNLOCKED, - .check = check + .check = check, + .me = THIS_MODULE, }; static unsigned int @@ -77,20 +78,20 @@ static struct nf_hook_ops ebt_ops_nat[] = { .hook = ebt_nat_dst, .pf = PF_BRIDGE, .hooknum = NF_BR_LOCAL_OUT, - .priority = NF_BR_PRI_NAT_DST_OTHER + .priority = NF_BR_PRI_NAT_DST_OTHER, }, { .hook = ebt_nat_src, .pf = PF_BRIDGE, .hooknum = NF_BR_POST_ROUTING, - .priority = NF_BR_PRI_NAT_SRC + .priority = NF_BR_PRI_NAT_SRC, }, { .hook = ebt_nat_dst, .pf = PF_BRIDGE, .hooknum = NF_BR_PRE_ROUTING, - .priority = NF_BR_PRI_NAT_DST_BRIDGED - } + .priority = NF_BR_PRI_NAT_DST_BRIDGED, + }, }; static int __init init(void) diff --git a/kernel/linux2.5/net/bridge/netfilter/ebtables.c b/kernel/linux2.5/net/bridge/netfilter/ebtables.c index e297900..8729898 100644 --- a/kernel/linux2.5/net/bridge/netfilter/ebtables.c +++ b/kernel/linux2.5/net/bridge/netfilter/ebtables.c @@ -175,6 +175,10 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb, char *base; struct ebt_table_info *private = table->private; + /* FIXME: Push down to extensions --RR */ + if (skb_is_nonlinear(*pskb) && skb_linearize(*pskb, GFP_ATOMIC) != 0) + return NF_DROP; + read_lock_bh(&table->lock); cb_base = COUNTER_BASE(private->counters, private->nentries, smp_processor_id()); @@ -969,8 +973,10 @@ static int do_replace(void *user, unsigned int len) goto free_counterstmp; t = find_table_lock(tmp.name, &ret, &ebt_mutex); - if (!t) + if (!t) { + ret = -ENOENT; goto free_iterate; + } /* the table doesn't like it */ if (t->check && (ret = t->check(newinfo, tmp.valid_hooks))) @@ -984,6 +990,12 @@ static int do_replace(void *user, unsigned int len) /* we have the mutex lock, so no danger in reading this pointer */ table = t->private; + /* make sure the table can only be rmmod'ed if it contains no rules */ + if (!table->nentries && newinfo->nentries && !try_module_get(t->me)) { + ret = -ENOENT; + goto free_unlock; + } else if (table->nentries && !newinfo->nentries) + module_put(t->me); /* we need an atomic snapshot of the counters */ write_lock_bh(&t->lock); if (tmp.num_counters) @@ -1168,6 +1180,11 @@ int ebt_register_table(struct ebt_table *table) goto free_unlock; } + /* Hold a reference count if the chains aren't empty */ + if (newinfo->nentries && !try_module_get(table->me)) { + ret = -ENOENT; + goto free_unlock; + } list_prepend(&ebt_tables, table); up(&ebt_mutex); return 0; @@ -1196,8 +1213,6 @@ void ebt_unregister_table(struct ebt_table *table) down(&ebt_mutex); LIST_DELETE(&ebt_tables, table); up(&ebt_mutex); - EBT_ENTRY_ITERATE(table->private->entries, - table->private->entries_size, ebt_cleanup_entry, NULL); if (table->private->entries) vfree(table->private->entries); if (table->private->chainstack) { -- cgit v1.2.3