Merge branch 'TEE' into TEE6

This commit is contained in:
Jan Engelhardt
2009-01-10 10:01:31 +01:00
11 changed files with 309 additions and 50 deletions

View File

@@ -1,5 +1,6 @@
# -*- Makefile -*- # -*- Makefile -*-
ACLOCAL_AMFLAGS = -I m4
AUTOMAKE_OPTIONS = foreign subdir-objects AUTOMAKE_OPTIONS = foreign subdir-objects
SUBDIRS = extensions SUBDIRS = extensions

View File

@@ -1,8 +1,9 @@
AC_INIT([xtables-addons], [1.6]) AC_INIT([xtables-addons], [1.7])
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
AC_PROG_INSTALL AC_PROG_INSTALL
AM_INIT_AUTOMAKE AM_INIT_AUTOMAKE([-Wall])
AC_PROG_CC AC_PROG_CC
AM_PROG_CC_C_O AM_PROG_CC_C_O
AC_DISABLE_STATIC AC_DISABLE_STATIC
@@ -63,4 +64,5 @@ AC_SUBST([kinclude_CFLAGS])
AC_SUBST([kbuilddir]) AC_SUBST([kbuilddir])
AC_SUBST([ksourcedir]) AC_SUBST([ksourcedir])
AC_SUBST([xtlibdir]) AC_SUBST([xtlibdir])
AC_OUTPUT([Makefile extensions/GNUmakefile extensions/ipset/GNUmakefile]) AC_CONFIG_FILES([Makefile extensions/GNUmakefile extensions/ipset/GNUmakefile])
AC_OUTPUT

View File

@@ -0,0 +1,4 @@
The \fBECHO\fP target will send back all packets it received. It serves as an
examples for an Xtables target.
.PP
ECHO takes no options.

View File

