Merge branch 'ipv4options'

This commit is contained in:
Jan Engelhardt
2009-03-19 11:03:26 +01:00
8 changed files with 328 additions and 0 deletions

View File

@@ -1,5 +1,8 @@
- added a reworked ipv4options match
Xtables-addons 1.12 (March 07 2009)
===================================
- ipset: fix for compilation with 2.6.29-rt

View File

@@ -19,6 +19,7 @@ obj-${build_fuzzy} += xt_fuzzy.o
obj-${build_geoip} += xt_geoip.o
obj-${build_ipp2p} += xt_ipp2p.o
obj-${build_ipset} += ipset/
obj-${build_ipv4options} += xt_ipv4options.o
obj-${build_length2} += xt_length2.o
obj-${build_lscan} += xt_lscan.o
obj-${build_quota2} += xt_quota2.o

View File

@@ -12,6 +12,7 @@ obj-${build_fuzzy} += libxt_fuzzy.so
obj-${build_geoip} += libxt_geoip.so
obj-${build_ipp2p} += libxt_ipp2p.so
obj-${build_ipset} += ipset/
obj-${build_ipv4options} += libxt_ipv4options.so
obj-${build_length2} += libxt_length2.so
obj-${build_lscan} += libxt_lscan.so
obj-${build_quota2} += libxt_quota2.so

View File

@@ -0,0 +1,177 @@
/*
* "ipv4options" match extension for iptables
* Coprygith © Jan Engelhardt, 2009
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License; either
* version 2 of the License, or any later version, as published by the
* Free Software Foundation.
*/
#include <getopt.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <xtables.h>
#include "xt_ipv4options.h"
/*
* Overview from http://www.networksorcery.com/enp/protocol/ip.htm
* Not providing strings for options that seem to be most distant in the past.
*/
static const char *const v4opt_names[32] = {
[ 1] = "nop",
[ 2] = "security", /* RFC 1108 */
[ 3] = "lsrr", /* RFC 791 */
[ 4] = "timestamp", /* RFC 781, 791 */
[ 7] = "record-route", /* RFC 791 */
[ 9] = "ssrr", /* RFC 791 */
[11] = "mtu-probe", /* RFC 1063 */
[12] = "mtu-reply", /* RFC 1063 */
[18] = "traceroute", /* RFC 1393 */
[20] = "router-alert", /* RFC 2113 */
};
static void ipv4options_mt_help(void)
{
printf(
"ipv4options match options:\n"
"--flags [!]symbol[,...] Match presence/absence (!) of option\n"
" (either by name or number)\n"
"--any Interpret --flags as OR-combined\n\n");
}
static const struct option ipv4options_mt_opts[] = {
{.name = "flags", .has_arg = true, .val = 'f'},
{.name = "any", .has_arg = false, .val = 'a'},
{NULL},
};
static void ipv4options_parse_flagspec(struct xt_ipv4options_mtinfo1 *info,
char *arg)
{
unsigned int i, opt;
bool inv;
char *p;
while (true) {
p = strchr(arg, ',');
if (p != NULL)
*p = '\0';
inv = false;
opt = 0;
if (*arg == '!') {
inv = true;
++arg;
}
for (i = 1; i < 32;++i)
if (v4opt_names[i] != NULL &&
strcmp(v4opt_names[i], arg) == 0) {
opt = i;
break;
}
if (opt == 0 &&
!strtonum(arg, NULL, &opt, 0, UINT8_MAX))
exit_error(PARAMETER_PROBLEM,
"ipv4options: Bad option value \"%s\"", arg);
if (opt == 0)
exit_error(PARAMETER_PROBLEM,
"ipv4options: Option value may not be zero");
info->map |= (1 << opt);
if (inv)
info->invert |= (1 << opt);
if (p == NULL)
break;
arg = p + 1;
}
}
static int ipv4options_mt_parse(int c, char **argv, int invert,
unsigned int *flags, const void *entry, struct xt_entry_match **match)
{
struct xt_ipv4options_mtinfo1 *info = (void *)(*match)->data;
switch (c) {
case 'a': /* --any */
param_act(P_NO_INVERT, "ipv4options", "--any", invert);
info->flags |= XT_V4OPTS_ANY;
return true;
case 'f': /* --flags */
param_act(P_NO_INVERT, "ipv4options", "--flags", invert);
ipv4options_parse_flagspec(info, optarg);
return true;
}
return false;
}
/* no checking of *flags - no IPv4 options is also valid */
static void ipv4options_print_flags(const struct xt_ipv4options_mtinfo1 *info,
bool numeric)
{
uint32_t tmp = info->map;
unsigned int i;
for (i = 1; i < 32; ++i)
if (tmp & (1 << i)) {
if (info->invert & (1 << i))
printf("!");
if (!numeric && v4opt_names[i] != NULL)
printf("%s", v4opt_names[i]);
else
printf("%u", i);
tmp &= ~(1 << i);
if (tmp)
printf(",");
}
}
static void ipv4options_mt_print(const void *ip,
const struct xt_entry_match *match, int numeric)
{
const struct xt_ipv4options_mtinfo1 *info = (void *)match->data;
printf("ipv4options %s ",
(info->flags & XT_V4OPTS_ANY) ? "any-of" : "all-of");
ipv4options_print_flags(info, numeric);
printf(" ");
}
static void ipv4options_mt_save(const void *ip,
const struct xt_entry_match *match)
{
const struct xt_ipv4options_mtinfo1 *info = (void *)match->data;
if (info->map != 0) {
printf("--flags ");
ipv4options_print_flags(info, true);
}
if (info->flags & XT_V4OPTS_ANY)
printf(" --any");
printf(" ");
}
static struct xtables_match ipv4options_mt_reg = {
.version = XTABLES_VERSION,
.name = "ipv4options",
.revision = 1,
.family = PF_INET,
.size = XT_ALIGN(sizeof(struct xt_ipv4options_mtinfo1)),
.userspacesize = XT_ALIGN(sizeof(struct xt_ipv4options_mtinfo1)),
.help = ipv4options_mt_help,
.parse = ipv4options_mt_parse,
.print = ipv4options_mt_print,
.save = ipv4options_mt_save,
.extra_opts = ipv4options_mt_opts,
};
static __attribute__((constructor)) void ipv4options_mt_ldr(void)
{
xtables_register_match(&ipv4options_mt_reg);
}

