+++ /dev/null
-From: Fabrice MARIE <fabrice@netfilter.org>
-From: Harald Welte <laforge@netfilter.org>
-Subject: netfilter ipv4options match from patch-o-matic-ng
-References: bnc#131728 - FATE#182
-
-This is a module which is used to match ipv4 options.
-
-Updated-by: Jeff Mahoney <jeffm@suse.com>
-
-Acked-by: Olaf Kirch <okir@suse.de>
-Acked-by: Jaroslav Kysela <perex@suse.de>
----
-
- include/linux/netfilter_ipv4/ipt_ipv4options.h | 21 +++
- net/ipv4/netfilter/Kconfig | 14 ++
- net/ipv4/netfilter/Makefile | 1
- net/ipv4/netfilter/ipt_ipv4options.c | 175 +++++++++++++++++++++++++
- 4 files changed, 211 insertions(+)
-
---- /dev/null
-+++ b/include/linux/netfilter_ipv4/ipt_ipv4options.h
-@@ -0,0 +1,21 @@
-+#ifndef __ipt_ipv4options_h_included__
-+#define __ipt_ipv4options_h_included__
-+
-+#define IPT_IPV4OPTION_MATCH_SSRR 0x01 /* For strict source routing */
-+#define IPT_IPV4OPTION_MATCH_LSRR 0x02 /* For loose source routing */
-+#define IPT_IPV4OPTION_DONT_MATCH_SRR 0x04 /* any source routing */
-+#define IPT_IPV4OPTION_MATCH_RR 0x08 /* For Record route */
-+#define IPT_IPV4OPTION_DONT_MATCH_RR 0x10
-+#define IPT_IPV4OPTION_MATCH_TIMESTAMP 0x20 /* For timestamp request */
-+#define IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP 0x40
-+#define IPT_IPV4OPTION_MATCH_ROUTER_ALERT 0x80 /* For router-alert */
-+#define IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT 0x100
-+#define IPT_IPV4OPTION_MATCH_ANY_OPT 0x200 /* match packet with any option */
-+#define IPT_IPV4OPTION_DONT_MATCH_ANY_OPT 0x400 /* match packet with no option */
-+
-+struct ipt_ipv4options_info {
-+ u_int16_t options;
-+};
-+
-+
-+#endif /* __ipt_ipv4options_h_included__ */
---- a/net/ipv4/netfilter/Kconfig
-+++ b/net/ipv4/netfilter/Kconfig
-@@ -111,6 +111,20 @@ config IP_NF_MATCH_ADDRTYPE
- If you want to compile it as a module, say M here and read
- <file:Documentation/kbuild/modules.txt>. If unsure, say `N'.
-
-+config IP_NF_MATCH_IPV4OPTIONS
-+ tristate 'IPV4OPTIONS match support'
-+ depends on IP_NF_IPTABLES
-+ help
-+ This option adds a IPV4OPTIONS match.
-+ It allows you to filter options like source routing,
-+ record route, timestamp and router-altert.
-+
-+ If you say Y here, try iptables -m ipv4options --help for more information.
-+
-+ If you want to compile it as a module, say M here and read
-+ Documentation/modules.txt. If unsure, say 'N'.
-+
-+
- # `filter', generic and specific targets
- config IP_NF_FILTER
- tristate "Packet filtering"
---- a/net/ipv4/netfilter/Makefile
-+++ b/net/ipv4/netfilter/Makefile
-@@ -50,6 +50,7 @@ obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o
- obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
- obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
- obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
-+obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
-
- # targets
- obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
---- /dev/null
-+++ b/net/ipv4/netfilter/ipt_ipv4options.c
-@@ -0,0 +1,175 @@
-+/*
-+ This is a module which is used to match ipv4 options.
-+ This file is distributed under the terms of the GNU General Public
-+ License (GPL). Copies of the GPL can be obtained from:
-+ ftp://prep.ai.mit.edu/pub/gnu/GPL
-+
-+ 11-mars-2001 Fabrice MARIE <fabrice@netfilter.org> : initial development.
-+ 12-july-2001 Fabrice MARIE <fabrice@netfilter.org> : added router-alert otions matching. Fixed a bug with no-srr
-+ 12-august-2001 Imran Patel <ipatel@crosswinds.net> : optimization of the match.
-+ 18-november-2001 Fabrice MARIE <fabrice@netfilter.org> : added [!] 'any' option match.
-+ 19-february-2004 Harald Welte <laforge@netfilter.org> : merge with 2.6.x
-+*/
-+
-+#include <linux/module.h>
-+#include <linux/skbuff.h>
-+#include <net/ip.h>
-+
-+#include <linux/netfilter_ipv4/ip_tables.h>
-+#include <linux/netfilter_ipv4/ipt_ipv4options.h>
-+
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
-+
-+static bool
-+match(const struct sk_buff *skb,
-+ const struct net_device *in,
-+ const struct net_device *out,
-+ const struct xt_match *match,
-+ const void *matchinfo,
-+ int offset,
-+ unsigned int protoff,
-+ bool *hotdrop)
-+{
-+ const struct ipt_ipv4options_info *info = matchinfo; /* match info for rule */
-+ const struct iphdr *iph = ip_hdr(skb);
-+ const struct ip_options *opt;
-+
-+ if (iph->ihl * 4 == sizeof(struct iphdr)) {
-+ /* No options, so we match only the "DONTs" and the "IGNOREs" */
-+
-+ if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) ||
-+ ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
-+ ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
-+ ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
-+ ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
-+ ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT))
-+ return 0;
-+ return 1;
-+ }
-+ else {
-+ if ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)
-+ /* there are options, and we don't need to care which one */
-+ return 1;
-+ else {
-+ if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)
-+ /* there are options but we don't want any ! */
-+ return 0;
-+ }
-+ }
-+
-+ opt = &(IPCB(skb)->opt);
-+
-+ /* source routing */
-+ if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) {
-+ if (!((opt->srr) && (opt->is_strictroute)))
-+ return 0;
-+ }
-+ else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) {
-+ if (!((opt->srr) && (!opt->is_strictroute)))
-+ return 0;
-+ }
-+ else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) {
-+ if (opt->srr)
-+ return 0;
-+ }
-+ /* record route */
-+ if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) {
-+ if (!opt->rr)
-+ return 0;
-+ }
-+ else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) {
-+ if (opt->rr)
-+ return 0;
-+ }
-+ /* timestamp */
-+ if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) {
-+ if (!opt->ts)
-+ return 0;
-+ }
-+ else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) {
-+ if (opt->ts)
-+ return 0;
-+ }
-+ /* router-alert option */
-+ if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) {
-+ if (!opt->router_alert)
-+ return 0;
-+ }
-+ else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) {
-+ if (opt->router_alert)
-+ return 0;
-+ }
-+
-+ /* we match ! */
-+ return 1;
-+}
-+
-+static bool
-+checkentry(const char *tablename,
-+ const void *ip,
-+ const struct xt_match *match,
-+ void *matchinfo,
-+ unsigned int hook_mask)
-+{
-+ const struct ipt_ipv4options_info *info = matchinfo; /* match info for rule */
-+ /* Check the size */
-+ if (match->matchsize != IPT_ALIGN(sizeof(struct ipt_ipv4options_info)))
-+ return 0;
-+ /* Now check the coherence of the data ... */
-+ if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) &&
-+ (((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) ||
-+ ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) ||
-+ ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) ||
-+ ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) ||
-+ ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)))
-+ return 0; /* opposites */
-+ if (((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) &&
-+ (((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
-+ ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
-+ ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
-+ ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
-+ ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) ||
-+ ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)))
-+ return 0; /* opposites */
-+ if (((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) &&
-+ ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR))
-+ return 0; /* cannot match in the same time loose and strict source routing */
-+ if ((((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
-+ ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR)) &&
-+ ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR))
-+ return 0; /* opposites */
-+ if (((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) &&
-+ ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR))
-+ return 0; /* opposites */
-+ if (((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) &&
-+ ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP))
-+ return 0; /* opposites */
-+ if (((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) &&
-+ ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))
-+ return 0; /* opposites */
-+
-+ /* everything looks ok. */
-+ return 1;
-+}
-+
-+static struct xt_match ipv4options_match = {
-+ .name = "ipv4options",
-+ .match = match,
-+ .matchsize = sizeof(struct ipt_ipv4options_info),
-+ .checkentry = checkentry,
-+ .me = THIS_MODULE
-+};
-+
-+static int __init init(void)
-+{
-+ return xt_register_match(&ipv4options_match);
-+}
-+
-+static void __exit fini(void)
-+{
-+ xt_unregister_match(&ipv4options_match);
-+}
-+
-+module_init(init);
-+module_exit(fini);