@@ -1,17 +1,19 @@
The SYSRQ target allows to remotely trigger sysrq on the local machine over the The SYSRQ target allows to remotely trigger sysrq on the local machine over the
network. This can be useful when vital parts of the machine hang, for example network. This can be useful when vital parts of the machine hang, for example
an oops in a filesystem causing locks to be not released and processes to get an oops in a filesystem causing locks to be not released and processes to get
stuck as a result -- if still possible, use /proc/sysrq-trigger. Even when stuck as a result - if still possible, use /proc/sysrq-trigger. Even when
processes are stuck, interrupts are likely to be still processed, and as such, processes are stuck, interrupts are likely to be still processed, and as such,
sysrq can be triggered through incoming network packets. sysrq can be triggered through incoming network packets.
.PP .PP
This xt_SYSRQ implementation does not use any encryption, so you should change The xt_SYSRQ implementation uses a salted hash and a sequence number to prevent
the SYSRQ password after use unless you have made sure it was transmitted network sniffers from either guessing the password or replaying earlier
securely and no one sniffed the network, e.g. by use of an IPsec tunnel whose requests. The initial sequence number comes from the time of day so you will
endpoint is at the machine where you want to trigger the sysrq. Also, you have a small window of vulnerability should time go backwards at a reboot.
should limit as to who can issue commands using \fB-s\fP and/or \fB-m mac\fP, However, the file /sys/module/xt_SYSREQ/seqno can be used to both query and
and also that the destination is correct using \fB-d\fP (to protect against update the current sequence number. Also, you should limit as to who can issue
potential broadcast packets), noting that it is still short of MAC/IP spoofing: commands using \fB-s\fP and/or \fB-m mac\fP, and also that the destination is
correct using \fB-d\fP (to protect against potential broadcast packets), noting
that it is still short of MAC/IP spoofing:
.IP .IP
-A INPUT -s 10.10.25.1 -m mac --mac-source aa:bb:cc:dd:ee:ff -d 10.10.25.7 -A INPUT -s 10.10.25.1 -m mac --mac-source aa:bb:cc:dd:ee:ff -d 10.10.25.7
-p udp --dport 9 -j SYSRQ -p udp --dport 9 -j SYSRQ
@@ -20,28 +22,59 @@ potential broadcast packets), noting that it is still short of MAC/IP spoofing:
ipsec --proto esp --tunnel-src 10.10.25.1 --tunnel-dst 10.10.25.7 ipsec --proto esp --tunnel-src 10.10.25.1 --tunnel-dst 10.10.25.7
-p udp --dport 9 -j SYSRQ -p udp --dport 9 -j SYSRQ
.PP .PP
You should also limit the rate at which connections can be received to limit
the CPU time taken by illegal requests, for example:
.IP
-A INPUT 0s 10.10.25.1 -m mac --mac-source aa:bb:cc:dd:ee:ff -d 10.10.25.7
-p udp --dport 9 -m limit --limit 5/minute -j SYSRQ
.PP
This extension does not take any options. The \fB-p udp\fP options are This extension does not take any options. The \fB-p udp\fP options are
required. required.
.PP .PP
The SYSRQ password can be changed through The SYSRQ password can be changed through
/sys/module/xt_SYSRQ/parameters/password; note you need to use `echo -n` to /sys/module/xt_SYSRQ/parameters/password, for example:
not add a newline to the password, i.e.
.IP .IP
echo -n "password" >/sys/.../password echo -n "password" >/sys/module/xt_SYSRQ/parameters/password
.PP .PP
Alternatively, the password may be specified at modprobe time, but this is Alternatively, the password may be specified at modprobe time, but this is
insecure as people can possible see it through ps(1). You can use an option insecure as people can possible see it through ps(1). You can use an option
line in /etc/modprobe.d/sysrq if it is properly guarded, that is, only readable line in e.g. /etc/modprobe.d/xt_sysrq if it is properly guarded, that is, only
by root. readable by root.
.IP .IP
options xt_SYSRQ password=cookies options xt_SYSRQ password=cookies
.PP .PP
To trigger SYSRQ from a remote host, just use netcat or socat, specifying the The hash algorithm can also be specified as a module option, for example, to
action (only one) as first character, followed by the password: use SHA-256 instead of the default SHA-1:
.IP .IP
echo -n "scookies" | socat stdin udp-sendto:10.10.25.7:9 options xt_SYSRQ hash=sha256
.IP
echo -n "scookies" | netcat -u 10.10.25.7 9
.PP .PP
See the Linux docs for possible sysrq keys. Important ones are: The xt_SYSRQ module is normally silent unless a successful request is received,
re(b)oot, power(o)ff, (s)ync filesystems, (u)mount and remount readonly. but the \fIdebug\fP module parameter can be used to find exactly why a
seemingly correct request is not being processed.
.PP
To trigger SYSRQ from a remote host, just use netcat or socat:
.PP
.nf
sysrq_key="s" # the SysRq key(s)
password="password"
seqno="$(date +%s)"
salt="$(dd bs=12 count=1 if=/dev/urandom 2>/dev/null |
openssl enc -base64)"
req="$sysrq_key,$seqno,$salt"
req="$req,$(echo -n "$req,$password" | sha1sum | cut -c1-40)"
echo "$req" | socat stdin udp-sendto:10.10.25.7:9
# or
echo "$req" | netcat -uw1 10.10.25.7 9
.fi
.PP
See the Linux docs for possible sysrq keys. Important ones are: re(b)oot,
power(o)ff, (s)ync filesystems, (u)mount and remount readonly. More than one
sysrq key can be used at once, but bear in mind that, for example, a sync may
not complete before a subsequent reboot or poweroff.
.PP
The hashing scheme should be enough to prevent mis-use of SYSRQ in many
environments, but it is not perfect: take reasonable precautions to
protect your machines. Most importantly ensure that each machine has a
different password; there is scant protection for a SYSRQ packet being
applied to a machine that happens to have the same password.

View File