View File

@@ -0,0 +1,47 @@
The "ipv4options" module allows to match against a set of IPv4 header options.
.TP
\fB\-\-flags\fP [\fB!\fP]\fIsymbol\fP[\fB,\fP[\fB!\fP]\fIsymbol...\fP]
Specify the options that shall appear or not appear in the header. Each
symbol specification is delimited by a comma, and a '!' can be prefixed to
a symbol to negate its presence. Symbols are either the name of an IPv4 option
or its number. See examples below.
.TP
\fB\-\-any\fP
By default, all of the flags specified must be present/absent, that is, they
form an AND condition. Use the \-\-any flag instead to use an OR condition
where only at least one symbol spec must be true.
.PP
Known symbol names (and their number):
.PP
1 - \fBnop\fP
.PP
2 - \fBsecurity\fP - RFC 1108
.PP
3 - \fBlsrr\fP - Loose Source Routing, RFC 791
.PP
4 - \fBtimestamp\fP - RFC 781, 791
.PP
7 - \fBrecord\-route\fP - RFC 791
.PP
9 - \fBssrr\fP - Strict Source Routing, RFC 791
.PP
11 - \fBmtu\-probe\fP - RFC 1063
.PP
12 - \fBmtu\-reply\fP - RFC 1063
.PP
18 - \fBtraceroute\fP - RFC 1393
.PP
20 - \fBrouter-alert\fP - RFC 2113
.PP
Examples:
.PP
Match packets that have both Timestamp and NOP:
\-m ipv4options \-\-flags nop,timestamp
.PP
~ that have either of Timestamp or NOP, or both:
\-\-flags nop,timestamp \-\-any
.PP
~ that have Timestamp and no NOP: \-\-flags '!nop,timestamp'
.PP
~ that have either no NOP or a timestamp (or both conditions):
\-\-flags '!nop,timestamp' \-\-any

View File

@@ -0,0 +1,72 @@
/*
* xt_ipv4opts - Netfilter module to match IPv4 options
* Copyright © Jan Engelhardt, 2009
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License; either
* version 2 of the License, or any later version, as published by the
* Free Software Foundation.
*/
#include <linux/ip.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/netfilter/x_tables.h>
#include <net/ip.h>
#include "xt_ipv4options.h"
#include "compat_xtables.h"
static uint32_t ipv4options_rd(const uint8_t *data, int len)
{
uint32_t opts = 0;
while (len >= 2) {
opts |= 1 << (data[0] & 0x1F);
len -= data[1];
data += data[1];
}
return opts;
}
static bool ipv4options_mt(const struct sk_buff *skb,
const struct xt_match_param *par)
{
const struct xt_ipv4options_mtinfo1 *info = par->matchinfo;
const struct iphdr *iph = ip_hdr(skb);
uint32_t opts = 0;
uint16_t len = ip_hdrlen(skb) - sizeof(struct iphdr);
if (len > 0)
opts = ipv4options_rd((const void *)iph +
sizeof(struct iphdr), len);
opts ^= info->invert;
opts &= info->map;
return (info->flags & XT_V4OPTS_ANY) ? opts : opts == info->map;
}
static struct xt_match ipv4options_mt_reg __read_mostly = {
.name = "ipv4options",
.revision = 1,
.family = NFPROTO_IPV4,
.match = ipv4options_mt,
.matchsize = XT_ALIGN(sizeof(struct xt_ipv4options_mtinfo1)),
.me = THIS_MODULE,
};
static int __init ipv4options_mt_init(void)
{
return xt_register_match(&ipv4options_mt_reg);
}
static void __exit ipv4options_mt_exit(void)
{
xt_unregister_match(&ipv4options_mt_reg);
}
MODULE_DESCRIPTION("Xatblse: IPv4 option match");
MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_ipv4options");
module_init(ipv4options_mt_init);
module_exit(ipv4options_mt_exit);

View File

@@ -0,0 +1,26 @@
#ifndef _LINUX_NETFILTER_XT_IPV4OPTIONS_H
#define _LINUX_NETFILTER_XT_IPV4OPTIONS_H 1
/* IPv4 allows for a 5-bit option number - 32 options */
/**
* %XT_V4OPTS_ALL: all options in @map must be present (respecting @invert)
* %XT_V4OPTS_ANY: any of the option in @map
*/
enum xt_ipv4options_flags {
XT_V4OPTS_ALL = 1 << 0,
XT_V4OPTS_ANY = 1 << 1,
};
/**
* @map: bitmask of options that should appear
* @invert: inversion map
* @flags: see above
*/
struct xt_ipv4options_mtinfo1 {
__u32 map;
__u32 invert;
__u8 flags;
};
#endif /* _LINUX_NETFILTER_XT_IPV4OPTIONS_H */

View File

@@ -14,6 +14,7 @@ build_fuzzy=m
build_geoip=m
build_ipp2p=m
build_ipset=m
build_ipv4options=m
build_length2=m
build_lscan=m
build_quota2=m