@@ -83,9 +83,9 @@ static void tee_tg_print(const void *ip, const struct xt_entry_target *target,
const struct xt_tee_tginfo *info = (const void *)target->data; const struct xt_tee_tginfo *info = (const void *)target->data;
if (numeric) if (numeric)
printf("TEE gw:%s ", ipaddr_to_anyname(&info->gw.in));
else
printf("TEE gw:%s ", ipaddr_to_numeric(&info->gw.in)); printf("TEE gw:%s ", ipaddr_to_numeric(&info->gw.in));
else
printf("TEE gw:%s ", ipaddr_to_anyname(&info->gw.in));
} }
static void tee_tg_save(const void *ip, const struct xt_entry_target *target) static void tee_tg_save(const void *ip, const struct xt_entry_target *target)
@@ -98,6 +98,8 @@ static void tee_tg_save(const void *ip, const struct xt_entry_target *target)
static struct xtables_target tee_tg_reg = { static struct xtables_target tee_tg_reg = {
.name = "TEE", .name = "TEE",
.version = XTABLES_VERSION, .version = XTABLES_VERSION,
.revision = 0,
.family = PF_INET,
.size = XT_ALIGN(sizeof(struct xt_tee_tginfo)), .size = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
.userspacesize = XT_ALIGN(sizeof(struct xt_tee_tginfo)), .userspacesize = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
.help = tee_tg_help, .help = tee_tg_help,

8
extensions/libxt_TEE.man Normal file
View File

@@ -0,0 +1,8 @@
The \fBTEE\fP target will clone a packet and redirect this clone to another
machine on the \fBlocal\fP network segment. In other words, the nexthop
must be the target, or you will have to configure the nexthop to forward it
further if so desired.
.TP
\fB--gw\fP \fIipaddr\fP
Send the cloned packet to the host reachable at the given IP address.
Use of 0.0.0.0 (for IPv4 packets) or :: (IPv6) is invalid.

View File

@@ -20,7 +20,11 @@ connection was torn down after completion of the 3-way handshake.
\fB--grscan\fR \fB--grscan\fR
Match if data in the connection only flew in the direction of the remote side, Match if data in the connection only flew in the direction of the remote side,
e.g. if the connection was terminated after a locally running daemon sent its e.g. if the connection was terminated after a locally running daemon sent its
identification. (e.g. openssh) identification. (E.g. openssh, smtp, ftpd.) This may falsely trigger on
warranted single-direction data flows, usually bulk data transfers such as
FTP DATA connections or IRC DCC. Grab Scan Detection should only be used on
ports where a protocol runs that is guaranteed to do a bidirectional exchange
of bytes.
.PP .PP
NOTE: Some clients (Windows XP for example) may do what looks like a SYN scan, NOTE: Some clients (Windows XP for example) may do what looks like a SYN scan,
so be advised to carefully use xt_portscan in conjunction with blocking rules, so be advised to carefully use xt_portscan in conjunction with blocking rules,

View File

@@ -3,7 +3,6 @@
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2008 * Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2008
* *
* Based upon the ipt_SYSRQ idea by Marek Zalem <marek [at] terminus sk> * Based upon the ipt_SYSRQ idea by Marek Zalem <marek [at] terminus sk>
* xt_SYSRQ does not use hashing or timestamps.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@@ -19,15 +18,145 @@
#include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv6/ip6_tables.h> #include <linux/netfilter_ipv6/ip6_tables.h>
#include <linux/netfilter/x_tables.h> #include <linux/netfilter/x_tables.h>
#include <linux/crypto.h>
#include <linux/scatterlist.h>
#include <net/ip.h> #include <net/ip.h>
#include "compat_xtables.h" #include "compat_xtables.h"
static bool sysrq_once; static bool sysrq_once;
static char sysrq_password[64]; static char sysrq_password[64];
static char sysrq_hash[16] = "sha1";
static long sysrq_seqno;
static int sysrq_debug;
module_param_string(password, sysrq_password, sizeof(sysrq_password), module_param_string(password, sysrq_password, sizeof(sysrq_password),
S_IRUSR | S_IWUSR); S_IRUSR | S_IWUSR);
module_param_string(hash, sysrq_hash, sizeof(sysrq_hash), S_IRUSR);
module_param_named(seqno, sysrq_seqno, long, S_IRUSR | S_IWUSR);
module_param_named(debug, sysrq_debug, int, S_IRUSR | S_IWUSR);
MODULE_PARM_DESC(password, "password for remote sysrq"); MODULE_PARM_DESC(password, "password for remote sysrq");
MODULE_PARM_DESC(hash, "hash algorithm, default sha1");
MODULE_PARM_DESC(seqno, "sequence number for remote sysrq");
MODULE_PARM_DESC(debug, "debugging: 0=off, 1=on");
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
static struct crypto_hash *sysrq_tfm;
static int sysrq_digest_size;
static unsigned char *sysrq_digest_password;
static unsigned char *sysrq_digest;
static char *sysrq_hexdigest;
/*
* The data is of the form "<requests>,<seqno>,<salt>,<hash>" where <requests>
* is a series of sysrq requests; <seqno> is a sequence number that must be
* greater than the last sequence number; <salt> is some random bytes; and
* <hash> is the hash of everything up to and including the preceding ","
* together with the password.
*
* For example
*
* salt=$RANDOM
* req="s,$(date +%s),$salt"
* echo "$req,$(echo -n $req,secret | sha1sum | cut -c1-40)"
*
* You will want a better salt and password than that though :-)
*/
static unsigned int sysrq_tg(const void *pdata, uint16_t len)
{
const char *data = pdata;
int i, n;
struct scatterlist sg[2];
struct hash_desc desc;
int ret;
long new_seqno = 0;
if (*sysrq_password == '\0') {
if (!sysrq_once)
printk(KERN_INFO KBUILD_MODNAME ": No password set\n");
sysrq_once = true;
return NF_DROP;
}
if (len == 0)
return NF_DROP;
for (i = 0; sysrq_password[i] != '\0' &&
sysrq_password[i] != '\n'; ++i)
/* loop */;
sysrq_password[i] = '\0';
i = 0;
for (n = 0; n < len - 1; ++n) {
if (i == 1 && '0' <= data[n] && data[n] <= '9')
new_seqno = 10L * new_seqno + data[n] - '0';
if (data[n] == ',' && ++i == 3)
break;
}
++n;
if (i != 3) {
if (sysrq_debug)
printk(KERN_WARNING KBUILD_MODNAME
": badly formatted request\n");
return NF_DROP;
}
if (sysrq_seqno >= new_seqno) {
if (sysrq_debug)
printk(KERN_WARNING KBUILD_MODNAME
": old sequence number ignored\n");
return NF_DROP;
}
desc.tfm = sysrq_tfm;
desc.flags = 0;
ret = crypto_hash_init(&desc);
if (ret != 0)
goto hash_fail;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
sg_init_table(sg, 2);
#endif
sg_set_buf(&sg[0], data, n);
strcpy(sysrq_digest_password, sysrq_password);
i = strlen(sysrq_digest_password);
sg_set_buf(&sg[1], sysrq_digest_password, i);
ret = crypto_hash_digest(&desc, sg, n + i, sysrq_digest);
if (ret != 0)
goto hash_fail;
for (i = 0; i < sysrq_digest_size; ++i) {
sysrq_hexdigest[2*i] =
"0123456789abcdef"[(sysrq_digest[i] >> 4) & 0xf];
sysrq_hexdigest[2*i+1] =
"0123456789abcdef"[sysrq_digest[i] & 0xf];
}
sysrq_hexdigest[2*sysrq_digest_size] = '\0';
if (len - n < sysrq_digest_size) {
if (sysrq_debug)
printk(KERN_INFO KBUILD_MODNAME ": Short digest,"
" expected %s\n", sysrq_hexdigest);
return NF_DROP;
}
if (strncmp(data + n, sysrq_hexdigest, sysrq_digest_size) != 0) {
if (sysrq_debug)
printk(KERN_INFO KBUILD_MODNAME ": Bad digest,"
" expected %s\n", sysrq_hexdigest);
return NF_DROP;
}
/* Now we trust the requester */
sysrq_seqno = new_seqno;
for (i = 0; i < len && data[i] != ','; ++i) {
printk(KERN_INFO KBUILD_MODNAME ": SysRq %c\n", data[i]);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
handle_sysrq(data[i], NULL);
#else
handle_sysrq(data[i], NULL, NULL);
#endif
}
return NF_ACCEPT;
hash_fail:
printk(KERN_WARNING KBUILD_MODNAME ": digest failure\n");
return NF_DROP;
}
#else
static unsigned int sysrq_tg(const void *pdata, uint16_t len) static unsigned int sysrq_tg(const void *pdata, uint16_t len)
{ {
const char *data = pdata; const char *data = pdata;
@@ -57,6 +186,7 @@ static unsigned int sysrq_tg(const void *pdata, uint16_t len)
#endif #endif
return NF_ACCEPT; return NF_ACCEPT;
} }
#endif
static unsigned int static unsigned int
sysrq_tg4(struct sk_buff **pskb, const struct xt_target_param *par) sysrq_tg4(struct sk_buff **pskb, const struct xt_target_param *par)
@@ -73,9 +203,11 @@ sysrq_tg4(struct sk_buff **pskb, const struct xt_target_param *par)
udph = (void *)iph + ip_hdrlen(skb); udph = (void *)iph + ip_hdrlen(skb);
len = ntohs(udph->len) - sizeof(struct udphdr); len = ntohs(udph->len) - sizeof(struct udphdr);
printk(KERN_INFO KBUILD_MODNAME ": " NIPQUAD_FMT ":%u -> :%u len=%u\n", if (sysrq_debug)
NIPQUAD(iph->saddr), htons(udph->source), htons(udph->dest), printk(KERN_INFO KBUILD_MODNAME
len); ": " NIPQUAD_FMT ":%u -> :%u len=%u\n",
NIPQUAD(iph->saddr), htons(udph->source),
htons(udph->dest), len);
return sysrq_tg((void *)udph + sizeof(struct udphdr), len); return sysrq_tg((void *)udph + sizeof(struct udphdr), len);
} }
@@ -94,14 +226,17 @@ sysrq_tg6(struct sk_buff **pskb, const struct xt_target_param *par)
udph = udp_hdr(skb); udph = udp_hdr(skb);
len = ntohs(udph->len) - sizeof(struct udphdr); len = ntohs(udph->len) - sizeof(struct udphdr);
printk(KERN_INFO KBUILD_MODNAME ": " NIP6_FMT ":%hu -> :%hu len=%u\n", if (sysrq_debug)
NIP6(iph->saddr), ntohs(udph->source), printk(KERN_INFO KBUILD_MODNAME
ntohs(udph->dest), len); ": " NIP6_FMT ":%hu -> :%hu len=%u\n",
NIP6(iph->saddr), ntohs(udph->source),
ntohs(udph->dest), len);
return sysrq_tg(udph + sizeof(struct udphdr), len); return sysrq_tg(udph + sizeof(struct udphdr), len);
} }
static bool sysrq_tg_check(const struct xt_tgchk_param *par) static bool sysrq_tg_check(const struct xt_tgchk_param *par)
{ {
if (par->target->family == NFPROTO_IPV4) { if (par->target->family == NFPROTO_IPV4) {
const struct ipt_entry *entry = par->entryinfo; const struct ipt_entry *entry = par->entryinfo;
@@ -146,11 +281,64 @@ static struct xt_target sysrq_tg_reg[] __read_mostly = {
static int __init sysrq_tg_init(void) static int __init sysrq_tg_init(void)
{ {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
struct timeval now;
sysrq_tfm = crypto_alloc_hash(sysrq_hash, 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(sysrq_tfm)) {
printk(KERN_WARNING KBUILD_MODNAME
": Error: Could not find or load %s hash\n",
sysrq_hash);
sysrq_tfm = NULL;
goto fail;
}
sysrq_digest_size = crypto_hash_digestsize(sysrq_tfm);
sysrq_digest = kmalloc(sysrq_digest_size, GFP_KERNEL);
if (sysrq_digest == NULL) {
printk(KERN_WARNING KBUILD_MODNAME
": Cannot allocate digest\n");
goto fail;
}
sysrq_hexdigest = kmalloc(2 * sysrq_digest_size + 1, GFP_KERNEL);
if (sysrq_hexdigest == NULL) {
printk(KERN_WARNING KBUILD_MODNAME
": Cannot allocate hexdigest\n");
goto fail;
}
sysrq_digest_password = kmalloc(sizeof(sysrq_password), GFP_KERNEL);
if (sysrq_digest_password == NULL) {
printk(KERN_WARNING KBUILD_MODNAME
": Cannot allocate password digest space\n");
goto fail;
}
do_gettimeofday(&now);
sysrq_seqno = now.tv_sec;
return xt_register_targets(sysrq_tg_reg, ARRAY_SIZE(sysrq_tg_reg)); return xt_register_targets(sysrq_tg_reg, ARRAY_SIZE(sysrq_tg_reg));
fail:
if (sysrq_tfm)
crypto_free_hash(sysrq_tfm);
if (sysrq_digest)
kfree(sysrq_digest);
if (sysrq_hexdigest)
kfree(sysrq_hexdigest);
if (sysrq_digest_password)
kfree(sysrq_digest_password);
return -EINVAL;
#else
printk(KERN_WARNING "xt_SYSRQ does not provide crypto for <= 2.6.18\n");
return xt_register_targets(sysrq_tg_reg, ARRAY_SIZE(sysrq_tg_reg));
#endif
} }
static void __exit sysrq_tg_exit(void) static void __exit sysrq_tg_exit(void)
{ {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
crypto_free_hash(sysrq_tfm);
kfree(sysrq_digest);
kfree(sysrq_hexdigest);
kfree(sysrq_digest_password);
#endif
return xt_unregister_targets(sysrq_tg_reg, ARRAY_SIZE(sysrq_tg_reg)); return xt_unregister_targets(sysrq_tg_reg, ARRAY_SIZE(sysrq_tg_reg));
} }

View File

@@ -597,27 +597,42 @@ search_all_gnu(const unsigned char *payload, const unsigned int plen)
} }
/* check for KaZaA download commands and other typical data */ /* check for KaZaA download commands and other typical data */
/* plen is guaranteed to be >= 5 (see @matchlist) */
static unsigned int static unsigned int
search_all_kazaa(const unsigned char *payload, const unsigned int plen) search_all_kazaa(const unsigned char *payload, const unsigned int plen)
{ {
if (payload[plen-2] == 0x0d && payload[plen-1] == 0x0a) { uint16_t c, end, rem;
if (memcmp(payload, "GIVE ", 5) == 0)
return IPP2P_KAZAA * 100 + 1;
if (memcmp(payload, "GET /", 5) == 0) { if (plen >= 5) {
uint16_t c = 8; printk(KERN_WARNING KBUILD_MODNAME ": %s: plen (%u) < 5\n",
const uint16_t end = plen - 22; __func__, plen);
return 0;
while (c < end) {
if (payload[c] == 0x0a &&
payload[c+1] == 0x0d &&
(memcmp(&payload[c+2], "X-Kazaa-Username: ", 18) == 0 ||
memcmp(&payload[c+2], "User-Agent: PeerEnabler/", 24) == 0))
return IPP2P_KAZAA * 100 + 2;
c++;
}
}
} }
if (payload[plen-2] != 0x0d || payload[plen-1] != 0x0a)
return 0;
if (memcmp(payload, "GIVE ", 5) == 0)
return IPP2P_KAZAA * 100 + 1;
if (memcmp(payload, "GET /", 5) != 0)
return 0;
end = plen - 18;
rem = plen - 5;
for (c = 5; c < end; ++c, --rem) {
if (payload[c] != 0x0d)
continue;
if (payload[c+1] != 0x0a)
continue;
if (rem >= 18 &&
memcmp(&payload[c+2], "X-Kazaa-Username: ", 18) == 0)
return IPP2P_KAZAA * 100 + 2;
if (rem >= 24 &&
memcmp(&payload[c+2], "User-Agent: PeerEnabler/", 24) == 0)
return IPP2P_KAZAA * 100 + 2;
}
return 0; return 0;
} }

2
m4/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/libtool.m4
/lt*.m4

View File

@@ -1,4 +1,4 @@
.TH xtables\-addons 8 2008\-11\-18 .TH xtables\-addons 8 "v1.7 (2008\-12\-25)" "" "v1.7 (2008\-12\-25)"
.SH NAME .SH NAME
Xtables\-addons - additional extensions for iptables, ip6tables, etc. Xtables\-addons - additional extensions for iptables, ip6tables, etc.
.SH TARGETS .SH TARGETS