Mod aaa-12 添加iptable1.6.0,支持imq
RCA: SOL: 修改人:huangxin 检视人:huangxin
This commit is contained in:
parent
3121ffeecb
commit
7609ba4215
libs/src/iptables-1.6.0
.gitignoreCOMMIT_NOTESCOPYINGINCOMPATIBILITIESINSTALLMakefile.amautogen.shconfigure.ac
etc
extensions
.gitignoreGNUmakefile.indscp_helper.clibarpt_mangle.clibebt_802_3.clibebt_ip.clibebt_limit.clibebt_log.clibebt_mark.clibebt_mark_m.clibebt_nflog.clibip6t_DNAT.clibip6t_DNPT.clibip6t_DNPT.manlibip6t_HL.clibip6t_HL.manlibip6t_LOG.clibip6t_MASQUERADE.clibip6t_NETMAP.clibip6t_REDIRECT.clibip6t_REJECT.clibip6t_REJECT.manlibip6t_SNAT.clibip6t_SNPT.clibip6t_SNPT.manlibip6t_ah.clibip6t_ah.manlibip6t_dst.clibip6t_dst.manlibip6t_eui64.clibip6t_eui64.manlibip6t_frag.clibip6t_frag.manlibip6t_hbh.clibip6t_hbh.manlibip6t_hl.clibip6t_hl.manlibip6t_icmp6.clibip6t_icmp6.manlibip6t_ipv6header.clibip6t_ipv6header.manlibip6t_mh.clibip6t_mh.manlibip6t_rt.clibip6t_rt.manlibipt_CLUSTERIP.clibipt_CLUSTERIP.manlibipt_DNAT.clibipt_ECN.clibipt_ECN.manlibipt_LOG.clibipt_MASQUERADE.clibipt_NETMAP.clibipt_REDIRECT.clibipt_REJECT.clibipt_REJECT.manlibipt_SNAT.clibipt_TTL.clibipt_TTL.manlibipt_ULOG.clibipt_ULOG.manlibipt_ah.clibipt_ah.manlibipt_icmp.clibipt_icmp.manlibipt_realm.clibipt_realm.manlibipt_ttl.clibipt_ttl.manlibxt_AUDIT.clibxt_AUDIT.manlibxt_CHECKSUM.clibxt_CHECKSUM.manlibxt_CLASSIFY.clibxt_CLASSIFY.manlibxt_CONNMARK.clibxt_CONNMARK.manlibxt_CONNSECMARK.clibxt_CONNSECMARK.manlibxt_CT.clibxt_CT.manlibxt_DNAT.manlibxt_DSCP.clibxt_DSCP.manlibxt_HMARK.clibxt_HMARK.manlibxt_IDLETIMER.clibxt_IDLETIMER.manlibxt_IMQ.clibxt_IMQ.man
|
@ -0,0 +1,21 @@
|
|||
*.a
|
||||
*.la
|
||||
*.lo
|
||||
*.so
|
||||
*.o
|
||||
.deps/
|
||||
.dirstamp
|
||||
.libs/
|
||||
Makefile
|
||||
Makefile.in
|
||||
|
||||
/include/xtables-version.h
|
||||
/include/iptables/internal.h
|
||||
|
||||
/aclocal.m4
|
||||
/autom4te.cache/
|
||||
/build-aux/
|
||||
/config.*
|
||||
/configure
|
||||
/libtool
|
||||
/stamp-h1
|
|
@ -0,0 +1,19 @@
|
|||
A quick list of rules for committing stuff into netfilter git:
|
||||
|
||||
- Always add an appropriate description, in git format
|
||||
(i.e. first line is a summary)
|
||||
|
||||
- Please try to include references to bugs when the description does not
|
||||
include total discussion coverage or when the bug report is external to
|
||||
netfilter-devel, e.g.
|
||||
"Closes: netfilter bugzilla #123", or
|
||||
"Reference: http://bugs.{debian,gentoo}.org/..."
|
||||
|
||||
- If you touch any parts of libxtables (xtables.c, include/xtables.h.in),
|
||||
make sure the so-version is updated _appropriately_ (i.e. read the
|
||||
libtool manual about Versioning:: first, if need be) in configure.ac.
|
||||
Adding fields to a struct always entails a vcurrent bump.
|
||||
|
||||
- Check, whether a bump (vcurrent,vage) has already been made since the
|
||||
last release (no more than one per release), e.g.:
|
||||
git log v1.4.4.. configure.ac
|
|
@ -0,0 +1,339 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
|
@ -0,0 +1,14 @@
|
|||
INCOMPATIBILITIES:
|
||||
|
||||
- The REJECT target has an '--reject-with admin-prohib' option which used
|
||||
with kernels that do not support it, will result in a plain DROP instead
|
||||
of REJECT. Use with caution.
|
||||
Kernels that do support it:
|
||||
2.4 - since 2.4.22-pre9
|
||||
2.6 - all
|
||||
|
||||
- There are some issues related to upgrading from 1.2.x to 1.3.x on a system
|
||||
with dynamic ruleset changes during runtime. (Please see
|
||||
https://bugzilla.netfilter.org/bugzilla/show_bug.cgi?id=334).
|
||||
After upgrading from 1.2 to 1.3, it suggest go do an iptables-save, then
|
||||
iptables-restore to ensure your dynamic rule changes continue to work.
|
|
@ -0,0 +1,101 @@
|
|||
Installation instructions for iptables
|
||||
======================================
|
||||
|
||||
iptables uses the well-known configure(autotools) infrastructure.
|
||||
|
||||
$ ./configure
|
||||
$ make
|
||||
# make install
|
||||
|
||||
|
||||
Prerequisites
|
||||
=============
|
||||
|
||||
* no kernel-source required
|
||||
|
||||
* but obviously a compiler, glibc-devel and linux-kernel-headers
|
||||
(/usr/include/linux)
|
||||
|
||||
|
||||
Configuring and compiling
|
||||
=========================
|
||||
|
||||
./configure [options]
|
||||
|
||||
--prefix=
|
||||
|
||||
The prefix to put all installed files under. It defaults to
|
||||
/usr/local, so the binaries will go into /usr/local/bin, sbin,
|
||||
manpages into /usr/local/share/man, etc.
|
||||
|
||||
--with-xtlibdir=
|
||||
|
||||
The path to where Xtables extensions should be installed to. It
|
||||
defaults to ${libdir}/xtables.
|
||||
|
||||
--enable-devel (or --disable-devel)
|
||||
|
||||
This option causes development files to be installed to
|
||||
${includedir}, which is needed for building additional packages,
|
||||
such as Xtables-addons or other 3rd-party extensions.
|
||||
|
||||
It is enabled by default.
|
||||
|
||||
--enable-static
|
||||
|
||||
Produce additional binaries, iptables-static/ip6tables-static,
|
||||
which have all shipped extensions compiled in.
|
||||
|
||||
--disable-shared
|
||||
|
||||
Produce binaries that have dynamic loading of extensions disabled.
|
||||
This implies --enable-static.
|
||||
(See some details below.)
|
||||
|
||||
--enable-libipq
|
||||
|
||||
This option causes libipq to be installed into ${libdir} and
|
||||
${includedir}.
|
||||
|
||||
--with-ksource=
|
||||
|
||||
Xtables does not depend on kernel headers anymore, but you can
|
||||
optionally specify a search path to include anyway. This is
|
||||
probably only useful for development.
|
||||
|
||||
If you want to enable debugging, use
|
||||
|
||||
./configure CFLAGS="-ggdb3 -O0"
|
||||
|
||||
(-O0 is used to turn off instruction reordering, which makes debugging
|
||||
much easier.)
|
||||
|
||||
To show debug traces you can add -DDEBUG to CFLAGS option
|
||||
|
||||
|
||||
Other notes
|
||||
===========
|
||||
|
||||
The make process will automatically build multipurpose binaries.
|
||||
These have the core (iptables), -save, -restore and -xml code
|
||||
compiled into one binary, but extensions remain as modules.
|
||||
|
||||
|
||||
Static and shared
|
||||
=================
|
||||
|
||||
Basically there are three configuration modes defined:
|
||||
|
||||
--disable-static --enable-shared (this is the default)
|
||||
|
||||
Build a binary that relies upon dynamic loading of extensions.
|
||||
|
||||
--enable-static --enable-shared
|
||||
|
||||
Build a binary that has the shipped extensions built-in, but
|
||||
is still capable of loading additional extensions.
|
||||
|
||||
--enable-static --disable-shared
|
||||
|
||||
Shipped extensions are built-in, and dynamic loading is
|
||||
deactivated.
|
|
@ -0,0 +1,33 @@
|
|||
# -*- Makefile -*-
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
AUTOMAKE_OPTIONS = foreign subdir-objects
|
||||
|
||||
SUBDIRS = libiptc libxtables
|
||||
if ENABLE_DEVEL
|
||||
SUBDIRS += include
|
||||
endif
|
||||
if ENABLE_LIBIPQ
|
||||
SUBDIRS += libipq
|
||||
endif
|
||||
SUBDIRS += utils
|
||||
# Depends on libxtables:
|
||||
SUBDIRS += extensions
|
||||
# Depends on extensions/libext.a:
|
||||
SUBDIRS += iptables
|
||||
|
||||
if ENABLE_NFTABLES
|
||||
confdir = $(sysconfdir)
|
||||
dist_conf_DATA = etc/ethertypes
|
||||
endif
|
||||
|
||||
.PHONY: tarball
|
||||
tarball:
|
||||
rm -Rf /tmp/${PACKAGE_TARNAME}-${PACKAGE_VERSION};
|
||||
pushd ${top_srcdir} && git archive --prefix=${PACKAGE_TARNAME}-${PACKAGE_VERSION}/ HEAD | tar -C /tmp -x && popd;
|
||||
pushd /tmp/${PACKAGE_TARNAME}-${PACKAGE_VERSION} && ./autogen.sh && popd;
|
||||
tar --exclude=*.t --exclude=iptables-test.py -C /tmp -cjf ${PACKAGE_TARNAME}-${PACKAGE_VERSION}.tar.bz2 --owner=root --group=root ${PACKAGE_TARNAME}-${PACKAGE_VERSION}/;
|
||||
rm -Rf /tmp/${PACKAGE_TARNAME}-${PACKAGE_VERSION};
|
||||
|
||||
config.status: extensions/GNUmakefile.in \
|
||||
include/xtables-version.h.in include/iptables/internal.h.in
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
autoreconf -fi;
|
||||
rm -Rf autom4te*.cache;
|
|
@ -0,0 +1,265 @@
|
|||
|
||||
AC_INIT([iptables], [1.6.0])
|
||||
|
||||
# See libtool.info "Libtool's versioning system"
|
||||
libxtables_vcurrent=11
|
||||
libxtables_vage=0
|
||||
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_PROG_INSTALL
|
||||
AM_INIT_AUTOMAKE([-Wall])
|
||||
AC_PROG_CC
|
||||
AM_PROG_CC_C_O
|
||||
AC_DISABLE_STATIC
|
||||
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
|
||||
AM_PROG_LIBTOOL
|
||||
|
||||
AC_ARG_WITH([kernel],
|
||||
AS_HELP_STRING([--with-kernel=PATH],
|
||||
[Path to kernel source/build directory]),
|
||||
[kbuilddir="$withval"; ksourcedir="$withval";])
|
||||
AC_ARG_WITH([kbuild],
|
||||
AS_HELP_STRING([--with-kbuild=PATH],
|
||||
[Path to kernel build directory [[/lib/modules/CURRENT/build]]]),
|
||||
[kbuilddir="$withval"])
|
||||
AC_ARG_WITH([ksource],
|
||||
AS_HELP_STRING([--with-ksource=PATH],
|
||||
[Path to kernel source directory [[/lib/modules/CURRENT/source]]]),
|
||||
[ksourcedir="$withval"])
|
||||
AC_ARG_WITH([xtlibdir],
|
||||
AS_HELP_STRING([--with-xtlibdir=PATH],
|
||||
[Path where to install Xtables extensions [[LIBEXECDIR/xtables]]]),
|
||||
[xtlibdir="$withval"],
|
||||
[xtlibdir="${libdir}/xtables"])
|
||||
AC_ARG_ENABLE([ipv4],
|
||||
AS_HELP_STRING([--disable-ipv4], [Do not build iptables]),
|
||||
[enable_ipv4="$enableval"], [enable_ipv4="yes"])
|
||||
AC_ARG_ENABLE([ipv6],
|
||||
AS_HELP_STRING([--disable-ipv6], [Do not build ip6tables]),
|
||||
[enable_ipv6="$enableval"], [enable_ipv6="yes"])
|
||||
AC_ARG_ENABLE([largefile],
|
||||
AS_HELP_STRING([--disable-largefile], [Do not build largefile support]),
|
||||
[enable_largefile="$enableval"],
|
||||
[enable_largefile="yes";
|
||||
largefile_cppflags='-D_LARGEFILE_SOURCE=1 -D_LARGE_FILES -D_FILE_OFFSET_BITS=64'])
|
||||
AC_ARG_ENABLE([devel],
|
||||
AS_HELP_STRING([--enable-devel],
|
||||
[Install Xtables development headers]),
|
||||
[enable_devel="$enableval"], [enable_devel="yes"])
|
||||
AC_ARG_ENABLE([libipq],
|
||||
AS_HELP_STRING([--enable-libipq], [Build and install libipq]),
|
||||
[enable_libipq="$enableval"], [enable_libipq="no"])
|
||||
AC_ARG_ENABLE([bpf-compiler],
|
||||
AS_HELP_STRING([--enable-bpf-compiler], [Build bpf compiler]),
|
||||
[enable_bpfc="$enableval"], [enable_bpfc="no"])
|
||||
AC_ARG_ENABLE([nfsynproxy],
|
||||
AS_HELP_STRING([--enable-nfsynproxy], [Build SYNPROXY configuration tool]),
|
||||
[enable_nfsynproxy="$enableval"], [enable_nfsynproxy="no"])
|
||||
AC_ARG_WITH([pkgconfigdir], AS_HELP_STRING([--with-pkgconfigdir=PATH],
|
||||
[Path to the pkgconfig directory [[LIBDIR/pkgconfig]]]),
|
||||
[pkgconfigdir="$withval"], [pkgconfigdir='${libdir}/pkgconfig'])
|
||||
AC_ARG_ENABLE([nftables],
|
||||
AS_HELP_STRING([--disable-nftables], [Do not build nftables compat]),
|
||||
[enable_nftables="$enableval"], [enable_nftables="yes"])
|
||||
|
||||
libiptc_LDFLAGS2="";
|
||||
AX_CHECK_LINKER_FLAGS([-Wl,--no-as-needed],
|
||||
[libiptc_LDFLAGS2="-Wl,--no-as-needed"])
|
||||
AC_SUBST([libiptc_LDFLAGS2])
|
||||
|
||||
AC_MSG_CHECKING([whether $LD knows -Wl,--no-undefined])
|
||||
saved_LDFLAGS="$LDFLAGS";
|
||||
LDFLAGS="-Wl,--no-undefined";
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE([int main(void) {}])],
|
||||
[noundef_LDFLAGS="$LDFLAGS"; AC_MSG_RESULT([yes])],
|
||||
[AC_MSG_RESULT([no])]
|
||||
)
|
||||
LDFLAGS="$saved_LDFLAGS";
|
||||
|
||||
blacklist_modules=""
|
||||
blacklist_x_modules=""
|
||||
blacklist_b_modules=""
|
||||
blacklist_a_modules=""
|
||||
blacklist_4_modules=""
|
||||
blacklist_6_modules=""
|
||||
|
||||
AC_CHECK_HEADERS([linux/dccp.h linux/ip_vs.h linux/magic.h linux/proc_fs.h])
|
||||
if test "$ac_cv_header_linux_dccp_h" != "yes"; then
|
||||
blacklist_modules="$blacklist_modules dccp";
|
||||
fi;
|
||||
if test "$ac_cv_header_linux_ip_vs_h" != "yes"; then
|
||||
blacklist_modules="$blacklist_modules ipvs";
|
||||
fi;
|
||||
|
||||
PKG_CHECK_MODULES([libnetfilter_conntrack], [libnetfilter_conntrack >= 1.0.4],
|
||||
[nfconntrack=1], [nfconntrack=0])
|
||||
AM_CONDITIONAL([HAVE_LIBNETFILTER_CONNTRACK], [test "$nfconntrack" = 1])
|
||||
|
||||
if test "$nfconntrack" -ne 1; then
|
||||
blacklist_modules="$blacklist_modules connlabel";
|
||||
echo "WARNING: libnetfilter_conntrack not found, connlabel match will not be built";
|
||||
fi;
|
||||
|
||||
AC_CHECK_SIZEOF([struct ip6_hdr], [], [#include <netinet/ip6.h>])
|
||||
|
||||
AM_CONDITIONAL([ENABLE_STATIC], [test "$enable_static" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_SHARED], [test "$enable_shared" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_IPV4], [test "$enable_ipv4" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_IPV6], [test "$enable_ipv6" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_LARGEFILE], [test "$enable_largefile" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_DEVEL], [test "$enable_devel" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_LIBIPQ], [test "$enable_libipq" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_BPFC], [test "$enable_bpfc" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_SYNCONF], [test "$enable_nfsynproxy" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_NFTABLES], [test "$enable_nftables" = "yes"])
|
||||
|
||||
if test "x$enable_bpfc" = "xyes" || test "x$enable_nfsynproxy" = "xyes"; then
|
||||
AC_CHECK_LIB(pcap, pcap_compile,, AC_MSG_ERROR(missing libpcap library required by bpf compiler or nfsynproxy tool))
|
||||
fi
|
||||
|
||||
PKG_CHECK_MODULES([libnfnetlink], [libnfnetlink >= 1.0],
|
||||
[nfnetlink=1], [nfnetlink=0])
|
||||
AM_CONDITIONAL([HAVE_LIBNFNETLINK], [test "$nfnetlink" = 1])
|
||||
|
||||
if test "x$enable_nftables" = "xyes"; then
|
||||
PKG_CHECK_MODULES([libmnl], [libmnl >= 1.0], [mnl=1], [mnl=0])
|
||||
|
||||
PKG_CHECK_MODULES([libnftnl], [libnftnl >= 1.0.5], [nftables=1], [nftables=0])
|
||||
|
||||
AM_PROG_LEX
|
||||
AC_PROG_YACC
|
||||
|
||||
if test -z "$ac_cv_prog_YACC"
|
||||
then
|
||||
echo "*** Error: No suitable bison/yacc found. ***"
|
||||
echo " Please install the 'bison' package."
|
||||
exit 1
|
||||
fi
|
||||
if test -z "$ac_cv_prog_LEX"
|
||||
then
|
||||
echo "*** Error: No suitable flex/lex found. ***"
|
||||
echo " Please install the 'flex' package."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING(flex version)
|
||||
flex_version=`$ac_cv_prog_LEX --version | sed 's/version//g' | awk '/flex/ {print $2}'`
|
||||
flex_major=`echo $flex_version| cut -d . -f 1`
|
||||
flex_minor=`echo $flex_version| cut -d . -f 2`
|
||||
flex_rev=`echo $flex_version| cut -d . -f 3`
|
||||
|
||||
if test "$flex_major" -eq "2" && test "$flex_minor" -eq "5" && test "$flex_rev" -ge "33"; then
|
||||
AC_MSG_RESULT([$flex_version. OK])
|
||||
else
|
||||
AC_MSG_WARN([flex version $flex_version found.
|
||||
Version 2.5.33 or greater is required. You may experience problems
|
||||
while compilating the nftables compatibility layer for iptables.
|
||||
Please, consider to upgrade flex.])
|
||||
fi
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL([HAVE_LIBMNL], [test "$mnl" = 1])
|
||||
AM_CONDITIONAL([HAVE_LIBNFTNL], [test "$nftables" = 1])
|
||||
|
||||
if test "$nftables" != 1; then
|
||||
blacklist_b_modules="$blacklist_b_modules limit mark nflog mangle"
|
||||
blacklist_a_modules="$blacklist_a_modules mangle"
|
||||
fi
|
||||
|
||||
AC_SUBST([blacklist_modules])
|
||||
AC_SUBST([blacklist_x_modules])
|
||||
AC_SUBST([blacklist_b_modules])
|
||||
AC_SUBST([blacklist_a_modules])
|
||||
AC_SUBST([blacklist_4_modules])
|
||||
AC_SUBST([blacklist_6_modules])
|
||||
|
||||
regular_CFLAGS="-Wall -Waggregate-return -Wmissing-declarations \
|
||||
-Wmissing-prototypes -Wredundant-decls -Wshadow -Wstrict-prototypes \
|
||||
-Winline -pipe";
|
||||
regular_CPPFLAGS="${largefile_cppflags} -D_REENTRANT \
|
||||
-DXTABLES_LIBDIR=\\\"\${xtlibdir}\\\" -DXTABLES_INTERNAL";
|
||||
kinclude_CPPFLAGS="";
|
||||
if [[ -n "$kbuilddir" ]]; then
|
||||
kinclude_CPPFLAGS="$kinclude_CPPFLAGS -I$kbuilddir/include/uapi -I$kbuilddir/include";
|
||||
fi;
|
||||
if [[ -n "$ksourcedir" ]]; then
|
||||
kinclude_CPPFLAGS="$kinclude_CPPFLAGS -I$ksourcedir/include/uapi -I$ksourcedir/include";
|
||||
fi;
|
||||
pkgdatadir='${datadir}/xtables';
|
||||
|
||||
define([EXPAND_VARIABLE],
|
||||
[$2=[$]$1
|
||||
if test $prefix = 'NONE'; then
|
||||
prefix="/usr/local"
|
||||
fi
|
||||
while true; do
|
||||
case "[$]$2" in
|
||||
*\[$]* ) eval "$2=[$]$2" ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
eval "$2=[$]$2"
|
||||
])dnl EXPAND_VARIABLE
|
||||
|
||||
AC_SUBST([regular_CFLAGS])
|
||||
AC_SUBST([regular_CPPFLAGS])
|
||||
AC_SUBST([noundef_LDFLAGS])
|
||||
AC_SUBST([kinclude_CPPFLAGS])
|
||||
AC_SUBST([kbuilddir])
|
||||
AC_SUBST([ksourcedir])
|
||||
AC_SUBST([xtlibdir])
|
||||
AC_SUBST([pkgconfigdir])
|
||||
AC_SUBST([pkgdatadir])
|
||||
AC_SUBST([libxtables_vcurrent])
|
||||
AC_SUBST([libxtables_vage])
|
||||
libxtables_vmajor=$(($libxtables_vcurrent - $libxtables_vage));
|
||||
AC_SUBST([libxtables_vmajor])
|
||||
|
||||
AC_CONFIG_FILES([Makefile extensions/GNUmakefile include/Makefile
|
||||
iptables/Makefile iptables/xtables.pc
|
||||
iptables/iptables.8 iptables/iptables-extensions.8.tmpl
|
||||
iptables/iptables-save.8 iptables/iptables-restore.8
|
||||
iptables/iptables-apply.8 iptables/iptables-xml.1
|
||||
libipq/Makefile libipq/libipq.pc
|
||||
libiptc/Makefile libiptc/libiptc.pc
|
||||
libiptc/libip4tc.pc libiptc/libip6tc.pc
|
||||
libxtables/Makefile utils/Makefile
|
||||
include/xtables-version.h include/iptables/internal.h])
|
||||
AC_OUTPUT
|
||||
|
||||
|
||||
EXPAND_VARIABLE(xtlibdir, e_xtlibdir)
|
||||
EXPAND_VARIABLE(pkgconfigdir, e_pkgconfigdir)
|
||||
|
||||
echo "
|
||||
Iptables Configuration:
|
||||
IPv4 support: ${enable_ipv4}
|
||||
IPv6 support: ${enable_ipv6}
|
||||
Devel support: ${enable_devel}
|
||||
IPQ support: ${enable_libipq}
|
||||
Large file support: ${enable_largefile}
|
||||
BPF utils support: ${enable_bpfc}
|
||||
nfsynproxy util support: ${enable_nfsynproxy}
|
||||
nftables support: ${enable_nftables}
|
||||
|
||||
Build parameters:
|
||||
Put plugins into executable (static): ${enable_static}
|
||||
Support plugins via dlopen (shared): ${enable_shared}
|
||||
Installation prefix (--prefix): ${prefix}
|
||||
Xtables extension directory: ${e_xtlibdir}
|
||||
Pkg-config directory: ${e_pkgconfigdir}"
|
||||
|
||||
if [[ -n "$ksourcedir" ]]; then
|
||||
echo " Kernel source directory: ${ksourcedir}"
|
||||
fi;
|
||||
if [[ -n "$kbuilddir" ]]; then
|
||||
echo " Kernel build directory: ${kbuilddir}"
|
||||
fi;
|
||||
|
||||
echo " Host: ${host}
|
||||
GCC binary: ${CC}"
|
||||
|
||||
test x"$blacklist_modules" = "x" || echo "
|
||||
Iptables modules that will not be built: $blacklist_modules"
|
|
@ -0,0 +1,39 @@
|
|||
#
|
||||
# Ethernet frame types
|
||||
# This file describes some of the various Ethernet
|
||||
# protocol types that are used on Ethernet networks.
|
||||
#
|
||||
# This list could be found on:
|
||||
# http://www.iana.org/assignments/ethernet-numbers
|
||||
# http://www.iana.org/assignments/ieee-802-numbers
|
||||
#
|
||||
# <name> <hexnumber> <alias1>...<alias35> #Comment
|
||||
#
|
||||
IPv4 0800 ip ip4 # Internet IP (IPv4)
|
||||
X25 0805
|
||||
ARP 0806 ether-arp #
|
||||
FR_ARP 0808 # Frame Relay ARP [RFC1701]
|
||||
BPQ 08FF # G8BPQ AX.25 Ethernet Packet
|
||||
DEC 6000 # DEC Assigned proto
|
||||
DNA_DL 6001 # DEC DNA Dump/Load
|
||||
DNA_RC 6002 # DEC DNA Remote Console
|
||||
DNA_RT 6003 # DEC DNA Routing
|
||||
LAT 6004 # DEC LAT
|
||||
DIAG 6005 # DEC Diagnostics
|
||||
CUST 6006 # DEC Customer use
|
||||
SCA 6007 # DEC Systems Comms Arch
|
||||
TEB 6558 # Trans Ether Bridging [RFC1701]
|
||||
RAW_FR 6559 # Raw Frame Relay [RFC1701]
|
||||
RARP 8035 # Reverse ARP [RFC903]
|
||||
AARP 80F3 # Appletalk AARP
|
||||
ATALK 809B # Appletalk
|
||||
802_1Q 8100 8021q 1q 802.1q dot1q # 802.1Q Virtual LAN tagged frame
|
||||
IPX 8137 # Novell IPX
|
||||
NetBEUI 8191 # NetBEUI
|
||||
IPv6 86DD ip6 # IP version 6
|
||||
PPP 880B # PPP
|
||||
ATMMPOA 884C # MultiProtocol over ATM
|
||||
PPP_DISC 8863 # PPPoE discovery messages
|
||||
PPP_SES 8864 # PPPoE session messages
|
||||
ATMFATE 8884 # Frame-based ATM Transport over Ethernet
|
||||
LOOP 9000 loopback # loop proto
|
|
@ -0,0 +1,75 @@
|
|||
family ipv4 {
|
||||
table raw {
|
||||
chain PREROUTING hook NF_INET_PRE_ROUTING prio -300
|
||||
chain OUTPUT hook NF_INET_LOCAL_OUT prio -300
|
||||
}
|
||||
|
||||
table mangle {
|
||||
chain PREROUTING hook NF_INET_PRE_ROUTING prio -150
|
||||
chain INPUT hook NF_INET_LOCAL_IN prio -150
|
||||
chain FORWARD hook NF_INET_FORWARD prio -150
|
||||
chain OUTPUT hook NF_INET_LOCAL_OUT prio -150
|
||||
chain POSTROUTING hook NF_INET_POST_ROUTING prio -150
|
||||
}
|
||||
|
||||
table filter {
|
||||
chain INPUT hook NF_INET_LOCAL_IN prio 0
|
||||
chain FORWARD hook NF_INET_FORWARD prio 0
|
||||
chain OUTPUT hook NF_INET_LOCAL_OUT prio 0
|
||||
}
|
||||
|
||||
table nat {
|
||||
chain PREROUTING hook NF_INET_PRE_ROUTING prio -100
|
||||
chain INPUT hook NF_INET_LOCAL_IN prio -100
|
||||
chain OUTPUT hook NF_INET_LOCAL_OUT prio 100
|
||||
chain POSTROUTING hook NF_INET_POST_ROUTING prio 100
|
||||
}
|
||||
|
||||
table security {
|
||||
chain INPUT hook NF_INET_LOCAL_IN prio 50
|
||||
chain FORWARD hook NF_INET_FORWARD prio 50
|
||||
chain OUTPUT hook NF_INET_LOCAL_OUT prio 50
|
||||
}
|
||||
}
|
||||
|
||||
family ipv6 {
|
||||
table raw {
|
||||
chain PREROUTING hook NF_INET_PRE_ROUTING prio -300
|
||||
chain OUTPUT hook NF_INET_LOCAL_OUT prio -300
|
||||
}
|
||||
|
||||
table mangle {
|
||||
chain PREROUTING hook NF_INET_PRE_ROUTING prio -150
|
||||
chain INPUT hook NF_INET_LOCAL_IN prio -150
|
||||
chain FORWARD hook NF_INET_FORWARD prio -150
|
||||
chain OUTPUT hook NF_INET_LOCAL_OUT prio -150
|
||||
chain POSTROUTING hook NF_INET_POST_ROUTING prio -150
|
||||
}
|
||||
|
||||
table filter {
|
||||
chain INPUT hook NF_INET_LOCAL_IN prio 0
|
||||
chain FORWARD hook NF_INET_FORWARD prio 0
|
||||
chain OUTPUT hook NF_INET_LOCAL_OUT prio 0
|
||||
}
|
||||
|
||||
table nat {
|
||||
chain PREROUTING hook NF_INET_PRE_ROUTING prio -100
|
||||
chain INPUT hook NF_INET_LOCAL_IN prio -100
|
||||
chain OUTPUT hook NF_INET_LOCAL_OUT prio 100
|
||||
chain POSTROUTING hook NF_INET_POST_ROUTING prio 100
|
||||
}
|
||||
|
||||
table security {
|
||||
chain INPUT hook NF_INET_LOCAL_IN prio 50
|
||||
chain FORWARD hook NF_INET_FORWARD prio 50
|
||||
chain OUTPUT hook NF_INET_LOCAL_OUT prio 50
|
||||
}
|
||||
}
|
||||
|
||||
family arp {
|
||||
table filter {
|
||||
chain INPUT hook NF_ARP_IN prio 0
|
||||
chain FORWARD hook NF_ARP_FORWARD prio 0
|
||||
chain OUTPUT hook NF_ARP_OUT prio 0
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
.*.d
|
||||
.*.dd
|
||||
*.oo
|
||||
|
||||
/GNUmakefile
|
||||
/initext.c
|
||||
/initext?.c
|
||||
/matches.man
|
||||
/targets.man
|
|
@ -0,0 +1,286 @@
|
|||
# -*- Makefile -*-
|
||||
|
||||
top_builddir = @top_builddir@
|
||||
builddir = @builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
ksourcedir = @ksourcedir@
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
xtlibdir = @xtlibdir@
|
||||
|
||||
CC = @CC@
|
||||
CCLD = ${CC}
|
||||
CFLAGS = @CFLAGS@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
regular_CFLAGS = @regular_CFLAGS@
|
||||
regular_CPPFLAGS = @regular_CPPFLAGS@
|
||||
kinclude_CPPFLAGS = @kinclude_CPPFLAGS@
|
||||
|
||||
AM_CFLAGS = ${regular_CFLAGS}
|
||||
AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include -I${top_builddir} -I${top_srcdir}/include ${kinclude_CPPFLAGS} ${CPPFLAGS} @libnetfilter_conntrack_CFLAGS@ @libnftnl_CFLAGS@
|
||||
AM_DEPFLAGS = -Wp,-MMD,$(@D)/.$(@F).d,-MT,$@
|
||||
AM_LDFLAGS = @noundef_LDFLAGS@
|
||||
|
||||
ifeq (${V},)
|
||||
AM_LIBTOOL_SILENT = --silent
|
||||
AM_VERBOSE_CC = @echo " CC " $@;
|
||||
AM_VERBOSE_CCLD = @echo " CCLD " $@;
|
||||
AM_VERBOSE_CXX = @echo " CXX " $@;
|
||||
AM_VERBOSE_CXXLD = @echo " CXXLD " $@;
|
||||
AM_VERBOSE_AR = @echo " AR " $@;
|
||||
AM_VERBOSE_GEN = @echo " GEN " $@;
|
||||
endif
|
||||
|
||||
#
|
||||
# Wildcard module list
|
||||
#
|
||||
pfx_build_mod := $(patsubst ${srcdir}/libxt_%.c,%,$(sort $(wildcard ${srcdir}/libxt_*.c)))
|
||||
pfb_build_mod := $(patsubst ${srcdir}/libebt_%.c,%,$(sort $(wildcard ${srcdir}/libebt_*.c)))
|
||||
pfa_build_mod := $(patsubst ${srcdir}/libarpt_%.c,%,$(sort $(wildcard ${srcdir}/libarpt_*.c)))
|
||||
pfx_symlinks := NOTRACK state
|
||||
@ENABLE_IPV4_TRUE@ pf4_build_mod := $(patsubst ${srcdir}/libipt_%.c,%,$(sort $(wildcard ${srcdir}/libipt_*.c)))
|
||||
@ENABLE_IPV6_TRUE@ pf6_build_mod := $(patsubst ${srcdir}/libip6t_%.c,%,$(sort $(wildcard ${srcdir}/libip6t_*.c)))
|
||||
pfx_build_mod := $(filter-out @blacklist_modules@ @blacklist_x_modules@,${pfx_build_mod})
|
||||
pfb_build_mod := $(filter-out @blacklist_modules@ @blacklist_b_modules@,${pfb_build_mod})
|
||||
pfa_build_mod := $(filter-out @blacklist_modules@ @blacklist_a_modules@,${pfa_build_mod})
|
||||
pf4_build_mod := $(filter-out @blacklist_modules@ @blacklist_4_modules@,${pf4_build_mod})
|
||||
pf6_build_mod := $(filter-out @blacklist_modules@ @blacklist_6_modules@,${pf6_build_mod})
|
||||
pfx_objs := $(patsubst %,libxt_%.o,${pfx_build_mod})
|
||||
pfb_objs := $(patsubst %,libebt_%.o,${pfb_build_mod})
|
||||
pfa_objs := $(patsubst %,libarpt_%.o,${pfa_build_mod})
|
||||
pf4_objs := $(patsubst %,libipt_%.o,${pf4_build_mod})
|
||||
pf6_objs := $(patsubst %,libip6t_%.o,${pf6_build_mod})
|
||||
pfx_solibs := $(patsubst %,libxt_%.so,${pfx_build_mod} ${pfx_symlinks})
|
||||
pfb_solibs := $(patsubst %,libebt_%.so,${pfb_build_mod})
|
||||
pfa_solibs := $(patsubst %,libarpt_%.so,${pfa_build_mod})
|
||||
pf4_solibs := $(patsubst %,libipt_%.so,${pf4_build_mod})
|
||||
pf6_solibs := $(patsubst %,libip6t_%.so,${pf6_build_mod})
|
||||
|
||||
|
||||
#
|
||||
# Building blocks
|
||||
#
|
||||
targets := libext.a libext4.a libext6.a libext_ebt.a libext_arpt.a matches.man targets.man
|
||||
targets_install :=
|
||||
@ENABLE_STATIC_TRUE@ libext_objs := ${pfx_objs}
|
||||
@ENABLE_STATIC_TRUE@ libext_ebt_objs := ${pfb_objs}
|
||||
@ENABLE_STATIC_TRUE@ libext_arpt_objs := ${pfa_objs}
|
||||
@ENABLE_STATIC_TRUE@ libext4_objs := ${pf4_objs}
|
||||
@ENABLE_STATIC_TRUE@ libext6_objs := ${pf6_objs}
|
||||
@ENABLE_STATIC_FALSE@ targets += ${pfx_solibs} ${pfb_solibs} ${pf4_solibs} ${pf6_solibs} ${pfa_solibs}
|
||||
@ENABLE_STATIC_FALSE@ targets_install += ${pfx_solibs} ${pfb_solibs} ${pf4_solibs} ${pf6_solibs} ${pfa_solibs}
|
||||
|
||||
.SECONDARY:
|
||||
|
||||
.PHONY: all install clean distclean FORCE
|
||||
|
||||
all: ${targets}
|
||||
|
||||
install: ${targets_install}
|
||||
@mkdir -p "${DESTDIR}${xtlibdir}";
|
||||
if test -n "${targets_install}"; then install -pm0755 $^ "${DESTDIR}${xtlibdir}/"; fi;
|
||||
|
||||
clean:
|
||||
rm -f *.o *.oo *.so *.a {matches,targets}.man initext.c initext4.c initext6.c initextb.c initexta.c;
|
||||
rm -f .*.d .*.dd;
|
||||
|
||||
distclean: clean
|
||||
|
||||
init%.o: init%.c
|
||||
${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=$*_init ${CFLAGS} -o $@ -c $<;
|
||||
|
||||
-include .*.d
|
||||
|
||||
|
||||
#
|
||||
# Shared libraries
|
||||
#
|
||||
lib%.so: lib%.oo
|
||||
${AM_VERBOSE_CCLD} ${CCLD} ${AM_LDFLAGS} -shared ${LDFLAGS} -o $@ $< -L../libxtables/.libs -lxtables ${$*_LIBADD};
|
||||
|
||||
lib%.oo: ${srcdir}/lib%.c
|
||||
${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} -o $@ -c $<;
|
||||
|
||||
libxt_NOTRACK.so: libxt_CT.so
|
||||
ln -fs $< $@
|
||||
libxt_state.so: libxt_conntrack.so
|
||||
ln -fs $< $@
|
||||
|
||||
# Need the LIBADDs in iptables/Makefile.am too for libxtables_la_LIBADD
|
||||
xt_RATEEST_LIBADD = -lm
|
||||
xt_statistic_LIBADD = -lm
|
||||
xt_connlabel_LIBADD = @libnetfilter_conntrack_LIBS@
|
||||
|
||||
#
|
||||
# Static bits
|
||||
#
|
||||
# If static building is disabled, libext*.a will still be generated,
|
||||
# but will be empty. This is good since we can do with less case
|
||||
# handling code in the Makefiles.
|
||||
#
|
||||
lib%.o: ${srcdir}/lib%.c
|
||||
${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -DNO_SHARED_LIBS=1 -D_INIT=lib$*_init ${CFLAGS} -o $@ -c $<;
|
||||
|
||||
libext.a: initext.o ${libext_objs}
|
||||
${AM_VERBOSE_AR} ${AR} crs $@ $^;
|
||||
|
||||
libext_ebt.a: initextb.o ${libext_ebt_objs}
|
||||
${AM_VERBOSE_AR} ${AR} crs $@ $^;
|
||||
|
||||
libext_arpt.a: initexta.o ${libext_arpt_objs}
|
||||
${AM_VERBOSE_AR} ${AR} crs $@ $^;
|
||||
|
||||
libext4.a: initext4.o ${libext4_objs}
|
||||
${AM_VERBOSE_AR} ${AR} crs $@ $^;
|
||||
|
||||
libext6.a: initext6.o ${libext6_objs}
|
||||
${AM_VERBOSE_AR} ${AR} crs $@ $^;
|
||||
|
||||
initext_func := $(addprefix xt_,${pfx_build_mod})
|
||||
initextb_func := $(addprefix ebt_,${pfb_build_mod})
|
||||
initexta_func := $(addprefix arpt_,${pfa_build_mod})
|
||||
initext4_func := $(addprefix ipt_,${pf4_build_mod})
|
||||
initext6_func := $(addprefix ip6t_,${pf6_build_mod})
|
||||
|
||||
.initext.dd: FORCE
|
||||
@echo "${initext_func}" >$@.tmp; \
|
||||
cmp -s $@ $@.tmp || mv $@.tmp $@; \
|
||||
rm -f $@.tmp;
|
||||
|
||||
.initextb.dd: FORCE
|
||||
@echo "${initextb_func}" >$@.tmp; \
|
||||
cmp -s $@ $@.tmp || mv $@.tmp $@; \
|
||||
rm -f $@.tmp;
|
||||
|
||||
.initexta.dd: FORCE
|
||||
@echo "${initexta_func}" >$@.tmp; \
|
||||
cmp -s $@ $@.tmp || mv $@.tmp $@; \
|
||||
rm -f $@.tmp;
|
||||
|
||||
.initext4.dd: FORCE
|
||||
@echo "${initext4_func}" >$@.tmp; \
|
||||
cmp -s $@ $@.tmp || mv $@.tmp $@; \
|
||||
rm -f $@.tmp;
|
||||
|
||||
.initext6.dd: FORCE
|
||||
@echo "${initext6_func}" >$@.tmp; \
|
||||
cmp -s $@ $@.tmp || mv $@.tmp $@; \
|
||||
rm -f $@.tmp;
|
||||
|
||||
initext.c: .initext.dd
|
||||
${AM_VERBOSE_GEN}
|
||||
@( \
|
||||
echo "" >$@; \
|
||||
for i in ${initext_func}; do \
|
||||
echo "extern void lib$${i}_init(void);" >>$@; \
|
||||
done; \
|
||||
echo "void init_extensions(void);" >>$@; \
|
||||
echo "void init_extensions(void)" >>$@; \
|
||||
echo "{" >>$@; \
|
||||
for i in ${initext_func}; do \
|
||||
echo " ""lib$${i}_init();" >>$@; \
|
||||
done; \
|
||||
echo "}" >>$@; \
|
||||
);
|
||||
|
||||
initextb.c: .initextb.dd
|
||||
${AM_VERBOSE_GEN}
|
||||
@( \
|
||||
echo "" >$@; \
|
||||
for i in ${initextb_func}; do \
|
||||
echo "extern void lib$${i}_init(void);" >>$@; \
|
||||
done; \
|
||||
echo "void init_extensionsb(void);" >>$@; \
|
||||
echo "void init_extensionsb(void)" >>$@; \
|
||||
echo "{" >>$@; \
|
||||
for i in ${initextb_func}; do \
|
||||
echo " ""lib$${i}_init();" >>$@; \
|
||||
done; \
|
||||
echo "}" >>$@; \
|
||||
);
|
||||
|
||||
initexta.c: .initexta.dd
|
||||
${AM_VERBOSE_GEN}
|
||||
@( \
|
||||
echo "" >$@; \
|
||||
for i in ${initexta_func}; do \
|
||||
echo "extern void lib$${i}_init(void);" >>$@; \
|
||||
done; \
|
||||
echo "void init_extensionsa(void);" >>$@; \
|
||||
echo "void init_extensionsa(void)" >>$@; \
|
||||
echo "{" >>$@; \
|
||||
for i in ${initexta_func}; do \
|
||||
echo " ""lib$${i}_init();" >>$@; \
|
||||
done; \
|
||||
echo "}" >>$@; \
|
||||
);
|
||||
|
||||
initext4.c: .initext4.dd
|
||||
${AM_VERBOSE_GEN}
|
||||
@( \
|
||||
echo "" >$@; \
|
||||
for i in ${initext4_func}; do \
|
||||
echo "extern void lib$${i}_init(void);" >>$@; \
|
||||
done; \
|
||||
echo "void init_extensions4(void);" >>$@; \
|
||||
echo "void init_extensions4(void)" >>$@; \
|
||||
echo "{" >>$@; \
|
||||
for i in ${initext4_func}; do \
|
||||
echo " ""lib$${i}_init();" >>$@; \
|
||||
done; \
|
||||
echo "}" >>$@; \
|
||||
);
|
||||
|
||||
initext6.c: .initext6.dd
|
||||
${AM_VERBOSE_GEN}
|
||||
@( \
|
||||
echo "" >$@; \
|
||||
for i in ${initext6_func}; do \
|
||||
echo "extern void lib$${i}_init(void);" >>$@; \
|
||||
done; \
|
||||
echo "void init_extensions6(void);" >>$@; \
|
||||
echo "void init_extensions6(void)" >>$@; \
|
||||
echo "{" >>$@; \
|
||||
for i in ${initext6_func}; do \
|
||||
echo " ""lib$${i}_init();" >>$@; \
|
||||
done; \
|
||||
echo "}" >>$@; \
|
||||
);
|
||||
|
||||
#
|
||||
# Manual pages
|
||||
#
|
||||
ex_matches = $(shell echo ${1} | LC_ALL=POSIX grep -Eo '\b[[:lower:][:digit:]_]+\b')
|
||||
ex_targets = $(shell echo ${1} | LC_ALL=POSIX grep -Eo '\b[[:upper:][:digit:]_]+\b')
|
||||
man_run = \
|
||||
${AM_VERBOSE_GEN} \
|
||||
for ext in $(sort ${1}); do \
|
||||
f="${srcdir}/libxt_$$ext.man"; \
|
||||
if [ -f "$$f" ]; then \
|
||||
echo -e "\t+ $$f" >&2; \
|
||||
echo ".SS $$ext"; \
|
||||
cat "$$f" || exit $$?; \
|
||||
fi; \
|
||||
f="${srcdir}/libip6t_$$ext.man"; \
|
||||
if [ -f "$$f" ]; then \
|
||||
echo -e "\t+ $$f" >&2; \
|
||||
echo ".SS $$ext (IPv6-specific)"; \
|
||||
cat "$$f" || exit $$?; \
|
||||
fi; \
|
||||
f="${srcdir}/libipt_$$ext.man"; \
|
||||
if [ -f "$$f" ]; then \
|
||||
echo -e "\t+ $$f" >&2; \
|
||||
echo ".SS $$ext (IPv4-specific)"; \
|
||||
cat "$$f" || exit $$?; \
|
||||
fi; \
|
||||
done >$@;
|
||||
|
||||
matches.man: .initext.dd .initextb.dd .initexta.dd .initext4.dd .initext6.dd $(wildcard ${srcdir}/lib*.man)
|
||||
$(call man_run,$(call ex_matches,${pfx_build_mod} ${pfb_build_mod} ${pfa_build_mod} ${pf4_build_mod} ${pf6_build_mod} ${pfx_symlinks}))
|
||||
|
||||
targets.man: .initext.dd .initextb.dd .initexta.dd .initext4.dd .initext6.dd $(wildcard ${srcdir}/lib*.man)
|
||||
$(call man_run,$(call ex_targets,${pfx_build_mod} ${pfb_build_mod} ${pfa_build_mod} ${pf4_build_mod} ${pf6_build_mod} ${pfx_symlinks}))
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* DiffServ classname <-> DiffServ codepoint mapping functions.
|
||||
*
|
||||
* The latest list of the mappings can be found at:
|
||||
* <http://www.iana.org/assignments/dscp-registry>
|
||||
*
|
||||
* This code is released under the GNU GPL v2, 1991
|
||||
*
|
||||
* Author: Iain Barnes
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <xtables.h>
|
||||
|
||||
|
||||
static const struct ds_class
|
||||
{
|
||||
const char *name;
|
||||
unsigned int dscp;
|
||||
} ds_classes[] =
|
||||
{
|
||||
{ "CS0", 0x00 },
|
||||
{ "CS1", 0x08 },
|
||||
{ "CS2", 0x10 },
|
||||
{ "CS3", 0x18 },
|
||||
{ "CS4", 0x20 },
|
||||
{ "CS5", 0x28 },
|
||||
{ "CS6", 0x30 },
|
||||
{ "CS7", 0x38 },
|
||||
{ "BE", 0x00 },
|
||||
{ "AF11", 0x0a },
|
||||
{ "AF12", 0x0c },
|
||||
{ "AF13", 0x0e },
|
||||
{ "AF21", 0x12 },
|
||||
{ "AF22", 0x14 },
|
||||
{ "AF23", 0x16 },
|
||||
{ "AF31", 0x1a },
|
||||
{ "AF32", 0x1c },
|
||||
{ "AF33", 0x1e },
|
||||
{ "AF41", 0x22 },
|
||||
{ "AF42", 0x24 },
|
||||
{ "AF43", 0x26 },
|
||||
{ "EF", 0x2e }
|
||||
};
|
||||
|
||||
|
||||
|
||||
static unsigned int
|
||||
class_to_dscp(const char *name)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ds_classes); i++) {
|
||||
if (!strncasecmp(name, ds_classes[i].name,
|
||||
strlen(ds_classes[i].name)))
|
||||
return ds_classes[i].dscp;
|
||||
}
|
||||
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Invalid DSCP value `%s'\n", name);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static const char *
|
||||
dscp_to_name(unsigned int dscp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ds_classes); ++i)
|
||||
if (dscp == ds_classes[i].dscp)
|
||||
return ds_classes[i].name;
|
||||
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Invalid DSCP value `%d'\n", dscp);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
* Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com> adapted
|
||||
* this code to libxtables for arptables-compat in 2015
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <getopt.h>
|
||||
#include <netinet/ether.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_arp/arpt_mangle.h>
|
||||
#include "iptables/nft.h"
|
||||
#include "iptables/nft-arp.h"
|
||||
|
||||
static void arpmangle_print_help(void)
|
||||
{
|
||||
printf(
|
||||
"mangle target options:\n"
|
||||
"--mangle-ip-s IP address\n"
|
||||
"--mangle-ip-d IP address\n"
|
||||
"--mangle-mac-s MAC address\n"
|
||||
"--mangle-mac-d MAC address\n"
|
||||
"--mangle-target target (DROP, CONTINUE or ACCEPT -- default is ACCEPT)\n");
|
||||
}
|
||||
|
||||
#define MANGLE_IPS '1'
|
||||
#define MANGLE_IPT '2'
|
||||
#define MANGLE_DEVS '3'
|
||||
#define MANGLE_DEVT '4'
|
||||
#define MANGLE_TARGET '5'
|
||||
|
||||
static struct option arpmangle_opts[] = {
|
||||
{ .name = "mangle-ip-s", .has_arg = true, .val = MANGLE_IPS },
|
||||
{ .name = "mangle-ip-d", .has_arg = true, .val = MANGLE_IPT },
|
||||
{ .name = "mangle-mac-s", .has_arg = true, .val = MANGLE_DEVS },
|
||||
{ .name = "mangle-mac-d", .has_arg = true, .val = MANGLE_DEVT },
|
||||
{ .name = "mangle-target", .has_arg = true, .val = MANGLE_TARGET },
|
||||
XT_GETOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void arpmangle_init(struct xt_entry_target *target)
|
||||
{
|
||||
struct arpt_mangle *mangle = (struct arpt_mangle *)target->data;
|
||||
|
||||
mangle->target = NF_ACCEPT;
|
||||
}
|
||||
|
||||
static int
|
||||
arpmangle_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_target **target)
|
||||
{
|
||||
struct arpt_mangle *mangle = (struct arpt_mangle *)(*target)->data;
|
||||
struct in_addr *ipaddr, mask;
|
||||
struct ether_addr *macaddr;
|
||||
const struct arpt_entry *e = (const struct arpt_entry *)entry;
|
||||
unsigned int nr;
|
||||
int ret = 1;
|
||||
|
||||
memset(&mask, 0, sizeof(mask));
|
||||
|
||||
switch (c) {
|
||||
case MANGLE_IPS:
|
||||
xtables_ipparse_any(optarg, &ipaddr, &mask, &nr);
|
||||
mangle->u_s.src_ip.s_addr = ipaddr->s_addr;
|
||||
free(ipaddr);
|
||||
mangle->flags |= ARPT_MANGLE_SIP;
|
||||
break;
|
||||
case MANGLE_IPT:
|
||||
xtables_ipparse_any(optarg, &ipaddr, &mask, &nr);
|
||||
mangle->u_t.tgt_ip.s_addr = ipaddr->s_addr;
|
||||
free(ipaddr);
|
||||
mangle->flags |= ARPT_MANGLE_TIP;
|
||||
break;
|
||||
case MANGLE_DEVS:
|
||||
if (e->arp.arhln_mask == 0)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"no --h-length defined");
|
||||
if (e->arp.invflags & ARPT_INV_ARPHLN)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"! --h-length not allowed for "
|
||||
"--mangle-mac-s");
|
||||
if (e->arp.arhln != 6)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"only --h-length 6 supported");
|
||||
macaddr = ether_aton(optarg);
|
||||
if (macaddr == NULL)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"invalid source MAC");
|
||||
memcpy(mangle->src_devaddr, macaddr, e->arp.arhln);
|
||||
mangle->flags |= ARPT_MANGLE_SDEV;
|
||||
break;
|
||||
case MANGLE_DEVT:
|
||||
if (e->arp.arhln_mask == 0)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"no --h-length defined");
|
||||
if (e->arp.invflags & ARPT_INV_ARPHLN)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"! hln not allowed for --mangle-mac-d");
|
||||
if (e->arp.arhln != 6)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"only --h-length 6 supported");
|
||||
macaddr = ether_aton(optarg);
|
||||
if (macaddr == NULL)
|
||||
xtables_error(PARAMETER_PROBLEM, "invalid target MAC");
|
||||
memcpy(mangle->tgt_devaddr, macaddr, e->arp.arhln);
|
||||
mangle->flags |= ARPT_MANGLE_TDEV;
|
||||
break;
|
||||
case MANGLE_TARGET:
|
||||
if (!strcmp(optarg, "DROP"))
|
||||
mangle->target = NF_DROP;
|
||||
else if (!strcmp(optarg, "ACCEPT"))
|
||||
mangle->target = NF_ACCEPT;
|
||||
else if (!strcmp(optarg, "CONTINUE"))
|
||||
mangle->target = XT_CONTINUE;
|
||||
else
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"bad target for --mangle-target");
|
||||
break;
|
||||
default:
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void arpmangle_final_check(unsigned int flags)
|
||||
{
|
||||
}
|
||||
|
||||
static void print_mac(const unsigned char *mac, int l)
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = 0; j < l; j++)
|
||||
printf("%02x%s", mac[j],
|
||||
(j==l-1) ? "" : ":");
|
||||
}
|
||||
|
||||
static void
|
||||
arpmangle_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
struct arpt_mangle *m = (struct arpt_mangle *)(target->data);
|
||||
char buf[100];
|
||||
|
||||
if (m->flags & ARPT_MANGLE_SIP) {
|
||||
if (numeric)
|
||||
sprintf(buf, "%s",
|
||||
xtables_ipaddr_to_numeric(&(m->u_s.src_ip)));
|
||||
else
|
||||
sprintf(buf, "%s",
|
||||
xtables_ipaddr_to_anyname(&(m->u_s.src_ip)));
|
||||
printf("--mangle-ip-s %s ", buf);
|
||||
}
|
||||
if (m->flags & ARPT_MANGLE_SDEV) {
|
||||
printf("--mangle-mac-s ");
|
||||
print_mac((unsigned char *)m->src_devaddr, 6);
|
||||
printf(" ");
|
||||
}
|
||||
if (m->flags & ARPT_MANGLE_TIP) {
|
||||
if (numeric)
|
||||
sprintf(buf, "%s",
|
||||
xtables_ipaddr_to_numeric(&(m->u_t.tgt_ip)));
|
||||
else
|
||||
sprintf(buf, "%s",
|
||||
xtables_ipaddr_to_anyname(&(m->u_t.tgt_ip)));
|
||||
printf("--mangle-ip-d %s ", buf);
|
||||
}
|
||||
if (m->flags & ARPT_MANGLE_TDEV) {
|
||||
printf("--mangle-mac-d ");
|
||||
print_mac((unsigned char *)m->tgt_devaddr, 6);
|
||||
printf(" ");
|
||||
}
|
||||
if (m->target != NF_ACCEPT) {
|
||||
printf("--mangle-target ");
|
||||
if (m->target == NF_DROP)
|
||||
printf("DROP ");
|
||||
else
|
||||
printf("CONTINUE ");
|
||||
}
|
||||
}
|
||||
|
||||
static struct xtables_target arpmangle_target = {
|
||||
.name = "mangle",
|
||||
.revision = 0,
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_ARP,
|
||||
.size = XT_ALIGN(sizeof(struct arpt_mangle)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct arpt_mangle)),
|
||||
.help = arpmangle_print_help,
|
||||
.init = arpmangle_init,
|
||||
.parse = arpmangle_parse,
|
||||
.final_check = arpmangle_final_check,
|
||||
.print = arpmangle_print,
|
||||
.extra_opts = arpmangle_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&arpmangle_target);
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
/* 802_3
|
||||
*
|
||||
* Author:
|
||||
* Chris Vitale <csv@bluetail.com>
|
||||
*
|
||||
* May 2003
|
||||
*
|
||||
* Adapted by Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
|
||||
* to use libxtables for ebtables-compat
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_bridge/ebt_802_3.h>
|
||||
|
||||
#define _802_3_SAP '1'
|
||||
#define _802_3_TYPE '2'
|
||||
|
||||
static const struct option br802_3_opts[] = {
|
||||
{ .name = "802_3-sap", .has_arg = true, .val = _802_3_SAP },
|
||||
{ .name = "802_3-type", .has_arg = true, .val = _802_3_TYPE },
|
||||
XT_GETOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void br802_3_print_help(void)
|
||||
{
|
||||
printf(
|
||||
"802_3 options:\n"
|
||||
"--802_3-sap [!] protocol : 802.3 DSAP/SSAP- 1 byte value (hex)\n"
|
||||
" DSAP and SSAP are always the same. One SAP applies to both fields\n"
|
||||
"--802_3-type [!] protocol : 802.3 SNAP Type- 2 byte value (hex)\n"
|
||||
" Type implies SAP value 0xaa\n");
|
||||
}
|
||||
|
||||
static void br802_3_init(struct xt_entry_match *match)
|
||||
{
|
||||
struct ebt_802_3_info *info = (struct ebt_802_3_info *)match->data;
|
||||
|
||||
info->invflags = 0;
|
||||
info->bitmask = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
br802_3_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_match **match)
|
||||
{
|
||||
struct ebt_802_3_info *info = (struct ebt_802_3_info *) (*match)->data;
|
||||
unsigned int i;
|
||||
char *end;
|
||||
|
||||
switch (c) {
|
||||
case _802_3_SAP:
|
||||
if (invert)
|
||||
info->invflags |= EBT_802_3_SAP;
|
||||
i = strtoul(optarg, &end, 16);
|
||||
if (i > 255 || *end != '\0')
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Problem with specified "
|
||||
"sap hex value, %x",i);
|
||||
info->sap = i; /* one byte, so no byte order worries */
|
||||
info->bitmask |= EBT_802_3_SAP;
|
||||
break;
|
||||
case _802_3_TYPE:
|
||||
if (invert)
|
||||
info->invflags |= EBT_802_3_TYPE;
|
||||
i = strtoul(optarg, &end, 16);
|
||||
if (i > 65535 || *end != '\0') {
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Problem with the specified "
|
||||
"type hex value, %x",i);
|
||||
}
|
||||
info->type = htons(i);
|
||||
info->bitmask |= EBT_802_3_TYPE;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
*flags |= info->bitmask;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
br802_3_final_check(unsigned int flags)
|
||||
{
|
||||
if (!flags)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"You must specify proper arguments");
|
||||
}
|
||||
|
||||
static void br802_3_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
struct ebt_802_3_info *info = (struct ebt_802_3_info *)match->data;
|
||||
|
||||
if (info->bitmask & EBT_802_3_SAP) {
|
||||
printf("--802_3-sap ");
|
||||
if (info->invflags & EBT_802_3_SAP)
|
||||
printf("! ");
|
||||
printf("0x%.2x ", info->sap);
|
||||
}
|
||||
if (info->bitmask & EBT_802_3_TYPE) {
|
||||
printf("--802_3-type ");
|
||||
if (info->invflags & EBT_802_3_TYPE)
|
||||
printf("! ");
|
||||
printf("0x%.4x ", ntohs(info->type));
|
||||
}
|
||||
}
|
||||
|
||||
static struct xtables_match br802_3_match =
|
||||
{
|
||||
.name = "802_3",
|
||||
.revision = 0,
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_BRIDGE,
|
||||
.size = XT_ALIGN(sizeof(struct ebt_802_3_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ebt_802_3_info)),
|
||||
.init = br802_3_init,
|
||||
.help = br802_3_print_help,
|
||||
.parse = br802_3_parse,
|
||||
.final_check = br802_3_final_check,
|
||||
.print = br802_3_print,
|
||||
.extra_opts = br802_3_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_match(&br802_3_match);
|
||||
}
|
|
@ -0,0 +1,312 @@
|
|||
/* ebt_ip
|
||||
*
|
||||
* Authors:
|
||||
* Bart De Schuymer <bdschuym@pandora.be>
|
||||
*
|
||||
* Changes:
|
||||
* added ip-sport and ip-dport; parsing of port arguments is
|
||||
* based on code from iptables-1.2.7a
|
||||
* Innominate Security Technologies AG <mhopf@innominate.com>
|
||||
* September, 2002
|
||||
*
|
||||
* Adapted by Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
|
||||
* to use libxtables for ebtables-compat in 2015.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <netdb.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_bridge/ebt_ip.h>
|
||||
|
||||
#define IP_SOURCE '1'
|
||||
#define IP_DEST '2'
|
||||
#define IP_EBT_TOS '3' /* include/bits/in.h seems to already define IP_TOS */
|
||||
#define IP_PROTO '4'
|
||||
#define IP_SPORT '5'
|
||||
#define IP_DPORT '6'
|
||||
|
||||
static const struct option brip_opts[] = {
|
||||
{ .name = "ip-source", .has_arg = true, .val = IP_SOURCE },
|
||||
{ .name = "ip-src", .has_arg = true, .val = IP_SOURCE },
|
||||
{ .name = "ip-destination", .has_arg = true, .val = IP_DEST },
|
||||
{ .name = "ip-dst", .has_arg = true, .val = IP_DEST },
|
||||
{ .name = "ip-tos", .has_arg = true, .val = IP_EBT_TOS },
|
||||
{ .name = "ip-protocol", .has_arg = true, .val = IP_PROTO },
|
||||
{ .name = "ip-proto", .has_arg = true, .val = IP_PROTO },
|
||||
{ .name = "ip-source-port", .has_arg = true, .val = IP_SPORT },
|
||||
{ .name = "ip-sport", .has_arg = true, .val = IP_SPORT },
|
||||
{ .name = "ip-destination-port",.has_arg = true, .val = IP_DPORT },
|
||||
{ .name = "ip-dport", .has_arg = true, .val = IP_DPORT },
|
||||
XT_GETOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void brip_print_help(void)
|
||||
{
|
||||
printf(
|
||||
"ip options:\n"
|
||||
"--ip-src [!] address[/mask]: ip source specification\n"
|
||||
"--ip-dst [!] address[/mask]: ip destination specification\n"
|
||||
"--ip-tos [!] tos : ip tos specification\n"
|
||||
"--ip-proto [!] protocol : ip protocol specification\n"
|
||||
"--ip-sport [!] port[:port] : tcp/udp source port or port range\n"
|
||||
"--ip-dport [!] port[:port] : tcp/udp destination port or port range\n");
|
||||
}
|
||||
|
||||
static void brip_init(struct xt_entry_match *match)
|
||||
{
|
||||
struct ebt_ip_info *info = (struct ebt_ip_info *)match->data;
|
||||
|
||||
info->invflags = 0;
|
||||
info->bitmask = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
parse_port_range(const char *protocol, const char *portstring, uint16_t *ports)
|
||||
{
|
||||
char *buffer;
|
||||
char *cp;
|
||||
|
||||
buffer = strdup(portstring);
|
||||
if ((cp = strchr(buffer, ':')) == NULL)
|
||||
ports[0] = ports[1] = xtables_parse_port(buffer, NULL);
|
||||
else {
|
||||
*cp = '\0';
|
||||
cp++;
|
||||
|
||||
ports[0] = buffer[0] ? xtables_parse_port(buffer, NULL) : 0;
|
||||
ports[1] = cp[0] ? xtables_parse_port(cp, NULL) : 0xFFFF;
|
||||
|
||||
if (ports[0] > ports[1])
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"invalid portrange (min > max)");
|
||||
}
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
/* original code from ebtables: useful_functions.c */
|
||||
static int undot_ip(char *ip, unsigned char *ip2)
|
||||
{
|
||||
char *p, *q, *end;
|
||||
long int onebyte;
|
||||
int i;
|
||||
char buf[20];
|
||||
|
||||
strncpy(buf, ip, sizeof(buf) - 1);
|
||||
|
||||
p = buf;
|
||||
for (i = 0; i < 3; i++) {
|
||||
if ((q = strchr(p, '.')) == NULL)
|
||||
return -1;
|
||||
*q = '\0';
|
||||
onebyte = strtol(p, &end, 10);
|
||||
if (*end != '\0' || onebyte > 255 || onebyte < 0)
|
||||
return -1;
|
||||
ip2[i] = (unsigned char)onebyte;
|
||||
p = q + 1;
|
||||
}
|
||||
|
||||
onebyte = strtol(p, &end, 10);
|
||||
if (*end != '\0' || onebyte > 255 || onebyte < 0)
|
||||
return -1;
|
||||
ip2[3] = (unsigned char)onebyte;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ip_mask(char *mask, unsigned char *mask2)
|
||||
{
|
||||
char *end;
|
||||
long int bits;
|
||||
uint32_t mask22;
|
||||
|
||||
if (undot_ip(mask, mask2)) {
|
||||
/* not the /a.b.c.e format, maybe the /x format */
|
||||
bits = strtol(mask, &end, 10);
|
||||
if (*end != '\0' || bits > 32 || bits < 0)
|
||||
return -1;
|
||||
if (bits != 0) {
|
||||
mask22 = htonl(0xFFFFFFFF << (32 - bits));
|
||||
memcpy(mask2, &mask22, 4);
|
||||
} else {
|
||||
mask22 = 0xFFFFFFFF;
|
||||
memcpy(mask2, &mask22, 4);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ebt_parse_ip_address(char *address, uint32_t *addr, uint32_t *msk)
|
||||
{
|
||||
char *p;
|
||||
|
||||
/* first the mask */
|
||||
if ((p = strrchr(address, '/')) != NULL) {
|
||||
*p = '\0';
|
||||
if (ip_mask(p + 1, (unsigned char *)msk)) {
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Problem with the IP mask '%s'", p + 1);
|
||||
return;
|
||||
}
|
||||
} else
|
||||
*msk = 0xFFFFFFFF;
|
||||
|
||||
if (undot_ip(address, (unsigned char *)addr)) {
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Problem with the IP address '%s'", address);
|
||||
return;
|
||||
}
|
||||
*addr = *addr & *msk;
|
||||
}
|
||||
|
||||
static int
|
||||
brip_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_match **match)
|
||||
{
|
||||
struct ebt_ip_info *info = (struct ebt_ip_info *)(*match)->data;
|
||||
|
||||
switch (c) {
|
||||
case IP_SOURCE:
|
||||
if (invert)
|
||||
info->invflags |= EBT_IP_SOURCE;
|
||||
ebt_parse_ip_address(optarg, &info->saddr, &info->smsk);
|
||||
info->bitmask |= EBT_IP_SOURCE;
|
||||
break;
|
||||
case IP_DEST:
|
||||
if (invert)
|
||||
info->invflags |= EBT_IP_DEST;
|
||||
ebt_parse_ip_address(optarg, &info->daddr, &info->dmsk);
|
||||
info->bitmask |= EBT_IP_DEST;
|
||||
break;
|
||||
case IP_SPORT:
|
||||
if (invert)
|
||||
info->invflags |= EBT_IP_SPORT;
|
||||
parse_port_range(NULL, optarg, info->sport);
|
||||
info->bitmask |= EBT_IP_SPORT;
|
||||
break;
|
||||
case IP_DPORT:
|
||||
if (invert)
|
||||
info->invflags |= EBT_IP_DPORT;
|
||||
parse_port_range(NULL, optarg, info->dport);
|
||||
info->bitmask |= EBT_IP_DPORT;
|
||||
break;
|
||||
case IP_EBT_TOS:
|
||||
if (invert)
|
||||
info->invflags |= EBT_IP_TOS;
|
||||
if (!xtables_strtoul(optarg, NULL, (uintmax_t *)&info->tos,
|
||||
0, 255))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Problem with specified IP tos");
|
||||
info->bitmask |= EBT_IP_TOS;
|
||||
break;
|
||||
case IP_PROTO:
|
||||
if (invert)
|
||||
info->invflags |= EBT_IP_PROTO;
|
||||
info->protocol = xtables_parse_protocol(optarg);
|
||||
if (info->protocol == -1)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Unknown specified IP protocol - %s",
|
||||
optarg);
|
||||
info->bitmask |= EBT_IP_PROTO;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
*flags |= info->bitmask;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void brip_final_check(unsigned int flags)
|
||||
{
|
||||
if (!flags)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"You must specify proper arguments");
|
||||
}
|
||||
|
||||
static void print_port_range(uint16_t *ports)
|
||||
{
|
||||
if (ports[0] == ports[1])
|
||||
printf("%d ", ports[0]);
|
||||
else
|
||||
printf("%d:%d ", ports[0], ports[1]);
|
||||
}
|
||||
|
||||
static void brip_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
struct ebt_ip_info *info = (struct ebt_ip_info *)match->data;
|
||||
struct in_addr *addrp, *maskp;
|
||||
|
||||
if (info->bitmask & EBT_IP_SOURCE) {
|
||||
printf("--ip-src ");
|
||||
if (info->invflags & EBT_IP_SOURCE)
|
||||
printf("! ");
|
||||
addrp = (struct in_addr *)&info->saddr;
|
||||
maskp = (struct in_addr *)&info->smsk;
|
||||
printf("%s%s ", xtables_ipaddr_to_numeric(addrp),
|
||||
xtables_ipmask_to_numeric(maskp));
|
||||
}
|
||||
if (info->bitmask & EBT_IP_DEST) {
|
||||
printf("--ip-dst ");
|
||||
if (info->invflags & EBT_IP_DEST)
|
||||
printf("! ");
|
||||
addrp = (struct in_addr *)&info->daddr;
|
||||
maskp = (struct in_addr *)&info->dmsk;
|
||||
printf("%s%s ", xtables_ipaddr_to_numeric(addrp),
|
||||
xtables_ipmask_to_numeric(maskp));
|
||||
}
|
||||
if (info->bitmask & EBT_IP_TOS) {
|
||||
printf("--ip-tos ");
|
||||
if (info->invflags & EBT_IP_TOS)
|
||||
printf("! ");
|
||||
printf("0x%02X ", info->tos);
|
||||
}
|
||||
if (info->bitmask & EBT_IP_PROTO) {
|
||||
struct protoent *pe;
|
||||
|
||||
printf("--ip-proto ");
|
||||
if (info->invflags & EBT_IP_PROTO)
|
||||
printf("! ");
|
||||
pe = getprotobynumber(info->protocol);
|
||||
if (pe == NULL) {
|
||||
printf("%d ", info->protocol);
|
||||
} else {
|
||||
printf("%s ", pe->p_name);
|
||||
}
|
||||
}
|
||||
if (info->bitmask & EBT_IP_SPORT) {
|
||||
printf("--ip-sport ");
|
||||
if (info->invflags & EBT_IP_SPORT)
|
||||
printf("! ");
|
||||
print_port_range(info->sport);
|
||||
}
|
||||
if (info->bitmask & EBT_IP_DPORT) {
|
||||
printf("--ip-dport ");
|
||||
if (info->invflags & EBT_IP_DPORT)
|
||||
printf("! ");
|
||||
print_port_range(info->dport);
|
||||
}
|
||||
}
|
||||
|
||||
static struct xtables_match brip_match = {
|
||||
.name = "ip",
|
||||
.revision = 0,
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_BRIDGE,
|
||||
.size = XT_ALIGN(sizeof(struct ebt_ip_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ebt_ip_info)),
|
||||
.init = brip_init,
|
||||
.help = brip_print_help,
|
||||
.parse = brip_parse,
|
||||
.final_check = brip_final_check,
|
||||
.print = brip_print,
|
||||
.extra_opts = brip_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_match(&brip_match);
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
/* ebt_limit
|
||||
*
|
||||
* Authors:
|
||||
* Tom Marshall <tommy@home.tig-grr.com>
|
||||
*
|
||||
* Mostly copied from iptables' limit match.
|
||||
*
|
||||
* September, 2003
|
||||
*
|
||||
* Translated to use libxtables for ebtables-compat in 2015 by
|
||||
* Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_bridge/ebt_limit.h>
|
||||
#include "iptables/nft.h"
|
||||
#include "iptables/nft-bridge.h"
|
||||
|
||||
#define EBT_LIMIT_AVG "3/hour"
|
||||
#define EBT_LIMIT_BURST 5
|
||||
|
||||
#define FLAG_LIMIT 0x01
|
||||
#define FLAG_LIMIT_BURST 0x02
|
||||
#define ARG_LIMIT '1'
|
||||
#define ARG_LIMIT_BURST '2'
|
||||
|
||||
static struct option brlimit_opts[] =
|
||||
{
|
||||
{ .name = "limit", .has_arg = true, .val = ARG_LIMIT },
|
||||
{ .name = "limit-burst",.has_arg = true, .val = ARG_LIMIT_BURST },
|
||||
XT_GETOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void brlimit_print_help(void)
|
||||
{
|
||||
printf(
|
||||
"limit options:\n"
|
||||
"--limit avg : max average match rate: default "EBT_LIMIT_AVG"\n"
|
||||
" [Packets per second unless followed by \n"
|
||||
" /sec /minute /hour /day postfixes]\n"
|
||||
"--limit-burst number : number to match in a burst, -1 < number < 10001,\n"
|
||||
" default %u\n", EBT_LIMIT_BURST);
|
||||
}
|
||||
|
||||
static int parse_rate(const char *rate, uint32_t *val)
|
||||
{
|
||||
const char *delim;
|
||||
uint32_t r;
|
||||
uint32_t mult = 1; /* Seconds by default. */
|
||||
|
||||
delim = strchr(rate, '/');
|
||||
if (delim) {
|
||||
if (strlen(delim+1) == 0)
|
||||
return 0;
|
||||
|
||||
if (strncasecmp(delim+1, "second", strlen(delim+1)) == 0)
|
||||
mult = 1;
|
||||
else if (strncasecmp(delim+1, "minute", strlen(delim+1)) == 0)
|
||||
mult = 60;
|
||||
else if (strncasecmp(delim+1, "hour", strlen(delim+1)) == 0)
|
||||
mult = 60*60;
|
||||
else if (strncasecmp(delim+1, "day", strlen(delim+1)) == 0)
|
||||
mult = 24*60*60;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
r = atoi(rate);
|
||||
if (!r)
|
||||
return 0;
|
||||
|
||||
/* This would get mapped to infinite (1/day is minimum they
|
||||
can specify, so we're ok at that end). */
|
||||
if (r / mult > EBT_LIMIT_SCALE)
|
||||
return 0;
|
||||
|
||||
*val = EBT_LIMIT_SCALE * mult / r;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void brlimit_init(struct xt_entry_match *match)
|
||||
{
|
||||
struct ebt_limit_info *r = (struct ebt_limit_info *)match->data;
|
||||
|
||||
parse_rate(EBT_LIMIT_AVG, &r->avg);
|
||||
r->burst = EBT_LIMIT_BURST;
|
||||
}
|
||||
|
||||
static int brlimit_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_match **match)
|
||||
{
|
||||
struct ebt_limit_info *r = (struct ebt_limit_info *)(*match)->data;
|
||||
uintmax_t num;
|
||||
|
||||
switch (c) {
|
||||
case ARG_LIMIT:
|
||||
EBT_CHECK_OPTION(flags, FLAG_LIMIT);
|
||||
if (invert)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Unexpected `!' after --limit");
|
||||
if (!parse_rate(optarg, &r->avg))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"bad rate `%s'", optarg);
|
||||
break;
|
||||
case ARG_LIMIT_BURST:
|
||||
EBT_CHECK_OPTION(flags, FLAG_LIMIT_BURST);
|
||||
if (invert)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Unexpected `!' after --limit-burst");
|
||||
if (!xtables_strtoul(optarg, NULL, &num, 0, 10000))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"bad --limit-burst `%s'", optarg);
|
||||
r->burst = num;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct rates
|
||||
{
|
||||
const char *name;
|
||||
uint32_t mult;
|
||||
};
|
||||
|
||||
static struct rates g_rates[] =
|
||||
{
|
||||
{ "day", EBT_LIMIT_SCALE*24*60*60 },
|
||||
{ "hour", EBT_LIMIT_SCALE*60*60 },
|
||||
{ "min", EBT_LIMIT_SCALE*60 },
|
||||
{ "sec", EBT_LIMIT_SCALE }
|
||||
};
|
||||
|
||||
static void print_rate(uint32_t period)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 1; i < sizeof(g_rates)/sizeof(struct rates); i++)
|
||||
if (period > g_rates[i].mult ||
|
||||
g_rates[i].mult/period < g_rates[i].mult%period)
|
||||
break;
|
||||
|
||||
printf("%u/%s ", g_rates[i-1].mult / period, g_rates[i-1].name);
|
||||
}
|
||||
|
||||
static void brlimit_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
struct ebt_limit_info *r = (struct ebt_limit_info *)match->data;
|
||||
|
||||
printf("--limit ");
|
||||
print_rate(r->avg);
|
||||
printf("--limit-burst %u ", r->burst);
|
||||
}
|
||||
|
||||
static struct xtables_match brlimit_match = {
|
||||
.name = "limit",
|
||||
.revision = 0,
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_BRIDGE,
|
||||
.size = XT_ALIGN(sizeof(struct ebt_limit_info)),
|
||||
.userspacesize = offsetof(struct ebt_limit_info, prev),
|
||||
.init = brlimit_init,
|
||||
.help = brlimit_print_help,
|
||||
.parse = brlimit_parse,
|
||||
.print = brlimit_print,
|
||||
.extra_opts = brlimit_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_match(&brlimit_match);
|
||||
}
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* Bart De Schuymer <bdschuym@pandora.be>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Giuseppe Longo <giuseppelng@gmail.com> adapted the original code to the
|
||||
* xtables-compat environment in 2015.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_bridge/ebt_log.h>
|
||||
|
||||
#define LOG_DEFAULT_LEVEL LOG_INFO
|
||||
|
||||
#define LOG_PREFIX '1'
|
||||
#define LOG_LEVEL '2'
|
||||
#define LOG_ARP '3'
|
||||
#define LOG_IP '4'
|
||||
#define LOG_LOG '5'
|
||||
#define LOG_IP6 '6'
|
||||
|
||||
typedef struct _code {
|
||||
char *c_name;
|
||||
int c_val;
|
||||
} CODE;
|
||||
|
||||
static CODE eight_priority[] = {
|
||||
{ "emerg", LOG_EMERG },
|
||||
{ "alert", LOG_ALERT },
|
||||
{ "crit", LOG_CRIT },
|
||||
{ "error", LOG_ERR },
|
||||
{ "warning", LOG_WARNING },
|
||||
{ "notice", LOG_NOTICE },
|
||||
{ "info", LOG_INFO },
|
||||
{ "debug", LOG_DEBUG }
|
||||
};
|
||||
|
||||
static int name_to_loglevel(const char *arg)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
if (!strcmp(arg, eight_priority[i].c_name))
|
||||
return eight_priority[i].c_val;
|
||||
|
||||
/* return bad loglevel */
|
||||
return 9;
|
||||
}
|
||||
|
||||
static const struct option brlog_opts[] = {
|
||||
{ .name = "log-prefix", .has_arg = true, .val = LOG_PREFIX },
|
||||
{ .name = "log-level", .has_arg = true, .val = LOG_LEVEL },
|
||||
{ .name = "log-arp", .has_arg = false, .val = LOG_ARP },
|
||||
{ .name = "log-ip", .has_arg = false, .val = LOG_IP },
|
||||
{ .name = "log", .has_arg = false, .val = LOG_LOG },
|
||||
{ .name = "log-ip6", .has_arg = false, .val = LOG_IP6 },
|
||||
XT_GETOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void brlog_help(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf(
|
||||
"log options:\n"
|
||||
"--log : use this if you're not specifying anything\n"
|
||||
"--log-level level : level = [1-8] or a string\n"
|
||||
"--log-prefix prefix : max. %d chars.\n"
|
||||
"--log-ip : put ip info. in the log for ip packets\n"
|
||||
"--log-arp : put (r)arp info. in the log for (r)arp packets\n"
|
||||
"--log-ip6 : put ip6 info. in the log for ip6 packets\n"
|
||||
, EBT_LOG_PREFIX_SIZE - 1);
|
||||
for (i = 0; i < 8; i++)
|
||||
printf("%d = %s\n", eight_priority[i].c_val,
|
||||
eight_priority[i].c_name);
|
||||
}
|
||||
|
||||
static void brlog_init(struct xt_entry_target *t)
|
||||
{
|
||||
struct ebt_log_info *loginfo = (struct ebt_log_info *)t->data;
|
||||
|
||||
loginfo->bitmask = 0;
|
||||
loginfo->prefix[0] = '\0';
|
||||
loginfo->loglevel = LOG_NOTICE;
|
||||
}
|
||||
|
||||
static int brlog_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_target **target)
|
||||
{
|
||||
struct ebt_log_info *loginfo = (struct ebt_log_info *)(*target)->data;
|
||||
long int i;
|
||||
char *end;
|
||||
|
||||
switch (c) {
|
||||
case LOG_PREFIX:
|
||||
if (invert)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Unexpected `!` after --log-prefix");
|
||||
if (strlen(optarg) > sizeof(loginfo->prefix) - 1)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Prefix too long");
|
||||
if (strchr(optarg, '\"'))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Use of \\\" is not allowed"
|
||||
" in the prefix");
|
||||
strcpy((char *)loginfo->prefix, (char *)optarg);
|
||||
break;
|
||||
case LOG_LEVEL:
|
||||
i = strtol(optarg, &end, 16);
|
||||
if (*end != '\0' || i < 0 || i > 7)
|
||||
loginfo->loglevel = name_to_loglevel(optarg);
|
||||
else
|
||||
loginfo->loglevel = i;
|
||||
|
||||
if (loginfo->loglevel == 9)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Problem with the log-level");
|
||||
break;
|
||||
case LOG_IP:
|
||||
if (invert)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Unexpected `!' after --log-ip");
|
||||
loginfo->bitmask |= EBT_LOG_IP;
|
||||
break;
|
||||
case LOG_ARP:
|
||||
if (invert)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Unexpected `!' after --log-arp");
|
||||
loginfo->bitmask |= EBT_LOG_ARP;
|
||||
case LOG_LOG:
|
||||
if (invert)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Unexpected `!' after --log");
|
||||
break;
|
||||
case LOG_IP6:
|
||||
if (invert)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Unexpected `!' after --log-ip6");
|
||||
loginfo->bitmask |= EBT_LOG_IP6;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
*flags |= loginfo->bitmask;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void brlog_final_check(unsigned int flags)
|
||||
{
|
||||
}
|
||||
|
||||
static void brlog_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
struct ebt_log_info *loginfo = (struct ebt_log_info *)target->data;
|
||||
|
||||
printf("--log-level %s --log-prefix \"%s\"",
|
||||
eight_priority[loginfo->loglevel].c_name,
|
||||
loginfo->prefix);
|
||||
|
||||
if (loginfo->bitmask & EBT_LOG_IP)
|
||||
printf(" --log-ip");
|
||||
if (loginfo->bitmask & EBT_LOG_ARP)
|
||||
printf(" --log-arp");
|
||||
if (loginfo->bitmask & EBT_LOG_IP6)
|
||||
printf(" --log-ip6");
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
static struct xtables_target brlog_target = {
|
||||
.name = "log",
|
||||
.revision = 0,
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_BRIDGE,
|
||||
.size = XT_ALIGN(sizeof(struct ebt_log_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ebt_log_info)),
|
||||
.init = brlog_init,
|
||||
.help = brlog_help,
|
||||
.parse = brlog_parse,
|
||||
.final_check = brlog_final_check,
|
||||
.print = brlog_print,
|
||||
.extra_opts = brlog_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&brlog_target);
|
||||
}
|
|
@ -0,0 +1,191 @@
|
|||
/* ebt_mark
|
||||
*
|
||||
* Authors:
|
||||
* Bart De Schuymer <bdschuym@pandora.be>
|
||||
*
|
||||
* July, 2002, September 2006
|
||||
*
|
||||
* Adapted by Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
|
||||
* to use libxtables for ebtables-compat in 2015.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_bridge/ebt_mark_t.h>
|
||||
#include "iptables/nft.h"
|
||||
#include "iptables/nft-bridge.h"
|
||||
|
||||
static int mark_supplied;
|
||||
|
||||
#define MARK_TARGET '1'
|
||||
#define MARK_SETMARK '2'
|
||||
#define MARK_ORMARK '3'
|
||||
#define MARK_ANDMARK '4'
|
||||
#define MARK_XORMARK '5'
|
||||
static struct option brmark_opts[] = {
|
||||
{ .name = "mark-target",.has_arg = true, .val = MARK_TARGET },
|
||||
/* an oldtime messup, we should have always used the scheme
|
||||
* <extension-name>-<option> */
|
||||
{ .name = "set-mark", .has_arg = true, .val = MARK_SETMARK },
|
||||
{ .name = "mark-set", .has_arg = true, .val = MARK_SETMARK },
|
||||
{ .name = "mark-or", .has_arg = true, .val = MARK_ORMARK },
|
||||
{ .name = "mark-and", .has_arg = true, .val = MARK_ANDMARK },
|
||||
{ .name = "mark-xor", .has_arg = true, .val = MARK_XORMARK },
|
||||
XT_GETOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void brmark_print_help(void)
|
||||
{
|
||||
printf(
|
||||
"mark target options:\n"
|
||||
" --mark-set value : Set nfmark value\n"
|
||||
" --mark-or value : Or nfmark with value (nfmark |= value)\n"
|
||||
" --mark-and value : And nfmark with value (nfmark &= value)\n"
|
||||
" --mark-xor value : Xor nfmark with value (nfmark ^= value)\n"
|
||||
" --mark-target target : ACCEPT, DROP, RETURN or CONTINUE\n");
|
||||
}
|
||||
|
||||
static void brmark_init(struct xt_entry_target *target)
|
||||
{
|
||||
struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)target->data;
|
||||
|
||||
info->target = EBT_ACCEPT;
|
||||
info->mark = 0;
|
||||
mark_supplied = 0;
|
||||
}
|
||||
|
||||
#define OPT_MARK_TARGET 0x01
|
||||
#define OPT_MARK_SETMARK 0x02
|
||||
#define OPT_MARK_ORMARK 0x04
|
||||
#define OPT_MARK_ANDMARK 0x08
|
||||
#define OPT_MARK_XORMARK 0x10
|
||||
|
||||
static int
|
||||
brmark_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_target **target)
|
||||
{
|
||||
struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)
|
||||
(*target)->data;
|
||||
char *end;
|
||||
uint32_t mask;
|
||||
|
||||
switch (c) {
|
||||
case MARK_TARGET:
|
||||
{ unsigned int tmp;
|
||||
EBT_CHECK_OPTION(flags, OPT_MARK_TARGET);
|
||||
if (ebt_fill_target(optarg, &tmp))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Illegal --mark-target target");
|
||||
/* the 4 lsb are left to designate the target */
|
||||
info->target = (info->target & ~EBT_VERDICT_BITS) |
|
||||
(tmp & EBT_VERDICT_BITS);
|
||||
}
|
||||
return 1;
|
||||
case MARK_SETMARK:
|
||||
EBT_CHECK_OPTION(flags, OPT_MARK_SETMARK);
|
||||
mask = (OPT_MARK_ORMARK|OPT_MARK_ANDMARK|OPT_MARK_XORMARK);
|
||||
if (*flags & mask)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"--mark-set cannot be used together with"
|
||||
" specific --mark option");
|
||||
info->target = (info->target & EBT_VERDICT_BITS) |
|
||||
MARK_SET_VALUE;
|
||||
break;
|
||||
case MARK_ORMARK:
|
||||
EBT_CHECK_OPTION(flags, OPT_MARK_ORMARK);
|
||||
mask = (OPT_MARK_SETMARK|OPT_MARK_ANDMARK|OPT_MARK_XORMARK);
|
||||
if (*flags & mask)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"--mark-or cannot be used together with"
|
||||
" specific --mark option");
|
||||
info->target = (info->target & EBT_VERDICT_BITS) |
|
||||
MARK_OR_VALUE;
|
||||
break;
|
||||
case MARK_ANDMARK:
|
||||
EBT_CHECK_OPTION(flags, OPT_MARK_ANDMARK);
|
||||
mask = (OPT_MARK_SETMARK|OPT_MARK_ORMARK|OPT_MARK_XORMARK);
|
||||
if (*flags & mask)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"--mark-and cannot be used together with"
|
||||
" specific --mark option");
|
||||
info->target = (info->target & EBT_VERDICT_BITS) |
|
||||
MARK_AND_VALUE;
|
||||
break;
|
||||
case MARK_XORMARK:
|
||||
EBT_CHECK_OPTION(flags, OPT_MARK_XORMARK);
|
||||
mask = (OPT_MARK_SETMARK|OPT_MARK_ANDMARK|OPT_MARK_ORMARK);
|
||||
if (*flags & mask)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"--mark-xor cannot be used together with"
|
||||
" specific --mark option");
|
||||
info->target = (info->target & EBT_VERDICT_BITS) |
|
||||
MARK_XOR_VALUE;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
/* mutual code */
|
||||
info->mark = strtoul(optarg, &end, 0);
|
||||
if (*end != '\0' || end == optarg)
|
||||
xtables_error(PARAMETER_PROBLEM, "Bad MARK value '%s'",
|
||||
optarg);
|
||||
|
||||
mark_supplied = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void brmark_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)target->data;
|
||||
int tmp;
|
||||
|
||||
tmp = info->target & ~EBT_VERDICT_BITS;
|
||||
if (tmp == MARK_SET_VALUE)
|
||||
printf("--mark-set");
|
||||
else if (tmp == MARK_OR_VALUE)
|
||||
printf("--mark-or");
|
||||
else if (tmp == MARK_XOR_VALUE)
|
||||
printf("--mark-xor");
|
||||
else if (tmp == MARK_AND_VALUE)
|
||||
printf("--mark-and");
|
||||
else
|
||||
xtables_error(PARAMETER_PROBLEM, "Unknown mark action");
|
||||
|
||||
printf(" 0x%lx", info->mark);
|
||||
tmp = info->target | ~EBT_VERDICT_BITS;
|
||||
printf(" --mark-target %s", ebt_target_name(tmp));
|
||||
}
|
||||
|
||||
static void brmark_final_check(unsigned int flags)
|
||||
{
|
||||
if (mark_supplied == 0)
|
||||
xtables_error(PARAMETER_PROBLEM, "No mark value supplied");
|
||||
|
||||
if (!flags)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"You must specify some option");
|
||||
}
|
||||
|
||||
static struct xtables_target brmark_target = {
|
||||
.name = "mark",
|
||||
.revision = 0,
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_BRIDGE,
|
||||
.size = XT_ALIGN(sizeof(struct ebt_mark_t_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ebt_mark_t_info)),
|
||||
.help = brmark_print_help,
|
||||
.init = brmark_init,
|
||||
.parse = brmark_parse,
|
||||
.final_check = brmark_final_check,
|
||||
.print = brmark_print,
|
||||
.extra_opts = brmark_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&brmark_target);
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
/* ebt_mark_m
|
||||
*
|
||||
* Authors:
|
||||
* Bart De Schuymer <bdschuym@pandora.be>
|
||||
*
|
||||
* July, 2002
|
||||
*
|
||||
* Adapted by Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
|
||||
* to use libxtables for ebtables-compat in 2015.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_bridge/ebt_mark_m.h>
|
||||
|
||||
#define MARK '1'
|
||||
|
||||
static struct option brmark_m_opts[] = {
|
||||
{ .name = "mark", .has_arg = true, .val = MARK },
|
||||
XT_GETOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void brmark_m_print_help(void)
|
||||
{
|
||||
printf(
|
||||
"mark option:\n"
|
||||
"--mark [!] [value][/mask]: Match nfmask value (see man page)\n");
|
||||
}
|
||||
|
||||
static void brmark_m_init(struct xt_entry_match *match)
|
||||
{
|
||||
struct ebt_mark_m_info *info = (struct ebt_mark_m_info *)match->data;
|
||||
|
||||
info->mark = 0;
|
||||
info->mask = 0;
|
||||
info->invert = 0;
|
||||
info->bitmask = 0;
|
||||
}
|
||||
|
||||
#define OPT_MARK 0x01
|
||||
static int
|
||||
brmark_m_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_match **match)
|
||||
{
|
||||
struct ebt_mark_m_info *info = (struct ebt_mark_m_info *)
|
||||
(*match)->data;
|
||||
char *end;
|
||||
|
||||
switch (c) {
|
||||
case MARK:
|
||||
if (invert)
|
||||
info->invert = 1;
|
||||
info->mark = strtoul(optarg, &end, 0);
|
||||
info->bitmask = EBT_MARK_AND;
|
||||
if (*end == '/') {
|
||||
if (end == optarg)
|
||||
info->bitmask = EBT_MARK_OR;
|
||||
info->mask = strtoul(end+1, &end, 0);
|
||||
} else {
|
||||
info->mask = 0xffffffff;
|
||||
}
|
||||
if (*end != '\0' || end == optarg)
|
||||
xtables_error(PARAMETER_PROBLEM, "Bad mark value '%s'",
|
||||
optarg);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
*flags |= info->bitmask;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void brmark_m_final_check(unsigned int flags)
|
||||
{
|
||||
if (!flags)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"You must specify proper arguments");
|
||||
}
|
||||
|
||||
static void brmark_m_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
struct ebt_mark_m_info *info = (struct ebt_mark_m_info *)match->data;
|
||||
|
||||
printf("--mark ");
|
||||
if (info->invert)
|
||||
printf("! ");
|
||||
if (info->bitmask == EBT_MARK_OR)
|
||||
printf("/0x%lx ", info->mask);
|
||||
else if (info->mask != 0xffffffff)
|
||||
printf("0x%lx/0x%lx ", info->mark, info->mask);
|
||||
else
|
||||
printf("0x%lx ", info->mark);
|
||||
}
|
||||
|
||||
static struct xtables_match brmark_m_match = {
|
||||
.name = "mark_m",
|
||||
.revision = 0,
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_BRIDGE,
|
||||
.size = XT_ALIGN(sizeof(struct ebt_mark_m_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ebt_mark_m_info)),
|
||||
.init = brmark_m_init,
|
||||
.help = brmark_m_print_help,
|
||||
.parse = brmark_m_parse,
|
||||
.final_check = brmark_m_final_check,
|
||||
.print = brmark_m_print,
|
||||
.extra_opts = brmark_m_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_match(&brmark_m_match);
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
/* ebt_nflog
|
||||
*
|
||||
* Authors:
|
||||
* Peter Warasin <peter@endian.com>
|
||||
*
|
||||
* February, 2008
|
||||
*
|
||||
* Based on:
|
||||
* ebt_ulog.c, (C) 2004, Bart De Schuymer <bdschuym@pandora.be>
|
||||
* libxt_NFLOG.c
|
||||
*
|
||||
* Adapted to libxtables for ebtables-compat in 2015 by
|
||||
* Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <xtables.h>
|
||||
#include "iptables/nft.h"
|
||||
#include "iptables/nft-bridge.h"
|
||||
#include <linux/netfilter_bridge/ebt_nflog.h>
|
||||
|
||||
enum {
|
||||
NFLOG_GROUP = 0x1,
|
||||
NFLOG_PREFIX = 0x2,
|
||||
NFLOG_RANGE = 0x4,
|
||||
NFLOG_THRESHOLD = 0x8,
|
||||
NFLOG_NFLOG = 0x16,
|
||||
};
|
||||
|
||||
static struct option brnflog_opts[] = {
|
||||
{ .name = "nflog-group", .has_arg = true, .val = NFLOG_GROUP},
|
||||
{ .name = "nflog-prefix", .has_arg = true, .val = NFLOG_PREFIX},
|
||||
{ .name = "nflog-range", .has_arg = true, .val = NFLOG_RANGE},
|
||||
{ .name = "nflog-threshold", .has_arg = true, .val = NFLOG_THRESHOLD},
|
||||
{ .name = "nflog", .has_arg = false, .val = NFLOG_NFLOG},
|
||||
XT_GETOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void brnflog_help(void)
|
||||
{
|
||||
printf("nflog options:\n"
|
||||
"--nflog : use the default nflog parameters\n"
|
||||
"--nflog-prefix prefix : Prefix string for log message\n"
|
||||
"--nflog-group group : NETLINK group used for logging\n"
|
||||
"--nflog-range range : Number of byte to copy\n"
|
||||
"--nflog-threshold : Message threshold of"
|
||||
"in-kernel queue\n");
|
||||
}
|
||||
|
||||
static void brnflog_init(struct xt_entry_target *t)
|
||||
{
|
||||
struct ebt_nflog_info *info = (struct ebt_nflog_info *)t->data;
|
||||
|
||||
info->prefix[0] = '\0';
|
||||
info->group = EBT_NFLOG_DEFAULT_GROUP;
|
||||
info->threshold = EBT_NFLOG_DEFAULT_THRESHOLD;
|
||||
}
|
||||
|
||||
static int brnflog_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_target **target)
|
||||
{
|
||||
struct ebt_nflog_info *info = (struct ebt_nflog_info *)(*target)->data;
|
||||
unsigned int i;
|
||||
|
||||
if (invert)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"The use of '!' makes no sense for the"
|
||||
" nflog watcher");
|
||||
|
||||
switch (c) {
|
||||
case NFLOG_PREFIX:
|
||||
EBT_CHECK_OPTION(flags, NFLOG_PREFIX);
|
||||
if (strlen(optarg) > EBT_NFLOG_PREFIX_SIZE - 1)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Prefix too long for nflog-prefix");
|
||||
strncpy(info->prefix, optarg, EBT_NFLOG_PREFIX_SIZE);
|
||||
break;
|
||||
case NFLOG_GROUP:
|
||||
EBT_CHECK_OPTION(flags, NFLOG_GROUP);
|
||||
if (!xtables_strtoui(optarg, NULL, &i, 1, UINT32_MAX))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"--nflog-group must be a number!");
|
||||
info->group = i;
|
||||
break;
|
||||
case NFLOG_RANGE:
|
||||
EBT_CHECK_OPTION(flags, NFLOG_RANGE);
|
||||
if (!xtables_strtoui(optarg, NULL, &i, 1, UINT32_MAX))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"--nflog-range must be a number!");
|
||||
info->len = i;
|
||||
break;
|
||||
case NFLOG_THRESHOLD:
|
||||
EBT_CHECK_OPTION(flags, NFLOG_THRESHOLD);
|
||||
if (!xtables_strtoui(optarg, NULL, &i, 1, UINT32_MAX))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"--nflog-threshold must be a number!");
|
||||
info->threshold = i;
|
||||
break;
|
||||
case NFLOG_NFLOG:
|
||||
EBT_CHECK_OPTION(flags, NFLOG_NFLOG);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
brnflog_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
struct ebt_nflog_info *info = (struct ebt_nflog_info *)target->data;
|
||||
|
||||
if (info->prefix[0] != '\0')
|
||||
printf("--nflog-prefix \"%s\" ", info->prefix);
|
||||
if (info->group)
|
||||
printf("--nflog-group %d ", info->group);
|
||||
if (info->len)
|
||||
printf("--nflog-range %d ", info->len);
|
||||
if (info->threshold != EBT_NFLOG_DEFAULT_THRESHOLD)
|
||||
printf("--nflog-threshold %d ", info->threshold);
|
||||
}
|
||||
|
||||
static struct xtables_target brnflog_watcher = {
|
||||
.name = "nflog",
|
||||
.revision = 0,
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_BRIDGE,
|
||||
.size = XT_ALIGN(sizeof(struct ebt_nflog_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ebt_nflog_info)),
|
||||
.init = brnflog_init,
|
||||
.help = brnflog_help,
|
||||
.parse = brnflog_parse,
|
||||
.print = brnflog_print,
|
||||
.extra_opts = brnflog_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&brnflog_watcher);
|
||||
}
|
|
@ -0,0 +1,252 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
|
||||
*
|
||||
* Based on Rusty Russell's IPv4 DNAT target. Development of IPv6 NAT
|
||||
* funded by Astaro.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <xtables.h>
|
||||
#include <iptables.h>
|
||||
#include <limits.h> /* INT_MAX in ip_tables.h */
|
||||
#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
#include <linux/netfilter/nf_nat.h>
|
||||
|
||||
enum {
|
||||
O_TO_DEST = 0,
|
||||
O_RANDOM,
|
||||
O_PERSISTENT,
|
||||
O_X_TO_DEST,
|
||||
F_TO_DEST = 1 << O_TO_DEST,
|
||||
F_RANDOM = 1 << O_RANDOM,
|
||||
F_X_TO_DEST = 1 << O_X_TO_DEST,
|
||||
};
|
||||
|
||||
static void DNAT_help(void)
|
||||
{
|
||||
printf(
|
||||
"DNAT target options:\n"
|
||||
" --to-destination [<ipaddr>[-<ipaddr>]][:port[-port]]\n"
|
||||
" Address to map destination to.\n"
|
||||
"[--random] [--persistent]\n");
|
||||
}
|
||||
|
||||
static const struct xt_option_entry DNAT_opts[] = {
|
||||
{.name = "to-destination", .id = O_TO_DEST, .type = XTTYPE_STRING,
|
||||
.flags = XTOPT_MAND | XTOPT_MULTI},
|
||||
{.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
|
||||
{.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
/* Ranges expected in network order. */
|
||||
static void
|
||||
parse_to(const char *orig_arg, int portok, struct nf_nat_range *range)
|
||||
{
|
||||
char *arg, *start, *end = NULL, *colon = NULL, *dash, *error;
|
||||
const struct in6_addr *ip;
|
||||
|
||||
arg = strdup(orig_arg);
|
||||
if (arg == NULL)
|
||||
xtables_error(RESOURCE_PROBLEM, "strdup");
|
||||
|
||||
start = strchr(arg, '[');
|
||||
if (start == NULL) {
|
||||
start = arg;
|
||||
/* Lets assume one colon is port information. Otherwise its an IPv6 address */
|
||||
colon = strchr(arg, ':');
|
||||
if (colon && strchr(colon+1, ':'))
|
||||
colon = NULL;
|
||||
}
|
||||
else {
|
||||
start++;
|
||||
end = strchr(start, ']');
|
||||
if (end == NULL)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Invalid address format");
|
||||
|
||||
*end = '\0';
|
||||
colon = strchr(end + 1, ':');
|
||||
}
|
||||
|
||||
if (colon) {
|
||||
int port;
|
||||
|
||||
if (!portok)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Need TCP, UDP, SCTP or DCCP with port specification");
|
||||
|
||||
range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
|
||||
|
||||
port = atoi(colon+1);
|
||||
if (port <= 0 || port > 65535)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Port `%s' not valid\n", colon+1);
|
||||
|
||||
error = strchr(colon+1, ':');
|
||||
if (error)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Invalid port:port syntax - use dash\n");
|
||||
|
||||
dash = strchr(colon, '-');
|
||||
if (!dash) {
|
||||
range->min_proto.tcp.port
|
||||
= range->max_proto.tcp.port
|
||||
= htons(port);
|
||||
} else {
|
||||
int maxport;
|
||||
|
||||
maxport = atoi(dash + 1);
|
||||
if (maxport <= 0 || maxport > 65535)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Port `%s' not valid\n", dash+1);
|
||||
if (maxport < port)
|
||||
/* People are stupid. */
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Port range `%s' funky\n", colon+1);
|
||||
range->min_proto.tcp.port = htons(port);
|
||||
range->max_proto.tcp.port = htons(maxport);
|
||||
}
|
||||
/* Starts with colon or [] colon? No IP info...*/
|
||||
if (colon == arg || colon == arg+2) {
|
||||
free(arg);
|
||||
return;
|
||||
}
|
||||
*colon = '\0';
|
||||
}
|
||||
|
||||
range->flags |= NF_NAT_RANGE_MAP_IPS;
|
||||
dash = strchr(start, '-');
|
||||
if (colon && dash && dash > colon)
|
||||
dash = NULL;
|
||||
|
||||
if (dash)
|
||||
*dash = '\0';
|
||||
|
||||
ip = xtables_numeric_to_ip6addr(start);
|
||||
if (!ip)
|
||||
xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
|
||||
start);
|
||||
range->min_addr.in6 = *ip;
|
||||
if (dash) {
|
||||
ip = xtables_numeric_to_ip6addr(dash + 1);
|
||||
if (!ip)
|
||||
xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
|
||||
dash+1);
|
||||
range->max_addr.in6 = *ip;
|
||||
} else
|
||||
range->max_addr = range->min_addr;
|
||||
|
||||
free(arg);
|
||||
return;
|
||||
}
|
||||
|
||||
static void DNAT_parse(struct xt_option_call *cb)
|
||||
{
|
||||
const struct ip6t_entry *entry = cb->xt_entry;
|
||||
struct nf_nat_range *range = cb->data;
|
||||
int portok;
|
||||
|
||||
if (entry->ipv6.proto == IPPROTO_TCP ||
|
||||
entry->ipv6.proto == IPPROTO_UDP ||
|
||||
entry->ipv6.proto == IPPROTO_SCTP ||
|
||||
entry->ipv6.proto == IPPROTO_DCCP ||
|
||||
entry->ipv6.proto == IPPROTO_ICMP)
|
||||
portok = 1;
|
||||
else
|
||||
portok = 0;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_TO_DEST:
|
||||
if (cb->xflags & F_X_TO_DEST) {
|
||||
if (!kernel_version)
|
||||
get_kernel_version();
|
||||
if (kernel_version > LINUX_VERSION(2, 6, 10))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"DNAT: Multiple --to-destination not supported");
|
||||
}
|
||||
parse_to(cb->arg, portok, range);
|
||||
break;
|
||||
case O_PERSISTENT:
|
||||
range->flags |= NF_NAT_RANGE_PERSISTENT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void DNAT_fcheck(struct xt_fcheck_call *cb)
|
||||
{
|
||||
static const unsigned int f = F_TO_DEST | F_RANDOM;
|
||||
struct nf_nat_range *mr = cb->data;
|
||||
|
||||
if ((cb->xflags & f) == f)
|
||||
mr->flags |= NF_NAT_RANGE_PROTO_RANDOM;
|
||||
}
|
||||
|
||||
static void print_range(const struct nf_nat_range *range)
|
||||
{
|
||||
if (range->flags & NF_NAT_RANGE_MAP_IPS) {
|
||||
if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)
|
||||
printf("[");
|
||||
printf("%s", xtables_ip6addr_to_numeric(&range->min_addr.in6));
|
||||
if (memcmp(&range->min_addr, &range->max_addr,
|
||||
sizeof(range->min_addr)))
|
||||
printf("-%s", xtables_ip6addr_to_numeric(&range->max_addr.in6));
|
||||
if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)
|
||||
printf("]");
|
||||
}
|
||||
if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
|
||||
printf(":");
|
||||
printf("%hu", ntohs(range->min_proto.tcp.port));
|
||||
if (range->max_proto.tcp.port != range->min_proto.tcp.port)
|
||||
printf("-%hu", ntohs(range->max_proto.tcp.port));
|
||||
}
|
||||
}
|
||||
|
||||
static void DNAT_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct nf_nat_range *range = (const void *)target->data;
|
||||
|
||||
printf(" to:");
|
||||
print_range(range);
|
||||
if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
|
||||
printf(" random");
|
||||
if (range->flags & NF_NAT_RANGE_PERSISTENT)
|
||||
printf(" persistent");
|
||||
}
|
||||
|
||||
static void DNAT_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct nf_nat_range *range = (const void *)target->data;
|
||||
|
||||
printf(" --to-destination ");
|
||||
print_range(range);
|
||||
if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
|
||||
printf(" --random");
|
||||
if (range->flags & NF_NAT_RANGE_PERSISTENT)
|
||||
printf(" --persistent");
|
||||
}
|
||||
|
||||
static struct xtables_target snat_tg_reg = {
|
||||
.name = "DNAT",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV6,
|
||||
.revision = 1,
|
||||
.size = XT_ALIGN(sizeof(struct nf_nat_range)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
|
||||
.help = DNAT_help,
|
||||
.x6_parse = DNAT_parse,
|
||||
.x6_fcheck = DNAT_fcheck,
|
||||
.print = DNAT_print,
|
||||
.save = DNAT_save,
|
||||
.x6_options = DNAT_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&snat_tg_reg);
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2013 Patrick McHardy <kaber@trash.net>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
#include <linux/netfilter_ipv6/ip6t_NPT.h>
|
||||
|
||||
enum {
|
||||
O_SRC_PFX = 1 << 0,
|
||||
O_DST_PFX = 1 << 1,
|
||||
};
|
||||
|
||||
static const struct xt_option_entry DNPT_options[] = {
|
||||
{ .name = "src-pfx", .id = O_SRC_PFX, .type = XTTYPE_HOSTMASK,
|
||||
.flags = XTOPT_MAND },
|
||||
{ .name = "dst-pfx", .id = O_DST_PFX, .type = XTTYPE_HOSTMASK,
|
||||
.flags = XTOPT_MAND },
|
||||
{ }
|
||||
};
|
||||
|
||||
static void DNPT_help(void)
|
||||
{
|
||||
printf("DNPT target options:"
|
||||
"\n"
|
||||
" --src-pfx prefix/length\n"
|
||||
" --dst-pfx prefix/length\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
static void DNPT_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ip6t_npt_tginfo *npt = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_SRC_PFX:
|
||||
npt->src_pfx = cb->val.haddr;
|
||||
npt->src_pfx_len = cb->val.hlen;
|
||||
break;
|
||||
case O_DST_PFX:
|
||||
npt->dst_pfx = cb->val.haddr;
|
||||
npt->dst_pfx_len = cb->val.hlen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void DNPT_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct ip6t_npt_tginfo *npt = (const void *)target->data;
|
||||
|
||||
printf(" DNPT src-pfx %s/%u", xtables_ip6addr_to_numeric(&npt->src_pfx.in6),
|
||||
npt->src_pfx_len);
|
||||
printf(" dst-pfx %s/%u", xtables_ip6addr_to_numeric(&npt->dst_pfx.in6),
|
||||
npt->dst_pfx_len);
|
||||
}
|
||||
|
||||
static void DNPT_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
static const struct in6_addr zero_addr;
|
||||
const struct ip6t_npt_tginfo *info = (const void *)target->data;
|
||||
|
||||
if (memcmp(&info->src_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 ||
|
||||
info->src_pfx_len != 0)
|
||||
printf(" --src-pfx %s/%u",
|
||||
xtables_ip6addr_to_numeric(&info->src_pfx.in6),
|
||||
info->src_pfx_len);
|
||||
if (memcmp(&info->dst_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 ||
|
||||
info->dst_pfx_len != 0)
|
||||
printf(" --dst-pfx %s/%u",
|
||||
xtables_ip6addr_to_numeric(&info->dst_pfx.in6),
|
||||
info->dst_pfx_len);
|
||||
}
|
||||
|
||||
static struct xtables_target snpt_tg_reg = {
|
||||
.name = "DNPT",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(struct ip6t_npt_tginfo)),
|
||||
.userspacesize = offsetof(struct ip6t_npt_tginfo, adjustment),
|
||||
.help = DNPT_help,
|
||||
.x6_parse = DNPT_parse,
|
||||
.print = DNPT_print,
|
||||
.save = DNPT_save,
|
||||
.x6_options = DNPT_options,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&snpt_tg_reg);
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
Provides stateless destination IPv6-to-IPv6 Network Prefix Translation (as
|
||||
described by RFC 6296).
|
||||
.PP
|
||||
You have to use this target in the
|
||||
.B mangle
|
||||
table, not in the
|
||||
.B nat
|
||||
table. It takes the following options:
|
||||
.TP
|
||||
\fB\-\-src\-pfx\fP [\fIprefix/\fP\fIlength]
|
||||
Set source prefix that you want to translate and length
|
||||
.TP
|
||||
\fB\-\-dst\-pfx\fP [\fIprefix/\fP\fIlength]
|
||||
Set destination prefix that you want to use in the translation and length
|
||||
.PP
|
||||
You have to use the SNPT target to undo the translation. Example:
|
||||
.IP
|
||||
ip6tables \-t mangle \-I POSTROUTING \-s fd00::/64 \! \-o vboxnet0
|
||||
\-j SNPT \-\-src-pfx fd00::/64 \-\-dst-pfx 2001:e20:2000:40f::/64
|
||||
.IP
|
||||
ip6tables \-t mangle \-I PREROUTING \-i wlan0 \-d 2001:e20:2000:40f::/64
|
||||
\-j DNPT \-\-src-pfx 2001:e20:2000:40f::/64 \-\-dst-pfx fd00::/64
|
||||
.PP
|
||||
You may need to enable IPv6 neighbor proxy:
|
||||
.IP
|
||||
sysctl -w net.ipv6.conf.all.proxy_ndp=1
|
||||
.PP
|
||||
You also have to use the
|
||||
.B NOTRACK
|
||||
target to disable connection tracking for translated flows.
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* IPv6 Hop Limit Target module
|
||||
* Maciej Soltysiak <solt@dns.toxicfilms.tv>
|
||||
* Based on HW's ttl target
|
||||
* This program is distributed under the terms of GNU GPL
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_ipv6/ip6t_HL.h>
|
||||
|
||||
enum {
|
||||
O_HL_SET = 0,
|
||||
O_HL_INC,
|
||||
O_HL_DEC,
|
||||
F_HL_SET = 1 << O_HL_SET,
|
||||
F_HL_INC = 1 << O_HL_INC,
|
||||
F_HL_DEC = 1 << O_HL_DEC,
|
||||
F_ANY = F_HL_SET | F_HL_INC | F_HL_DEC,
|
||||
};
|
||||
|
||||
#define s struct ip6t_HL_info
|
||||
static const struct xt_option_entry HL_opts[] = {
|
||||
{.name = "hl-set", .type = XTTYPE_UINT8, .id = O_HL_SET,
|
||||
.excl = F_ANY, .flags = XTOPT_PUT, XTOPT_POINTER(s, hop_limit)},
|
||||
{.name = "hl-dec", .type = XTTYPE_UINT8, .id = O_HL_DEC,
|
||||
.excl = F_ANY, .flags = XTOPT_PUT, XTOPT_POINTER(s, hop_limit),
|
||||
.min = 1},
|
||||
{.name = "hl-inc", .type = XTTYPE_UINT8, .id = O_HL_INC,
|
||||
.excl = F_ANY, .flags = XTOPT_PUT, XTOPT_POINTER(s, hop_limit),
|
||||
.min = 1},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
#undef s
|
||||
|
||||
static void HL_help(void)
|
||||
{
|
||||
printf(
|
||||
"HL target options\n"
|
||||
" --hl-set value Set HL to <value 0-255>\n"
|
||||
" --hl-dec value Decrement HL by <value 1-255>\n"
|
||||
" --hl-inc value Increment HL by <value 1-255>\n");
|
||||
}
|
||||
|
||||
static void HL_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ip6t_HL_info *info = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_HL_SET:
|
||||
info->mode = IP6T_HL_SET;
|
||||
break;
|
||||
case O_HL_INC:
|
||||
info->mode = IP6T_HL_INC;
|
||||
break;
|
||||
case O_HL_DEC:
|
||||
info->mode = IP6T_HL_DEC;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void HL_check(struct xt_fcheck_call *cb)
|
||||
{
|
||||
if (!(cb->xflags & F_ANY))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"HL: You must specify an action");
|
||||
}
|
||||
|
||||
static void HL_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct ip6t_HL_info *info =
|
||||
(struct ip6t_HL_info *) target->data;
|
||||
|
||||
switch (info->mode) {
|
||||
case IP6T_HL_SET:
|
||||
printf(" --hl-set");
|
||||
break;
|
||||
case IP6T_HL_DEC:
|
||||
printf(" --hl-dec");
|
||||
break;
|
||||
|
||||
case IP6T_HL_INC:
|
||||
printf(" --hl-inc");
|
||||
break;
|
||||
}
|
||||
printf(" %u", info->hop_limit);
|
||||
}
|
||||
|
||||
static void HL_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct ip6t_HL_info *info =
|
||||
(struct ip6t_HL_info *) target->data;
|
||||
|
||||
printf(" HL ");
|
||||
switch (info->mode) {
|
||||
case IP6T_HL_SET:
|
||||
printf("set to");
|
||||
break;
|
||||
case IP6T_HL_DEC:
|
||||
printf("decrement by");
|
||||
break;
|
||||
case IP6T_HL_INC:
|
||||
printf("increment by");
|
||||
break;
|
||||
}
|
||||
printf(" %u", info->hop_limit);
|
||||
}
|
||||
|
||||
static struct xtables_target hl_tg6_reg = {
|
||||
.name = "HL",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(struct ip6t_HL_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ip6t_HL_info)),
|
||||
.help = HL_help,
|
||||
.print = HL_print,
|
||||
.save = HL_save,
|
||||
.x6_parse = HL_parse,
|
||||
.x6_fcheck = HL_check,
|
||||
.x6_options = HL_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&hl_tg6_reg);
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
This is used to modify the Hop Limit field in IPv6 header. The Hop Limit field
|
||||
is similar to what is known as TTL value in IPv4. Setting or incrementing the
|
||||
Hop Limit field can potentially be very dangerous, so it should be avoided at
|
||||
any cost. This target is only valid in
|
||||
.B mangle
|
||||
table.
|
||||
.PP
|
||||
.B Don't ever set or increment the value on packets that leave your local network!
|
||||
.TP
|
||||
\fB\-\-hl\-set\fP \fIvalue\fP
|
||||
Set the Hop Limit to `value'.
|
||||
.TP
|
||||
\fB\-\-hl\-dec\fP \fIvalue\fP
|
||||
Decrement the Hop Limit `value' times.
|
||||
.TP
|
||||
\fB\-\-hl\-inc\fP \fIvalue\fP
|
||||
Increment the Hop Limit `value' times.
|
|
@ -0,0 +1,186 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_ipv6/ip6t_LOG.h>
|
||||
|
||||
#ifndef IP6T_LOG_UID /* Old kernel */
|
||||
#define IP6T_LOG_UID 0x08
|
||||
#undef IP6T_LOG_MASK
|
||||
#define IP6T_LOG_MASK 0x0f
|
||||
#endif
|
||||
|
||||
#define LOG_DEFAULT_LEVEL LOG_WARNING
|
||||
|
||||
enum {
|
||||
O_LOG_LEVEL = 0,
|
||||
O_LOG_PREFIX,
|
||||
O_LOG_TCPSEQ,
|
||||
O_LOG_TCPOPTS,
|
||||
O_LOG_IPOPTS,
|
||||
O_LOG_UID,
|
||||
O_LOG_MAC,
|
||||
};
|
||||
|
||||
static void LOG_help(void)
|
||||
{
|
||||
printf(
|
||||
"LOG target options:\n"
|
||||
" --log-level level Level of logging (numeric or see syslog.conf)\n"
|
||||
" --log-prefix prefix Prefix log messages with this prefix.\n"
|
||||
" --log-tcp-sequence Log TCP sequence numbers.\n"
|
||||
" --log-tcp-options Log TCP options.\n"
|
||||
" --log-ip-options Log IP options.\n"
|
||||
" --log-uid Log UID owning the local socket.\n"
|
||||
" --log-macdecode Decode MAC addresses and protocol.\n");
|
||||
}
|
||||
|
||||
#define s struct ip6t_log_info
|
||||
static const struct xt_option_entry LOG_opts[] = {
|
||||
{.name = "log-level", .id = O_LOG_LEVEL, .type = XTTYPE_SYSLOGLEVEL,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(s, level)},
|
||||
{.name = "log-prefix", .id = O_LOG_PREFIX, .type = XTTYPE_STRING,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(s, prefix), .min = 1},
|
||||
{.name = "log-tcp-sequence", .id = O_LOG_TCPSEQ, .type = XTTYPE_NONE},
|
||||
{.name = "log-tcp-options", .id = O_LOG_TCPOPTS, .type = XTTYPE_NONE},
|
||||
{.name = "log-ip-options", .id = O_LOG_IPOPTS, .type = XTTYPE_NONE},
|
||||
{.name = "log-uid", .id = O_LOG_UID, .type = XTTYPE_NONE},
|
||||
{.name = "log-macdecode", .id = O_LOG_MAC, .type = XTTYPE_NONE},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
#undef s
|
||||
|
||||
static void LOG_init(struct xt_entry_target *t)
|
||||
{
|
||||
struct ip6t_log_info *loginfo = (struct ip6t_log_info *)t->data;
|
||||
|
||||
loginfo->level = LOG_DEFAULT_LEVEL;
|
||||
|
||||
}
|
||||
|
||||
struct ip6t_log_names {
|
||||
const char *name;
|
||||
unsigned int level;
|
||||
};
|
||||
|
||||
static const struct ip6t_log_names ip6t_log_names[]
|
||||
= { { .name = "alert", .level = LOG_ALERT },
|
||||
{ .name = "crit", .level = LOG_CRIT },
|
||||
{ .name = "debug", .level = LOG_DEBUG },
|
||||
{ .name = "emerg", .level = LOG_EMERG },
|
||||
{ .name = "error", .level = LOG_ERR }, /* DEPRECATED */
|
||||
{ .name = "info", .level = LOG_INFO },
|
||||
{ .name = "notice", .level = LOG_NOTICE },
|
||||
{ .name = "panic", .level = LOG_EMERG }, /* DEPRECATED */
|
||||
{ .name = "warning", .level = LOG_WARNING }
|
||||
};
|
||||
|
||||
static void LOG_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ip6t_log_info *info = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_LOG_PREFIX:
|
||||
if (strchr(cb->arg, '\n') != NULL)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Newlines not allowed in --log-prefix");
|
||||
break;
|
||||
case O_LOG_TCPSEQ:
|
||||
info->logflags |= IP6T_LOG_TCPSEQ;
|
||||
break;
|
||||
case O_LOG_TCPOPTS:
|
||||
info->logflags |= IP6T_LOG_TCPOPT;
|
||||
break;
|
||||
case O_LOG_IPOPTS:
|
||||
info->logflags |= IP6T_LOG_IPOPT;
|
||||
break;
|
||||
case O_LOG_UID:
|
||||
info->logflags |= IP6T_LOG_UID;
|
||||
break;
|
||||
case O_LOG_MAC:
|
||||
info->logflags |= IP6T_LOG_MACDECODE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void LOG_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct ip6t_log_info *loginfo
|
||||
= (const struct ip6t_log_info *)target->data;
|
||||
unsigned int i = 0;
|
||||
|
||||
printf(" LOG");
|
||||
if (numeric)
|
||||
printf(" flags %u level %u",
|
||||
loginfo->logflags, loginfo->level);
|
||||
else {
|
||||
for (i = 0; i < ARRAY_SIZE(ip6t_log_names); ++i)
|
||||
if (loginfo->level == ip6t_log_names[i].level) {
|
||||
printf(" level %s", ip6t_log_names[i].name);
|
||||
break;
|
||||
}
|
||||
if (i == ARRAY_SIZE(ip6t_log_names))
|
||||
printf(" UNKNOWN level %u", loginfo->level);
|
||||
if (loginfo->logflags & IP6T_LOG_TCPSEQ)
|
||||
printf(" tcp-sequence");
|
||||
if (loginfo->logflags & IP6T_LOG_TCPOPT)
|
||||
printf(" tcp-options");
|
||||
if (loginfo->logflags & IP6T_LOG_IPOPT)
|
||||
printf(" ip-options");
|
||||
if (loginfo->logflags & IP6T_LOG_UID)
|
||||
printf(" uid");
|
||||
if (loginfo->logflags & IP6T_LOG_MACDECODE)
|
||||
printf(" macdecode");
|
||||
if (loginfo->logflags & ~(IP6T_LOG_MASK))
|
||||
printf(" unknown-flags");
|
||||
}
|
||||
|
||||
if (strcmp(loginfo->prefix, "") != 0)
|
||||
printf(" prefix \"%s\"", loginfo->prefix);
|
||||
}
|
||||
|
||||
static void LOG_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct ip6t_log_info *loginfo
|
||||
= (const struct ip6t_log_info *)target->data;
|
||||
|
||||
if (strcmp(loginfo->prefix, "") != 0) {
|
||||
printf(" --log-prefix");
|
||||
xtables_save_string(loginfo->prefix);
|
||||
}
|
||||
|
||||
if (loginfo->level != LOG_DEFAULT_LEVEL)
|
||||
printf(" --log-level %d", loginfo->level);
|
||||
|
||||
if (loginfo->logflags & IP6T_LOG_TCPSEQ)
|
||||
printf(" --log-tcp-sequence");
|
||||
if (loginfo->logflags & IP6T_LOG_TCPOPT)
|
||||
printf(" --log-tcp-options");
|
||||
if (loginfo->logflags & IP6T_LOG_IPOPT)
|
||||
printf(" --log-ip-options");
|
||||
if (loginfo->logflags & IP6T_LOG_UID)
|
||||
printf(" --log-uid");
|
||||
if (loginfo->logflags & IP6T_LOG_MACDECODE)
|
||||
printf(" --log-macdecode");
|
||||
}
|
||||
|
||||
static struct xtables_target log_tg6_reg = {
|
||||
.name = "LOG",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(struct ip6t_log_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ip6t_log_info)),
|
||||
.help = LOG_help,
|
||||
.init = LOG_init,
|
||||
.print = LOG_print,
|
||||
.save = LOG_save,
|
||||
.x6_parse = LOG_parse,
|
||||
.x6_options = LOG_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&log_tg6_reg);
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
|
||||
*
|
||||
* Based on Rusty Russell's IPv4 MASQUERADE target. Development of IPv6 NAT
|
||||
* funded by Astaro.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <xtables.h>
|
||||
#include <limits.h> /* INT_MAX in ip_tables.h */
|
||||
#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
#include <linux/netfilter/nf_nat.h>
|
||||
|
||||
enum {
|
||||
O_TO_PORTS = 0,
|
||||
O_RANDOM,
|
||||
};
|
||||
|
||||
static void MASQUERADE_help(void)
|
||||
{
|
||||
printf(
|
||||
"MASQUERADE target options:\n"
|
||||
" --to-ports <port>[-<port>]\n"
|
||||
" Port (range) to map to.\n"
|
||||
" --random\n"
|
||||
" Randomize source port.\n");
|
||||
}
|
||||
|
||||
static const struct xt_option_entry MASQUERADE_opts[] = {
|
||||
{.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING},
|
||||
{.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
/* Parses ports */
|
||||
static void
|
||||
parse_ports(const char *arg, struct nf_nat_range *r)
|
||||
{
|
||||
char *end;
|
||||
unsigned int port, maxport;
|
||||
|
||||
r->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
|
||||
|
||||
if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX))
|
||||
xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg);
|
||||
|
||||
switch (*end) {
|
||||
case '\0':
|
||||
r->min_proto.tcp.port
|
||||
= r->max_proto.tcp.port
|
||||
= htons(port);
|
||||
return;
|
||||
case '-':
|
||||
if (!xtables_strtoui(end + 1, NULL, &maxport, 0, UINT16_MAX))
|
||||
break;
|
||||
|
||||
if (maxport < port)
|
||||
break;
|
||||
|
||||
r->min_proto.tcp.port = htons(port);
|
||||
r->max_proto.tcp.port = htons(maxport);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg);
|
||||
}
|
||||
|
||||
static void MASQUERADE_parse(struct xt_option_call *cb)
|
||||
{
|
||||
const struct ip6t_entry *entry = cb->xt_entry;
|
||||
struct nf_nat_range *r = cb->data;
|
||||
int portok;
|
||||
|
||||
if (entry->ipv6.proto == IPPROTO_TCP ||
|
||||
entry->ipv6.proto == IPPROTO_UDP ||
|
||||
entry->ipv6.proto == IPPROTO_SCTP ||
|
||||
entry->ipv6.proto == IPPROTO_DCCP ||
|
||||
entry->ipv6.proto == IPPROTO_ICMP)
|
||||
portok = 1;
|
||||
else
|
||||
portok = 0;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_TO_PORTS:
|
||||
if (!portok)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Need TCP, UDP, SCTP or DCCP with port specification");
|
||||
parse_ports(cb->arg, r);
|
||||
break;
|
||||
case O_RANDOM:
|
||||
r->flags |= NF_NAT_RANGE_PROTO_RANDOM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
MASQUERADE_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct nf_nat_range *r = (const void *)target->data;
|
||||
|
||||
if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
|
||||
printf(" masq ports: ");
|
||||
printf("%hu", ntohs(r->min_proto.tcp.port));
|
||||
if (r->max_proto.tcp.port != r->min_proto.tcp.port)
|
||||
printf("-%hu", ntohs(r->max_proto.tcp.port));
|
||||
}
|
||||
|
||||
if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
|
||||
printf(" random");
|
||||
}
|
||||
|
||||
static void
|
||||
MASQUERADE_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct nf_nat_range *r = (const void *)target->data;
|
||||
|
||||
if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
|
||||
printf(" --to-ports %hu", ntohs(r->min_proto.tcp.port));
|
||||
if (r->max_proto.tcp.port != r->min_proto.tcp.port)
|
||||
printf("-%hu", ntohs(r->max_proto.tcp.port));
|
||||
}
|
||||
|
||||
if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
|
||||
printf(" --random");
|
||||
}
|
||||
|
||||
static struct xtables_target masquerade_tg_reg = {
|
||||
.name = "MASQUERADE",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(struct nf_nat_range)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
|
||||
.help = MASQUERADE_help,
|
||||
.x6_parse = MASQUERADE_parse,
|
||||
.print = MASQUERADE_print,
|
||||
.save = MASQUERADE_save,
|
||||
.x6_options = MASQUERADE_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&masquerade_tg_reg);
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
|
||||
*
|
||||
* Based on Svenning Soerensen's IPv4 NETMAP target. Development of IPv6 NAT
|
||||
* funded by Astaro.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <xtables.h>
|
||||
#include <libiptc/libip6tc.h>
|
||||
#include <linux/netfilter/nf_nat.h>
|
||||
|
||||
#define MODULENAME "NETMAP"
|
||||
|
||||
enum {
|
||||
O_TO = 0,
|
||||
};
|
||||
|
||||
static const struct xt_option_entry NETMAP_opts[] = {
|
||||
{.name = "to", .id = O_TO, .type = XTTYPE_HOSTMASK,
|
||||
.flags = XTOPT_MAND},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void NETMAP_help(void)
|
||||
{
|
||||
printf(MODULENAME" target options:\n"
|
||||
" --%s address[/mask]\n"
|
||||
" Network address to map to.\n\n",
|
||||
NETMAP_opts[0].name);
|
||||
}
|
||||
|
||||
static void NETMAP_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct nf_nat_range *range = cb->data;
|
||||
unsigned int i;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
range->flags |= NF_NAT_RANGE_MAP_IPS;
|
||||
for (i = 0; i < 4; i++) {
|
||||
range->min_addr.ip6[i] = cb->val.haddr.ip6[i] &
|
||||
cb->val.hmask.ip6[i];
|
||||
range->max_addr.ip6[i] = range->min_addr.ip6[i] |
|
||||
~cb->val.hmask.ip6[i];
|
||||
}
|
||||
}
|
||||
|
||||
static void NETMAP_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct nf_nat_range *r = (const void *)target->data;
|
||||
struct in6_addr a;
|
||||
unsigned int i;
|
||||
int bits;
|
||||
|
||||
a = r->min_addr.in6;
|
||||
printf("%s", xtables_ip6addr_to_numeric(&a));
|
||||
for (i = 0; i < 4; i++)
|
||||
a.s6_addr32[i] = ~(r->min_addr.ip6[i] ^ r->max_addr.ip6[i]);
|
||||
bits = xtables_ip6mask_to_cidr(&a);
|
||||
if (bits < 0)
|
||||
printf("/%s", xtables_ip6addr_to_numeric(&a));
|
||||
else
|
||||
printf("/%d", bits);
|
||||
}
|
||||
|
||||
static void NETMAP_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
printf(" --%s ", NETMAP_opts[0].name);
|
||||
NETMAP_print(ip, target, 0);
|
||||
}
|
||||
|
||||
static struct xtables_target netmap_tg_reg = {
|
||||
.name = MODULENAME,
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(struct nf_nat_range)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
|
||||
.help = NETMAP_help,
|
||||
.x6_parse = NETMAP_parse,
|
||||
.print = NETMAP_print,
|
||||
.save = NETMAP_save,
|
||||
.x6_options = NETMAP_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&netmap_tg_reg);
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
|
||||
*
|
||||
* Based on Rusty Russell's IPv4 REDIRECT target. Development of IPv6 NAT
|
||||
* funded by Astaro.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <xtables.h>
|
||||
#include <limits.h> /* INT_MAX in ip_tables.h */
|
||||
#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
#include <linux/netfilter/nf_nat.h>
|
||||
|
||||
enum {
|
||||
O_TO_PORTS = 0,
|
||||
O_RANDOM,
|
||||
F_TO_PORTS = 1 << O_TO_PORTS,
|
||||
F_RANDOM = 1 << O_RANDOM,
|
||||
};
|
||||
|
||||
static void REDIRECT_help(void)
|
||||
{
|
||||
printf(
|
||||
"REDIRECT target options:\n"
|
||||
" --to-ports <port>[-<port>]\n"
|
||||
" Port (range) to map to.\n"
|
||||
" [--random]\n");
|
||||
}
|
||||
|
||||
static const struct xt_option_entry REDIRECT_opts[] = {
|
||||
{.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING},
|
||||
{.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
/* Parses ports */
|
||||
static void
|
||||
parse_ports(const char *arg, struct nf_nat_range *range)
|
||||
{
|
||||
char *end = "";
|
||||
unsigned int port, maxport;
|
||||
|
||||
range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
|
||||
|
||||
if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX) &&
|
||||
(port = xtables_service_to_port(arg, NULL)) == (unsigned)-1)
|
||||
xtables_param_act(XTF_BAD_VALUE, "REDIRECT", "--to-ports", arg);
|
||||
|
||||
switch (*end) {
|
||||
case '\0':
|
||||
range->min_proto.tcp.port
|
||||
= range->max_proto.tcp.port
|
||||
= htons(port);
|
||||
return;
|
||||
case '-':
|
||||
if (!xtables_strtoui(end + 1, NULL, &maxport, 0, UINT16_MAX) &&
|
||||
(maxport = xtables_service_to_port(end + 1, NULL)) == (unsigned)-1)
|
||||
break;
|
||||
|
||||
if (maxport < port)
|
||||
break;
|
||||
|
||||
range->min_proto.tcp.port = htons(port);
|
||||
range->max_proto.tcp.port = htons(maxport);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
xtables_param_act(XTF_BAD_VALUE, "REDIRECT", "--to-ports", arg);
|
||||
}
|
||||
|
||||
static void REDIRECT_parse(struct xt_option_call *cb)
|
||||
{
|
||||
const struct ip6t_entry *entry = cb->xt_entry;
|
||||
struct nf_nat_range *range = (void *)(*cb->target)->data;
|
||||
int portok;
|
||||
|
||||
if (entry->ipv6.proto == IPPROTO_TCP
|
||||
|| entry->ipv6.proto == IPPROTO_UDP
|
||||
|| entry->ipv6.proto == IPPROTO_SCTP
|
||||
|| entry->ipv6.proto == IPPROTO_DCCP
|
||||
|| entry->ipv6.proto == IPPROTO_ICMP)
|
||||
portok = 1;
|
||||
else
|
||||
portok = 0;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_TO_PORTS:
|
||||
if (!portok)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Need TCP, UDP, SCTP or DCCP with port specification");
|
||||
parse_ports(cb->arg, range);
|
||||
if (cb->xflags & F_RANDOM)
|
||||
range->flags |= NF_NAT_RANGE_PROTO_RANDOM;
|
||||
break;
|
||||
case O_RANDOM:
|
||||
if (cb->xflags & F_TO_PORTS)
|
||||
range->flags |= NF_NAT_RANGE_PROTO_RANDOM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void REDIRECT_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct nf_nat_range *range = (const void *)target->data;
|
||||
|
||||
if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
|
||||
printf(" redir ports ");
|
||||
printf("%hu", ntohs(range->min_proto.tcp.port));
|
||||
if (range->max_proto.tcp.port != range->min_proto.tcp.port)
|
||||
printf("-%hu", ntohs(range->max_proto.tcp.port));
|
||||
if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
|
||||
printf(" random");
|
||||
}
|
||||
}
|
||||
|
||||
static void REDIRECT_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct nf_nat_range *range = (const void *)target->data;
|
||||
|
||||
if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
|
||||
printf(" --to-ports ");
|
||||
printf("%hu", ntohs(range->min_proto.tcp.port));
|
||||
if (range->max_proto.tcp.port != range->min_proto.tcp.port)
|
||||
printf("-%hu", ntohs(range->max_proto.tcp.port));
|
||||
if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
|
||||
printf(" --random");
|
||||
}
|
||||
}
|
||||
|
||||
static struct xtables_target redirect_tg_reg = {
|
||||
.name = "REDIRECT",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(struct nf_nat_range)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
|
||||
.help = REDIRECT_help,
|
||||
.x6_parse = REDIRECT_parse,
|
||||
.print = REDIRECT_print,
|
||||
.save = REDIRECT_save,
|
||||
.x6_options = REDIRECT_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&redirect_tg_reg);
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
/* Shared library add-on to ip6tables to add customized REJECT support.
|
||||
*
|
||||
* (C) 2000 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* ported to IPv6 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_ipv6/ip6t_REJECT.h>
|
||||
|
||||
struct reject_names {
|
||||
const char *name;
|
||||
const char *alias;
|
||||
enum ip6t_reject_with with;
|
||||
const char *desc;
|
||||
};
|
||||
|
||||
enum {
|
||||
O_REJECT_WITH = 0,
|
||||
};
|
||||
|
||||
static const struct reject_names reject_table[] = {
|
||||
{"icmp6-no-route", "no-route",
|
||||
IP6T_ICMP6_NO_ROUTE, "ICMPv6 no route"},
|
||||
{"icmp6-adm-prohibited", "adm-prohibited",
|
||||
IP6T_ICMP6_ADM_PROHIBITED, "ICMPv6 administratively prohibited"},
|
||||
#if 0
|
||||
{"icmp6-not-neighbor", "not-neighbor"},
|
||||
IP6T_ICMP6_NOT_NEIGHBOR, "ICMPv6 not a neighbor"},
|
||||
#endif
|
||||
{"icmp6-addr-unreachable", "addr-unreach",
|
||||
IP6T_ICMP6_ADDR_UNREACH, "ICMPv6 address unreachable"},
|
||||
{"icmp6-port-unreachable", "port-unreach",
|
||||
IP6T_ICMP6_PORT_UNREACH, "ICMPv6 port unreachable"},
|
||||
{"tcp-reset", "tcp-reset",
|
||||
IP6T_TCP_RESET, "TCP RST packet"},
|
||||
{"icmp6-policy-fail", "policy-fail",
|
||||
IP6T_ICMP6_POLICY_FAIL, "ICMPv6 policy fail"},
|
||||
{"icmp6-reject-route", "reject-route",
|
||||
IP6T_ICMP6_REJECT_ROUTE, "ICMPv6 reject route"}
|
||||
};
|
||||
|
||||
static void
|
||||
print_reject_types(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
printf("Valid reject types:\n");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(reject_table); ++i) {
|
||||
printf(" %-25s\t%s\n", reject_table[i].name, reject_table[i].desc);
|
||||
printf(" %-25s\talias\n", reject_table[i].alias);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void REJECT_help(void)
|
||||
{
|
||||
printf(
|
||||
"REJECT target options:\n"
|
||||
"--reject-with type drop input packet and send back\n"
|
||||
" a reply packet according to type:\n");
|
||||
|
||||
print_reject_types();
|
||||
}
|
||||
|
||||
static const struct xt_option_entry REJECT_opts[] = {
|
||||
{.name = "reject-with", .id = O_REJECT_WITH, .type = XTTYPE_STRING},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void REJECT_init(struct xt_entry_target *t)
|
||||
{
|
||||
struct ip6t_reject_info *reject = (struct ip6t_reject_info *)t->data;
|
||||
|
||||
/* default */
|
||||
reject->with = IP6T_ICMP6_PORT_UNREACH;
|
||||
|
||||
}
|
||||
|
||||
static void REJECT_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ip6t_reject_info *reject = cb->data;
|
||||
unsigned int i;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
for (i = 0; i < ARRAY_SIZE(reject_table); ++i)
|
||||
if (strncasecmp(reject_table[i].name,
|
||||
cb->arg, strlen(cb->arg)) == 0 ||
|
||||
strncasecmp(reject_table[i].alias,
|
||||
cb->arg, strlen(cb->arg)) == 0) {
|
||||
reject->with = reject_table[i].with;
|
||||
return;
|
||||
}
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"unknown reject type \"%s\"", cb->arg);
|
||||
}
|
||||
|
||||
static void REJECT_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct ip6t_reject_info *reject
|
||||
= (const struct ip6t_reject_info *)target->data;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(reject_table); ++i)
|
||||
if (reject_table[i].with == reject->with)
|
||||
break;
|
||||
printf(" reject-with %s", reject_table[i].name);
|
||||
}
|
||||
|
||||
static void REJECT_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct ip6t_reject_info *reject
|
||||
= (const struct ip6t_reject_info *)target->data;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(reject_table); ++i)
|
||||
if (reject_table[i].with == reject->with)
|
||||
break;
|
||||
|
||||
printf(" --reject-with %s", reject_table[i].name);
|
||||
}
|
||||
|
||||
static struct xtables_target reject_tg6_reg = {
|
||||
.name = "REJECT",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(struct ip6t_reject_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ip6t_reject_info)),
|
||||
.help = REJECT_help,
|
||||
.init = REJECT_init,
|
||||
.print = REJECT_print,
|
||||
.save = REJECT_save,
|
||||
.x6_parse = REJECT_parse,
|
||||
.x6_options = REJECT_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&reject_tg6_reg);
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
This is used to send back an error packet in response to the matched
|
||||
packet: otherwise it is equivalent to
|
||||
.B DROP
|
||||
so it is a terminating TARGET, ending rule traversal.
|
||||
This target is only valid in the
|
||||
.BR INPUT ,
|
||||
.B FORWARD
|
||||
and
|
||||
.B OUTPUT
|
||||
chains, and user-defined chains which are only called from those
|
||||
chains. The following option controls the nature of the error packet
|
||||
returned:
|
||||
.TP
|
||||
\fB\-\-reject\-with\fP \fItype\fP
|
||||
The type given can be
|
||||
\fBicmp6\-no\-route\fP,
|
||||
\fBno\-route\fP,
|
||||
\fBicmp6\-adm\-prohibited\fP,
|
||||
\fBadm\-prohibited\fP,
|
||||
\fBicmp6\-addr\-unreachable\fP,
|
||||
\fBaddr\-unreach\fP, or
|
||||
\fBicmp6\-port\-unreachable\fP,
|
||||
which return the appropriate ICMPv6 error message (\fBicmp6\-port\-unreachable\fP is
|
||||
the default). Finally, the option
|
||||
\fBtcp\-reset\fP
|
||||
can be used on rules which only match the TCP protocol: this causes a
|
||||
TCP RST packet to be sent back. This is mainly useful for blocking
|
||||
.I ident
|
||||
(113/tcp) probes which frequently occur when sending mail to broken mail
|
||||
hosts (which won't accept your mail otherwise).
|
||||
\fBtcp\-reset\fP
|
||||
can only be used with kernel versions 2.6.14 or later.
|
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
|
||||
*
|
||||
* Based on Rusty Russell's IPv4 SNAT target. Development of IPv6 NAT
|
||||
* funded by Astaro.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <xtables.h>
|
||||
#include <iptables.h>
|
||||
#include <limits.h> /* INT_MAX in ip_tables.h */
|
||||
#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
#include <linux/netfilter/nf_nat.h>
|
||||
|
||||
enum {
|
||||
O_TO_SRC = 0,
|
||||
O_RANDOM,
|
||||
O_RANDOM_FULLY,
|
||||
O_PERSISTENT,
|
||||
O_X_TO_SRC,
|
||||
F_TO_SRC = 1 << O_TO_SRC,
|
||||
F_RANDOM = 1 << O_RANDOM,
|
||||
F_RANDOM_FULLY = 1 << O_RANDOM_FULLY,
|
||||
F_X_TO_SRC = 1 << O_X_TO_SRC,
|
||||
};
|
||||
|
||||
static void SNAT_help(void)
|
||||
{
|
||||
printf(
|
||||
"SNAT target options:\n"
|
||||
" --to-source [<ipaddr>[-<ipaddr>]][:port[-port]]\n"
|
||||
" Address to map source to.\n"
|
||||
"[--random] [--random-fully] [--persistent]\n");
|
||||
}
|
||||
|
||||
static const struct xt_option_entry SNAT_opts[] = {
|
||||
{.name = "to-source", .id = O_TO_SRC, .type = XTTYPE_STRING,
|
||||
.flags = XTOPT_MAND | XTOPT_MULTI},
|
||||
{.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
|
||||
{.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE},
|
||||
{.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
/* Ranges expected in network order. */
|
||||
static void
|
||||
parse_to(const char *orig_arg, int portok, struct nf_nat_range *range)
|
||||
{
|
||||
char *arg, *start, *end = NULL, *colon = NULL, *dash, *error;
|
||||
const struct in6_addr *ip;
|
||||
|
||||
arg = strdup(orig_arg);
|
||||
if (arg == NULL)
|
||||
xtables_error(RESOURCE_PROBLEM, "strdup");
|
||||
|
||||
start = strchr(arg, '[');
|
||||
if (start == NULL) {
|
||||
start = arg;
|
||||
/* Lets assume one colon is port information. Otherwise its an IPv6 address */
|
||||
colon = strchr(arg, ':');
|
||||
if (colon && strchr(colon+1, ':'))
|
||||
colon = NULL;
|
||||
}
|
||||
else {
|
||||
start++;
|
||||
end = strchr(start, ']');
|
||||
if (end == NULL)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Invalid address format");
|
||||
|
||||
*end = '\0';
|
||||
colon = strchr(end + 1, ':');
|
||||
}
|
||||
|
||||
if (colon) {
|
||||
int port;
|
||||
|
||||
if (!portok)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Need TCP, UDP, SCTP or DCCP with port specification");
|
||||
|
||||
range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
|
||||
|
||||
port = atoi(colon+1);
|
||||
if (port <= 0 || port > 65535)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Port `%s' not valid\n", colon+1);
|
||||
|
||||
error = strchr(colon+1, ':');
|
||||
if (error)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Invalid port:port syntax - use dash\n");
|
||||
|
||||
dash = strchr(colon, '-');
|
||||
if (!dash) {
|
||||
range->min_proto.tcp.port
|
||||
= range->max_proto.tcp.port
|
||||
= htons(port);
|
||||
} else {
|
||||
int maxport;
|
||||
|
||||
maxport = atoi(dash + 1);
|
||||
if (maxport <= 0 || maxport > 65535)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Port `%s' not valid\n", dash+1);
|
||||
if (maxport < port)
|
||||
/* People are stupid. */
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Port range `%s' funky\n", colon+1);
|
||||
range->min_proto.tcp.port = htons(port);
|
||||
range->max_proto.tcp.port = htons(maxport);
|
||||
}
|
||||
/* Starts with colon or [] colon? No IP info...*/
|
||||
if (colon == arg || colon == arg+2) {
|
||||
free(arg);
|
||||
return;
|
||||
}
|
||||
*colon = '\0';
|
||||
}
|
||||
|
||||
range->flags |= NF_NAT_RANGE_MAP_IPS;
|
||||
dash = strchr(start, '-');
|
||||
if (colon && dash && dash > colon)
|
||||
dash = NULL;
|
||||
|
||||
if (dash)
|
||||
*dash = '\0';
|
||||
|
||||
ip = xtables_numeric_to_ip6addr(start);
|
||||
if (!ip)
|
||||
xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
|
||||
start);
|
||||
range->min_addr.in6 = *ip;
|
||||
if (dash) {
|
||||
ip = xtables_numeric_to_ip6addr(dash + 1);
|
||||
if (!ip)
|
||||
xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
|
||||
dash+1);
|
||||
range->max_addr.in6 = *ip;
|
||||
} else
|
||||
range->max_addr = range->min_addr;
|
||||
|
||||
free(arg);
|
||||
return;
|
||||
}
|
||||
|
||||
static void SNAT_parse(struct xt_option_call *cb)
|
||||
{
|
||||
const struct ip6t_entry *entry = cb->xt_entry;
|
||||
struct nf_nat_range *range = cb->data;
|
||||
int portok;
|
||||
|
||||
if (entry->ipv6.proto == IPPROTO_TCP ||
|
||||
entry->ipv6.proto == IPPROTO_UDP ||
|
||||
entry->ipv6.proto == IPPROTO_SCTP ||
|
||||
entry->ipv6.proto == IPPROTO_DCCP ||
|
||||
entry->ipv6.proto == IPPROTO_ICMP)
|
||||
portok = 1;
|
||||
else
|
||||
portok = 0;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_TO_SRC:
|
||||
if (cb->xflags & F_X_TO_SRC) {
|
||||
if (!kernel_version)
|
||||
get_kernel_version();
|
||||
if (kernel_version > LINUX_VERSION(2, 6, 10))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"SNAT: Multiple --to-source not supported");
|
||||
}
|
||||
parse_to(cb->arg, portok, range);
|
||||
break;
|
||||
case O_PERSISTENT:
|
||||
range->flags |= NF_NAT_RANGE_PERSISTENT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void SNAT_fcheck(struct xt_fcheck_call *cb)
|
||||
{
|
||||
static const unsigned int f = F_TO_SRC | F_RANDOM;
|
||||
static const unsigned int r = F_TO_SRC | F_RANDOM_FULLY;
|
||||
struct nf_nat_range *range = cb->data;
|
||||
|
||||
if ((cb->xflags & f) == f)
|
||||
range->flags |= NF_NAT_RANGE_PROTO_RANDOM;
|
||||
if ((cb->xflags & r) == r)
|
||||
range->flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY;
|
||||
}
|
||||
|
||||
static void print_range(const struct nf_nat_range *range)
|
||||
{
|
||||
if (range->flags & NF_NAT_RANGE_MAP_IPS) {
|
||||
if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)
|
||||
printf("[");
|
||||
printf("%s", xtables_ip6addr_to_numeric(&range->min_addr.in6));
|
||||
if (memcmp(&range->min_addr, &range->max_addr,
|
||||
sizeof(range->min_addr)))
|
||||
printf("-%s", xtables_ip6addr_to_numeric(&range->max_addr.in6));
|
||||
if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)
|
||||
printf("]");
|
||||
}
|
||||
if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
|
||||
printf(":");
|
||||
printf("%hu", ntohs(range->min_proto.tcp.port));
|
||||
if (range->max_proto.tcp.port != range->min_proto.tcp.port)
|
||||
printf("-%hu", ntohs(range->max_proto.tcp.port));
|
||||
}
|
||||
}
|
||||
|
||||
static void SNAT_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct nf_nat_range *range = (const void *)target->data;
|
||||
|
||||
printf(" to:");
|
||||
print_range(range);
|
||||
if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
|
||||
printf(" random");
|
||||
if (range->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
|
||||
printf(" random-fully");
|
||||
if (range->flags & NF_NAT_RANGE_PERSISTENT)
|
||||
printf(" persistent");
|
||||
}
|
||||
|
||||
static void SNAT_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct nf_nat_range *range = (const void *)target->data;
|
||||
|
||||
printf(" --to-source ");
|
||||
print_range(range);
|
||||
if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
|
||||
printf(" --random");
|
||||
if (range->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
|
||||
printf(" --random-fully");
|
||||
if (range->flags & NF_NAT_RANGE_PERSISTENT)
|
||||
printf(" --persistent");
|
||||
}
|
||||
|
||||
static struct xtables_target snat_tg_reg = {
|
||||
.name = "SNAT",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV6,
|
||||
.revision = 1,
|
||||
.size = XT_ALIGN(sizeof(struct nf_nat_range)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
|
||||
.help = SNAT_help,
|
||||
.x6_parse = SNAT_parse,
|
||||
.x6_fcheck = SNAT_fcheck,
|
||||
.print = SNAT_print,
|
||||
.save = SNAT_save,
|
||||
.x6_options = SNAT_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&snat_tg_reg);
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2013 Patrick McHardy <kaber@trash.net>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
#include <linux/netfilter_ipv6/ip6t_NPT.h>
|
||||
|
||||
enum {
|
||||
O_SRC_PFX = 1 << 0,
|
||||
O_DST_PFX = 1 << 1,
|
||||
};
|
||||
|
||||
static const struct xt_option_entry SNPT_options[] = {
|
||||
{ .name = "src-pfx", .id = O_SRC_PFX, .type = XTTYPE_HOSTMASK,
|
||||
.flags = XTOPT_MAND },
|
||||
{ .name = "dst-pfx", .id = O_DST_PFX, .type = XTTYPE_HOSTMASK,
|
||||
.flags = XTOPT_MAND },
|
||||
{ }
|
||||
};
|
||||
|
||||
static void SNPT_help(void)
|
||||
{
|
||||
printf("SNPT target options:"
|
||||
"\n"
|
||||
" --src-pfx prefix/length\n"
|
||||
" --dst-pfx prefix/length\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
static void SNPT_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ip6t_npt_tginfo *npt = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_SRC_PFX:
|
||||
npt->src_pfx = cb->val.haddr;
|
||||
npt->src_pfx_len = cb->val.hlen;
|
||||
break;
|
||||
case O_DST_PFX:
|
||||
npt->dst_pfx = cb->val.haddr;
|
||||
npt->dst_pfx_len = cb->val.hlen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void SNPT_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct ip6t_npt_tginfo *npt = (const void *)target->data;
|
||||
|
||||
printf(" SNPT src-pfx %s/%u", xtables_ip6addr_to_numeric(&npt->src_pfx.in6),
|
||||
npt->src_pfx_len);
|
||||
printf(" dst-pfx %s/%u", xtables_ip6addr_to_numeric(&npt->dst_pfx.in6),
|
||||
npt->dst_pfx_len);
|
||||
}
|
||||
|
||||
static void SNPT_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
static const struct in6_addr zero_addr;
|
||||
const struct ip6t_npt_tginfo *info = (const void *)target->data;
|
||||
|
||||
if (memcmp(&info->src_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 ||
|
||||
info->src_pfx_len != 0)
|
||||
printf(" --src-pfx %s/%u",
|
||||
xtables_ip6addr_to_numeric(&info->src_pfx.in6),
|
||||
info->src_pfx_len);
|
||||
if (memcmp(&info->dst_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 ||
|
||||
info->dst_pfx_len != 0)
|
||||
printf(" --dst-pfx %s/%u",
|
||||
xtables_ip6addr_to_numeric(&info->dst_pfx.in6),
|
||||
info->dst_pfx_len);
|
||||
}
|
||||
|
||||
static struct xtables_target snpt_tg_reg = {
|
||||
.name = "SNPT",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(struct ip6t_npt_tginfo)),
|
||||
.userspacesize = offsetof(struct ip6t_npt_tginfo, adjustment),
|
||||
.help = SNPT_help,
|
||||
.x6_parse = SNPT_parse,
|
||||
.print = SNPT_print,
|
||||
.save = SNPT_save,
|
||||
.x6_options = SNPT_options,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&snpt_tg_reg);
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
Provides stateless source IPv6-to-IPv6 Network Prefix Translation (as described
|
||||
by RFC 6296).
|
||||
.PP
|
||||
You have to use this target in the
|
||||
.B mangle
|
||||
table, not in the
|
||||
.B nat
|
||||
table. It takes the following options:
|
||||
.TP
|
||||
\fB\-\-src\-pfx\fP [\fIprefix/\fP\fIlength]
|
||||
Set source prefix that you want to translate and length
|
||||
.TP
|
||||
\fB\-\-dst\-pfx\fP [\fIprefix/\fP\fIlength]
|
||||
Set destination prefix that you want to use in the translation and length
|
||||
.PP
|
||||
You have to use the DNPT target to undo the translation. Example:
|
||||
.IP
|
||||
ip6tables \-t mangle \-I POSTROUTING \-s fd00::/64 \! \-o vboxnet0
|
||||
\-j SNPT \-\-src-pfx fd00::/64 \-\-dst-pfx 2001:e20:2000:40f::/64
|
||||
.IP
|
||||
ip6tables \-t mangle \-I PREROUTING \-i wlan0 \-d 2001:e20:2000:40f::/64
|
||||
\-j DNPT \-\-src-pfx 2001:e20:2000:40f::/64 \-\-dst-pfx fd00::/64
|
||||
.PP
|
||||
You may need to enable IPv6 neighbor proxy:
|
||||
.IP
|
||||
sysctl -w net.ipv6.conf.all.proxy_ndp=1
|
||||
.PP
|
||||
You also have to use the
|
||||
.B NOTRACK
|
||||
target to disable connection tracking for translated flows.
|
|
@ -0,0 +1,149 @@
|
|||
#include <stdio.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_ipv6/ip6t_ah.h>
|
||||
|
||||
enum {
|
||||
O_AHSPI = 0,
|
||||
O_AHLEN,
|
||||
O_AHRES,
|
||||
};
|
||||
|
||||
static void ah_help(void)
|
||||
{
|
||||
printf(
|
||||
"ah match options:\n"
|
||||
"[!] --ahspi spi[:spi] match spi (range)\n"
|
||||
"[!] --ahlen length total length of this header\n"
|
||||
" --ahres check the reserved field too\n");
|
||||
}
|
||||
|
||||
#define s struct ip6t_ah
|
||||
static const struct xt_option_entry ah_opts[] = {
|
||||
{.name = "ahspi", .id = O_AHSPI, .type = XTTYPE_UINT32RC,
|
||||
.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, spis)},
|
||||
{.name = "ahlen", .id = O_AHLEN, .type = XTTYPE_UINT32,
|
||||
.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdrlen)},
|
||||
{.name = "ahres", .id = O_AHRES, .type = XTTYPE_NONE},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
#undef s
|
||||
|
||||
static void ah_init(struct xt_entry_match *m)
|
||||
{
|
||||
struct ip6t_ah *ahinfo = (void *)m->data;
|
||||
|
||||
/* Defaults for when no --ahspi is used at all */
|
||||
ahinfo->spis[1] = ~0U;
|
||||
}
|
||||
|
||||
static void ah_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ip6t_ah *ahinfo = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_AHSPI:
|
||||
if (cb->nvals == 1)
|
||||
ahinfo->spis[1] = ahinfo->spis[0];
|
||||
if (cb->invert)
|
||||
ahinfo->invflags |= IP6T_AH_INV_SPI;
|
||||
break;
|
||||
case O_AHLEN:
|
||||
if (cb->invert)
|
||||
ahinfo->invflags |= IP6T_AH_INV_LEN;
|
||||
break;
|
||||
case O_AHRES:
|
||||
ahinfo->hdrres = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_spis(const char *name, uint32_t min, uint32_t max,
|
||||
int invert)
|
||||
{
|
||||
const char *inv = invert ? "!" : "";
|
||||
|
||||
if (min != 0 || max != 0xFFFFFFFF || invert) {
|
||||
if (min == max)
|
||||
printf("%s:%s%u", name, inv, min);
|
||||
else
|
||||
printf("%ss:%s%u:%u", name, inv, min, max);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_len(const char *name, uint32_t len, int invert)
|
||||
{
|
||||
const char *inv = invert ? "!" : "";
|
||||
|
||||
if (len != 0 || invert)
|
||||
printf("%s:%s%u", name, inv, len);
|
||||
}
|
||||
|
||||
static void ah_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
const struct ip6t_ah *ah = (struct ip6t_ah *)match->data;
|
||||
|
||||
printf(" ah ");
|
||||
print_spis("spi", ah->spis[0], ah->spis[1],
|
||||
ah->invflags & IP6T_AH_INV_SPI);
|
||||
print_len("length", ah->hdrlen,
|
||||
ah->invflags & IP6T_AH_INV_LEN);
|
||||
|
||||
if (ah->hdrres)
|
||||
printf(" reserved");
|
||||
|
||||
if (ah->invflags & ~IP6T_AH_INV_MASK)
|
||||
printf(" Unknown invflags: 0x%X",
|
||||
ah->invflags & ~IP6T_AH_INV_MASK);
|
||||
}
|
||||
|
||||
static void ah_save(const void *ip, const struct xt_entry_match *match)
|
||||
{
|
||||
const struct ip6t_ah *ahinfo = (struct ip6t_ah *)match->data;
|
||||
|
||||
if (!(ahinfo->spis[0] == 0
|
||||
&& ahinfo->spis[1] == 0xFFFFFFFF)) {
|
||||
printf("%s --ahspi ",
|
||||
(ahinfo->invflags & IP6T_AH_INV_SPI) ? " !" : "");
|
||||
if (ahinfo->spis[0]
|
||||
!= ahinfo->spis[1])
|
||||
printf("%u:%u",
|
||||
ahinfo->spis[0],
|
||||
ahinfo->spis[1]);
|
||||
else
|
||||
printf("%u",
|
||||
ahinfo->spis[0]);
|
||||
}
|
||||
|
||||
if (ahinfo->hdrlen != 0 || (ahinfo->invflags & IP6T_AH_INV_LEN) ) {
|
||||
printf("%s --ahlen %u",
|
||||
(ahinfo->invflags & IP6T_AH_INV_LEN) ? " !" : "",
|
||||
ahinfo->hdrlen);
|
||||
}
|
||||
|
||||
if (ahinfo->hdrres != 0 )
|
||||
printf(" --ahres");
|
||||
}
|
||||
|
||||
static struct xtables_match ah_mt6_reg = {
|
||||
.name = "ah",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(struct ip6t_ah)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ip6t_ah)),
|
||||
.help = ah_help,
|
||||
.init = ah_init,
|
||||
.print = ah_print,
|
||||
.save = ah_save,
|
||||
.x6_parse = ah_parse,
|
||||
.x6_options = ah_opts,
|
||||
};
|
||||
|
||||
void
|
||||
_init(void)
|
||||
{
|
||||
xtables_register_match(&ah_mt6_reg);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
This module matches the parameters in Authentication header of IPsec packets.
|
||||
.TP
|
||||
[\fB!\fP] \fB\-\-ahspi\fP \fIspi\fP[\fB:\fP\fIspi\fP]
|
||||
Matches SPI.
|
||||
.TP
|
||||
[\fB!\fP] \fB\-\-ahlen\fP \fIlength\fP
|
||||
Total length of this header in octets.
|
||||
.TP
|
||||
\fB\-\-ahres\fP
|
||||
Matches if the reserved field is filled with zero.
|
|
@ -0,0 +1,196 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_ipv6/ip6t_opts.h>
|
||||
|
||||
enum {
|
||||
O_DSTLEN = 0,
|
||||
O_DSTOPTS,
|
||||
};
|
||||
|
||||
static void dst_help(void)
|
||||
{
|
||||
printf(
|
||||
"dst match options:\n"
|
||||
"[!] --dst-len length total length of this header\n"
|
||||
" --dst-opts TYPE[:LEN][,TYPE[:LEN]...]\n"
|
||||
" Options and its length (list, max: %d)\n",
|
||||
IP6T_OPTS_OPTSNR);
|
||||
}
|
||||
|
||||
static const struct xt_option_entry dst_opts[] = {
|
||||
{.name = "dst-len", .id = O_DSTLEN, .type = XTTYPE_UINT32,
|
||||
.flags = XTOPT_INVERT | XTOPT_PUT,
|
||||
XTOPT_POINTER(struct ip6t_opts, hdrlen)},
|
||||
{.name = "dst-opts", .id = O_DSTOPTS, .type = XTTYPE_STRING},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static uint32_t
|
||||
parse_opts_num(const char *idstr, const char *typestr)
|
||||
{
|
||||
unsigned long int id;
|
||||
char* ep;
|
||||
|
||||
id = strtoul(idstr, &ep, 0);
|
||||
|
||||
if ( idstr == ep ) {
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"dst: no valid digits in %s `%s'", typestr, idstr);
|
||||
}
|
||||
if ( id == ULONG_MAX && errno == ERANGE ) {
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"%s `%s' specified too big: would overflow",
|
||||
typestr, idstr);
|
||||
}
|
||||
if ( *idstr != '\0' && *ep != '\0' ) {
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"dst: error parsing %s `%s'", typestr, idstr);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_options(const char *optsstr, uint16_t *opts)
|
||||
{
|
||||
char *buffer, *cp, *next, *range;
|
||||
unsigned int i;
|
||||
|
||||
buffer = strdup(optsstr);
|
||||
if (!buffer)
|
||||
xtables_error(OTHER_PROBLEM, "strdup failed");
|
||||
|
||||
for (cp = buffer, i = 0; cp && i < IP6T_OPTS_OPTSNR; cp = next, i++)
|
||||
{
|
||||
next = strchr(cp, ',');
|
||||
|
||||
if (next)
|
||||
*next++='\0';
|
||||
|
||||
range = strchr(cp, ':');
|
||||
|
||||
if (range) {
|
||||
if (i == IP6T_OPTS_OPTSNR-1)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"too many ports specified");
|
||||
*range++ = '\0';
|
||||
}
|
||||
|
||||
opts[i] = (parse_opts_num(cp, "opt") & 0xFF) << 8;
|
||||
if (range) {
|
||||
if (opts[i] == 0)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"PAD0 hasn't got length");
|
||||
opts[i] |= parse_opts_num(range, "length") & 0xFF;
|
||||
} else
|
||||
opts[i] |= (0x00FF);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("opts str: %s %s\n", cp, range);
|
||||
printf("opts opt: %04X\n", opts[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (cp)
|
||||
xtables_error(PARAMETER_PROBLEM, "too many addresses specified");
|
||||
|
||||
free(buffer);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("addr nr: %d\n", i);
|
||||
#endif
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static void dst_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ip6t_opts *optinfo = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_DSTLEN:
|
||||
if (cb->invert)
|
||||
optinfo->invflags |= IP6T_OPTS_INV_LEN;
|
||||
optinfo->flags |= IP6T_OPTS_LEN;
|
||||
break;
|
||||
case O_DSTOPTS:
|
||||
optinfo->optsnr = parse_options(cb->arg, optinfo->opts);
|
||||
optinfo->flags |= IP6T_OPTS_OPTS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_options(unsigned int optsnr, uint16_t *optsp)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
printf(" ");
|
||||
for(i = 0; i < optsnr; i++) {
|
||||
printf("%d", (optsp[i] & 0xFF00) >> 8);
|
||||
|
||||
if ((optsp[i] & 0x00FF) != 0x00FF)
|
||||
printf(":%d", (optsp[i] & 0x00FF));
|
||||
|
||||
printf("%c", (i != optsnr - 1) ? ',' : ' ');
|
||||
}
|
||||
}
|
||||
|
||||
static void dst_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
const struct ip6t_opts *optinfo = (struct ip6t_opts *)match->data;
|
||||
|
||||
printf(" dst");
|
||||
if (optinfo->flags & IP6T_OPTS_LEN)
|
||||
printf(" length:%s%u",
|
||||
optinfo->invflags & IP6T_OPTS_INV_LEN ? "!" : "",
|
||||
optinfo->hdrlen);
|
||||
|
||||
if (optinfo->flags & IP6T_OPTS_OPTS)
|
||||
printf(" opts");
|
||||
|
||||
print_options(optinfo->optsnr, (uint16_t *)optinfo->opts);
|
||||
|
||||
if (optinfo->invflags & ~IP6T_OPTS_INV_MASK)
|
||||
printf(" Unknown invflags: 0x%X",
|
||||
optinfo->invflags & ~IP6T_OPTS_INV_MASK);
|
||||
}
|
||||
|
||||
static void dst_save(const void *ip, const struct xt_entry_match *match)
|
||||
{
|
||||
const struct ip6t_opts *optinfo = (struct ip6t_opts *)match->data;
|
||||
|
||||
if (optinfo->flags & IP6T_OPTS_LEN) {
|
||||
printf("%s --dst-len %u",
|
||||
(optinfo->invflags & IP6T_OPTS_INV_LEN) ? " !" : "",
|
||||
optinfo->hdrlen);
|
||||
}
|
||||
|
||||
if (optinfo->flags & IP6T_OPTS_OPTS)
|
||||
printf(" --dst-opts");
|
||||
|
||||
print_options(optinfo->optsnr, (uint16_t *)optinfo->opts);
|
||||
}
|
||||
|
||||
static struct xtables_match dst_mt6_reg = {
|
||||
.name = "dst",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(struct ip6t_opts)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ip6t_opts)),
|
||||
.help = dst_help,
|
||||
.print = dst_print,
|
||||
.save = dst_save,
|
||||
.x6_parse = dst_parse,
|
||||
.x6_options = dst_opts,
|
||||
};
|
||||
|
||||
void
|
||||
_init(void)
|
||||
{
|
||||
xtables_register_match(&dst_mt6_reg);
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
This module matches the parameters in Destination Options header
|
||||
.TP
|
||||
[\fB!\fP] \fB\-\-dst\-len\fP \fIlength\fP
|
||||
Total length of this header in octets.
|
||||
.TP
|
||||
\fB\-\-dst\-opts\fP \fItype\fP[\fB:\fP\fIlength\fP][\fB,\fP\fItype\fP[\fB:\fP\fIlength\fP]...]
|
||||
numeric type of option and the length of the option data in octets.
|
|
@ -0,0 +1,15 @@
|
|||
/* Shared library add-on to ip6tables to add EUI64 address checking support. */
|
||||
#include <xtables.h>
|
||||
|
||||
static struct xtables_match eui64_mt6_reg = {
|
||||
.name = "eui64",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(int)),
|
||||
.userspacesize = XT_ALIGN(sizeof(int)),
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_match(&eui64_mt6_reg);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
This module matches the EUI-64 part of a stateless autoconfigured IPv6 address.
|
||||
It compares the EUI-64 derived from the source MAC address in Ethernet frame
|
||||
with the lower 64 bits of the IPv6 source address. But "Universal/Local"
|
||||
bit is not compared. This module doesn't match other link layer frame, and
|
||||
is only valid in the
|
||||
.BR PREROUTING ,
|
||||
.BR INPUT
|
||||
and
|
||||
.BR FORWARD
|
||||
chains.
|
|
@ -0,0 +1,194 @@
|
|||
#include <stdio.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_ipv6/ip6t_frag.h>
|
||||
|
||||
enum {
|
||||
O_FRAGID = 0,
|
||||
O_FRAGLEN,
|
||||
O_FRAGRES,
|
||||
O_FRAGFIRST,
|
||||
O_FRAGMORE,
|
||||
O_FRAGLAST,
|
||||
F_FRAGMORE = 1 << O_FRAGMORE,
|
||||
F_FRAGLAST = 1 << O_FRAGLAST,
|
||||
};
|
||||
|
||||
static void frag_help(void)
|
||||
{
|
||||
printf(
|
||||
"frag match options:\n"
|
||||
"[!] --fragid id[:id] match the id (range)\n"
|
||||
"[!] --fraglen length total length of this header\n"
|
||||
" --fragres check the reserved field too\n"
|
||||
" --fragfirst matches on the first fragment\n"
|
||||
" [--fragmore|--fraglast] there are more fragments or this\n"
|
||||
" is the last one\n");
|
||||
}
|
||||
|
||||
#define s struct ip6t_frag
|
||||
static const struct xt_option_entry frag_opts[] = {
|
||||
{.name = "fragid", .id = O_FRAGID, .type = XTTYPE_UINT32RC,
|
||||
.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, ids)},
|
||||
{.name = "fraglen", .id = O_FRAGLEN, .type = XTTYPE_UINT32,
|
||||
.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdrlen)},
|
||||
{.name = "fragres", .id = O_FRAGRES, .type = XTTYPE_NONE},
|
||||
{.name = "fragfirst", .id = O_FRAGFIRST, .type = XTTYPE_NONE},
|
||||
{.name = "fragmore", .id = O_FRAGMORE, .type = XTTYPE_NONE,
|
||||
.excl = F_FRAGLAST},
|
||||
{.name = "fraglast", .id = O_FRAGLAST, .type = XTTYPE_NONE,
|
||||
.excl = F_FRAGMORE},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
#undef s
|
||||
|
||||
static void frag_init(struct xt_entry_match *m)
|
||||
{
|
||||
struct ip6t_frag *fraginfo = (void *)m->data;
|
||||
|
||||
fraginfo->ids[1] = ~0U;
|
||||
}
|
||||
|
||||
static void frag_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ip6t_frag *fraginfo = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_FRAGID:
|
||||
if (cb->nvals == 1)
|
||||
fraginfo->ids[1] = fraginfo->ids[0];
|
||||
if (cb->invert)
|
||||
fraginfo->invflags |= IP6T_FRAG_INV_IDS;
|
||||
/*
|
||||
* Note however that IP6T_FRAG_IDS is not tested by anything,
|
||||
* so it is merely here for completeness.
|
||||
*/
|
||||
fraginfo->flags |= IP6T_FRAG_IDS;
|
||||
break;
|
||||
case O_FRAGLEN:
|
||||
/*
|
||||
* As of Linux 3.0, the kernel does not check for
|
||||
* fraglen at all.
|
||||
*/
|
||||
if (cb->invert)
|
||||
fraginfo->invflags |= IP6T_FRAG_INV_LEN;
|
||||
fraginfo->flags |= IP6T_FRAG_LEN;
|
||||
break;
|
||||
case O_FRAGRES:
|
||||
fraginfo->flags |= IP6T_FRAG_RES;
|
||||
break;
|
||||
case O_FRAGFIRST:
|
||||
fraginfo->flags |= IP6T_FRAG_FST;
|
||||
break;
|
||||
case O_FRAGMORE:
|
||||
fraginfo->flags |= IP6T_FRAG_MF;
|
||||
break;
|
||||
case O_FRAGLAST:
|
||||
fraginfo->flags |= IP6T_FRAG_NMF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_ids(const char *name, uint32_t min, uint32_t max,
|
||||
int invert)
|
||||
{
|
||||
const char *inv = invert ? "!" : "";
|
||||
|
||||
if (min != 0 || max != 0xFFFFFFFF || invert) {
|
||||
printf("%s", name);
|
||||
if (min == max)
|
||||
printf(":%s%u", inv, min);
|
||||
else
|
||||
printf("s:%s%u:%u", inv, min, max);
|
||||
}
|
||||
}
|
||||
|
||||
static void frag_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
const struct ip6t_frag *frag = (struct ip6t_frag *)match->data;
|
||||
|
||||
printf(" frag ");
|
||||
print_ids("id", frag->ids[0], frag->ids[1],
|
||||
frag->invflags & IP6T_FRAG_INV_IDS);
|
||||
|
||||
if (frag->flags & IP6T_FRAG_LEN) {
|
||||
printf(" length:%s%u",
|
||||
frag->invflags & IP6T_FRAG_INV_LEN ? "!" : "",
|
||||
frag->hdrlen);
|
||||
}
|
||||
|
||||
if (frag->flags & IP6T_FRAG_RES)
|
||||
printf(" reserved");
|
||||
|
||||
if (frag->flags & IP6T_FRAG_FST)
|
||||
printf(" first");
|
||||
|
||||
if (frag->flags & IP6T_FRAG_MF)
|
||||
printf(" more");
|
||||
|
||||
if (frag->flags & IP6T_FRAG_NMF)
|
||||
printf(" last");
|
||||
|
||||
if (frag->invflags & ~IP6T_FRAG_INV_MASK)
|
||||
printf(" Unknown invflags: 0x%X",
|
||||
frag->invflags & ~IP6T_FRAG_INV_MASK);
|
||||
}
|
||||
|
||||
static void frag_save(const void *ip, const struct xt_entry_match *match)
|
||||
{
|
||||
const struct ip6t_frag *fraginfo = (struct ip6t_frag *)match->data;
|
||||
|
||||
if (!(fraginfo->ids[0] == 0
|
||||
&& fraginfo->ids[1] == 0xFFFFFFFF)) {
|
||||
printf("%s --fragid ",
|
||||
(fraginfo->invflags & IP6T_FRAG_INV_IDS) ? " !" : "");
|
||||
if (fraginfo->ids[0]
|
||||
!= fraginfo->ids[1])
|
||||
printf("%u:%u",
|
||||
fraginfo->ids[0],
|
||||
fraginfo->ids[1]);
|
||||
else
|
||||
printf("%u",
|
||||
fraginfo->ids[0]);
|
||||
}
|
||||
|
||||
if (fraginfo->flags & IP6T_FRAG_LEN) {
|
||||
printf("%s --fraglen %u",
|
||||
(fraginfo->invflags & IP6T_FRAG_INV_LEN) ? " !" : "",
|
||||
fraginfo->hdrlen);
|
||||
}
|
||||
|
||||
if (fraginfo->flags & IP6T_FRAG_RES)
|
||||
printf(" --fragres");
|
||||
|
||||
if (fraginfo->flags & IP6T_FRAG_FST)
|
||||
printf(" --fragfirst");
|
||||
|
||||
if (fraginfo->flags & IP6T_FRAG_MF)
|
||||
printf(" --fragmore");
|
||||
|
||||
if (fraginfo->flags & IP6T_FRAG_NMF)
|
||||
printf(" --fraglast");
|
||||
}
|
||||
|
||||
static struct xtables_match frag_mt6_reg = {
|
||||
.name = "frag",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(struct ip6t_frag)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ip6t_frag)),
|
||||
.help = frag_help,
|
||||
.init = frag_init,
|
||||
.print = frag_print,
|
||||
.save = frag_save,
|
||||
.x6_parse = frag_parse,
|
||||
.x6_options = frag_opts,
|
||||
};
|
||||
|
||||
void
|
||||
_init(void)
|
||||
{
|
||||
xtables_register_match(&frag_mt6_reg);
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
This module matches the parameters in Fragment header.
|
||||
.TP
|
||||
[\fB!\fP] \fB\-\-fragid\fP \fIid\fP[\fB:\fP\fIid\fP]
|
||||
Matches the given Identification or range of it.
|
||||
.TP
|
||||
[\fB!\fP] \fB\-\-fraglen\fP \fIlength\fP
|
||||
This option cannot be used with kernel version 2.6.10 or later. The length of
|
||||
Fragment header is static and this option doesn't make sense.
|
||||
.TP
|
||||
\fB\-\-fragres\fP
|
||||
Matches if the reserved fields are filled with zero.
|
||||
.TP
|
||||
\fB\-\-fragfirst\fP
|
||||
Matches on the first fragment.
|
||||
.TP
|
||||
\fB\-\-fragmore\fP
|
||||
Matches if there are more fragments.
|
||||
.TP
|
||||
\fB\-\-fraglast\fP
|
||||
Matches if this is the last fragment.
|
|
@ -0,0 +1,184 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_ipv6/ip6t_opts.h>
|
||||
|
||||
#define DEBUG 0
|
||||
|
||||
enum {
|
||||
O_HBH_LEN = 0,
|
||||
O_HBH_OPTS,
|
||||
};
|
||||
|
||||
static void hbh_help(void)
|
||||
{
|
||||
printf(
|
||||
"hbh match options:\n"
|
||||
"[!] --hbh-len length total length of this header\n"
|
||||
" --hbh-opts TYPE[:LEN][,TYPE[:LEN]...] \n"
|
||||
" Options and its length (list, max: %d)\n",
|
||||
IP6T_OPTS_OPTSNR);
|
||||
}
|
||||
|
||||
static const struct xt_option_entry hbh_opts[] = {
|
||||
{.name = "hbh-len", .id = O_HBH_LEN, .type = XTTYPE_UINT32,
|
||||
.flags = XTOPT_INVERT | XTOPT_PUT,
|
||||
XTOPT_POINTER(struct ip6t_opts, hdrlen)},
|
||||
{.name = "hbh-opts", .id = O_HBH_OPTS, .type = XTTYPE_STRING},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static uint32_t
|
||||
parse_opts_num(const char *idstr, const char *typestr)
|
||||
{
|
||||
unsigned long int id;
|
||||
char* ep;
|
||||
|
||||
id = strtoul(idstr,&ep,0) ;
|
||||
|
||||
if ( idstr == ep ) {
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"hbh: no valid digits in %s `%s'", typestr, idstr);
|
||||
}
|
||||
if ( id == ULONG_MAX && errno == ERANGE ) {
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"%s `%s' specified too big: would overflow",
|
||||
typestr, idstr);
|
||||
}
|
||||
if ( *idstr != '\0' && *ep != '\0' ) {
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"hbh: error parsing %s `%s'", typestr, idstr);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_options(const char *optsstr, uint16_t *opts)
|
||||
{
|
||||
char *buffer, *cp, *next, *range;
|
||||
unsigned int i;
|
||||
|
||||
buffer = strdup(optsstr);
|
||||
if (!buffer) xtables_error(OTHER_PROBLEM, "strdup failed");
|
||||
|
||||
for (cp=buffer, i=0; cp && i<IP6T_OPTS_OPTSNR; cp=next,i++)
|
||||
{
|
||||
next=strchr(cp, ',');
|
||||
if (next) *next++='\0';
|
||||
range = strchr(cp, ':');
|
||||
if (range) {
|
||||
if (i == IP6T_OPTS_OPTSNR-1)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"too many ports specified");
|
||||
*range++ = '\0';
|
||||
}
|
||||
opts[i] = (parse_opts_num(cp, "opt") & 0xFF) << 8;
|
||||
if (range) {
|
||||
if (opts[i] == 0)
|
||||
xtables_error(PARAMETER_PROBLEM, "PAD0 has not got length");
|
||||
opts[i] |= parse_opts_num(range, "length") & 0xFF;
|
||||
} else {
|
||||
opts[i] |= (0x00FF);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
printf("opts str: %s %s\n", cp, range);
|
||||
printf("opts opt: %04X\n", opts[i]);
|
||||
#endif
|
||||
}
|
||||
if (cp) xtables_error(PARAMETER_PROBLEM, "too many addresses specified");
|
||||
|
||||
free(buffer);
|
||||
|
||||
#if DEBUG
|
||||
printf("addr nr: %d\n", i);
|
||||
#endif
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static void hbh_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ip6t_opts *optinfo = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_HBH_LEN:
|
||||
if (cb->invert)
|
||||
optinfo->invflags |= IP6T_OPTS_INV_LEN;
|
||||
optinfo->flags |= IP6T_OPTS_LEN;
|
||||
break;
|
||||
case O_HBH_OPTS:
|
||||
optinfo->optsnr = parse_options(cb->arg, optinfo->opts);
|
||||
optinfo->flags |= IP6T_OPTS_OPTS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_options(unsigned int optsnr, uint16_t *optsp)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for(i=0; i<optsnr; i++){
|
||||
printf("%c", (i==0)?' ':',');
|
||||
printf("%d", (optsp[i] & 0xFF00)>>8);
|
||||
if ((optsp[i] & 0x00FF) != 0x00FF){
|
||||
printf(":%d", (optsp[i] & 0x00FF));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void hbh_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
const struct ip6t_opts *optinfo = (struct ip6t_opts *)match->data;
|
||||
|
||||
printf(" hbh");
|
||||
if (optinfo->flags & IP6T_OPTS_LEN) {
|
||||
printf(" length");
|
||||
printf(":%s", optinfo->invflags & IP6T_OPTS_INV_LEN ? "!" : "");
|
||||
printf("%u", optinfo->hdrlen);
|
||||
}
|
||||
if (optinfo->flags & IP6T_OPTS_OPTS) printf(" opts");
|
||||
print_options(optinfo->optsnr, (uint16_t *)optinfo->opts);
|
||||
if (optinfo->invflags & ~IP6T_OPTS_INV_MASK)
|
||||
printf(" Unknown invflags: 0x%X",
|
||||
optinfo->invflags & ~IP6T_OPTS_INV_MASK);
|
||||
}
|
||||
|
||||
static void hbh_save(const void *ip, const struct xt_entry_match *match)
|
||||
{
|
||||
const struct ip6t_opts *optinfo = (struct ip6t_opts *)match->data;
|
||||
|
||||
if (optinfo->flags & IP6T_OPTS_LEN) {
|
||||
printf("%s --hbh-len %u",
|
||||
(optinfo->invflags & IP6T_OPTS_INV_LEN) ? " !" : "",
|
||||
optinfo->hdrlen);
|
||||
}
|
||||
|
||||
if (optinfo->flags & IP6T_OPTS_OPTS)
|
||||
printf(" --hbh-opts");
|
||||
print_options(optinfo->optsnr, (uint16_t *)optinfo->opts);
|
||||
}
|
||||
|
||||
static struct xtables_match hbh_mt6_reg = {
|
||||
.name = "hbh",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(struct ip6t_opts)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ip6t_opts)),
|
||||
.help = hbh_help,
|
||||
.print = hbh_print,
|
||||
.save = hbh_save,
|
||||
.x6_parse = hbh_parse,
|
||||
.x6_options = hbh_opts,
|
||||
};
|
||||
|
||||
void
|
||||
_init(void)
|
||||
{
|
||||
xtables_register_match(&hbh_mt6_reg);
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
This module matches the parameters in Hop-by-Hop Options header
|
||||
.TP
|
||||
[\fB!\fP] \fB\-\-hbh\-len\fP \fIlength\fP
|
||||
Total length of this header in octets.
|
||||
.TP
|
||||
\fB\-\-hbh\-opts\fP \fItype\fP[\fB:\fP\fIlength\fP][\fB,\fP\fItype\fP[\fB:\fP\fIlength\fP]...]
|
||||
numeric type of option and the length of the option data in octets.
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* IPv6 Hop Limit matching module
|
||||
* Maciej Soltysiak <solt@dns.toxicfilms.tv>
|
||||
* Based on HW's ttl match
|
||||
* This program is released under the terms of GNU GPL
|
||||
* Cleanups by Stephane Ouellette <ouellettes@videotron.ca>
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_ipv6/ip6t_hl.h>
|
||||
|
||||
enum {
|
||||
O_HL_EQ = 0,
|
||||
O_HL_LT,
|
||||
O_HL_GT,
|
||||
F_HL_EQ = 1 << O_HL_EQ,
|
||||
F_HL_LT = 1 << O_HL_LT,
|
||||
F_HL_GT = 1 << O_HL_GT,
|
||||
F_ANY = F_HL_EQ | F_HL_LT | F_HL_GT,
|
||||
};
|
||||
|
||||
static void hl_help(void)
|
||||
{
|
||||
printf(
|
||||
"hl match options:\n"
|
||||
"[!] --hl-eq value Match hop limit value\n"
|
||||
" --hl-lt value Match HL < value\n"
|
||||
" --hl-gt value Match HL > value\n");
|
||||
}
|
||||
|
||||
static void hl_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ip6t_hl_info *info = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_HL_EQ:
|
||||
info->mode = cb->invert ? IP6T_HL_NE : IP6T_HL_EQ;
|
||||
break;
|
||||
case O_HL_LT:
|
||||
info->mode = IP6T_HL_LT;
|
||||
break;
|
||||
case O_HL_GT:
|
||||
info->mode = IP6T_HL_GT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void hl_check(struct xt_fcheck_call *cb)
|
||||
{
|
||||
if (!(cb->xflags & F_ANY))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"HL match: You must specify one of "
|
||||
"`--hl-eq', `--hl-lt', `--hl-gt'");
|
||||
}
|
||||
|
||||
static void hl_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
static const char *const op[] = {
|
||||
[IP6T_HL_EQ] = "==",
|
||||
[IP6T_HL_NE] = "!=",
|
||||
[IP6T_HL_LT] = "<",
|
||||
[IP6T_HL_GT] = ">" };
|
||||
|
||||
const struct ip6t_hl_info *info =
|
||||
(struct ip6t_hl_info *) match->data;
|
||||
|
||||
printf(" HL match HL %s %u", op[info->mode], info->hop_limit);
|
||||
}
|
||||
|
||||
static void hl_save(const void *ip, const struct xt_entry_match *match)
|
||||
{
|
||||
static const char *const op[] = {
|
||||
[IP6T_HL_EQ] = "--hl-eq",
|
||||
[IP6T_HL_NE] = "! --hl-eq",
|
||||
[IP6T_HL_LT] = "--hl-lt",
|
||||
[IP6T_HL_GT] = "--hl-gt" };
|
||||
|
||||
const struct ip6t_hl_info *info =
|
||||
(struct ip6t_hl_info *) match->data;
|
||||
|
||||
printf(" %s %u", op[info->mode], info->hop_limit);
|
||||
}
|
||||
|
||||
#define s struct ip6t_hl_info
|
||||
static const struct xt_option_entry hl_opts[] = {
|
||||
{.name = "hl-lt", .id = O_HL_LT, .excl = F_ANY, .type = XTTYPE_UINT8,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(s, hop_limit)},
|
||||
{.name = "hl-gt", .id = O_HL_GT, .excl = F_ANY, .type = XTTYPE_UINT8,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(s, hop_limit)},
|
||||
{.name = "hl-eq", .id = O_HL_EQ, .excl = F_ANY, .type = XTTYPE_UINT8,
|
||||
.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hop_limit)},
|
||||
{.name = "hl", .id = O_HL_EQ, .excl = F_ANY, .type = XTTYPE_UINT8,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(s, hop_limit)},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
#undef s
|
||||
|
||||
static struct xtables_match hl_mt6_reg = {
|
||||
.name = "hl",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(struct ip6t_hl_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ip6t_hl_info)),
|
||||
.help = hl_help,
|
||||
.print = hl_print,
|
||||
.save = hl_save,
|
||||
.x6_parse = hl_parse,
|
||||
.x6_fcheck = hl_check,
|
||||
.x6_options = hl_opts,
|
||||
};
|
||||
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_match(&hl_mt6_reg);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
This module matches the Hop Limit field in the IPv6 header.
|
||||
.TP
|
||||
[\fB!\fP] \fB\-\-hl\-eq\fP \fIvalue\fP
|
||||
Matches if Hop Limit equals \fIvalue\fP.
|
||||
.TP
|
||||
\fB\-\-hl\-lt\fP \fIvalue\fP
|
||||
Matches if Hop Limit is less than \fIvalue\fP.
|
||||
.TP
|
||||
\fB\-\-hl\-gt\fP \fIvalue\fP
|
||||
Matches if Hop Limit is greater than \fIvalue\fP.
|
|
@ -0,0 +1,242 @@
|
|||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <xtables.h>
|
||||
#include <limits.h> /* INT_MAX in ip6_tables.h */
|
||||
#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
|
||||
enum {
|
||||
O_ICMPV6_TYPE = 0,
|
||||
};
|
||||
|
||||
struct icmpv6_names {
|
||||
const char *name;
|
||||
uint8_t type;
|
||||
uint8_t code_min, code_max;
|
||||
};
|
||||
|
||||
static const struct icmpv6_names icmpv6_codes[] = {
|
||||
{ "destination-unreachable", 1, 0, 0xFF },
|
||||
{ "no-route", 1, 0, 0 },
|
||||
{ "communication-prohibited", 1, 1, 1 },
|
||||
{ "beyond-scope", 1, 2, 2 },
|
||||
{ "address-unreachable", 1, 3, 3 },
|
||||
{ "port-unreachable", 1, 4, 4 },
|
||||
{ "failed-policy", 1, 5, 5 },
|
||||
{ "reject-route", 1, 6, 6 },
|
||||
|
||||
{ "packet-too-big", 2, 0, 0xFF },
|
||||
|
||||
{ "time-exceeded", 3, 0, 0xFF },
|
||||
/* Alias */ { "ttl-exceeded", 3, 0, 0xFF },
|
||||
{ "ttl-zero-during-transit", 3, 0, 0 },
|
||||
{ "ttl-zero-during-reassembly", 3, 1, 1 },
|
||||
|
||||
{ "parameter-problem", 4, 0, 0xFF },
|
||||
{ "bad-header", 4, 0, 0 },
|
||||
{ "unknown-header-type", 4, 1, 1 },
|
||||
{ "unknown-option", 4, 2, 2 },
|
||||
|
||||
{ "echo-request", 128, 0, 0xFF },
|
||||
/* Alias */ { "ping", 128, 0, 0xFF },
|
||||
|
||||
{ "echo-reply", 129, 0, 0xFF },
|
||||
/* Alias */ { "pong", 129, 0, 0xFF },
|
||||
|
||||
{ "router-solicitation", 133, 0, 0xFF },
|
||||
|
||||
{ "router-advertisement", 134, 0, 0xFF },
|
||||
|
||||
{ "neighbour-solicitation", 135, 0, 0xFF },
|
||||
/* Alias */ { "neighbor-solicitation", 135, 0, 0xFF },
|
||||
|
||||
{ "neighbour-advertisement", 136, 0, 0xFF },
|
||||
/* Alias */ { "neighbor-advertisement", 136, 0, 0xFF },
|
||||
|
||||
{ "redirect", 137, 0, 0xFF },
|
||||
|
||||
};
|
||||
|
||||
static void
|
||||
print_icmpv6types(void)
|
||||
{
|
||||
unsigned int i;
|
||||
printf("Valid ICMPv6 Types:");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(icmpv6_codes); ++i) {
|
||||
if (i && icmpv6_codes[i].type == icmpv6_codes[i-1].type) {
|
||||
if (icmpv6_codes[i].code_min == icmpv6_codes[i-1].code_min
|
||||
&& (icmpv6_codes[i].code_max
|
||||
== icmpv6_codes[i-1].code_max))
|
||||
printf(" (%s)", icmpv6_codes[i].name);
|
||||
else
|
||||
printf("\n %s", icmpv6_codes[i].name);
|
||||
}
|
||||
else
|
||||
printf("\n%s", icmpv6_codes[i].name);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void icmp6_help(void)
|
||||
{
|
||||
printf(
|
||||
"icmpv6 match options:\n"
|
||||
"[!] --icmpv6-type typename match icmpv6 type\n"
|
||||
" (or numeric type or type/code)\n");
|
||||
print_icmpv6types();
|
||||
}
|
||||
|
||||
static const struct xt_option_entry icmp6_opts[] = {
|
||||
{.name = "icmpv6-type", .id = O_ICMPV6_TYPE, .type = XTTYPE_STRING,
|
||||
.flags = XTOPT_MAND | XTOPT_INVERT},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void
|
||||
parse_icmpv6(const char *icmpv6type, uint8_t *type, uint8_t code[])
|
||||
{
|
||||
static const unsigned int limit = ARRAY_SIZE(icmpv6_codes);
|
||||
unsigned int match = limit;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < limit; i++) {
|
||||
if (strncasecmp(icmpv6_codes[i].name, icmpv6type, strlen(icmpv6type))
|
||||
== 0) {
|
||||
if (match != limit)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Ambiguous ICMPv6 type `%s':"
|
||||
" `%s' or `%s'?",
|
||||
icmpv6type,
|
||||
icmpv6_codes[match].name,
|
||||
icmpv6_codes[i].name);
|
||||
match = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (match != limit) {
|
||||
*type = icmpv6_codes[match].type;
|
||||
code[0] = icmpv6_codes[match].code_min;
|
||||
code[1] = icmpv6_codes[match].code_max;
|
||||
} else {
|
||||
char *slash;
|
||||
char buffer[strlen(icmpv6type) + 1];
|
||||
unsigned int number;
|
||||
|
||||
strcpy(buffer, icmpv6type);
|
||||
slash = strchr(buffer, '/');
|
||||
|
||||
if (slash)
|
||||
*slash = '\0';
|
||||
|
||||
if (!xtables_strtoui(buffer, NULL, &number, 0, UINT8_MAX))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Invalid ICMPv6 type `%s'\n", buffer);
|
||||
*type = number;
|
||||
if (slash) {
|
||||
if (!xtables_strtoui(slash+1, NULL, &number, 0, UINT8_MAX))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Invalid ICMPv6 code `%s'\n",
|
||||
slash+1);
|
||||
code[0] = code[1] = number;
|
||||
} else {
|
||||
code[0] = 0;
|
||||
code[1] = 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void icmp6_init(struct xt_entry_match *m)
|
||||
{
|
||||
struct ip6t_icmp *icmpv6info = (struct ip6t_icmp *)m->data;
|
||||
|
||||
icmpv6info->code[1] = 0xFF;
|
||||
}
|
||||
|
||||
static void icmp6_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ip6t_icmp *icmpv6info = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
parse_icmpv6(cb->arg, &icmpv6info->type, icmpv6info->code);
|
||||
if (cb->invert)
|
||||
icmpv6info->invflags |= IP6T_ICMP_INV;
|
||||
}
|
||||
|
||||
static void print_icmpv6type(uint8_t type,
|
||||
uint8_t code_min, uint8_t code_max,
|
||||
int invert,
|
||||
int numeric)
|
||||
{
|
||||
if (!numeric) {
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(icmpv6_codes); ++i)
|
||||
if (icmpv6_codes[i].type == type
|
||||
&& icmpv6_codes[i].code_min == code_min
|
||||
&& icmpv6_codes[i].code_max == code_max)
|
||||
break;
|
||||
|
||||
if (i != ARRAY_SIZE(icmpv6_codes)) {
|
||||
printf(" %s%s",
|
||||
invert ? "!" : "",
|
||||
icmpv6_codes[i].name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (invert)
|
||||
printf(" !");
|
||||
|
||||
printf("type %u", type);
|
||||
if (code_min == code_max)
|
||||
printf(" code %u", code_min);
|
||||
else if (code_min != 0 || code_max != 0xFF)
|
||||
printf(" codes %u-%u", code_min, code_max);
|
||||
}
|
||||
|
||||
static void icmp6_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
const struct ip6t_icmp *icmpv6 = (struct ip6t_icmp *)match->data;
|
||||
|
||||
printf(" ipv6-icmp");
|
||||
print_icmpv6type(icmpv6->type, icmpv6->code[0], icmpv6->code[1],
|
||||
icmpv6->invflags & IP6T_ICMP_INV,
|
||||
numeric);
|
||||
|
||||
if (icmpv6->invflags & ~IP6T_ICMP_INV)
|
||||
printf(" Unknown invflags: 0x%X",
|
||||
icmpv6->invflags & ~IP6T_ICMP_INV);
|
||||
}
|
||||
|
||||
static void icmp6_save(const void *ip, const struct xt_entry_match *match)
|
||||
{
|
||||
const struct ip6t_icmp *icmpv6 = (struct ip6t_icmp *)match->data;
|
||||
|
||||
if (icmpv6->invflags & IP6T_ICMP_INV)
|
||||
printf(" !");
|
||||
|
||||
printf(" --icmpv6-type %u", icmpv6->type);
|
||||
if (icmpv6->code[0] != 0 || icmpv6->code[1] != 0xFF)
|
||||
printf("/%u", icmpv6->code[0]);
|
||||
}
|
||||
|
||||
static struct xtables_match icmp6_mt6_reg = {
|
||||
.name = "icmp6",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(struct ip6t_icmp)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ip6t_icmp)),
|
||||
.help = icmp6_help,
|
||||
.init = icmp6_init,
|
||||
.print = icmp6_print,
|
||||
.save = icmp6_save,
|
||||
.x6_parse = icmp6_parse,
|
||||
.x6_options = icmp6_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_match(&icmp6_mt6_reg);
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
This extension can be used if `\-\-protocol ipv6\-icmp' or `\-\-protocol icmpv6' is
|
||||
specified. It provides the following option:
|
||||
.TP
|
||||
[\fB!\fP] \fB\-\-icmpv6\-type\fP \fItype\fP[\fB/\fP\fIcode\fP]|\fItypename\fP
|
||||
This allows specification of the ICMPv6 type, which can be a numeric
|
||||
ICMPv6
|
||||
.IR type ,
|
||||
.IR type
|
||||
and
|
||||
.IR code ,
|
||||
or one of the ICMPv6 type names shown by the command
|
||||
.nf
|
||||
ip6tables \-p ipv6\-icmp \-h
|
||||
.fi
|
|
@ -0,0 +1,245 @@
|
|||
/* ipv6header match - matches IPv6 packets based
|
||||
on whether they contain certain headers */
|
||||
|
||||
/* Original idea: Brad Chapman
|
||||
* Rewritten by: Andras Kis-Szabo <kisza@sch.bme.hu> */
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <netdb.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_ipv6/ip6t_ipv6header.h>
|
||||
|
||||
enum {
|
||||
O_HEADER = 0,
|
||||
O_SOFT,
|
||||
};
|
||||
|
||||
/* A few hardcoded protocols for 'all' and in case the user has no
|
||||
* /etc/protocols */
|
||||
struct pprot {
|
||||
char *name;
|
||||
uint8_t num;
|
||||
};
|
||||
|
||||
struct numflag {
|
||||
uint8_t proto;
|
||||
uint8_t flag;
|
||||
};
|
||||
|
||||
static const struct pprot chain_protos[] = {
|
||||
{ "hop-by-hop", IPPROTO_HOPOPTS },
|
||||
{ "protocol", IPPROTO_RAW },
|
||||
{ "hop", IPPROTO_HOPOPTS },
|
||||
{ "dst", IPPROTO_DSTOPTS },
|
||||
{ "route", IPPROTO_ROUTING },
|
||||
{ "frag", IPPROTO_FRAGMENT },
|
||||
{ "auth", IPPROTO_AH },
|
||||
{ "esp", IPPROTO_ESP },
|
||||
{ "none", IPPROTO_NONE },
|
||||
{ "prot", IPPROTO_RAW },
|
||||
{ "0", IPPROTO_HOPOPTS },
|
||||
{ "60", IPPROTO_DSTOPTS },
|
||||
{ "43", IPPROTO_ROUTING },
|
||||
{ "44", IPPROTO_FRAGMENT },
|
||||
{ "51", IPPROTO_AH },
|
||||
{ "50", IPPROTO_ESP },
|
||||
{ "59", IPPROTO_NONE },
|
||||
{ "255", IPPROTO_RAW },
|
||||
/* { "all", 0 }, */
|
||||
};
|
||||
|
||||
static const struct numflag chain_flags[] = {
|
||||
{ IPPROTO_HOPOPTS, MASK_HOPOPTS },
|
||||
{ IPPROTO_DSTOPTS, MASK_DSTOPTS },
|
||||
{ IPPROTO_ROUTING, MASK_ROUTING },
|
||||
{ IPPROTO_FRAGMENT, MASK_FRAGMENT },
|
||||
{ IPPROTO_AH, MASK_AH },
|
||||
{ IPPROTO_ESP, MASK_ESP },
|
||||
{ IPPROTO_NONE, MASK_NONE },
|
||||
{ IPPROTO_RAW, MASK_PROTO },
|
||||
};
|
||||
|
||||
static const char *
|
||||
proto_to_name(uint8_t proto, int nolookup)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (proto && !nolookup) {
|
||||
const struct protoent *pent = getprotobynumber(proto);
|
||||
if (pent)
|
||||
return pent->p_name;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(chain_protos); ++i)
|
||||
if (chain_protos[i].num == proto)
|
||||
return chain_protos[i].name;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
name_to_proto(const char *s)
|
||||
{
|
||||
unsigned int proto=0;
|
||||
const struct protoent *pent;
|
||||
|
||||
if ((pent = getprotobyname(s)))
|
||||
proto = pent->p_proto;
|
||||
else {
|
||||
unsigned int i;
|
||||
for (i = 0; i < ARRAY_SIZE(chain_protos); ++i)
|
||||
if (strcmp(s, chain_protos[i].name) == 0) {
|
||||
proto = chain_protos[i].num;
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(chain_protos))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"unknown header `%s' specified",
|
||||
s);
|
||||
}
|
||||
|
||||
return proto;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
add_proto_to_mask(int proto){
|
||||
unsigned int i=0, flag=0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(chain_flags); ++i)
|
||||
if (proto == chain_flags[i].proto){
|
||||
flag = chain_flags[i].flag;
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(chain_flags))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"unknown header `%d' specified",
|
||||
proto);
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
static void ipv6header_help(void)
|
||||
{
|
||||
printf(
|
||||
"ipv6header match options:\n"
|
||||
"[!] --header headers Type of header to match, by name\n"
|
||||
" names: hop,dst,route,frag,auth,esp,none,prot\n"
|
||||
" long names: hop-by-hop,ipv6-opts,ipv6-route,\n"
|
||||
" ipv6-frag,ah,esp,ipv6-nonxt,protocol\n"
|
||||
" numbers: 0,60,43,44,51,50,59\n"
|
||||
"--soft The header CONTAINS the specified extensions\n");
|
||||
}
|
||||
|
||||
static const struct xt_option_entry ipv6header_opts[] = {
|
||||
{.name = "header", .id = O_HEADER, .type = XTTYPE_STRING,
|
||||
.flags = XTOPT_MAND | XTOPT_INVERT},
|
||||
{.name = "soft", .id = O_SOFT, .type = XTTYPE_NONE},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static unsigned int
|
||||
parse_header(const char *flags) {
|
||||
unsigned int ret = 0;
|
||||
char *ptr;
|
||||
char *buffer;
|
||||
|
||||
buffer = strdup(flags);
|
||||
|
||||
for (ptr = strtok(buffer, ","); ptr; ptr = strtok(NULL, ","))
|
||||
ret |= add_proto_to_mask(name_to_proto(ptr));
|
||||
|
||||
free(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ipv6header_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ip6t_ipv6header_info *info = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_HEADER:
|
||||
if (!(info->matchflags = parse_header(cb->arg)))
|
||||
xtables_error(PARAMETER_PROBLEM, "ip6t_ipv6header: cannot parse header names");
|
||||
if (cb->invert)
|
||||
info->invflags |= 0xFF;
|
||||
break;
|
||||
case O_SOFT:
|
||||
info->modeflag |= 0xFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_header(uint8_t flags){
|
||||
int have_flag = 0;
|
||||
|
||||
while (flags) {
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; (flags & chain_flags[i].flag) == 0; i++);
|
||||
|
||||
if (have_flag)
|
||||
printf(",");
|
||||
|
||||
printf("%s", proto_to_name(chain_flags[i].proto,0));
|
||||
have_flag = 1;
|
||||
|
||||
flags &= ~chain_flags[i].flag;
|
||||
}
|
||||
|
||||
if (!have_flag)
|
||||
printf("NONE");
|
||||
}
|
||||
|
||||
static void ipv6header_print(const void *ip,
|
||||
const struct xt_entry_match *match, int numeric)
|
||||
{
|
||||
const struct ip6t_ipv6header_info *info = (const struct ip6t_ipv6header_info *)match->data;
|
||||
printf(" ipv6header");
|
||||
|
||||
if (info->matchflags || info->invflags) {
|
||||
printf(" flags:%s", info->invflags ? "!" : "");
|
||||
if (numeric)
|
||||
printf("0x%02X", info->matchflags);
|
||||
else {
|
||||
print_header(info->matchflags);
|
||||
}
|
||||
}
|
||||
|
||||
if (info->modeflag)
|
||||
printf(" soft");
|
||||
}
|
||||
|
||||
static void ipv6header_save(const void *ip, const struct xt_entry_match *match)
|
||||
{
|
||||
|
||||
const struct ip6t_ipv6header_info *info = (const struct ip6t_ipv6header_info *)match->data;
|
||||
|
||||
printf("%s --header ", info->invflags ? " !" : "");
|
||||
print_header(info->matchflags);
|
||||
if (info->modeflag)
|
||||
printf(" --soft");
|
||||
}
|
||||
|
||||
static struct xtables_match ipv6header_mt6_reg = {
|
||||
.name = "ipv6header",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(struct ip6t_ipv6header_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ip6t_ipv6header_info)),
|
||||
.help = ipv6header_help,
|
||||
.print = ipv6header_print,
|
||||
.save = ipv6header_save,
|
||||
.x6_parse = ipv6header_parse,
|
||||
.x6_options = ipv6header_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_match(&ipv6header_mt6_reg);
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
This module matches IPv6 extension headers and/or upper layer header.
|
||||
.TP
|
||||
\fB\-\-soft\fP
|
||||
Matches if the packet includes \fBany\fP of the headers specified with
|
||||
\fB\-\-header\fP.
|
||||
.TP
|
||||
[\fB!\fP] \fB\-\-header\fP \fIheader\fP[\fB,\fP\fIheader\fP...]
|
||||
Matches the packet which EXACTLY includes all specified headers. The headers
|
||||
encapsulated with ESP header are out of scope.
|
||||
Possible \fIheader\fP types can be:
|
||||
.TP
|
||||
\fBhop\fP|\fBhop\-by\-hop\fP
|
||||
Hop-by-Hop Options header
|
||||
.TP
|
||||
\fBdst\fP
|
||||
Destination Options header
|
||||
.TP
|
||||
\fBroute\fP
|
||||
Routing header
|
||||
.TP
|
||||
\fBfrag\fP
|
||||
Fragment header
|
||||
.TP
|
||||
\fBauth\fP
|
||||
Authentication header
|
||||
.TP
|
||||
\fBesp\fP
|
||||
Encapsulating Security Payload header
|
||||
.TP
|
||||
\fBnone\fP
|
||||
No Next header which matches 59 in the 'Next Header field' of IPv6 header or
|
||||
any IPv6 extension headers
|
||||
.TP
|
||||
\fBprot\fP
|
||||
which matches any upper layer protocol header. A protocol name from
|
||||
/etc/protocols and numeric value also allowed. The number 255 is equivalent to
|
||||
\fBprot\fP.
|
|
@ -0,0 +1,228 @@
|
|||
/* Shared library add-on to ip6tables to add mobility header support. */
|
||||
/*
|
||||
* Copyright (C)2006 USAGI/WIDE Project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Author:
|
||||
* Masahide NAKAMURA @USAGI <masahide.nakamura.cz@hitachi.com>
|
||||
*
|
||||
* Based on libip6t_{icmpv6,udp}.c
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_ipv6/ip6t_mh.h>
|
||||
|
||||
enum {
|
||||
O_MH_TYPE = 0,
|
||||
};
|
||||
|
||||
struct mh_name {
|
||||
const char *name;
|
||||
uint8_t type;
|
||||
};
|
||||
|
||||
static const struct mh_name mh_names[] = {
|
||||
{ "binding-refresh-request", 0, },
|
||||
/* Alias */ { "brr", 0, },
|
||||
{ "home-test-init", 1, },
|
||||
/* Alias */ { "hoti", 1, },
|
||||
{ "careof-test-init", 2, },
|
||||
/* Alias */ { "coti", 2, },
|
||||
{ "home-test", 3, },
|
||||
/* Alias */ { "hot", 3, },
|
||||
{ "careof-test", 4, },
|
||||
/* Alias */ { "cot", 4, },
|
||||
{ "binding-update", 5, },
|
||||
/* Alias */ { "bu", 5, },
|
||||
{ "binding-acknowledgement", 6, },
|
||||
/* Alias */ { "ba", 6, },
|
||||
{ "binding-error", 7, },
|
||||
/* Alias */ { "be", 7, },
|
||||
};
|
||||
|
||||
static void print_types_all(void)
|
||||
{
|
||||
unsigned int i;
|
||||
printf("Valid MH types:");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mh_names); ++i) {
|
||||
if (i && mh_names[i].type == mh_names[i-1].type)
|
||||
printf(" (%s)", mh_names[i].name);
|
||||
else
|
||||
printf("\n%s", mh_names[i].name);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void mh_help(void)
|
||||
{
|
||||
printf(
|
||||
"mh match options:\n"
|
||||
"[!] --mh-type type[:type] match mh type\n");
|
||||
print_types_all();
|
||||
}
|
||||
|
||||
static void mh_init(struct xt_entry_match *m)
|
||||
{
|
||||
struct ip6t_mh *mhinfo = (struct ip6t_mh *)m->data;
|
||||
|
||||
mhinfo->types[1] = 0xFF;
|
||||
}
|
||||
|
||||
static unsigned int name_to_type(const char *name)
|
||||
{
|
||||
int namelen = strlen(name);
|
||||
static const unsigned int limit = ARRAY_SIZE(mh_names);
|
||||
unsigned int match = limit;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < limit; i++) {
|
||||
if (strncasecmp(mh_names[i].name, name, namelen) == 0) {
|
||||
int len = strlen(mh_names[i].name);
|
||||
if (match == limit || len == namelen)
|
||||
match = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (match != limit) {
|
||||
return mh_names[match].type;
|
||||
} else {
|
||||
unsigned int number;
|
||||
|
||||
if (!xtables_strtoui(name, NULL, &number, 0, UINT8_MAX))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Invalid MH type `%s'\n", name);
|
||||
return number;
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_mh_types(const char *mhtype, uint8_t *types)
|
||||
{
|
||||
char *buffer;
|
||||
char *cp;
|
||||
|
||||
buffer = strdup(mhtype);
|
||||
if ((cp = strchr(buffer, ':')) == NULL)
|
||||
types[0] = types[1] = name_to_type(buffer);
|
||||
else {
|
||||
*cp = '\0';
|
||||
cp++;
|
||||
|
||||
types[0] = buffer[0] ? name_to_type(buffer) : 0;
|
||||
types[1] = cp[0] ? name_to_type(cp) : 0xFF;
|
||||
|
||||
if (types[0] > types[1])
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Invalid MH type range (min > max)");
|
||||
}
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
static void mh_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ip6t_mh *mhinfo = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
parse_mh_types(cb->arg, mhinfo->types);
|
||||
if (cb->invert)
|
||||
mhinfo->invflags |= IP6T_MH_INV_TYPE;
|
||||
}
|
||||
|
||||
static const char *type_to_name(uint8_t type)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mh_names); ++i)
|
||||
if (mh_names[i].type == type)
|
||||
return mh_names[i].name;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void print_type(uint8_t type, int numeric)
|
||||
{
|
||||
const char *name;
|
||||
if (numeric || !(name = type_to_name(type)))
|
||||
printf("%u", type);
|
||||
else
|
||||
printf("%s", name);
|
||||
}
|
||||
|
||||
static void print_types(uint8_t min, uint8_t max, int invert, int numeric)
|
||||
{
|
||||
const char *inv = invert ? "!" : "";
|
||||
|
||||
if (min != 0 || max != 0xFF || invert) {
|
||||
printf(" ");
|
||||
if (min == max) {
|
||||
printf("%s", inv);
|
||||
print_type(min, numeric);
|
||||
} else {
|
||||
printf("%s", inv);
|
||||
print_type(min, numeric);
|
||||
printf(":");
|
||||
print_type(max, numeric);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void mh_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
const struct ip6t_mh *mhinfo = (struct ip6t_mh *)match->data;
|
||||
|
||||
printf(" mh");
|
||||
print_types(mhinfo->types[0], mhinfo->types[1],
|
||||
mhinfo->invflags & IP6T_MH_INV_TYPE,
|
||||
numeric);
|
||||
if (mhinfo->invflags & ~IP6T_MH_INV_MASK)
|
||||
printf(" Unknown invflags: 0x%X",
|
||||
mhinfo->invflags & ~IP6T_MH_INV_MASK);
|
||||
}
|
||||
|
||||
static void mh_save(const void *ip, const struct xt_entry_match *match)
|
||||
{
|
||||
const struct ip6t_mh *mhinfo = (struct ip6t_mh *)match->data;
|
||||
|
||||
if (mhinfo->types[0] == 0 && mhinfo->types[1] == 0xFF)
|
||||
return;
|
||||
|
||||
if (mhinfo->invflags & IP6T_MH_INV_TYPE)
|
||||
printf(" !");
|
||||
|
||||
if (mhinfo->types[0] != mhinfo->types[1])
|
||||
printf(" --mh-type %u:%u", mhinfo->types[0], mhinfo->types[1]);
|
||||
else
|
||||
printf(" --mh-type %u", mhinfo->types[0]);
|
||||
}
|
||||
|
||||
static const struct xt_option_entry mh_opts[] = {
|
||||
{.name = "mh-type", .id = O_MH_TYPE, .type = XTTYPE_STRING,
|
||||
.flags = XTOPT_INVERT},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static struct xtables_match mh_mt6_reg = {
|
||||
.name = "mh",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(struct ip6t_mh)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ip6t_mh)),
|
||||
.help = mh_help,
|
||||
.init = mh_init,
|
||||
.x6_parse = mh_parse,
|
||||
.print = mh_print,
|
||||
.save = mh_save,
|
||||
.x6_options = mh_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_match(&mh_mt6_reg);
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
This extension is loaded if `\-\-protocol ipv6\-mh' or `\-\-protocol mh' is
|
||||
specified. It provides the following option:
|
||||
.TP
|
||||
[\fB!\fP] \fB\-\-mh\-type\fP \fItype\fP[\fB:\fP\fItype\fP]
|
||||
This allows specification of the Mobility Header(MH) type, which can be
|
||||
a numeric MH
|
||||
.IR type ,
|
||||
.IR type
|
||||
or one of the MH type names shown by the command
|
||||
.nf
|
||||
ip6tables \-p mh \-h
|
||||
.fi
|
|
@ -0,0 +1,266 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_ipv6/ip6t_rt.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
enum {
|
||||
O_RT_TYPE = 0,
|
||||
O_RT_SEGSLEFT,
|
||||
O_RT_LEN,
|
||||
O_RT0RES,
|
||||
O_RT0ADDRS,
|
||||
O_RT0NSTRICT,
|
||||
F_RT_TYPE = 1 << O_RT_TYPE,
|
||||
F_RT0ADDRS = 1 << O_RT0ADDRS,
|
||||
};
|
||||
|
||||
static void rt_help(void)
|
||||
{
|
||||
printf(
|
||||
"rt match options:\n"
|
||||
"[!] --rt-type type match the type\n"
|
||||
"[!] --rt-segsleft num[:num] match the Segments Left field (range)\n"
|
||||
"[!] --rt-len length total length of this header\n"
|
||||
" --rt-0-res check the reserved field too (type 0)\n"
|
||||
" --rt-0-addrs ADDR[,ADDR...] Type=0 addresses (list, max: %d)\n"
|
||||
" --rt-0-not-strict List of Type=0 addresses not a strict list\n",
|
||||
IP6T_RT_HOPS);
|
||||
}
|
||||
|
||||
#define s struct ip6t_rt
|
||||
static const struct xt_option_entry rt_opts[] = {
|
||||
{.name = "rt-type", .id = O_RT_TYPE, .type = XTTYPE_UINT32,
|
||||
.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, rt_type)},
|
||||
{.name = "rt-segsleft", .id = O_RT_SEGSLEFT, .type = XTTYPE_UINT32RC,
|
||||
.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, segsleft)},
|
||||
{.name = "rt-len", .id = O_RT_LEN, .type = XTTYPE_UINT32,
|
||||
.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdrlen)},
|
||||
{.name = "rt-0-res", .id = O_RT0RES, .type = XTTYPE_NONE},
|
||||
{.name = "rt-0-addrs", .id = O_RT0ADDRS, .type = XTTYPE_STRING},
|
||||
{.name = "rt-0-not-strict", .id = O_RT0NSTRICT, .type = XTTYPE_NONE},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
#undef s
|
||||
|
||||
static const char *
|
||||
addr_to_numeric(const struct in6_addr *addrp)
|
||||
{
|
||||
static char buf[50+1];
|
||||
return inet_ntop(AF_INET6, addrp, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
static struct in6_addr *
|
||||
numeric_to_addr(const char *num)
|
||||
{
|
||||
static struct in6_addr ap;
|
||||
int err;
|
||||
|
||||
if ((err=inet_pton(AF_INET6, num, &ap)) == 1)
|
||||
return ≈
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "\nnumeric2addr: %d\n", err);
|
||||
#endif
|
||||
xtables_error(PARAMETER_PROBLEM, "bad address: %s", num);
|
||||
|
||||
return (struct in6_addr *)NULL;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
parse_addresses(const char *addrstr, struct in6_addr *addrp)
|
||||
{
|
||||
char *buffer, *cp, *next;
|
||||
unsigned int i;
|
||||
|
||||
buffer = strdup(addrstr);
|
||||
if (!buffer) xtables_error(OTHER_PROBLEM, "strdup failed");
|
||||
|
||||
for (cp=buffer, i=0; cp && i<IP6T_RT_HOPS; cp=next,i++)
|
||||
{
|
||||
next=strchr(cp, ',');
|
||||
if (next) *next++='\0';
|
||||
memcpy(&(addrp[i]), numeric_to_addr(cp), sizeof(struct in6_addr));
|
||||
#if DEBUG
|
||||
printf("addr str: %s\n", cp);
|
||||
printf("addr ip6: %s\n", addr_to_numeric((numeric_to_addr(cp))));
|
||||
printf("addr [%d]: %s\n", i, addr_to_numeric(&(addrp[i])));
|
||||
#endif
|
||||
}
|
||||
if (cp) xtables_error(PARAMETER_PROBLEM, "too many addresses specified");
|
||||
|
||||
free(buffer);
|
||||
|
||||
#if DEBUG
|
||||
printf("addr nr: %d\n", i);
|
||||
#endif
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static void rt_init(struct xt_entry_match *m)
|
||||
{
|
||||
struct ip6t_rt *rtinfo = (void *)m->data;
|
||||
|
||||
rtinfo->segsleft[1] = ~0U;
|
||||
}
|
||||
|
||||
static void rt_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ip6t_rt *rtinfo = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_RT_TYPE:
|
||||
if (cb->invert)
|
||||
rtinfo->invflags |= IP6T_RT_INV_TYP;
|
||||
rtinfo->flags |= IP6T_RT_TYP;
|
||||
break;
|
||||
case O_RT_SEGSLEFT:
|
||||
if (cb->nvals == 1)
|
||||
rtinfo->segsleft[1] = rtinfo->segsleft[0];
|
||||
if (cb->invert)
|
||||
rtinfo->invflags |= IP6T_RT_INV_SGS;
|
||||
rtinfo->flags |= IP6T_RT_SGS;
|
||||
break;
|
||||
case O_RT_LEN:
|
||||
if (cb->invert)
|
||||
rtinfo->invflags |= IP6T_RT_INV_LEN;
|
||||
rtinfo->flags |= IP6T_RT_LEN;
|
||||
break;
|
||||
case O_RT0RES:
|
||||
if (!(cb->xflags & F_RT_TYPE) || rtinfo->rt_type != 0 ||
|
||||
rtinfo->invflags & IP6T_RT_INV_TYP)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"`--rt-type 0' required before `--rt-0-res'");
|
||||
rtinfo->flags |= IP6T_RT_RES;
|
||||
break;
|
||||
case O_RT0ADDRS:
|
||||
if (!(cb->xflags & F_RT_TYPE) || rtinfo->rt_type != 0 ||
|
||||
rtinfo->invflags & IP6T_RT_INV_TYP)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"`--rt-type 0' required before `--rt-0-addrs'");
|
||||
rtinfo->addrnr = parse_addresses(cb->arg, rtinfo->addrs);
|
||||
rtinfo->flags |= IP6T_RT_FST;
|
||||
break;
|
||||
case O_RT0NSTRICT:
|
||||
if (!(cb->xflags & F_RT0ADDRS))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"`--rt-0-addr ...' required before `--rt-0-not-strict'");
|
||||
rtinfo->flags |= IP6T_RT_FST_NSTRICT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_nums(const char *name, uint32_t min, uint32_t max,
|
||||
int invert)
|
||||
{
|
||||
const char *inv = invert ? "!" : "";
|
||||
|
||||
if (min != 0 || max != 0xFFFFFFFF || invert) {
|
||||
printf(" %s", name);
|
||||
if (min == max) {
|
||||
printf(":%s", inv);
|
||||
printf("%u", min);
|
||||
} else {
|
||||
printf("s:%s", inv);
|
||||
printf("%u",min);
|
||||
printf(":");
|
||||
printf("%u",max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_addresses(unsigned int addrnr, struct in6_addr *addrp)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for(i=0; i<addrnr; i++){
|
||||
printf("%c%s", (i==0)?' ':',', addr_to_numeric(&(addrp[i])));
|
||||
}
|
||||
}
|
||||
|
||||
static void rt_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
const struct ip6t_rt *rtinfo = (struct ip6t_rt *)match->data;
|
||||
|
||||
printf(" rt");
|
||||
if (rtinfo->flags & IP6T_RT_TYP)
|
||||
printf(" type:%s%d", rtinfo->invflags & IP6T_RT_INV_TYP ? "!" : "",
|
||||
rtinfo->rt_type);
|
||||
print_nums("segsleft", rtinfo->segsleft[0], rtinfo->segsleft[1],
|
||||
rtinfo->invflags & IP6T_RT_INV_SGS);
|
||||
if (rtinfo->flags & IP6T_RT_LEN) {
|
||||
printf(" length");
|
||||
printf(":%s", rtinfo->invflags & IP6T_RT_INV_LEN ? "!" : "");
|
||||
printf("%u", rtinfo->hdrlen);
|
||||
}
|
||||
if (rtinfo->flags & IP6T_RT_RES) printf(" reserved");
|
||||
if (rtinfo->flags & IP6T_RT_FST) printf(" 0-addrs");
|
||||
print_addresses(rtinfo->addrnr, (struct in6_addr *)rtinfo->addrs);
|
||||
if (rtinfo->flags & IP6T_RT_FST_NSTRICT) printf(" 0-not-strict");
|
||||
if (rtinfo->invflags & ~IP6T_RT_INV_MASK)
|
||||
printf(" Unknown invflags: 0x%X",
|
||||
rtinfo->invflags & ~IP6T_RT_INV_MASK);
|
||||
}
|
||||
|
||||
static void rt_save(const void *ip, const struct xt_entry_match *match)
|
||||
{
|
||||
const struct ip6t_rt *rtinfo = (struct ip6t_rt *)match->data;
|
||||
|
||||
if (rtinfo->flags & IP6T_RT_TYP) {
|
||||
printf("%s --rt-type %u",
|
||||
(rtinfo->invflags & IP6T_RT_INV_TYP) ? " !" : "",
|
||||
rtinfo->rt_type);
|
||||
}
|
||||
|
||||
if (!(rtinfo->segsleft[0] == 0
|
||||
&& rtinfo->segsleft[1] == 0xFFFFFFFF)) {
|
||||
printf("%s --rt-segsleft ",
|
||||
(rtinfo->invflags & IP6T_RT_INV_SGS) ? " !" : "");
|
||||
if (rtinfo->segsleft[0]
|
||||
!= rtinfo->segsleft[1])
|
||||
printf("%u:%u",
|
||||
rtinfo->segsleft[0],
|
||||
rtinfo->segsleft[1]);
|
||||
else
|
||||
printf("%u",
|
||||
rtinfo->segsleft[0]);
|
||||
}
|
||||
|
||||
if (rtinfo->flags & IP6T_RT_LEN) {
|
||||
printf("%s --rt-len %u",
|
||||
(rtinfo->invflags & IP6T_RT_INV_LEN) ? " !" : "",
|
||||
rtinfo->hdrlen);
|
||||
}
|
||||
|
||||
if (rtinfo->flags & IP6T_RT_RES) printf(" --rt-0-res");
|
||||
if (rtinfo->flags & IP6T_RT_FST) printf(" --rt-0-addrs");
|
||||
print_addresses(rtinfo->addrnr, (struct in6_addr *)rtinfo->addrs);
|
||||
if (rtinfo->flags & IP6T_RT_FST_NSTRICT) printf(" --rt-0-not-strict");
|
||||
|
||||
}
|
||||
|
||||
static struct xtables_match rt_mt6_reg = {
|
||||
.name = "rt",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(struct ip6t_rt)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ip6t_rt)),
|
||||
.help = rt_help,
|
||||
.init = rt_init,
|
||||
.x6_parse = rt_parse,
|
||||
.print = rt_print,
|
||||
.save = rt_save,
|
||||
.x6_options = rt_opts,
|
||||
};
|
||||
|
||||
void
|
||||
_init(void)
|
||||
{
|
||||
xtables_register_match(&rt_mt6_reg);
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
Match on IPv6 routing header
|
||||
.TP
|
||||
[\fB!\fP] \fB\-\-rt\-type\fP \fItype\fP
|
||||
Match the type (numeric).
|
||||
.TP
|
||||
[\fB!\fP] \fB\-\-rt\-segsleft\fP \fInum\fP[\fB:\fP\fInum\fP]
|
||||
Match the `segments left' field (range).
|
||||
.TP
|
||||
[\fB!\fP] \fB\-\-rt\-len\fP \fIlength\fP
|
||||
Match the length of this header.
|
||||
.TP
|
||||
\fB\-\-rt\-0\-res\fP
|
||||
Match the reserved field, too (type=0)
|
||||
.TP
|
||||
\fB\-\-rt\-0\-addrs\fP \fIaddr\fP[\fB,\fP\fIaddr\fP...]
|
||||
Match type=0 addresses (list).
|
||||
.TP
|
||||
\fB\-\-rt\-0\-not\-strict\fP
|
||||
List of type=0 addresses is not a strict list.
|
|
@ -0,0 +1,195 @@
|
|||
/* Shared library add-on to iptables to add CLUSTERIP target support.
|
||||
* (C) 2003 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* Development of this code was funded by SuSE AG, http://www.suse.com/
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined(__GLIBC__) && __GLIBC__ == 2
|
||||
#include <net/ethernet.h>
|
||||
#else
|
||||
#include <linux/if_ether.h>
|
||||
#endif
|
||||
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_ipv4/ipt_CLUSTERIP.h>
|
||||
|
||||
enum {
|
||||
O_NEW = 0,
|
||||
O_HASHMODE,
|
||||
O_CLUSTERMAC,
|
||||
O_TOTAL_NODES,
|
||||
O_LOCAL_NODE,
|
||||
O_HASH_INIT,
|
||||
F_NEW = 1 << O_NEW,
|
||||
F_HASHMODE = 1 << O_HASHMODE,
|
||||
F_CLUSTERMAC = 1 << O_CLUSTERMAC,
|
||||
F_TOTAL_NODES = 1 << O_TOTAL_NODES,
|
||||
F_LOCAL_NODE = 1 << O_LOCAL_NODE,
|
||||
F_FULL = F_NEW | F_HASHMODE | F_CLUSTERMAC |
|
||||
F_TOTAL_NODES | F_LOCAL_NODE,
|
||||
};
|
||||
|
||||
static void CLUSTERIP_help(void)
|
||||
{
|
||||
printf(
|
||||
"CLUSTERIP target options:\n"
|
||||
" --new Create a new ClusterIP\n"
|
||||
" --hashmode <mode> Specify hashing mode\n"
|
||||
" sourceip\n"
|
||||
" sourceip-sourceport\n"
|
||||
" sourceip-sourceport-destport\n"
|
||||
" --clustermac <mac> Set clusterIP MAC address\n"
|
||||
" --total-nodes <num> Set number of total nodes in cluster\n"
|
||||
" --local-node <num> Set the local node number\n"
|
||||
" --hash-init <num> Set init value of the Jenkins hash\n");
|
||||
}
|
||||
|
||||
#define s struct ipt_clusterip_tgt_info
|
||||
static const struct xt_option_entry CLUSTERIP_opts[] = {
|
||||
{.name = "new", .id = O_NEW, .type = XTTYPE_NONE},
|
||||
{.name = "hashmode", .id = O_HASHMODE, .type = XTTYPE_STRING,
|
||||
.also = O_NEW},
|
||||
{.name = "clustermac", .id = O_CLUSTERMAC, .type = XTTYPE_ETHERMAC,
|
||||
.also = O_NEW, .flags = XTOPT_PUT, XTOPT_POINTER(s, clustermac)},
|
||||
{.name = "total-nodes", .id = O_TOTAL_NODES, .type = XTTYPE_UINT16,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(s, num_total_nodes),
|
||||
.also = O_NEW, .max = CLUSTERIP_MAX_NODES},
|
||||
{.name = "local-node", .id = O_LOCAL_NODE, .type = XTTYPE_UINT16,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(s, local_nodes[0]),
|
||||
.also = O_NEW, .max = CLUSTERIP_MAX_NODES},
|
||||
{.name = "hash-init", .id = O_HASH_INIT, .type = XTTYPE_UINT32,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(s, hash_initval),
|
||||
.also = O_NEW, .max = UINT_MAX},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
#undef s
|
||||
|
||||
static void CLUSTERIP_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ipt_clusterip_tgt_info *cipinfo = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_NEW:
|
||||
cipinfo->flags |= CLUSTERIP_FLAG_NEW;
|
||||
break;
|
||||
case O_HASHMODE:
|
||||
if (strcmp(cb->arg, "sourceip") == 0)
|
||||
cipinfo->hash_mode = CLUSTERIP_HASHMODE_SIP;
|
||||
else if (strcmp(cb->arg, "sourceip-sourceport") == 0)
|
||||
cipinfo->hash_mode = CLUSTERIP_HASHMODE_SIP_SPT;
|
||||
else if (strcmp(cb->arg, "sourceip-sourceport-destport") == 0)
|
||||
cipinfo->hash_mode = CLUSTERIP_HASHMODE_SIP_SPT_DPT;
|
||||
else
|
||||
xtables_error(PARAMETER_PROBLEM, "Unknown hashmode \"%s\"\n",
|
||||
cb->arg);
|
||||
break;
|
||||
case O_CLUSTERMAC:
|
||||
if (!(cipinfo->clustermac[0] & 0x01))
|
||||
xtables_error(PARAMETER_PROBLEM, "MAC has to be a multicast ethernet address\n");
|
||||
break;
|
||||
case O_LOCAL_NODE:
|
||||
cipinfo->num_local_nodes = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void CLUSTERIP_check(struct xt_fcheck_call *cb)
|
||||
{
|
||||
if (cb->xflags == 0)
|
||||
return;
|
||||
if ((cb->xflags & F_FULL) == F_FULL)
|
||||
return;
|
||||
|
||||
xtables_error(PARAMETER_PROBLEM, "CLUSTERIP target: Invalid parameter combination\n");
|
||||
}
|
||||
|
||||
static const char *hashmode2str(enum clusterip_hashmode mode)
|
||||
{
|
||||
const char *retstr;
|
||||
switch (mode) {
|
||||
case CLUSTERIP_HASHMODE_SIP:
|
||||
retstr = "sourceip";
|
||||
break;
|
||||
case CLUSTERIP_HASHMODE_SIP_SPT:
|
||||
retstr = "sourceip-sourceport";
|
||||
break;
|
||||
case CLUSTERIP_HASHMODE_SIP_SPT_DPT:
|
||||
retstr = "sourceip-sourceport-destport";
|
||||
break;
|
||||
default:
|
||||
retstr = "unknown-error";
|
||||
break;
|
||||
}
|
||||
return retstr;
|
||||
}
|
||||
|
||||
static const char *mac2str(const uint8_t mac[ETH_ALEN])
|
||||
{
|
||||
static char buf[ETH_ALEN*3];
|
||||
sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
|
||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void CLUSTERIP_print(const void *ip,
|
||||
const struct xt_entry_target *target, int numeric)
|
||||
{
|
||||
const struct ipt_clusterip_tgt_info *cipinfo =
|
||||
(const struct ipt_clusterip_tgt_info *)target->data;
|
||||
|
||||
if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) {
|
||||
printf(" CLUSTERIP");
|
||||
return;
|
||||
}
|
||||
|
||||
printf(" CLUSTERIP hashmode=%s clustermac=%s total_nodes=%u local_node=%u hash_init=%u",
|
||||
hashmode2str(cipinfo->hash_mode),
|
||||
mac2str(cipinfo->clustermac),
|
||||
cipinfo->num_total_nodes,
|
||||
cipinfo->local_nodes[0],
|
||||
cipinfo->hash_initval);
|
||||
}
|
||||
|
||||
static void CLUSTERIP_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct ipt_clusterip_tgt_info *cipinfo =
|
||||
(const struct ipt_clusterip_tgt_info *)target->data;
|
||||
|
||||
/* if this is not a new entry, we don't need to save target
|
||||
* parameters */
|
||||
if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW))
|
||||
return;
|
||||
|
||||
printf(" --new --hashmode %s --clustermac %s --total-nodes %d --local-node %d --hash-init %u",
|
||||
hashmode2str(cipinfo->hash_mode),
|
||||
mac2str(cipinfo->clustermac),
|
||||
cipinfo->num_total_nodes,
|
||||
cipinfo->local_nodes[0],
|
||||
cipinfo->hash_initval);
|
||||
}
|
||||
|
||||
static struct xtables_target clusterip_tg_reg = {
|
||||
.name = "CLUSTERIP",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV4,
|
||||
.size = XT_ALIGN(sizeof(struct ipt_clusterip_tgt_info)),
|
||||
.userspacesize = offsetof(struct ipt_clusterip_tgt_info, config),
|
||||
.help = CLUSTERIP_help,
|
||||
.x6_parse = CLUSTERIP_parse,
|
||||
.x6_fcheck = CLUSTERIP_check,
|
||||
.print = CLUSTERIP_print,
|
||||
.save = CLUSTERIP_save,
|
||||
.x6_options = CLUSTERIP_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&clusterip_tg_reg);
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
This module allows you to configure a simple cluster of nodes that share
|
||||
a certain IP and MAC address without an explicit load balancer in front of
|
||||
them. Connections are statically distributed between the nodes in this
|
||||
cluster.
|
||||
.TP
|
||||
\fB\-\-new\fP
|
||||
Create a new ClusterIP. You always have to set this on the first rule
|
||||
for a given ClusterIP.
|
||||
.TP
|
||||
\fB\-\-hashmode\fP \fImode\fP
|
||||
Specify the hashing mode. Has to be one of
|
||||
\fBsourceip\fP, \fBsourceip\-sourceport\fP, \fBsourceip\-sourceport\-destport\fP.
|
||||
.TP
|
||||
\fB\-\-clustermac\fP \fImac\fP
|
||||
Specify the ClusterIP MAC address. Has to be a link\-layer multicast address
|
||||
.TP
|
||||
\fB\-\-total\-nodes\fP \fInum\fP
|
||||
Number of total nodes within this cluster.
|
||||
.TP
|
||||
\fB\-\-local\-node\fP \fInum\fP
|
||||
Local node number within this cluster.
|
||||
.TP
|
||||
\fB\-\-hash\-init\fP \fIrnd\fP
|
||||
Specify the random seed used for hash initialization.
|
|
@ -0,0 +1,262 @@
|
|||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <xtables.h>
|
||||
#include <iptables.h> /* get_kernel_version */
|
||||
#include <limits.h> /* INT_MAX in ip_tables.h */
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include <linux/netfilter/nf_nat.h>
|
||||
|
||||
enum {
|
||||
O_TO_DEST = 0,
|
||||
O_RANDOM,
|
||||
O_PERSISTENT,
|
||||
O_X_TO_DEST, /* hidden flag */
|
||||
F_TO_DEST = 1 << O_TO_DEST,
|
||||
F_RANDOM = 1 << O_RANDOM,
|
||||
F_X_TO_DEST = 1 << O_X_TO_DEST,
|
||||
};
|
||||
|
||||
/* Dest NAT data consists of a multi-range, indicating where to map
|
||||
to. */
|
||||
struct ipt_natinfo
|
||||
{
|
||||
struct xt_entry_target t;
|
||||
struct nf_nat_ipv4_multi_range_compat mr;
|
||||
};
|
||||
|
||||
static void DNAT_help(void)
|
||||
{
|
||||
printf(
|
||||
"DNAT target options:\n"
|
||||
" --to-destination [<ipaddr>[-<ipaddr>]][:port[-port]]\n"
|
||||
" Address to map destination to.\n"
|
||||
"[--random] [--persistent]\n");
|
||||
}
|
||||
|
||||
static const struct xt_option_entry DNAT_opts[] = {
|
||||
{.name = "to-destination", .id = O_TO_DEST, .type = XTTYPE_STRING,
|
||||
.flags = XTOPT_MAND | XTOPT_MULTI},
|
||||
{.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
|
||||
{.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static struct ipt_natinfo *
|
||||
append_range(struct ipt_natinfo *info, const struct nf_nat_ipv4_range *range)
|
||||
{
|
||||
unsigned int size;
|
||||
|
||||
/* One rangesize already in struct ipt_natinfo */
|
||||
size = XT_ALIGN(sizeof(*info) + info->mr.rangesize * sizeof(*range));
|
||||
|
||||
info = realloc(info, size);
|
||||
if (!info)
|
||||
xtables_error(OTHER_PROBLEM, "Out of memory\n");
|
||||
|
||||
info->t.u.target_size = size;
|
||||
info->mr.range[info->mr.rangesize] = *range;
|
||||
info->mr.rangesize++;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
/* Ranges expected in network order. */
|
||||
static struct xt_entry_target *
|
||||
parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info)
|
||||
{
|
||||
struct nf_nat_ipv4_range range;
|
||||
char *arg, *colon, *dash, *error;
|
||||
const struct in_addr *ip;
|
||||
|
||||
arg = strdup(orig_arg);
|
||||
if (arg == NULL)
|
||||
xtables_error(RESOURCE_PROBLEM, "strdup");
|
||||
memset(&range, 0, sizeof(range));
|
||||
colon = strchr(arg, ':');
|
||||
|
||||
if (colon) {
|
||||
int port;
|
||||
|
||||
if (!portok)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Need TCP, UDP, SCTP or DCCP with port specification");
|
||||
|
||||
range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
|
||||
|
||||
port = atoi(colon+1);
|
||||
if (port <= 0 || port > 65535)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Port `%s' not valid\n", colon+1);
|
||||
|
||||
error = strchr(colon+1, ':');
|
||||
if (error)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Invalid port:port syntax - use dash\n");
|
||||
|
||||
dash = strchr(colon, '-');
|
||||
if (!dash) {
|
||||
range.min.tcp.port
|
||||
= range.max.tcp.port
|
||||
= htons(port);
|
||||
} else {
|
||||
int maxport;
|
||||
|
||||
maxport = atoi(dash + 1);
|
||||
if (maxport <= 0 || maxport > 65535)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Port `%s' not valid\n", dash+1);
|
||||
if (maxport < port)
|
||||
/* People are stupid. */
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Port range `%s' funky\n", colon+1);
|
||||
range.min.tcp.port = htons(port);
|
||||
range.max.tcp.port = htons(maxport);
|
||||
}
|
||||
/* Starts with a colon? No IP info...*/
|
||||
if (colon == arg) {
|
||||
free(arg);
|
||||
return &(append_range(info, &range)->t);
|
||||
}
|
||||
*colon = '\0';
|
||||
}
|
||||
|
||||
range.flags |= NF_NAT_RANGE_MAP_IPS;
|
||||
dash = strchr(arg, '-');
|
||||
if (colon && dash && dash > colon)
|
||||
dash = NULL;
|
||||
|
||||
if (dash)
|
||||
*dash = '\0';
|
||||
|
||||
ip = xtables_numeric_to_ipaddr(arg);
|
||||
if (!ip)
|
||||
xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
|
||||
arg);
|
||||
range.min_ip = ip->s_addr;
|
||||
if (dash) {
|
||||
ip = xtables_numeric_to_ipaddr(dash+1);
|
||||
if (!ip)
|
||||
xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
|
||||
dash+1);
|
||||
range.max_ip = ip->s_addr;
|
||||
} else
|
||||
range.max_ip = range.min_ip;
|
||||
|
||||
free(arg);
|
||||
return &(append_range(info, &range)->t);
|
||||
}
|
||||
|
||||
static void DNAT_parse(struct xt_option_call *cb)
|
||||
{
|
||||
const struct ipt_entry *entry = cb->xt_entry;
|
||||
struct ipt_natinfo *info = (void *)(*cb->target);
|
||||
int portok;
|
||||
|
||||
if (entry->ip.proto == IPPROTO_TCP
|
||||
|| entry->ip.proto == IPPROTO_UDP
|
||||
|| entry->ip.proto == IPPROTO_SCTP
|
||||
|| entry->ip.proto == IPPROTO_DCCP
|
||||
|| entry->ip.proto == IPPROTO_ICMP)
|
||||
portok = 1;
|
||||
else
|
||||
portok = 0;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_TO_DEST:
|
||||
if (cb->xflags & F_X_TO_DEST) {
|
||||
if (!kernel_version)
|
||||
get_kernel_version();
|
||||
if (kernel_version > LINUX_VERSION(2, 6, 10))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"DNAT: Multiple --to-destination not supported");
|
||||
}
|
||||
*cb->target = parse_to(cb->arg, portok, info);
|
||||
cb->xflags |= F_X_TO_DEST;
|
||||
break;
|
||||
case O_PERSISTENT:
|
||||
info->mr.range[0].flags |= NF_NAT_RANGE_PERSISTENT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void DNAT_fcheck(struct xt_fcheck_call *cb)
|
||||
{
|
||||
static const unsigned int f = F_TO_DEST | F_RANDOM;
|
||||
struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
|
||||
|
||||
if ((cb->xflags & f) == f)
|
||||
mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM;
|
||||
}
|
||||
|
||||
static void print_range(const struct nf_nat_ipv4_range *r)
|
||||
{
|
||||
if (r->flags & NF_NAT_RANGE_MAP_IPS) {
|
||||
struct in_addr a;
|
||||
|
||||
a.s_addr = r->min_ip;
|
||||
printf("%s", xtables_ipaddr_to_numeric(&a));
|
||||
if (r->max_ip != r->min_ip) {
|
||||
a.s_addr = r->max_ip;
|
||||
printf("-%s", xtables_ipaddr_to_numeric(&a));
|
||||
}
|
||||
}
|
||||
if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
|
||||
printf(":");
|
||||
printf("%hu", ntohs(r->min.tcp.port));
|
||||
if (r->max.tcp.port != r->min.tcp.port)
|
||||
printf("-%hu", ntohs(r->max.tcp.port));
|
||||
}
|
||||
}
|
||||
|
||||
static void DNAT_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct ipt_natinfo *info = (const void *)target;
|
||||
unsigned int i = 0;
|
||||
|
||||
printf(" to:");
|
||||
for (i = 0; i < info->mr.rangesize; i++) {
|
||||
print_range(&info->mr.range[i]);
|
||||
if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM)
|
||||
printf(" random");
|
||||
if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT)
|
||||
printf(" persistent");
|
||||
}
|
||||
}
|
||||
|
||||
static void DNAT_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct ipt_natinfo *info = (const void *)target;
|
||||
unsigned int i = 0;
|
||||
|
||||
for (i = 0; i < info->mr.rangesize; i++) {
|
||||
printf(" --to-destination ");
|
||||
print_range(&info->mr.range[i]);
|
||||
if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM)
|
||||
printf(" --random");
|
||||
if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT)
|
||||
printf(" --persistent");
|
||||
}
|
||||
}
|
||||
|
||||
static struct xtables_target dnat_tg_reg = {
|
||||
.name = "DNAT",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV4,
|
||||
.size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
|
||||
.help = DNAT_help,
|
||||
.x6_parse = DNAT_parse,
|
||||
.x6_fcheck = DNAT_fcheck,
|
||||
.print = DNAT_print,
|
||||
.save = DNAT_save,
|
||||
.x6_options = DNAT_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&dnat_tg_reg);
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
/* Shared library add-on to iptables for ECN, $Version$
|
||||
*
|
||||
* (C) 2002 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* This program is distributed under the terms of GNU GPL v2, 1991
|
||||
*
|
||||
* libipt_ECN.c borrowed heavily from libipt_DSCP.c
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_ipv4/ipt_ECN.h>
|
||||
|
||||
enum {
|
||||
O_ECN_TCP_REMOVE = 0,
|
||||
O_ECN_TCP_CWR,
|
||||
O_ECN_TCP_ECE,
|
||||
O_ECN_IP_ECT,
|
||||
F_ECN_TCP_REMOVE = 1 << O_ECN_TCP_REMOVE,
|
||||
F_ECN_TCP_CWR = 1 << O_ECN_TCP_CWR,
|
||||
F_ECN_TCP_ECE = 1 << O_ECN_TCP_ECE,
|
||||
};
|
||||
|
||||
static void ECN_help(void)
|
||||
{
|
||||
printf(
|
||||
"ECN target options\n"
|
||||
" --ecn-tcp-remove Remove all ECN bits from TCP header\n");
|
||||
}
|
||||
|
||||
#if 0
|
||||
"ECN target v%s EXPERIMENTAL options (use with extreme care!)\n"
|
||||
" --ecn-ip-ect Set the IPv4 ECT codepoint (0 to 3)\n"
|
||||
" --ecn-tcp-cwr Set the IPv4 CWR bit (0 or 1)\n"
|
||||
" --ecn-tcp-ece Set the IPv4 ECE bit (0 or 1)\n",
|
||||
#endif
|
||||
|
||||
static const struct xt_option_entry ECN_opts[] = {
|
||||
{.name = "ecn-tcp-remove", .id = O_ECN_TCP_REMOVE, .type = XTTYPE_NONE,
|
||||
.excl = F_ECN_TCP_CWR | F_ECN_TCP_ECE},
|
||||
{.name = "ecn-tcp-cwr", .id = O_ECN_TCP_CWR, .type = XTTYPE_UINT8,
|
||||
.min = 0, .max = 1, .excl = F_ECN_TCP_REMOVE},
|
||||
{.name = "ecn-tcp-ece", .id = O_ECN_TCP_ECE, .type = XTTYPE_UINT8,
|
||||
.min = 0, .max = 1, .excl = F_ECN_TCP_REMOVE},
|
||||
{.name = "ecn-ip-ect", .id = O_ECN_IP_ECT, .type = XTTYPE_UINT8,
|
||||
.min = 0, .max = 3},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void ECN_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ipt_ECN_info *einfo = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_ECN_TCP_REMOVE:
|
||||
einfo->operation = IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR;
|
||||
einfo->proto.tcp.ece = 0;
|
||||
einfo->proto.tcp.cwr = 0;
|
||||
break;
|
||||
case O_ECN_TCP_CWR:
|
||||
einfo->operation |= IPT_ECN_OP_SET_CWR;
|
||||
einfo->proto.tcp.cwr = cb->val.u8;
|
||||
break;
|
||||
case O_ECN_TCP_ECE:
|
||||
einfo->operation |= IPT_ECN_OP_SET_ECE;
|
||||
einfo->proto.tcp.ece = cb->val.u8;
|
||||
break;
|
||||
case O_ECN_IP_ECT:
|
||||
einfo->operation |= IPT_ECN_OP_SET_IP;
|
||||
einfo->ip_ect = cb->val.u8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ECN_check(struct xt_fcheck_call *cb)
|
||||
{
|
||||
if (cb->xflags == 0)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"ECN target: An operation is required");
|
||||
}
|
||||
|
||||
static void ECN_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct ipt_ECN_info *einfo =
|
||||
(const struct ipt_ECN_info *)target->data;
|
||||
|
||||
printf(" ECN");
|
||||
|
||||
if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)
|
||||
&& einfo->proto.tcp.ece == 0
|
||||
&& einfo->proto.tcp.cwr == 0)
|
||||
printf(" TCP remove");
|
||||
else {
|
||||
if (einfo->operation & IPT_ECN_OP_SET_ECE)
|
||||
printf(" ECE=%u", einfo->proto.tcp.ece);
|
||||
|
||||
if (einfo->operation & IPT_ECN_OP_SET_CWR)
|
||||
printf(" CWR=%u", einfo->proto.tcp.cwr);
|
||||
|
||||
if (einfo->operation & IPT_ECN_OP_SET_IP)
|
||||
printf(" ECT codepoint=%u", einfo->ip_ect);
|
||||
}
|
||||
}
|
||||
|
||||
static void ECN_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct ipt_ECN_info *einfo =
|
||||
(const struct ipt_ECN_info *)target->data;
|
||||
|
||||
if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)
|
||||
&& einfo->proto.tcp.ece == 0
|
||||
&& einfo->proto.tcp.cwr == 0)
|
||||
printf(" --ecn-tcp-remove");
|
||||
else {
|
||||
|
||||
if (einfo->operation & IPT_ECN_OP_SET_ECE)
|
||||
printf(" --ecn-tcp-ece %d", einfo->proto.tcp.ece);
|
||||
|
||||
if (einfo->operation & IPT_ECN_OP_SET_CWR)
|
||||
printf(" --ecn-tcp-cwr %d", einfo->proto.tcp.cwr);
|
||||
|
||||
if (einfo->operation & IPT_ECN_OP_SET_IP)
|
||||
printf(" --ecn-ip-ect %d", einfo->ip_ect);
|
||||
}
|
||||
}
|
||||
|
||||
static struct xtables_target ecn_tg_reg = {
|
||||
.name = "ECN",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV4,
|
||||
.size = XT_ALIGN(sizeof(struct ipt_ECN_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ipt_ECN_info)),
|
||||
.help = ECN_help,
|
||||
.print = ECN_print,
|
||||
.save = ECN_save,
|
||||
.x6_parse = ECN_parse,
|
||||
.x6_fcheck = ECN_check,
|
||||
.x6_options = ECN_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&ecn_tg_reg);
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
This target allows to selectively work around known ECN blackholes.
|
||||
It can only be used in the mangle table.
|
||||
.TP
|
||||
\fB\-\-ecn\-tcp\-remove\fP
|
||||
Remove all ECN bits from the TCP header. Of course, it can only be used
|
||||
in conjunction with
|
||||
\fB\-p tcp\fP.
|
|
@ -0,0 +1,186 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_ipv4/ipt_LOG.h>
|
||||
|
||||
#define LOG_DEFAULT_LEVEL LOG_WARNING
|
||||
|
||||
#ifndef IPT_LOG_UID /* Old kernel */
|
||||
#define IPT_LOG_UID 0x08 /* Log UID owning local socket */
|
||||
#undef IPT_LOG_MASK
|
||||
#define IPT_LOG_MASK 0x0f
|
||||
#endif
|
||||
|
||||
enum {
|
||||
O_LOG_LEVEL = 0,
|
||||
O_LOG_PREFIX,
|
||||
O_LOG_TCPSEQ,
|
||||
O_LOG_TCPOPTS,
|
||||
O_LOG_IPOPTS,
|
||||
O_LOG_UID,
|
||||
O_LOG_MAC,
|
||||
};
|
||||
|
||||
static void LOG_help(void)
|
||||
{
|
||||
printf(
|
||||
"LOG target options:\n"
|
||||
" --log-level level Level of logging (numeric or see syslog.conf)\n"
|
||||
" --log-prefix prefix Prefix log messages with this prefix.\n\n"
|
||||
" --log-tcp-sequence Log TCP sequence numbers.\n\n"
|
||||
" --log-tcp-options Log TCP options.\n\n"
|
||||
" --log-ip-options Log IP options.\n\n"
|
||||
" --log-uid Log UID owning the local socket.\n\n"
|
||||
" --log-macdecode Decode MAC addresses and protocol.\n\n");
|
||||
}
|
||||
|
||||
#define s struct ipt_log_info
|
||||
static const struct xt_option_entry LOG_opts[] = {
|
||||
{.name = "log-level", .id = O_LOG_LEVEL, .type = XTTYPE_SYSLOGLEVEL,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(s, level)},
|
||||
{.name = "log-prefix", .id = O_LOG_PREFIX, .type = XTTYPE_STRING,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(s, prefix), .min = 1},
|
||||
{.name = "log-tcp-sequence", .id = O_LOG_TCPSEQ, .type = XTTYPE_NONE},
|
||||
{.name = "log-tcp-options", .id = O_LOG_TCPOPTS, .type = XTTYPE_NONE},
|
||||
{.name = "log-ip-options", .id = O_LOG_IPOPTS, .type = XTTYPE_NONE},
|
||||
{.name = "log-uid", .id = O_LOG_UID, .type = XTTYPE_NONE},
|
||||
{.name = "log-macdecode", .id = O_LOG_MAC, .type = XTTYPE_NONE},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
#undef s
|
||||
|
||||
static void LOG_init(struct xt_entry_target *t)
|
||||
{
|
||||
struct ipt_log_info *loginfo = (struct ipt_log_info *)t->data;
|
||||
|
||||
loginfo->level = LOG_DEFAULT_LEVEL;
|
||||
|
||||
}
|
||||
|
||||
struct ipt_log_names {
|
||||
const char *name;
|
||||
unsigned int level;
|
||||
};
|
||||
|
||||
static const struct ipt_log_names ipt_log_names[]
|
||||
= { { .name = "alert", .level = LOG_ALERT },
|
||||
{ .name = "crit", .level = LOG_CRIT },
|
||||
{ .name = "debug", .level = LOG_DEBUG },
|
||||
{ .name = "emerg", .level = LOG_EMERG },
|
||||
{ .name = "error", .level = LOG_ERR }, /* DEPRECATED */
|
||||
{ .name = "info", .level = LOG_INFO },
|
||||
{ .name = "notice", .level = LOG_NOTICE },
|
||||
{ .name = "panic", .level = LOG_EMERG }, /* DEPRECATED */
|
||||
{ .name = "warning", .level = LOG_WARNING }
|
||||
};
|
||||
|
||||
static void LOG_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ipt_log_info *info = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_LOG_PREFIX:
|
||||
if (strchr(cb->arg, '\n') != NULL)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Newlines not allowed in --log-prefix");
|
||||
break;
|
||||
case O_LOG_TCPSEQ:
|
||||
info->logflags |= IPT_LOG_TCPSEQ;
|
||||
break;
|
||||
case O_LOG_TCPOPTS:
|
||||
info->logflags |= IPT_LOG_TCPOPT;
|
||||
break;
|
||||
case O_LOG_IPOPTS:
|
||||
info->logflags |= IPT_LOG_IPOPT;
|
||||
break;
|
||||
case O_LOG_UID:
|
||||
info->logflags |= IPT_LOG_UID;
|
||||
break;
|
||||
case O_LOG_MAC:
|
||||
info->logflags |= IPT_LOG_MACDECODE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void LOG_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct ipt_log_info *loginfo
|
||||
= (const struct ipt_log_info *)target->data;
|
||||
unsigned int i = 0;
|
||||
|
||||
printf(" LOG");
|
||||
if (numeric)
|
||||
printf(" flags %u level %u",
|
||||
loginfo->logflags, loginfo->level);
|
||||
else {
|
||||
for (i = 0; i < ARRAY_SIZE(ipt_log_names); ++i)
|
||||
if (loginfo->level == ipt_log_names[i].level) {
|
||||
printf(" level %s", ipt_log_names[i].name);
|
||||
break;
|
||||
}
|
||||
if (i == ARRAY_SIZE(ipt_log_names))
|
||||
printf(" UNKNOWN level %u", loginfo->level);
|
||||
if (loginfo->logflags & IPT_LOG_TCPSEQ)
|
||||
printf(" tcp-sequence");
|
||||
if (loginfo->logflags & IPT_LOG_TCPOPT)
|
||||
printf(" tcp-options");
|
||||
if (loginfo->logflags & IPT_LOG_IPOPT)
|
||||
printf(" ip-options");
|
||||
if (loginfo->logflags & IPT_LOG_UID)
|
||||
printf(" uid");
|
||||
if (loginfo->logflags & IPT_LOG_MACDECODE)
|
||||
printf(" macdecode");
|
||||
if (loginfo->logflags & ~(IPT_LOG_MASK))
|
||||
printf(" unknown-flags");
|
||||
}
|
||||
|
||||
if (strcmp(loginfo->prefix, "") != 0)
|
||||
printf(" prefix \"%s\"", loginfo->prefix);
|
||||
}
|
||||
|
||||
static void LOG_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct ipt_log_info *loginfo
|
||||
= (const struct ipt_log_info *)target->data;
|
||||
|
||||
if (strcmp(loginfo->prefix, "") != 0) {
|
||||
printf(" --log-prefix");
|
||||
xtables_save_string(loginfo->prefix);
|
||||
}
|
||||
|
||||
if (loginfo->level != LOG_DEFAULT_LEVEL)
|
||||
printf(" --log-level %d", loginfo->level);
|
||||
|
||||
if (loginfo->logflags & IPT_LOG_TCPSEQ)
|
||||
printf(" --log-tcp-sequence");
|
||||
if (loginfo->logflags & IPT_LOG_TCPOPT)
|
||||
printf(" --log-tcp-options");
|
||||
if (loginfo->logflags & IPT_LOG_IPOPT)
|
||||
printf(" --log-ip-options");
|
||||
if (loginfo->logflags & IPT_LOG_UID)
|
||||
printf(" --log-uid");
|
||||
if (loginfo->logflags & IPT_LOG_MACDECODE)
|
||||
printf(" --log-macdecode");
|
||||
}
|
||||
|
||||
static struct xtables_target log_tg_reg = {
|
||||
.name = "LOG",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV4,
|
||||
.size = XT_ALIGN(sizeof(struct ipt_log_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ipt_log_info)),
|
||||
.help = LOG_help,
|
||||
.init = LOG_init,
|
||||
.print = LOG_print,
|
||||
.save = LOG_save,
|
||||
.x6_parse = LOG_parse,
|
||||
.x6_options = LOG_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&log_tg_reg);
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <xtables.h>
|
||||
#include <limits.h> /* INT_MAX in ip_tables.h */
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include <linux/netfilter/nf_nat.h>
|
||||
|
||||
enum {
|
||||
O_TO_PORTS = 0,
|
||||
O_RANDOM,
|
||||
};
|
||||
|
||||
static void MASQUERADE_help(void)
|
||||
{
|
||||
printf(
|
||||
"MASQUERADE target options:\n"
|
||||
" --to-ports <port>[-<port>]\n"
|
||||
" Port (range) to map to.\n"
|
||||
" --random\n"
|
||||
" Randomize source port.\n");
|
||||
}
|
||||
|
||||
static const struct xt_option_entry MASQUERADE_opts[] = {
|
||||
{.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING},
|
||||
{.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void MASQUERADE_init(struct xt_entry_target *t)
|
||||
{
|
||||
struct nf_nat_ipv4_multi_range_compat *mr = (struct nf_nat_ipv4_multi_range_compat *)t->data;
|
||||
|
||||
/* Actually, it's 0, but it's ignored at the moment. */
|
||||
mr->rangesize = 1;
|
||||
}
|
||||
|
||||
/* Parses ports */
|
||||
static void
|
||||
parse_ports(const char *arg, struct nf_nat_ipv4_multi_range_compat *mr)
|
||||
{
|
||||
char *end;
|
||||
unsigned int port, maxport;
|
||||
|
||||
mr->range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
|
||||
|
||||
if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX))
|
||||
xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg);
|
||||
|
||||
switch (*end) {
|
||||
case '\0':
|
||||
mr->range[0].min.tcp.port
|
||||
= mr->range[0].max.tcp.port
|
||||
= htons(port);
|
||||
return;
|
||||
case '-':
|
||||
if (!xtables_strtoui(end + 1, NULL, &maxport, 0, UINT16_MAX))
|
||||
break;
|
||||
|
||||
if (maxport < port)
|
||||
break;
|
||||
|
||||
mr->range[0].min.tcp.port = htons(port);
|
||||
mr->range[0].max.tcp.port = htons(maxport);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg);
|
||||
}
|
||||
|
||||
static void MASQUERADE_parse(struct xt_option_call *cb)
|
||||
{
|
||||
const struct ipt_entry *entry = cb->xt_entry;
|
||||
int portok;
|
||||
struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
|
||||
|
||||
if (entry->ip.proto == IPPROTO_TCP
|
||||
|| entry->ip.proto == IPPROTO_UDP
|
||||
|| entry->ip.proto == IPPROTO_SCTP
|
||||
|| entry->ip.proto == IPPROTO_DCCP
|
||||
|| entry->ip.proto == IPPROTO_ICMP)
|
||||
portok = 1;
|
||||
else
|
||||
portok = 0;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_TO_PORTS:
|
||||
if (!portok)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Need TCP, UDP, SCTP or DCCP with port specification");
|
||||
parse_ports(cb->arg, mr);
|
||||
break;
|
||||
case O_RANDOM:
|
||||
mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
MASQUERADE_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data;
|
||||
const struct nf_nat_ipv4_range *r = &mr->range[0];
|
||||
|
||||
if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
|
||||
printf(" masq ports: ");
|
||||
printf("%hu", ntohs(r->min.tcp.port));
|
||||
if (r->max.tcp.port != r->min.tcp.port)
|
||||
printf("-%hu", ntohs(r->max.tcp.port));
|
||||
}
|
||||
|
||||
if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
|
||||
printf(" random");
|
||||
}
|
||||
|
||||
static void
|
||||
MASQUERADE_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data;
|
||||
const struct nf_nat_ipv4_range *r = &mr->range[0];
|
||||
|
||||
if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
|
||||
printf(" --to-ports %hu", ntohs(r->min.tcp.port));
|
||||
if (r->max.tcp.port != r->min.tcp.port)
|
||||
printf("-%hu", ntohs(r->max.tcp.port));
|
||||
}
|
||||
|
||||
if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
|
||||
printf(" --random");
|
||||
}
|
||||
|
||||
static struct xtables_target masquerade_tg_reg = {
|
||||
.name = "MASQUERADE",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV4,
|
||||
.size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
|
||||
.help = MASQUERADE_help,
|
||||
.init = MASQUERADE_init,
|
||||
.x6_parse = MASQUERADE_parse,
|
||||
.print = MASQUERADE_print,
|
||||
.save = MASQUERADE_save,
|
||||
.x6_options = MASQUERADE_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&masquerade_tg_reg);
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
/* Shared library add-on to iptables to add static NAT support.
|
||||
Author: Svenning Soerensen <svenning@post5.tele.dk>
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter/nf_nat.h>
|
||||
|
||||
#define MODULENAME "NETMAP"
|
||||
|
||||
enum {
|
||||
O_TO = 0,
|
||||
};
|
||||
|
||||
static const struct xt_option_entry NETMAP_opts[] = {
|
||||
{.name = "to", .id = O_TO, .type = XTTYPE_HOSTMASK,
|
||||
.flags = XTOPT_MAND},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void NETMAP_help(void)
|
||||
{
|
||||
printf(MODULENAME" target options:\n"
|
||||
" --%s address[/mask]\n"
|
||||
" Network address to map to.\n\n",
|
||||
NETMAP_opts[0].name);
|
||||
}
|
||||
|
||||
static int
|
||||
netmask2bits(uint32_t netmask)
|
||||
{
|
||||
uint32_t bm;
|
||||
int bits;
|
||||
|
||||
netmask = ntohl(netmask);
|
||||
for (bits = 0, bm = 0x80000000; netmask & bm; netmask <<= 1)
|
||||
bits++;
|
||||
if (netmask)
|
||||
return -1; /* holes in netmask */
|
||||
return bits;
|
||||
}
|
||||
|
||||
static void NETMAP_init(struct xt_entry_target *t)
|
||||
{
|
||||
struct nf_nat_ipv4_multi_range_compat *mr = (struct nf_nat_ipv4_multi_range_compat *)t->data;
|
||||
|
||||
/* Actually, it's 0, but it's ignored at the moment. */
|
||||
mr->rangesize = 1;
|
||||
}
|
||||
|
||||
static void NETMAP_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
|
||||
struct nf_nat_ipv4_range *range = &mr->range[0];
|
||||
|
||||
xtables_option_parse(cb);
|
||||
range->flags |= NF_NAT_RANGE_MAP_IPS;
|
||||
range->min_ip = cb->val.haddr.ip & cb->val.hmask.ip;
|
||||
range->max_ip = range->min_ip | ~cb->val.hmask.ip;
|
||||
}
|
||||
|
||||
static void NETMAP_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data;
|
||||
const struct nf_nat_ipv4_range *r = &mr->range[0];
|
||||
struct in_addr a;
|
||||
int bits;
|
||||
|
||||
a.s_addr = r->min_ip;
|
||||
printf("%s", xtables_ipaddr_to_numeric(&a));
|
||||
a.s_addr = ~(r->min_ip ^ r->max_ip);
|
||||
bits = netmask2bits(a.s_addr);
|
||||
if (bits < 0)
|
||||
printf("/%s", xtables_ipaddr_to_numeric(&a));
|
||||
else
|
||||
printf("/%d", bits);
|
||||
}
|
||||
|
||||
static void NETMAP_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
printf(" --%s ", NETMAP_opts[0].name);
|
||||
NETMAP_print(ip, target, 0);
|
||||
}
|
||||
|
||||
static struct xtables_target netmap_tg_reg = {
|
||||
.name = MODULENAME,
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV4,
|
||||
.size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
|
||||
.help = NETMAP_help,
|
||||
.init = NETMAP_init,
|
||||
.x6_parse = NETMAP_parse,
|
||||
.print = NETMAP_print,
|
||||
.save = NETMAP_save,
|
||||
.x6_options = NETMAP_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&netmap_tg_reg);
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <xtables.h>
|
||||
#include <limits.h> /* INT_MAX in ip_tables.h */
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include <linux/netfilter/nf_nat.h>
|
||||
|
||||
enum {
|
||||
O_TO_PORTS = 0,
|
||||
O_RANDOM,
|
||||
F_TO_PORTS = 1 << O_TO_PORTS,
|
||||
F_RANDOM = 1 << O_RANDOM,
|
||||
};
|
||||
|
||||
static void REDIRECT_help(void)
|
||||
{
|
||||
printf(
|
||||
"REDIRECT target options:\n"
|
||||
" --to-ports <port>[-<port>]\n"
|
||||
" Port (range) to map to.\n"
|
||||
" [--random]\n");
|
||||
}
|
||||
|
||||
static const struct xt_option_entry REDIRECT_opts[] = {
|
||||
{.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING},
|
||||
{.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void REDIRECT_init(struct xt_entry_target *t)
|
||||
{
|
||||
struct nf_nat_ipv4_multi_range_compat *mr = (struct nf_nat_ipv4_multi_range_compat *)t->data;
|
||||
|
||||
/* Actually, it's 0, but it's ignored at the moment. */
|
||||
mr->rangesize = 1;
|
||||
}
|
||||
|
||||
/* Parses ports */
|
||||
static void
|
||||
parse_ports(const char *arg, struct nf_nat_ipv4_multi_range_compat *mr)
|
||||
{
|
||||
char *end = "";
|
||||
unsigned int port, maxport;
|
||||
|
||||
mr->range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
|
||||
|
||||
if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX) &&
|
||||
(port = xtables_service_to_port(arg, NULL)) == (unsigned)-1)
|
||||
xtables_param_act(XTF_BAD_VALUE, "REDIRECT", "--to-ports", arg);
|
||||
|
||||
switch (*end) {
|
||||
case '\0':
|
||||
mr->range[0].min.tcp.port
|
||||
= mr->range[0].max.tcp.port
|
||||
= htons(port);
|
||||
return;
|
||||
case '-':
|
||||
if (!xtables_strtoui(end + 1, NULL, &maxport, 0, UINT16_MAX) &&
|
||||
(maxport = xtables_service_to_port(end + 1, NULL)) == (unsigned)-1)
|
||||
break;
|
||||
|
||||
if (maxport < port)
|
||||
break;
|
||||
|
||||
mr->range[0].min.tcp.port = htons(port);
|
||||
mr->range[0].max.tcp.port = htons(maxport);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
xtables_param_act(XTF_BAD_VALUE, "REDIRECT", "--to-ports", arg);
|
||||
}
|
||||
|
||||
static void REDIRECT_parse(struct xt_option_call *cb)
|
||||
{
|
||||
const struct ipt_entry *entry = cb->xt_entry;
|
||||
struct nf_nat_ipv4_multi_range_compat *mr = (void *)(*cb->target)->data;
|
||||
int portok;
|
||||
|
||||
if (entry->ip.proto == IPPROTO_TCP
|
||||
|| entry->ip.proto == IPPROTO_UDP
|
||||
|| entry->ip.proto == IPPROTO_SCTP
|
||||
|| entry->ip.proto == IPPROTO_DCCP
|
||||
|| entry->ip.proto == IPPROTO_ICMP)
|
||||
portok = 1;
|
||||
else
|
||||
portok = 0;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_TO_PORTS:
|
||||
if (!portok)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Need TCP, UDP, SCTP or DCCP with port specification");
|
||||
parse_ports(cb->arg, mr);
|
||||
if (cb->xflags & F_RANDOM)
|
||||
mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM;
|
||||
break;
|
||||
case O_RANDOM:
|
||||
if (cb->xflags & F_TO_PORTS)
|
||||
mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void REDIRECT_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data;
|
||||
const struct nf_nat_ipv4_range *r = &mr->range[0];
|
||||
|
||||
if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
|
||||
printf(" redir ports ");
|
||||
printf("%hu", ntohs(r->min.tcp.port));
|
||||
if (r->max.tcp.port != r->min.tcp.port)
|
||||
printf("-%hu", ntohs(r->max.tcp.port));
|
||||
if (mr->range[0].flags & NF_NAT_RANGE_PROTO_RANDOM)
|
||||
printf(" random");
|
||||
}
|
||||
}
|
||||
|
||||
static void REDIRECT_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data;
|
||||
const struct nf_nat_ipv4_range *r = &mr->range[0];
|
||||
|
||||
if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
|
||||
printf(" --to-ports ");
|
||||
printf("%hu", ntohs(r->min.tcp.port));
|
||||
if (r->max.tcp.port != r->min.tcp.port)
|
||||
printf("-%hu", ntohs(r->max.tcp.port));
|
||||
if (mr->range[0].flags & NF_NAT_RANGE_PROTO_RANDOM)
|
||||
printf(" --random");
|
||||
}
|
||||
}
|
||||
|
||||
static struct xtables_target redirect_tg_reg = {
|
||||
.name = "REDIRECT",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV4,
|
||||
.size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
|
||||
.help = REDIRECT_help,
|
||||
.init = REDIRECT_init,
|
||||
.x6_parse = REDIRECT_parse,
|
||||
.print = REDIRECT_print,
|
||||
.save = REDIRECT_save,
|
||||
.x6_options = REDIRECT_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&redirect_tg_reg);
|
||||
}
|
|
@ -0,0 +1,160 @@
|
|||
/* Shared library add-on to iptables to add customized REJECT support.
|
||||
*
|
||||
* (C) 2000 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_ipv4/ipt_REJECT.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
/* If we are compiling against a kernel that does not support
|
||||
* IPT_ICMP_ADMIN_PROHIBITED, we are emulating it.
|
||||
* The result will be a plain DROP of the packet instead of
|
||||
* reject. -- Maciej Soltysiak <solt@dns.toxicfilms.tv>
|
||||
*/
|
||||
#ifndef IPT_ICMP_ADMIN_PROHIBITED
|
||||
#define IPT_ICMP_ADMIN_PROHIBITED IPT_TCP_RESET + 1
|
||||
#endif
|
||||
|
||||
struct reject_names {
|
||||
const char *name;
|
||||
const char *alias;
|
||||
enum ipt_reject_with with;
|
||||
const char *desc;
|
||||
};
|
||||
|
||||
enum {
|
||||
O_REJECT_WITH = 0,
|
||||
};
|
||||
|
||||
static const struct reject_names reject_table[] = {
|
||||
{"icmp-net-unreachable", "net-unreach",
|
||||
IPT_ICMP_NET_UNREACHABLE, "ICMP network unreachable"},
|
||||
{"icmp-host-unreachable", "host-unreach",
|
||||
IPT_ICMP_HOST_UNREACHABLE, "ICMP host unreachable"},
|
||||
{"icmp-proto-unreachable", "proto-unreach",
|
||||
IPT_ICMP_PROT_UNREACHABLE, "ICMP protocol unreachable"},
|
||||
{"icmp-port-unreachable", "port-unreach",
|
||||
IPT_ICMP_PORT_UNREACHABLE, "ICMP port unreachable (default)"},
|
||||
#if 0
|
||||
{"echo-reply", "echoreply",
|
||||
IPT_ICMP_ECHOREPLY, "for ICMP echo only: faked ICMP echo reply"},
|
||||
#endif
|
||||
{"icmp-net-prohibited", "net-prohib",
|
||||
IPT_ICMP_NET_PROHIBITED, "ICMP network prohibited"},
|
||||
{"icmp-host-prohibited", "host-prohib",
|
||||
IPT_ICMP_HOST_PROHIBITED, "ICMP host prohibited"},
|
||||
{"tcp-reset", "tcp-rst",
|
||||
IPT_TCP_RESET, "TCP RST packet"},
|
||||
{"icmp-admin-prohibited", "admin-prohib",
|
||||
IPT_ICMP_ADMIN_PROHIBITED, "ICMP administratively prohibited (*)"}
|
||||
};
|
||||
|
||||
static void
|
||||
print_reject_types(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
printf("Valid reject types:\n");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(reject_table); ++i) {
|
||||
printf(" %-25s\t%s\n", reject_table[i].name, reject_table[i].desc);
|
||||
printf(" %-25s\talias\n", reject_table[i].alias);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void REJECT_help(void)
|
||||
{
|
||||
printf(
|
||||
"REJECT target options:\n"
|
||||
"--reject-with type drop input packet and send back\n"
|
||||
" a reply packet according to type:\n");
|
||||
|
||||
print_reject_types();
|
||||
|
||||
printf("(*) See man page or read the INCOMPATIBILITES file for compatibility issues.\n");
|
||||
}
|
||||
|
||||
static const struct xt_option_entry REJECT_opts[] = {
|
||||
{.name = "reject-with", .id = O_REJECT_WITH, .type = XTTYPE_STRING},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void REJECT_init(struct xt_entry_target *t)
|
||||
{
|
||||
struct ipt_reject_info *reject = (struct ipt_reject_info *)t->data;
|
||||
|
||||
/* default */
|
||||
reject->with = IPT_ICMP_PORT_UNREACHABLE;
|
||||
|
||||
}
|
||||
|
||||
static void REJECT_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ipt_reject_info *reject = cb->data;
|
||||
unsigned int i;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
for (i = 0; i < ARRAY_SIZE(reject_table); ++i)
|
||||
if (strncasecmp(reject_table[i].name,
|
||||
cb->arg, strlen(cb->arg)) == 0 ||
|
||||
strncasecmp(reject_table[i].alias,
|
||||
cb->arg, strlen(cb->arg)) == 0) {
|
||||
reject->with = reject_table[i].with;
|
||||
return;
|
||||
}
|
||||
/* This due to be dropped late in 2.4 pre-release cycle --RR */
|
||||
if (strncasecmp("echo-reply", cb->arg, strlen(cb->arg)) == 0 ||
|
||||
strncasecmp("echoreply", cb->arg, strlen(cb->arg)) == 0)
|
||||
fprintf(stderr, "--reject-with echo-reply no longer"
|
||||
" supported\n");
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"unknown reject type \"%s\"", cb->arg);
|
||||
}
|
||||
|
||||
static void REJECT_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct ipt_reject_info *reject
|
||||
= (const struct ipt_reject_info *)target->data;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(reject_table); ++i)
|
||||
if (reject_table[i].with == reject->with)
|
||||
break;
|
||||
printf(" reject-with %s", reject_table[i].name);
|
||||
}
|
||||
|
||||
static void REJECT_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct ipt_reject_info *reject
|
||||
= (const struct ipt_reject_info *)target->data;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(reject_table); ++i)
|
||||
if (reject_table[i].with == reject->with)
|
||||
break;
|
||||
|
||||
printf(" --reject-with %s", reject_table[i].name);
|
||||
}
|
||||
|
||||
static struct xtables_target reject_tg_reg = {
|
||||
.name = "REJECT",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV4,
|
||||
.size = XT_ALIGN(sizeof(struct ipt_reject_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ipt_reject_info)),
|
||||
.help = REJECT_help,
|
||||
.init = REJECT_init,
|
||||
.print = REJECT_print,
|
||||
.save = REJECT_save,
|
||||
.x6_parse = REJECT_parse,
|
||||
.x6_options = REJECT_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&reject_tg_reg);
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
This is used to send back an error packet in response to the matched
|
||||
packet: otherwise it is equivalent to
|
||||
.B DROP
|
||||
so it is a terminating TARGET, ending rule traversal.
|
||||
This target is only valid in the
|
||||
.BR INPUT ,
|
||||
.B FORWARD
|
||||
and
|
||||
.B OUTPUT
|
||||
chains, and user-defined chains which are only called from those
|
||||
chains. The following option controls the nature of the error packet
|
||||
returned:
|
||||
.TP
|
||||
\fB\-\-reject\-with\fP \fItype\fP
|
||||
The type given can be
|
||||
\fBicmp\-net\-unreachable\fP,
|
||||
\fBicmp\-host\-unreachable\fP,
|
||||
\fBicmp\-port\-unreachable\fP,
|
||||
\fBicmp\-proto\-unreachable\fP,
|
||||
\fBicmp\-net\-prohibited\fP,
|
||||
\fBicmp\-host\-prohibited\fP, or
|
||||
\fBicmp\-admin\-prohibited\fP (*),
|
||||
which return the appropriate ICMP error message (\fBicmp\-port\-unreachable\fP is
|
||||
the default). The option
|
||||
\fBtcp\-reset\fP
|
||||
can be used on rules which only match the TCP protocol: this causes a
|
||||
TCP RST packet to be sent back. This is mainly useful for blocking
|
||||
.I ident
|
||||
(113/tcp) probes which frequently occur when sending mail to broken mail
|
||||
hosts (which won't accept your mail otherwise).
|
||||
.PP
|
||||
(*) Using icmp\-admin\-prohibited with kernels that do not support it will result in a plain DROP instead of REJECT
|
|
@ -0,0 +1,272 @@
|
|||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <xtables.h>
|
||||
#include <iptables.h>
|
||||
#include <limits.h> /* INT_MAX in ip_tables.h */
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include <linux/netfilter/nf_nat.h>
|
||||
|
||||
enum {
|
||||
O_TO_SRC = 0,
|
||||
O_RANDOM,
|
||||
O_RANDOM_FULLY,
|
||||
O_PERSISTENT,
|
||||
O_X_TO_SRC,
|
||||
F_TO_SRC = 1 << O_TO_SRC,
|
||||
F_RANDOM = 1 << O_RANDOM,
|
||||
F_RANDOM_FULLY = 1 << O_RANDOM_FULLY,
|
||||
F_X_TO_SRC = 1 << O_X_TO_SRC,
|
||||
};
|
||||
|
||||
/* Source NAT data consists of a multi-range, indicating where to map
|
||||
to. */
|
||||
struct ipt_natinfo
|
||||
{
|
||||
struct xt_entry_target t;
|
||||
struct nf_nat_ipv4_multi_range_compat mr;
|
||||
};
|
||||
|
||||
static void SNAT_help(void)
|
||||
{
|
||||
printf(
|
||||
"SNAT target options:\n"
|
||||
" --to-source [<ipaddr>[-<ipaddr>]][:port[-port]]\n"
|
||||
" Address to map source to.\n"
|
||||
"[--random] [--random-fully] [--persistent]\n");
|
||||
}
|
||||
|
||||
static const struct xt_option_entry SNAT_opts[] = {
|
||||
{.name = "to-source", .id = O_TO_SRC, .type = XTTYPE_STRING,
|
||||
.flags = XTOPT_MAND | XTOPT_MULTI},
|
||||
{.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
|
||||
{.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE},
|
||||
{.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static struct ipt_natinfo *
|
||||
append_range(struct ipt_natinfo *info, const struct nf_nat_ipv4_range *range)
|
||||
{
|
||||
unsigned int size;
|
||||
|
||||
/* One rangesize already in struct ipt_natinfo */
|
||||
size = XT_ALIGN(sizeof(*info) + info->mr.rangesize * sizeof(*range));
|
||||
|
||||
info = realloc(info, size);
|
||||
if (!info)
|
||||
xtables_error(OTHER_PROBLEM, "Out of memory\n");
|
||||
|
||||
info->t.u.target_size = size;
|
||||
info->mr.range[info->mr.rangesize] = *range;
|
||||
info->mr.rangesize++;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
/* Ranges expected in network order. */
|
||||
static struct xt_entry_target *
|
||||
parse_to(const char *orig_arg, int portok, struct ipt_natinfo *info)
|
||||
{
|
||||
struct nf_nat_ipv4_range range;
|
||||
char *arg, *colon, *dash, *error;
|
||||
const struct in_addr *ip;
|
||||
|
||||
arg = strdup(orig_arg);
|
||||
if (arg == NULL)
|
||||
xtables_error(RESOURCE_PROBLEM, "strdup");
|
||||
memset(&range, 0, sizeof(range));
|
||||
colon = strchr(arg, ':');
|
||||
|
||||
if (colon) {
|
||||
int port;
|
||||
|
||||
if (!portok)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Need TCP, UDP, SCTP or DCCP with port specification");
|
||||
|
||||
range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
|
||||
|
||||
port = atoi(colon+1);
|
||||
if (port <= 0 || port > 65535)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Port `%s' not valid\n", colon+1);
|
||||
|
||||
error = strchr(colon+1, ':');
|
||||
if (error)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Invalid port:port syntax - use dash\n");
|
||||
|
||||
dash = strchr(colon, '-');
|
||||
if (!dash) {
|
||||
range.min.tcp.port
|
||||
= range.max.tcp.port
|
||||
= htons(port);
|
||||
} else {
|
||||
int maxport;
|
||||
|
||||
maxport = atoi(dash + 1);
|
||||
if (maxport <= 0 || maxport > 65535)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Port `%s' not valid\n", dash+1);
|
||||
if (maxport < port)
|
||||
/* People are stupid. */
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Port range `%s' funky\n", colon+1);
|
||||
range.min.tcp.port = htons(port);
|
||||
range.max.tcp.port = htons(maxport);
|
||||
}
|
||||
/* Starts with a colon? No IP info...*/
|
||||
if (colon == arg) {
|
||||
free(arg);
|
||||
return &(append_range(info, &range)->t);
|
||||
}
|
||||
*colon = '\0';
|
||||
}
|
||||
|
||||
range.flags |= NF_NAT_RANGE_MAP_IPS;
|
||||
dash = strchr(arg, '-');
|
||||
if (colon && dash && dash > colon)
|
||||
dash = NULL;
|
||||
|
||||
if (dash)
|
||||
*dash = '\0';
|
||||
|
||||
ip = xtables_numeric_to_ipaddr(arg);
|
||||
if (!ip)
|
||||
xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
|
||||
arg);
|
||||
range.min_ip = ip->s_addr;
|
||||
if (dash) {
|
||||
ip = xtables_numeric_to_ipaddr(dash+1);
|
||||
if (!ip)
|
||||
xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
|
||||
dash+1);
|
||||
range.max_ip = ip->s_addr;
|
||||
} else
|
||||
range.max_ip = range.min_ip;
|
||||
|
||||
free(arg);
|
||||
return &(append_range(info, &range)->t);
|
||||
}
|
||||
|
||||
static void SNAT_parse(struct xt_option_call *cb)
|
||||
{
|
||||
const struct ipt_entry *entry = cb->xt_entry;
|
||||
struct ipt_natinfo *info = (void *)(*cb->target);
|
||||
int portok;
|
||||
|
||||
if (entry->ip.proto == IPPROTO_TCP
|
||||
|| entry->ip.proto == IPPROTO_UDP
|
||||
|| entry->ip.proto == IPPROTO_SCTP
|
||||
|| entry->ip.proto == IPPROTO_DCCP
|
||||
|| entry->ip.proto == IPPROTO_ICMP)
|
||||
portok = 1;
|
||||
else
|
||||
portok = 0;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_TO_SRC:
|
||||
if (cb->xflags & F_X_TO_SRC) {
|
||||
if (!kernel_version)
|
||||
get_kernel_version();
|
||||
if (kernel_version > LINUX_VERSION(2, 6, 10))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"SNAT: Multiple --to-source not supported");
|
||||
}
|
||||
*cb->target = parse_to(cb->arg, portok, info);
|
||||
cb->xflags |= F_X_TO_SRC;
|
||||
break;
|
||||
case O_PERSISTENT:
|
||||
info->mr.range[0].flags |= NF_NAT_RANGE_PERSISTENT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void SNAT_fcheck(struct xt_fcheck_call *cb)
|
||||
{
|
||||
static const unsigned int f = F_TO_SRC | F_RANDOM;
|
||||
static const unsigned int r = F_TO_SRC | F_RANDOM_FULLY;
|
||||
struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
|
||||
|
||||
if ((cb->xflags & f) == f)
|
||||
mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM;
|
||||
if ((cb->xflags & r) == r)
|
||||
mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY;
|
||||
}
|
||||
|
||||
static void print_range(const struct nf_nat_ipv4_range *r)
|
||||
{
|
||||
if (r->flags & NF_NAT_RANGE_MAP_IPS) {
|
||||
struct in_addr a;
|
||||
|
||||
a.s_addr = r->min_ip;
|
||||
printf("%s", xtables_ipaddr_to_numeric(&a));
|
||||
if (r->max_ip != r->min_ip) {
|
||||
a.s_addr = r->max_ip;
|
||||
printf("-%s", xtables_ipaddr_to_numeric(&a));
|
||||
}
|
||||
}
|
||||
if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
|
||||
printf(":");
|
||||
printf("%hu", ntohs(r->min.tcp.port));
|
||||
if (r->max.tcp.port != r->min.tcp.port)
|
||||
printf("-%hu", ntohs(r->max.tcp.port));
|
||||
}
|
||||
}
|
||||
|
||||
static void SNAT_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct ipt_natinfo *info = (const void *)target;
|
||||
unsigned int i = 0;
|
||||
|
||||
printf(" to:");
|
||||
for (i = 0; i < info->mr.rangesize; i++) {
|
||||
print_range(&info->mr.range[i]);
|
||||
if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM)
|
||||
printf(" random");
|
||||
if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
|
||||
printf(" random-fully");
|
||||
if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT)
|
||||
printf(" persistent");
|
||||
}
|
||||
}
|
||||
|
||||
static void SNAT_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct ipt_natinfo *info = (const void *)target;
|
||||
unsigned int i = 0;
|
||||
|
||||
for (i = 0; i < info->mr.rangesize; i++) {
|
||||
printf(" --to-source ");
|
||||
print_range(&info->mr.range[i]);
|
||||
if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM)
|
||||
printf(" --random");
|
||||
if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
|
||||
printf(" --random-fully");
|
||||
if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT)
|
||||
printf(" --persistent");
|
||||
}
|
||||
}
|
||||
|
||||
static struct xtables_target snat_tg_reg = {
|
||||
.name = "SNAT",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV4,
|
||||
.size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
|
||||
.help = SNAT_help,
|
||||
.x6_parse = SNAT_parse,
|
||||
.x6_fcheck = SNAT_fcheck,
|
||||
.print = SNAT_print,
|
||||
.save = SNAT_save,
|
||||
.x6_options = SNAT_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&snat_tg_reg);
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
/* Shared library add-on to iptables for the TTL target
|
||||
* (C) 2000 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* This program is distributed under the terms of GNU GPL
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_ipv4/ipt_TTL.h>
|
||||
|
||||
enum {
|
||||
O_TTL_SET = 0,
|
||||
O_TTL_INC,
|
||||
O_TTL_DEC,
|
||||
F_TTL_SET = 1 << O_TTL_SET,
|
||||
F_TTL_INC = 1 << O_TTL_INC,
|
||||
F_TTL_DEC = 1 << O_TTL_DEC,
|
||||
F_ANY = F_TTL_SET | F_TTL_INC | F_TTL_DEC,
|
||||
};
|
||||
|
||||
#define s struct ipt_TTL_info
|
||||
static const struct xt_option_entry TTL_opts[] = {
|
||||
{.name = "ttl-set", .type = XTTYPE_UINT8, .id = O_TTL_SET,
|
||||
.excl = F_ANY, .flags = XTOPT_PUT, XTOPT_POINTER(s, ttl)},
|
||||
{.name = "ttl-dec", .type = XTTYPE_UINT8, .id = O_TTL_DEC,
|
||||
.excl = F_ANY, .flags = XTOPT_PUT, XTOPT_POINTER(s, ttl),
|
||||
.min = 1},
|
||||
{.name = "ttl-inc", .type = XTTYPE_UINT8, .id = O_TTL_INC,
|
||||
.excl = F_ANY, .flags = XTOPT_PUT, XTOPT_POINTER(s, ttl),
|
||||
.min = 1},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
#undef s
|
||||
|
||||
static void TTL_help(void)
|
||||
{
|
||||
printf(
|
||||
"TTL target options\n"
|
||||
" --ttl-set value Set TTL to <value 0-255>\n"
|
||||
" --ttl-dec value Decrement TTL by <value 1-255>\n"
|
||||
" --ttl-inc value Increment TTL by <value 1-255>\n");
|
||||
}
|
||||
|
||||
static void TTL_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ipt_TTL_info *info = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_TTL_SET:
|
||||
info->mode = IPT_TTL_SET;
|
||||
break;
|
||||
case O_TTL_DEC:
|
||||
info->mode = IPT_TTL_DEC;
|
||||
break;
|
||||
case O_TTL_INC:
|
||||
info->mode = IPT_TTL_INC;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void TTL_check(struct xt_fcheck_call *cb)
|
||||
{
|
||||
if (!(cb->xflags & F_ANY))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"TTL: You must specify an action");
|
||||
}
|
||||
|
||||
static void TTL_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct ipt_TTL_info *info =
|
||||
(struct ipt_TTL_info *) target->data;
|
||||
|
||||
switch (info->mode) {
|
||||
case IPT_TTL_SET:
|
||||
printf(" --ttl-set");
|
||||
break;
|
||||
case IPT_TTL_DEC:
|
||||
printf(" --ttl-dec");
|
||||
break;
|
||||
|
||||
case IPT_TTL_INC:
|
||||
printf(" --ttl-inc");
|
||||
break;
|
||||
}
|
||||
printf(" %u", info->ttl);
|
||||
}
|
||||
|
||||
static void TTL_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct ipt_TTL_info *info =
|
||||
(struct ipt_TTL_info *) target->data;
|
||||
|
||||
printf(" TTL ");
|
||||
switch (info->mode) {
|
||||
case IPT_TTL_SET:
|
||||
printf("set to");
|
||||
break;
|
||||
case IPT_TTL_DEC:
|
||||
printf("decrement by");
|
||||
break;
|
||||
case IPT_TTL_INC:
|
||||
printf("increment by");
|
||||
break;
|
||||
}
|
||||
printf(" %u", info->ttl);
|
||||
}
|
||||
|
||||
static struct xtables_target ttl_tg_reg = {
|
||||
.name = "TTL",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV4,
|
||||
.size = XT_ALIGN(sizeof(struct ipt_TTL_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ipt_TTL_info)),
|
||||
.help = TTL_help,
|
||||
.print = TTL_print,
|
||||
.save = TTL_save,
|
||||
.x6_parse = TTL_parse,
|
||||
.x6_fcheck = TTL_check,
|
||||
.x6_options = TTL_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&ttl_tg_reg);
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
This is used to modify the IPv4 TTL header field. The TTL field determines
|
||||
how many hops (routers) a packet can traverse until it's time to live is
|
||||
exceeded.
|
||||
.PP
|
||||
Setting or incrementing the TTL field can potentially be very dangerous,
|
||||
so it should be avoided at any cost. This target is only valid in
|
||||
.B mangle
|
||||
table.
|
||||
.PP
|
||||
.B Don't ever set or increment the value on packets that leave your local network!
|
||||
.TP
|
||||
\fB\-\-ttl\-set\fP \fIvalue\fP
|
||||
Set the TTL value to `value'.
|
||||
.TP
|
||||
\fB\-\-ttl\-dec\fP \fIvalue\fP
|
||||
Decrement the TTL value `value' times.
|
||||
.TP
|
||||
\fB\-\-ttl\-inc\fP \fIvalue\fP
|
||||
Increment the TTL value `value' times.
|
|
@ -0,0 +1,128 @@
|
|||
/* Shared library add-on to iptables to add ULOG support.
|
||||
*
|
||||
* (C) 2000 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* multipart netlink support based on ideas by Sebastian Zander
|
||||
* <zander@fokus.gmd.de>
|
||||
*
|
||||
* This software is released under the terms of GNU GPL
|
||||
*
|
||||
* libipt_ULOG.c,v 1.7 2001/01/30 11:55:02 laforge Exp
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <xtables.h>
|
||||
/* For 64bit kernel / 32bit userspace */
|
||||
#include <linux/netfilter_ipv4/ipt_ULOG.h>
|
||||
|
||||
enum {
|
||||
O_ULOG_NLGROUP = 0,
|
||||
O_ULOG_PREFIX,
|
||||
O_ULOG_CPRANGE,
|
||||
O_ULOG_QTHR,
|
||||
};
|
||||
|
||||
static void ULOG_help(void)
|
||||
{
|
||||
printf("ULOG target options:\n"
|
||||
" --ulog-nlgroup nlgroup NETLINK group used for logging\n"
|
||||
" --ulog-cprange size Bytes of each packet to be passed\n"
|
||||
" --ulog-qthreshold Threshold of in-kernel queue\n"
|
||||
" --ulog-prefix prefix Prefix log messages with this prefix.\n");
|
||||
}
|
||||
|
||||
static const struct xt_option_entry ULOG_opts[] = {
|
||||
{.name = "ulog-nlgroup", .id = O_ULOG_NLGROUP, .type = XTTYPE_UINT8,
|
||||
.min = 1, .max = 32},
|
||||
{.name = "ulog-prefix", .id = O_ULOG_PREFIX, .type = XTTYPE_STRING,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(struct ipt_ulog_info, prefix),
|
||||
.min = 1},
|
||||
{.name = "ulog-cprange", .id = O_ULOG_CPRANGE, .type = XTTYPE_UINT64},
|
||||
{.name = "ulog-qthreshold", .id = O_ULOG_QTHR, .type = XTTYPE_UINT64,
|
||||
.min = 1, .max = ULOG_MAX_QLEN},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void ULOG_init(struct xt_entry_target *t)
|
||||
{
|
||||
struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) t->data;
|
||||
|
||||
loginfo->nl_group = ULOG_DEFAULT_NLGROUP;
|
||||
loginfo->qthreshold = ULOG_DEFAULT_QTHRESHOLD;
|
||||
|
||||
}
|
||||
|
||||
static void ULOG_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ipt_ulog_info *loginfo = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_ULOG_NLGROUP:
|
||||
loginfo->nl_group = 1 << (cb->val.u8 - 1);
|
||||
break;
|
||||
case O_ULOG_PREFIX:
|
||||
if (strchr(cb->arg, '\n') != NULL)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Newlines not allowed in --ulog-prefix");
|
||||
break;
|
||||
case O_ULOG_CPRANGE:
|
||||
loginfo->copy_range = cb->val.u64;
|
||||
break;
|
||||
case O_ULOG_QTHR:
|
||||
loginfo->qthreshold = cb->val.u64;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ULOG_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct ipt_ulog_info *loginfo
|
||||
= (const struct ipt_ulog_info *) target->data;
|
||||
|
||||
if (strcmp(loginfo->prefix, "") != 0) {
|
||||
fputs(" --ulog-prefix", stdout);
|
||||
xtables_save_string(loginfo->prefix);
|
||||
}
|
||||
|
||||
if (loginfo->nl_group != ULOG_DEFAULT_NLGROUP)
|
||||
printf(" --ulog-nlgroup %d", ffs(loginfo->nl_group));
|
||||
if (loginfo->copy_range)
|
||||
printf(" --ulog-cprange %u", (unsigned int)loginfo->copy_range);
|
||||
|
||||
if (loginfo->qthreshold != ULOG_DEFAULT_QTHRESHOLD)
|
||||
printf(" --ulog-qthreshold %u", (unsigned int)loginfo->qthreshold);
|
||||
}
|
||||
|
||||
static void ULOG_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct ipt_ulog_info *loginfo
|
||||
= (const struct ipt_ulog_info *) target->data;
|
||||
|
||||
printf(" ULOG ");
|
||||
printf("copy_range %u nlgroup %d", (unsigned int)loginfo->copy_range,
|
||||
ffs(loginfo->nl_group));
|
||||
if (strcmp(loginfo->prefix, "") != 0)
|
||||
printf(" prefix \"%s\"", loginfo->prefix);
|
||||
printf(" queue_threshold %u", (unsigned int)loginfo->qthreshold);
|
||||
}
|
||||
|
||||
static struct xtables_target ulog_tg_reg = {
|
||||
.name = "ULOG",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV4,
|
||||
.size = XT_ALIGN(sizeof(struct ipt_ulog_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ipt_ulog_info)),
|
||||
.help = ULOG_help,
|
||||
.init = ULOG_init,
|
||||
.print = ULOG_print,
|
||||
.save = ULOG_save,
|
||||
.x6_parse = ULOG_parse,
|
||||
.x6_options = ULOG_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&ulog_tg_reg);
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
This is the deprecated ipv4-only predecessor of the NFLOG target.
|
||||
It provides userspace logging of matching packets. When this
|
||||
target is set for a rule, the Linux kernel will multicast this packet
|
||||
through a
|
||||
.IR netlink
|
||||
socket. One or more userspace processes may then subscribe to various
|
||||
multicast groups and receive the packets.
|
||||
Like LOG, this is a "non-terminating target", i.e. rule traversal
|
||||
continues at the next rule.
|
||||
.TP
|
||||
\fB\-\-ulog\-nlgroup\fP \fInlgroup\fP
|
||||
This specifies the netlink group (1-32) to which the packet is sent.
|
||||
Default value is 1.
|
||||
.TP
|
||||
\fB\-\-ulog\-prefix\fP \fIprefix\fP
|
||||
Prefix log messages with the specified prefix; up to 32 characters
|
||||
long, and useful for distinguishing messages in the logs.
|
||||
.TP
|
||||
\fB\-\-ulog\-cprange\fP \fIsize\fP
|
||||
Number of bytes to be copied to userspace. A value of 0 always copies
|
||||
the entire packet, regardless of its size. Default is 0.
|
||||
.TP
|
||||
\fB\-\-ulog\-qthreshold\fP \fIsize\fP
|
||||
Number of packet to queue inside kernel. Setting this value to, e.g. 10
|
||||
accumulates ten packets inside the kernel and transmits them as one
|
||||
netlink multipart message to userspace. Default is 1 (for backwards
|
||||
compatibility).
|
||||
.br
|
|
@ -0,0 +1,113 @@
|
|||
#include <stdio.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_ipv4/ipt_ah.h>
|
||||
|
||||
enum {
|
||||
O_AHSPI = 0,
|
||||
};
|
||||
|
||||
static void ah_help(void)
|
||||
{
|
||||
printf(
|
||||
"ah match options:\n"
|
||||
"[!] --ahspi spi[:spi]\n"
|
||||
" match spi (range)\n");
|
||||
}
|
||||
|
||||
static const struct xt_option_entry ah_opts[] = {
|
||||
{.name = "ahspi", .id = O_AHSPI, .type = XTTYPE_UINT32RC,
|
||||
.flags = XTOPT_INVERT | XTOPT_PUT,
|
||||
XTOPT_POINTER(struct ipt_ah, spis)},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void ah_init(struct xt_entry_match *m)
|
||||
{
|
||||
struct ipt_ah *ahinfo = (void *)m->data;
|
||||
|
||||
ahinfo->spis[1] = ~0U;
|
||||
}
|
||||
|
||||
static void ah_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ipt_ah *ahinfo = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
if (cb->nvals == 1)
|
||||
ahinfo->spis[1] = ahinfo->spis[0];
|
||||
if (cb->invert)
|
||||
ahinfo->invflags |= IPT_AH_INV_SPI;
|
||||
}
|
||||
|
||||
static void
|
||||
print_spis(const char *name, uint32_t min, uint32_t max,
|
||||
int invert)
|
||||
{
|
||||
const char *inv = invert ? "!" : "";
|
||||
|
||||
if (min != 0 || max != 0xFFFFFFFF || invert) {
|
||||
printf("%s", name);
|
||||
if (min == max) {
|
||||
printf(":%s", inv);
|
||||
printf("%u", min);
|
||||
} else {
|
||||
printf("s:%s", inv);
|
||||
printf("%u",min);
|
||||
printf(":");
|
||||
printf("%u",max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ah_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
const struct ipt_ah *ah = (struct ipt_ah *)match->data;
|
||||
|
||||
printf(" ah ");
|
||||
print_spis("spi", ah->spis[0], ah->spis[1],
|
||||
ah->invflags & IPT_AH_INV_SPI);
|
||||
if (ah->invflags & ~IPT_AH_INV_MASK)
|
||||
printf(" Unknown invflags: 0x%X",
|
||||
ah->invflags & ~IPT_AH_INV_MASK);
|
||||
}
|
||||
|
||||
static void ah_save(const void *ip, const struct xt_entry_match *match)
|
||||
{
|
||||
const struct ipt_ah *ahinfo = (struct ipt_ah *)match->data;
|
||||
|
||||
if (!(ahinfo->spis[0] == 0
|
||||
&& ahinfo->spis[1] == 0xFFFFFFFF)) {
|
||||
printf("%s --ahspi ",
|
||||
(ahinfo->invflags & IPT_AH_INV_SPI) ? " !" : "");
|
||||
if (ahinfo->spis[0]
|
||||
!= ahinfo->spis[1])
|
||||
printf("%u:%u",
|
||||
ahinfo->spis[0],
|
||||
ahinfo->spis[1]);
|
||||
else
|
||||
printf("%u",
|
||||
ahinfo->spis[0]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static struct xtables_match ah_mt_reg = {
|
||||
.name = "ah",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV4,
|
||||
.size = XT_ALIGN(sizeof(struct ipt_ah)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ipt_ah)),
|
||||
.help = ah_help,
|
||||
.init = ah_init,
|
||||
.print = ah_print,
|
||||
.save = ah_save,
|
||||
.x6_parse = ah_parse,
|
||||
.x6_options = ah_opts,
|
||||
};
|
||||
|
||||
void
|
||||
_init(void)
|
||||
{
|
||||
xtables_register_match(&ah_mt_reg);
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
This module matches the SPIs in Authentication header of IPsec packets.
|
||||
.TP
|
||||
[\fB!\fP] \fB\-\-ahspi\fP \fIspi\fP[\fB:\fP\fIspi\fP]
|
|
@ -0,0 +1,269 @@
|
|||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <xtables.h>
|
||||
#include <limits.h> /* INT_MAX in ip6_tables.h */
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
|
||||
/* special hack for icmp-type 'any':
|
||||
* Up to kernel <=2.4.20 the problem was:
|
||||
* '-p icmp ' matches all icmp packets
|
||||
* '-p icmp -m icmp' matches _only_ ICMP type 0 :(
|
||||
* This is now fixed by initializing the field * to icmp type 0xFF
|
||||
* See: https://bugzilla.netfilter.org/cgi-bin/bugzilla/show_bug.cgi?id=37
|
||||
*/
|
||||
|
||||
enum {
|
||||
O_ICMP_TYPE = 0,
|
||||
};
|
||||
|
||||
struct icmp_names {
|
||||
const char *name;
|
||||
uint8_t type;
|
||||
uint8_t code_min, code_max;
|
||||
};
|
||||
|
||||
static const struct icmp_names icmp_codes[] = {
|
||||
{ "any", 0xFF, 0, 0xFF },
|
||||
{ "echo-reply", 0, 0, 0xFF },
|
||||
/* Alias */ { "pong", 0, 0, 0xFF },
|
||||
|
||||
{ "destination-unreachable", 3, 0, 0xFF },
|
||||
{ "network-unreachable", 3, 0, 0 },
|
||||
{ "host-unreachable", 3, 1, 1 },
|
||||
{ "protocol-unreachable", 3, 2, 2 },
|
||||
{ "port-unreachable", 3, 3, 3 },
|
||||
{ "fragmentation-needed", 3, 4, 4 },
|
||||
{ "source-route-failed", 3, 5, 5 },
|
||||
{ "network-unknown", 3, 6, 6 },
|
||||
{ "host-unknown", 3, 7, 7 },
|
||||
{ "network-prohibited", 3, 9, 9 },
|
||||
{ "host-prohibited", 3, 10, 10 },
|
||||
{ "TOS-network-unreachable", 3, 11, 11 },
|
||||
{ "TOS-host-unreachable", 3, 12, 12 },
|
||||
{ "communication-prohibited", 3, 13, 13 },
|
||||
{ "host-precedence-violation", 3, 14, 14 },
|
||||
{ "precedence-cutoff", 3, 15, 15 },
|
||||
|
||||
{ "source-quench", 4, 0, 0xFF },
|
||||
|
||||
{ "redirect", 5, 0, 0xFF },
|
||||
{ "network-redirect", 5, 0, 0 },
|
||||
{ "host-redirect", 5, 1, 1 },
|
||||
{ "TOS-network-redirect", 5, 2, 2 },
|
||||
{ "TOS-host-redirect", 5, 3, 3 },
|
||||
|
||||
{ "echo-request", 8, 0, 0xFF },
|
||||
/* Alias */ { "ping", 8, 0, 0xFF },
|
||||
|
||||
{ "router-advertisement", 9, 0, 0xFF },
|
||||
|
||||
{ "router-solicitation", 10, 0, 0xFF },
|
||||
|
||||
{ "time-exceeded", 11, 0, 0xFF },
|
||||
/* Alias */ { "ttl-exceeded", 11, 0, 0xFF },
|
||||
{ "ttl-zero-during-transit", 11, 0, 0 },
|
||||
{ "ttl-zero-during-reassembly", 11, 1, 1 },
|
||||
|
||||
{ "parameter-problem", 12, 0, 0xFF },
|
||||
{ "ip-header-bad", 12, 0, 0 },
|
||||
{ "required-option-missing", 12, 1, 1 },
|
||||
|
||||
{ "timestamp-request", 13, 0, 0xFF },
|
||||
|
||||
{ "timestamp-reply", 14, 0, 0xFF },
|
||||
|
||||
{ "address-mask-request", 17, 0, 0xFF },
|
||||
|
||||
{ "address-mask-reply", 18, 0, 0xFF }
|
||||
};
|
||||
|
||||
static void
|
||||
print_icmptypes(void)
|
||||
{
|
||||
unsigned int i;
|
||||
printf("Valid ICMP Types:");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(icmp_codes); ++i) {
|
||||
if (i && icmp_codes[i].type == icmp_codes[i-1].type) {
|
||||
if (icmp_codes[i].code_min == icmp_codes[i-1].code_min
|
||||
&& (icmp_codes[i].code_max
|
||||
== icmp_codes[i-1].code_max))
|
||||
printf(" (%s)", icmp_codes[i].name);
|
||||
else
|
||||
printf("\n %s", icmp_codes[i].name);
|
||||
}
|
||||
else
|
||||
printf("\n%s", icmp_codes[i].name);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void icmp_help(void)
|
||||
{
|
||||
printf(
|
||||
"icmp match options:\n"
|
||||
"[!] --icmp-type typename match icmp type\n"
|
||||
"[!] --icmp-type type[/code] (or numeric type or type/code)\n");
|
||||
print_icmptypes();
|
||||
}
|
||||
|
||||
static const struct xt_option_entry icmp_opts[] = {
|
||||
{.name = "icmp-type", .id = O_ICMP_TYPE, .type = XTTYPE_STRING,
|
||||
.flags = XTOPT_MAND | XTOPT_INVERT},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void
|
||||
parse_icmp(const char *icmptype, uint8_t *type, uint8_t code[])
|
||||
{
|
||||
static const unsigned int limit = ARRAY_SIZE(icmp_codes);
|
||||
unsigned int match = limit;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < limit; i++) {
|
||||
if (strncasecmp(icmp_codes[i].name, icmptype, strlen(icmptype))
|
||||
== 0) {
|
||||
if (match != limit)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Ambiguous ICMP type `%s':"
|
||||
" `%s' or `%s'?",
|
||||
icmptype,
|
||||
icmp_codes[match].name,
|
||||
icmp_codes[i].name);
|
||||
match = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (match != limit) {
|
||||
*type = icmp_codes[match].type;
|
||||
code[0] = icmp_codes[match].code_min;
|
||||
code[1] = icmp_codes[match].code_max;
|
||||
} else {
|
||||
char *slash;
|
||||
char buffer[strlen(icmptype) + 1];
|
||||
unsigned int number;
|
||||
|
||||
strcpy(buffer, icmptype);
|
||||
slash = strchr(buffer, '/');
|
||||
|
||||
if (slash)
|
||||
*slash = '\0';
|
||||
|
||||
if (!xtables_strtoui(buffer, NULL, &number, 0, UINT8_MAX))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Invalid ICMP type `%s'\n", buffer);
|
||||
*type = number;
|
||||
if (slash) {
|
||||
if (!xtables_strtoui(slash+1, NULL, &number, 0, UINT8_MAX))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Invalid ICMP code `%s'\n",
|
||||
slash+1);
|
||||
code[0] = code[1] = number;
|
||||
} else {
|
||||
code[0] = 0;
|
||||
code[1] = 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void icmp_init(struct xt_entry_match *m)
|
||||
{
|
||||
struct ipt_icmp *icmpinfo = (struct ipt_icmp *)m->data;
|
||||
|
||||
icmpinfo->type = 0xFF;
|
||||
icmpinfo->code[1] = 0xFF;
|
||||
}
|
||||
|
||||
static void icmp_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ipt_icmp *icmpinfo = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
parse_icmp(cb->arg, &icmpinfo->type, icmpinfo->code);
|
||||
if (cb->invert)
|
||||
icmpinfo->invflags |= IPT_ICMP_INV;
|
||||
}
|
||||
|
||||
static void print_icmptype(uint8_t type,
|
||||
uint8_t code_min, uint8_t code_max,
|
||||
int invert,
|
||||
int numeric)
|
||||
{
|
||||
if (!numeric) {
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(icmp_codes); ++i)
|
||||
if (icmp_codes[i].type == type
|
||||
&& icmp_codes[i].code_min == code_min
|
||||
&& icmp_codes[i].code_max == code_max)
|
||||
break;
|
||||
|
||||
if (i != ARRAY_SIZE(icmp_codes)) {
|
||||
printf(" %s%s",
|
||||
invert ? "!" : "",
|
||||
icmp_codes[i].name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (invert)
|
||||
printf(" !");
|
||||
|
||||
printf("type %u", type);
|
||||
if (code_min == code_max)
|
||||
printf(" code %u", code_min);
|
||||
else if (code_min != 0 || code_max != 0xFF)
|
||||
printf(" codes %u-%u", code_min, code_max);
|
||||
}
|
||||
|
||||
static void icmp_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
const struct ipt_icmp *icmp = (struct ipt_icmp *)match->data;
|
||||
|
||||
printf(" icmp");
|
||||
print_icmptype(icmp->type, icmp->code[0], icmp->code[1],
|
||||
icmp->invflags & IPT_ICMP_INV,
|
||||
numeric);
|
||||
|
||||
if (icmp->invflags & ~IPT_ICMP_INV)
|
||||
printf(" Unknown invflags: 0x%X",
|
||||
icmp->invflags & ~IPT_ICMP_INV);
|
||||
}
|
||||
|
||||
static void icmp_save(const void *ip, const struct xt_entry_match *match)
|
||||
{
|
||||
const struct ipt_icmp *icmp = (struct ipt_icmp *)match->data;
|
||||
|
||||
if (icmp->invflags & IPT_ICMP_INV)
|
||||
printf(" !");
|
||||
|
||||
/* special hack for 'any' case */
|
||||
if (icmp->type == 0xFF) {
|
||||
printf(" --icmp-type any");
|
||||
} else {
|
||||
printf(" --icmp-type %u", icmp->type);
|
||||
if (icmp->code[0] != 0 || icmp->code[1] != 0xFF)
|
||||
printf("/%u", icmp->code[0]);
|
||||
}
|
||||
}
|
||||
|
||||
static struct xtables_match icmp_mt_reg = {
|
||||
.name = "icmp",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV4,
|
||||
.size = XT_ALIGN(sizeof(struct ipt_icmp)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ipt_icmp)),
|
||||
.help = icmp_help,
|
||||
.init = icmp_init,
|
||||
.print = icmp_print,
|
||||
.save = icmp_save,
|
||||
.x6_parse = icmp_parse,
|
||||
.x6_options = icmp_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_match(&icmp_mt_reg);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
This extension can be used if `\-\-protocol icmp' is specified. It
|
||||
provides the following option:
|
||||
.TP
|
||||
[\fB!\fP] \fB\-\-icmp\-type\fP {\fItype\fP[\fB/\fP\fIcode\fP]|\fItypename\fP}
|
||||
This allows specification of the ICMP type, which can be a numeric
|
||||
ICMP type, type/code pair, or one of the ICMP type names shown by the command
|
||||
.nf
|
||||
iptables \-p icmp \-h
|
||||
.fi
|
|
@ -0,0 +1,127 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#if defined(__GLIBC__) && __GLIBC__ == 2
|
||||
#include <net/ethernet.h>
|
||||
#else
|
||||
#include <linux/if_ether.h>
|
||||
#endif
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_ipv4/ipt_realm.h>
|
||||
|
||||
enum {
|
||||
O_REALM = 0,
|
||||
};
|
||||
|
||||
static void realm_help(void)
|
||||
{
|
||||
printf(
|
||||
"realm match options:\n"
|
||||
"[!] --realm value[/mask]\n"
|
||||
" Match realm\n");
|
||||
}
|
||||
|
||||
static const struct xt_option_entry realm_opts[] = {
|
||||
{.name = "realm", .id = O_REALM, .type = XTTYPE_STRING,
|
||||
.flags = XTOPT_MAND | XTOPT_INVERT},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
/* array of realms from /etc/iproute2/rt_realms */
|
||||
static struct xtables_lmap *realms;
|
||||
|
||||
static void realm_init(struct xt_entry_match *m)
|
||||
{
|
||||
const char file[] = "/etc/iproute2/rt_realms";
|
||||
realms = xtables_lmap_init(file);
|
||||
if (realms == NULL && errno != ENOENT)
|
||||
fprintf(stderr, "Warning: %s: %s\n", file, strerror(errno));
|
||||
}
|
||||
|
||||
static void realm_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct xt_realm_info *realminfo = cb->data;
|
||||
int id;
|
||||
char *end;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
realminfo->id = strtoul(cb->arg, &end, 0);
|
||||
if (end != cb->arg && (*end == '/' || *end == '\0')) {
|
||||
if (*end == '/')
|
||||
realminfo->mask = strtoul(end+1, &end, 0);
|
||||
else
|
||||
realminfo->mask = 0xffffffff;
|
||||
if (*end != '\0' || end == cb->arg)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Bad realm value \"%s\"", cb->arg);
|
||||
} else {
|
||||
id = xtables_lmap_name2id(realms, cb->arg);
|
||||
if (id == -1)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Realm \"%s\" not found", cb->arg);
|
||||
realminfo->id = id;
|
||||
realminfo->mask = 0xffffffff;
|
||||
}
|
||||
if (cb->invert)
|
||||
realminfo->invert = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
print_realm(unsigned long id, unsigned long mask, int numeric)
|
||||
{
|
||||
const char* name = NULL;
|
||||
|
||||
if (mask != 0xffffffff)
|
||||
printf(" 0x%lx/0x%lx", id, mask);
|
||||
else {
|
||||
if (numeric == 0)
|
||||
name = xtables_lmap_id2name(realms, id);
|
||||
if (name)
|
||||
printf(" %s", name);
|
||||
else
|
||||
printf(" 0x%lx", id);
|
||||
}
|
||||
}
|
||||
|
||||
static void realm_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_realm_info *ri = (const void *)match->data;
|
||||
|
||||
if (ri->invert)
|
||||
printf(" !");
|
||||
|
||||
printf(" realm");
|
||||
print_realm(ri->id, ri->mask, numeric);
|
||||
}
|
||||
|
||||
static void realm_save(const void *ip, const struct xt_entry_match *match)
|
||||
{
|
||||
const struct xt_realm_info *ri = (const void *)match->data;
|
||||
|
||||
if (ri->invert)
|
||||
printf(" !");
|
||||
|
||||
printf(" --realm");
|
||||
print_realm(ri->id, ri->mask, 0);
|
||||
}
|
||||
|
||||
static struct xtables_match realm_mt_reg = {
|
||||
.name = "realm",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV4,
|
||||
.size = XT_ALIGN(sizeof(struct xt_realm_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_realm_info)),
|
||||
.help = realm_help,
|
||||
.init = realm_init,
|
||||
.print = realm_print,
|
||||
.save = realm_save,
|
||||
.x6_parse = realm_parse,
|
||||
.x6_options = realm_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_match(&realm_mt_reg);
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
This matches the routing realm. Routing realms are used in complex routing
|
||||
setups involving dynamic routing protocols like BGP.
|
||||
.TP
|
||||
[\fB!\fP] \fB\-\-realm\fP \fIvalue\fP[\fB/\fP\fImask\fP]
|
||||
Matches a given realm number (and optionally mask). If not a number, value
|
||||
can be a named realm from /etc/iproute2/rt_realms (mask can not be used in
|
||||
that case).
|
|
@ -0,0 +1,135 @@
|
|||
/* Shared library add-on to iptables to add TTL matching support
|
||||
* (C) 2000 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* This program is released under the terms of GNU GPL */
|
||||
#include <stdio.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter_ipv4/ipt_ttl.h>
|
||||
|
||||
enum {
|
||||
O_TTL_EQ = 0,
|
||||
O_TTL_LT,
|
||||
O_TTL_GT,
|
||||
F_TTL_EQ = 1 << O_TTL_EQ,
|
||||
F_TTL_LT = 1 << O_TTL_LT,
|
||||
F_TTL_GT = 1 << O_TTL_GT,
|
||||
F_ANY = F_TTL_EQ | F_TTL_LT | F_TTL_GT,
|
||||
};
|
||||
|
||||
static void ttl_help(void)
|
||||
{
|
||||
printf(
|
||||
"ttl match options:\n"
|
||||
"[!] --ttl-eq value Match time to live value\n"
|
||||
" --ttl-lt value Match TTL < value\n"
|
||||
" --ttl-gt value Match TTL > value\n");
|
||||
}
|
||||
|
||||
static void ttl_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct ipt_ttl_info *info = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_TTL_EQ:
|
||||
info->mode = cb->invert ? IPT_TTL_NE : IPT_TTL_EQ;
|
||||
break;
|
||||
case O_TTL_LT:
|
||||
info->mode = IPT_TTL_LT;
|
||||
break;
|
||||
case O_TTL_GT:
|
||||
info->mode = IPT_TTL_GT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ttl_check(struct xt_fcheck_call *cb)
|
||||
{
|
||||
if (!(cb->xflags & F_ANY))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"TTL match: You must specify one of "
|
||||
"`--ttl-eq', `--ttl-lt', `--ttl-gt");
|
||||
}
|
||||
|
||||
static void ttl_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
const struct ipt_ttl_info *info =
|
||||
(struct ipt_ttl_info *) match->data;
|
||||
|
||||
printf(" TTL match ");
|
||||
switch (info->mode) {
|
||||
case IPT_TTL_EQ:
|
||||
printf("TTL ==");
|
||||
break;
|
||||
case IPT_TTL_NE:
|
||||
printf("TTL !=");
|
||||
break;
|
||||
case IPT_TTL_LT:
|
||||
printf("TTL <");
|
||||
break;
|
||||
case IPT_TTL_GT:
|
||||
printf("TTL >");
|
||||
break;
|
||||
}
|
||||
printf(" %u", info->ttl);
|
||||
}
|
||||
|
||||
static void ttl_save(const void *ip, const struct xt_entry_match *match)
|
||||
{
|
||||
const struct ipt_ttl_info *info =
|
||||
(struct ipt_ttl_info *) match->data;
|
||||
|
||||
switch (info->mode) {
|
||||
case IPT_TTL_EQ:
|
||||
printf(" --ttl-eq");
|
||||
break;
|
||||
case IPT_TTL_NE:
|
||||
printf(" ! --ttl-eq");
|
||||
break;
|
||||
case IPT_TTL_LT:
|
||||
printf(" --ttl-lt");
|
||||
break;
|
||||
case IPT_TTL_GT:
|
||||
printf(" --ttl-gt");
|
||||
break;
|
||||
default:
|
||||
/* error */
|
||||
break;
|
||||
}
|
||||
printf(" %u", info->ttl);
|
||||
}
|
||||
|
||||
#define s struct ipt_ttl_info
|
||||
static const struct xt_option_entry ttl_opts[] = {
|
||||
{.name = "ttl-lt", .id = O_TTL_LT, .excl = F_ANY, .type = XTTYPE_UINT8,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(s, ttl)},
|
||||
{.name = "ttl-gt", .id = O_TTL_GT, .excl = F_ANY, .type = XTTYPE_UINT8,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(s, ttl)},
|
||||
{.name = "ttl-eq", .id = O_TTL_EQ, .excl = F_ANY, .type = XTTYPE_UINT8,
|
||||
.flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, ttl)},
|
||||
{.name = "ttl", .id = O_TTL_EQ, .excl = F_ANY, .type = XTTYPE_UINT8,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(s, ttl)},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
#undef s
|
||||
|
||||
static struct xtables_match ttl_mt_reg = {
|
||||
.name = "ttl",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV4,
|
||||
.size = XT_ALIGN(sizeof(struct ipt_ttl_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct ipt_ttl_info)),
|
||||
.help = ttl_help,
|
||||
.print = ttl_print,
|
||||
.save = ttl_save,
|
||||
.x6_parse = ttl_parse,
|
||||
.x6_fcheck = ttl_check,
|
||||
.x6_options = ttl_opts,
|
||||
};
|
||||
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_match(&ttl_mt_reg);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
This module matches the time to live field in the IP header.
|
||||
.TP
|
||||
[\fB!\fP] \fB\-\-ttl\-eq\fP \fIttl\fP
|
||||
Matches the given TTL value.
|
||||
.TP
|
||||
\fB\-\-ttl\-gt\fP \fIttl\fP
|
||||
Matches if TTL is greater than the given TTL value.
|
||||
.TP
|
||||
\fB\-\-ttl\-lt\fP \fIttl\fP
|
||||
Matches if TTL is less than the given TTL value.
|
|
@ -0,0 +1,101 @@
|
|||
/* Shared library add-on to xtables for AUDIT
|
||||
*
|
||||
* (C) 2010-2011, Thomas Graf <tgraf@redhat.com>
|
||||
* (C) 2010-2011, Red Hat, Inc.
|
||||
*
|
||||
* This program is distributed under the terms of GNU GPL v2, 1991
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter/xt_AUDIT.h>
|
||||
|
||||
enum {
|
||||
O_AUDIT_TYPE = 0,
|
||||
};
|
||||
|
||||
static void audit_help(void)
|
||||
{
|
||||
printf(
|
||||
"AUDIT target options\n"
|
||||
" --type TYPE Action type to be recorded.\n");
|
||||
}
|
||||
|
||||
static const struct xt_option_entry audit_opts[] = {
|
||||
{.name = "type", .id = O_AUDIT_TYPE, .type = XTTYPE_STRING,
|
||||
.flags = XTOPT_MAND},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void audit_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct xt_audit_info *einfo = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
if (strcasecmp(cb->arg, "accept") == 0)
|
||||
einfo->type = XT_AUDIT_TYPE_ACCEPT;
|
||||
else if (strcasecmp(cb->arg, "drop") == 0)
|
||||
einfo->type = XT_AUDIT_TYPE_DROP;
|
||||
else if (strcasecmp(cb->arg, "reject") == 0)
|
||||
einfo->type = XT_AUDIT_TYPE_REJECT;
|
||||
else
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Bad action type value \"%s\"", cb->arg);
|
||||
}
|
||||
|
||||
static void audit_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_audit_info *einfo =
|
||||
(const struct xt_audit_info *)target->data;
|
||||
|
||||
printf(" AUDIT ");
|
||||
|
||||
switch(einfo->type) {
|
||||
case XT_AUDIT_TYPE_ACCEPT:
|
||||
printf("accept");
|
||||
break;
|
||||
case XT_AUDIT_TYPE_DROP:
|
||||
printf("drop");
|
||||
break;
|
||||
case XT_AUDIT_TYPE_REJECT:
|
||||
printf("reject");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void audit_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct xt_audit_info *einfo =
|
||||
(const struct xt_audit_info *)target->data;
|
||||
|
||||
switch(einfo->type) {
|
||||
case XT_AUDIT_TYPE_ACCEPT:
|
||||
printf(" --type accept");
|
||||
break;
|
||||
case XT_AUDIT_TYPE_DROP:
|
||||
printf(" --type drop");
|
||||
break;
|
||||
case XT_AUDIT_TYPE_REJECT:
|
||||
printf(" --type reject");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct xtables_target audit_tg_reg = {
|
||||
.name = "AUDIT",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.size = XT_ALIGN(sizeof(struct xt_audit_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_audit_info)),
|
||||
.help = audit_help,
|
||||
.print = audit_print,
|
||||
.save = audit_save,
|
||||
.x6_parse = audit_parse,
|
||||
.x6_options = audit_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&audit_tg_reg);
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
This target allows to create audit records for packets hitting the target.
|
||||
It can be used to record accepted, dropped, and rejected packets. See
|
||||
auditd(8) for additional details.
|
||||
.TP
|
||||
\fB\-\-type\fP {\fBaccept\fP|\fBdrop\fP|\fBreject\fP}
|
||||
Set type of audit record.
|
||||
.PP
|
||||
Example:
|
||||
.IP
|
||||
iptables \-N AUDIT_DROP
|
||||
.IP
|
||||
iptables \-A AUDIT_DROP \-j AUDIT \-\-type drop
|
||||
.IP
|
||||
iptables \-A AUDIT_DROP \-j DROP
|
|
@ -0,0 +1,77 @@
|
|||
/* Shared library add-on to xtables for CHECKSUM
|
||||
*
|
||||
* (C) 2002 by Harald Welte <laforge@gnumonks.org>
|
||||
* (C) 2010 by Red Hat, Inc
|
||||
* Author: Michael S. Tsirkin <mst@redhat.com>
|
||||
*
|
||||
* This program is distributed under the terms of GNU GPL v2, 1991
|
||||
*
|
||||
* libxt_CHECKSUM.c borrowed some bits from libipt_ECN.c
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter/xt_CHECKSUM.h>
|
||||
|
||||
enum {
|
||||
O_CHECKSUM_FILL = 0,
|
||||
};
|
||||
|
||||
static void CHECKSUM_help(void)
|
||||
{
|
||||
printf(
|
||||
"CHECKSUM target options\n"
|
||||
" --checksum-fill Fill in packet checksum.\n");
|
||||
}
|
||||
|
||||
static const struct xt_option_entry CHECKSUM_opts[] = {
|
||||
{.name = "checksum-fill", .id = O_CHECKSUM_FILL,
|
||||
.flags = XTOPT_MAND, .type = XTTYPE_NONE},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void CHECKSUM_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct xt_CHECKSUM_info *einfo = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
einfo->operation = XT_CHECKSUM_OP_FILL;
|
||||
}
|
||||
|
||||
static void CHECKSUM_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_CHECKSUM_info *einfo =
|
||||
(const struct xt_CHECKSUM_info *)target->data;
|
||||
|
||||
printf(" CHECKSUM");
|
||||
|
||||
if (einfo->operation & XT_CHECKSUM_OP_FILL)
|
||||
printf(" fill");
|
||||
}
|
||||
|
||||
static void CHECKSUM_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct xt_CHECKSUM_info *einfo =
|
||||
(const struct xt_CHECKSUM_info *)target->data;
|
||||
|
||||
if (einfo->operation & XT_CHECKSUM_OP_FILL)
|
||||
printf(" --checksum-fill");
|
||||
}
|
||||
|
||||
static struct xtables_target checksum_tg_reg = {
|
||||
.name = "CHECKSUM",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.size = XT_ALIGN(sizeof(struct xt_CHECKSUM_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_CHECKSUM_info)),
|
||||
.help = CHECKSUM_help,
|
||||
.print = CHECKSUM_print,
|
||||
.save = CHECKSUM_save,
|
||||
.x6_parse = CHECKSUM_parse,
|
||||
.x6_options = CHECKSUM_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&checksum_tg_reg);
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
This target allows to selectively work around broken/old applications.
|
||||
It can only be used in the mangle table.
|
||||
.TP
|
||||
\fB\-\-checksum\-fill\fP
|
||||
Compute and fill in the checksum in a packet that lacks a checksum.
|
||||
This is particularly useful, if you need to work around old applications
|
||||
such as dhcp clients, that do not work well with checksum offloads,
|
||||
but don't want to disable checksum offload in your device.
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2013 Patrick McHardy <kaber@trash.net>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter/xt_CLASSIFY.h>
|
||||
#include <linux/pkt_sched.h>
|
||||
|
||||
enum {
|
||||
O_SET_CLASS = 0,
|
||||
};
|
||||
|
||||
static void
|
||||
CLASSIFY_help(void)
|
||||
{
|
||||
printf(
|
||||
"CLASSIFY target options:\n"
|
||||
"--set-class MAJOR:MINOR Set skb->priority value (always hexadecimal!)\n");
|
||||
}
|
||||
|
||||
static const struct xt_option_entry CLASSIFY_opts[] = {
|
||||
{.name = "set-class", .id = O_SET_CLASS, .type = XTTYPE_STRING,
|
||||
.flags = XTOPT_MAND},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static int CLASSIFY_string_to_priority(const char *s, unsigned int *p)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
if (sscanf(s, "%x:%x", &i, &j) != 2)
|
||||
return 1;
|
||||
|
||||
*p = TC_H_MAKE(i<<16, j);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void CLASSIFY_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct xt_classify_target_info *clinfo = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
if (CLASSIFY_string_to_priority(cb->arg, &clinfo->priority))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Bad class value \"%s\"", cb->arg);
|
||||
}
|
||||
|
||||
static void
|
||||
CLASSIFY_print_class(unsigned int priority, int numeric)
|
||||
{
|
||||
printf(" %x:%x", TC_H_MAJ(priority)>>16, TC_H_MIN(priority));
|
||||
}
|
||||
|
||||
static void
|
||||
CLASSIFY_print(const void *ip,
|
||||
const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_classify_target_info *clinfo =
|
||||
(const struct xt_classify_target_info *)target->data;
|
||||
printf(" CLASSIFY set");
|
||||
CLASSIFY_print_class(clinfo->priority, numeric);
|
||||
}
|
||||
|
||||
static void
|
||||
CLASSIFY_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct xt_classify_target_info *clinfo =
|
||||
(const struct xt_classify_target_info *)target->data;
|
||||
|
||||
printf(" --set-class %.4x:%.4x",
|
||||
TC_H_MAJ(clinfo->priority)>>16, TC_H_MIN(clinfo->priority));
|
||||
}
|
||||
|
||||
static void
|
||||
arpCLASSIFY_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
CLASSIFY_save(ip, target);
|
||||
}
|
||||
|
||||
static struct xtables_target classify_target[] = {
|
||||
{
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.name = "CLASSIFY",
|
||||
.version = XTABLES_VERSION,
|
||||
.size = XT_ALIGN(sizeof(struct xt_classify_target_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_classify_target_info)),
|
||||
.help = CLASSIFY_help,
|
||||
.print = CLASSIFY_print,
|
||||
.save = CLASSIFY_save,
|
||||
.x6_parse = CLASSIFY_parse,
|
||||
.x6_options = CLASSIFY_opts,
|
||||
},
|
||||
{
|
||||
.family = NFPROTO_ARP,
|
||||
.name = "CLASSIFY",
|
||||
.version = XTABLES_VERSION,
|
||||
.size = XT_ALIGN(sizeof(struct xt_classify_target_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_classify_target_info)),
|
||||
.help = CLASSIFY_help,
|
||||
.print = arpCLASSIFY_print,
|
||||
.x6_parse = CLASSIFY_parse,
|
||||
.x6_options = CLASSIFY_opts,
|
||||
},
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_targets(classify_target, ARRAY_SIZE(classify_target));
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
This module allows you to set the skb\->priority value (and thus classify the packet into a specific CBQ class).
|
||||
.TP
|
||||
\fB\-\-set\-class\fP \fImajor\fP\fB:\fP\fIminor\fP
|
||||
Set the major and minor class value. The values are always interpreted as
|
||||
hexadecimal even if no 0x prefix is given.
|
|
@ -0,0 +1,386 @@
|
|||
/* Shared library add-on to iptables to add CONNMARK target support.
|
||||
*
|
||||
* (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
|
||||
* by Henrik Nordstrom <hno@marasystems.com>
|
||||
*
|
||||
* Version 1.1
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter/xt_CONNMARK.h>
|
||||
|
||||
struct xt_connmark_target_info {
|
||||
unsigned long mark;
|
||||
unsigned long mask;
|
||||
uint8_t mode;
|
||||
};
|
||||
|
||||
enum {
|
||||
O_SET_MARK = 0,
|
||||
O_SAVE_MARK,
|
||||
O_RESTORE_MARK,
|
||||
O_AND_MARK,
|
||||
O_OR_MARK,
|
||||
O_XOR_MARK,
|
||||
O_SET_XMARK,
|
||||
O_CTMASK,
|
||||
O_NFMASK,
|
||||
O_MASK,
|
||||
F_SET_MARK = 1 << O_SET_MARK,
|
||||
F_SAVE_MARK = 1 << O_SAVE_MARK,
|
||||
F_RESTORE_MARK = 1 << O_RESTORE_MARK,
|
||||
F_AND_MARK = 1 << O_AND_MARK,
|
||||
F_OR_MARK = 1 << O_OR_MARK,
|
||||
F_XOR_MARK = 1 << O_XOR_MARK,
|
||||
F_SET_XMARK = 1 << O_SET_XMARK,
|
||||
F_CTMASK = 1 << O_CTMASK,
|
||||
F_NFMASK = 1 << O_NFMASK,
|
||||
F_MASK = 1 << O_MASK,
|
||||
F_OP_ANY = F_SET_MARK | F_SAVE_MARK | F_RESTORE_MARK |
|
||||
F_AND_MARK | F_OR_MARK | F_XOR_MARK | F_SET_XMARK,
|
||||
};
|
||||
|
||||
static void CONNMARK_help(void)
|
||||
{
|
||||
printf(
|
||||
"CONNMARK target options:\n"
|
||||
" --set-mark value[/mask] Set conntrack mark value\n"
|
||||
" --save-mark [--mask mask] Save the packet nfmark in the connection\n"
|
||||
" --restore-mark [--mask mask] Restore saved nfmark value\n");
|
||||
}
|
||||
|
||||
#define s struct xt_connmark_target_info
|
||||
static const struct xt_option_entry CONNMARK_opts[] = {
|
||||
{.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_MARKMASK32,
|
||||
.excl = F_OP_ANY},
|
||||
{.name = "save-mark", .id = O_SAVE_MARK, .type = XTTYPE_NONE,
|
||||
.excl = F_OP_ANY},
|
||||
{.name = "restore-mark", .id = O_RESTORE_MARK, .type = XTTYPE_NONE,
|
||||
.excl = F_OP_ANY},
|
||||
{.name = "mask", .id = O_MASK, .type = XTTYPE_UINT32},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
#undef s
|
||||
|
||||
#define s struct xt_connmark_tginfo1
|
||||
static const struct xt_option_entry connmark_tg_opts[] = {
|
||||
{.name = "set-xmark", .id = O_SET_XMARK, .type = XTTYPE_MARKMASK32,
|
||||
.excl = F_OP_ANY},
|
||||
{.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_MARKMASK32,
|
||||
.excl = F_OP_ANY},
|
||||
{.name = "and-mark", .id = O_AND_MARK, .type = XTTYPE_UINT32,
|
||||
.excl = F_OP_ANY},
|
||||
{.name = "or-mark", .id = O_OR_MARK, .type = XTTYPE_UINT32,
|
||||
.excl = F_OP_ANY},
|
||||
{.name = "xor-mark", .id = O_XOR_MARK, .type = XTTYPE_UINT32,
|
||||
.excl = F_OP_ANY},
|
||||
{.name = "save-mark", .id = O_SAVE_MARK, .type = XTTYPE_NONE,
|
||||
.excl = F_OP_ANY},
|
||||
{.name = "restore-mark", .id = O_RESTORE_MARK, .type = XTTYPE_NONE,
|
||||
.excl = F_OP_ANY},
|
||||
{.name = "ctmask", .id = O_CTMASK, .type = XTTYPE_UINT32,
|
||||
.excl = F_MASK, .flags = XTOPT_PUT, XTOPT_POINTER(s, ctmask)},
|
||||
{.name = "nfmask", .id = O_NFMASK, .type = XTTYPE_UINT32,
|
||||
.excl = F_MASK, .flags = XTOPT_PUT, XTOPT_POINTER(s, nfmask)},
|
||||
{.name = "mask", .id = O_MASK, .type = XTTYPE_UINT32,
|
||||
.excl = F_CTMASK | F_NFMASK},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
#undef s
|
||||
|
||||
static void connmark_tg_help(void)
|
||||
{
|
||||
printf(
|
||||
"CONNMARK target options:\n"
|
||||
" --set-xmark value[/ctmask] Zero mask bits and XOR ctmark with value\n"
|
||||
" --save-mark [--ctmask mask] [--nfmask mask]\n"
|
||||
" Copy ctmark to nfmark using masks\n"
|
||||
" --restore-mark [--ctmask mask] [--nfmask mask]\n"
|
||||
" Copy nfmark to ctmark using masks\n"
|
||||
" --set-mark value[/mask] Set conntrack mark value\n"
|
||||
" --save-mark [--mask mask] Save the packet nfmark in the connection\n"
|
||||
" --restore-mark [--mask mask] Restore saved nfmark value\n"
|
||||
" --and-mark value Binary AND the ctmark with bits\n"
|
||||
" --or-mark value Binary OR the ctmark with bits\n"
|
||||
" --xor-mark value Binary XOR the ctmark with bits\n"
|
||||
);
|
||||
}
|
||||
|
||||
static void connmark_tg_init(struct xt_entry_target *target)
|
||||
{
|
||||
struct xt_connmark_tginfo1 *info = (void *)target->data;
|
||||
|
||||
/*
|
||||
* Need these defaults for --save-mark/--restore-mark if no
|
||||
* --ctmark or --nfmask is given.
|
||||
*/
|
||||
info->ctmask = UINT32_MAX;
|
||||
info->nfmask = UINT32_MAX;
|
||||
}
|
||||
|
||||
static void CONNMARK_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct xt_connmark_target_info *markinfo = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_SET_MARK:
|
||||
markinfo->mode = XT_CONNMARK_SET;
|
||||
markinfo->mark = cb->val.mark;
|
||||
markinfo->mask = cb->val.mask;
|
||||
break;
|
||||
case O_SAVE_MARK:
|
||||
markinfo->mode = XT_CONNMARK_SAVE;
|
||||
break;
|
||||
case O_RESTORE_MARK:
|
||||
markinfo->mode = XT_CONNMARK_RESTORE;
|
||||
break;
|
||||
case O_MASK:
|
||||
markinfo->mask = cb->val.u32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void connmark_tg_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct xt_connmark_tginfo1 *info = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_SET_XMARK:
|
||||
info->mode = XT_CONNMARK_SET;
|
||||
info->ctmark = cb->val.mark;
|
||||
info->ctmask = cb->val.mask;
|
||||
break;
|
||||
case O_SET_MARK:
|
||||
info->mode = XT_CONNMARK_SET;
|
||||
info->ctmark = cb->val.mark;
|
||||
info->ctmask = cb->val.mark | cb->val.mask;
|
||||
break;
|
||||
case O_AND_MARK:
|
||||
info->mode = XT_CONNMARK_SET;
|
||||
info->ctmark = 0;
|
||||
info->ctmask = ~cb->val.u32;
|
||||
break;
|
||||
case O_OR_MARK:
|
||||
info->mode = XT_CONNMARK_SET;
|
||||
info->ctmark = cb->val.u32;
|
||||
info->ctmask = cb->val.u32;
|
||||
break;
|
||||
case O_XOR_MARK:
|
||||
info->mode = XT_CONNMARK_SET;
|
||||
info->ctmark = cb->val.u32;
|
||||
info->ctmask = 0;
|
||||
break;
|
||||
case O_SAVE_MARK:
|
||||
info->mode = XT_CONNMARK_SAVE;
|
||||
break;
|
||||
case O_RESTORE_MARK:
|
||||
info->mode = XT_CONNMARK_RESTORE;
|
||||
break;
|
||||
case O_MASK:
|
||||
info->nfmask = info->ctmask = cb->val.u32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void connmark_tg_check(struct xt_fcheck_call *cb)
|
||||
{
|
||||
if (!(cb->xflags & F_OP_ANY))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"CONNMARK target: No operation specified");
|
||||
}
|
||||
|
||||
static void
|
||||
print_mark(unsigned long mark)
|
||||
{
|
||||
printf("0x%lx", mark);
|
||||
}
|
||||
|
||||
static void
|
||||
print_mask(const char *text, unsigned long mask)
|
||||
{
|
||||
if (mask != 0xffffffffUL)
|
||||
printf("%s0x%lx", text, mask);
|
||||
}
|
||||
|
||||
static void CONNMARK_print(const void *ip,
|
||||
const struct xt_entry_target *target, int numeric)
|
||||
{
|
||||
const struct xt_connmark_target_info *markinfo =
|
||||
(const struct xt_connmark_target_info *)target->data;
|
||||
switch (markinfo->mode) {
|
||||
case XT_CONNMARK_SET:
|
||||
printf(" CONNMARK set ");
|
||||
print_mark(markinfo->mark);
|
||||
print_mask("/", markinfo->mask);
|
||||
break;
|
||||
case XT_CONNMARK_SAVE:
|
||||
printf(" CONNMARK save ");
|
||||
print_mask("mask ", markinfo->mask);
|
||||
break;
|
||||
case XT_CONNMARK_RESTORE:
|
||||
printf(" CONNMARK restore ");
|
||||
print_mask("mask ", markinfo->mask);
|
||||
break;
|
||||
default:
|
||||
printf(" ERROR: UNKNOWN CONNMARK MODE");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
connmark_tg_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_connmark_tginfo1 *info = (const void *)target->data;
|
||||
|
||||
switch (info->mode) {
|
||||
case XT_CONNMARK_SET:
|
||||
if (info->ctmark == 0)
|
||||
printf(" CONNMARK and 0x%x",
|
||||
(unsigned int)(uint32_t)~info->ctmask);
|
||||
else if (info->ctmark == info->ctmask)
|
||||
printf(" CONNMARK or 0x%x", info->ctmark);
|
||||
else if (info->ctmask == 0)
|
||||
printf(" CONNMARK xor 0x%x", info->ctmark);
|
||||
else if (info->ctmask == 0xFFFFFFFFU)
|
||||
printf(" CONNMARK set 0x%x", info->ctmark);
|
||||
else
|
||||
printf(" CONNMARK xset 0x%x/0x%x",
|
||||
info->ctmark, info->ctmask);
|
||||
break;
|
||||
case XT_CONNMARK_SAVE:
|
||||
if (info->nfmask == UINT32_MAX && info->ctmask == UINT32_MAX)
|
||||
printf(" CONNMARK save");
|
||||
else if (info->nfmask == info->ctmask)
|
||||
printf(" CONNMARK save mask 0x%x", info->nfmask);
|
||||
else
|
||||
printf(" CONNMARK save nfmask 0x%x ctmask ~0x%x",
|
||||
info->nfmask, info->ctmask);
|
||||
break;
|
||||
case XT_CONNMARK_RESTORE:
|
||||
if (info->ctmask == UINT32_MAX && info->nfmask == UINT32_MAX)
|
||||
printf(" CONNMARK restore");
|
||||
else if (info->ctmask == info->nfmask)
|
||||
printf(" CONNMARK restore mask 0x%x", info->ctmask);
|
||||
else
|
||||
printf(" CONNMARK restore ctmask 0x%x nfmask ~0x%x",
|
||||
info->ctmask, info->nfmask);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf(" ERROR: UNKNOWN CONNMARK MODE");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void CONNMARK_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct xt_connmark_target_info *markinfo =
|
||||
(const struct xt_connmark_target_info *)target->data;
|
||||
|
||||
switch (markinfo->mode) {
|
||||
case XT_CONNMARK_SET:
|
||||
printf(" --set-mark ");
|
||||
print_mark(markinfo->mark);
|
||||
print_mask("/", markinfo->mask);
|
||||
break;
|
||||
case XT_CONNMARK_SAVE:
|
||||
printf(" --save-mark ");
|
||||
print_mask("--mask ", markinfo->mask);
|
||||
break;
|
||||
case XT_CONNMARK_RESTORE:
|
||||
printf(" --restore-mark ");
|
||||
print_mask("--mask ", markinfo->mask);
|
||||
break;
|
||||
default:
|
||||
printf(" ERROR: UNKNOWN CONNMARK MODE");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void CONNMARK_init(struct xt_entry_target *t)
|
||||
{
|
||||
struct xt_connmark_target_info *markinfo
|
||||
= (struct xt_connmark_target_info *)t->data;
|
||||
|
||||
markinfo->mask = 0xffffffffUL;
|
||||
}
|
||||
|
||||
static void
|
||||
connmark_tg_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct xt_connmark_tginfo1 *info = (const void *)target->data;
|
||||
|
||||
switch (info->mode) {
|
||||
case XT_CONNMARK_SET:
|
||||
printf(" --set-xmark 0x%x/0x%x", info->ctmark, info->ctmask);
|
||||
break;
|
||||
case XT_CONNMARK_SAVE:
|
||||
printf(" --save-mark --nfmask 0x%x --ctmask 0x%x",
|
||||
info->nfmask, info->ctmask);
|
||||
break;
|
||||
case XT_CONNMARK_RESTORE:
|
||||
printf(" --restore-mark --nfmask 0x%x --ctmask 0x%x",
|
||||
info->nfmask, info->ctmask);
|
||||
break;
|
||||
default:
|
||||
printf(" ERROR: UNKNOWN CONNMARK MODE");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct xtables_target connmark_tg_reg[] = {
|
||||
{
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.name = "CONNMARK",
|
||||
.revision = 0,
|
||||
.version = XTABLES_VERSION,
|
||||
.size = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
|
||||
.help = CONNMARK_help,
|
||||
.init = CONNMARK_init,
|
||||
.print = CONNMARK_print,
|
||||
.save = CONNMARK_save,
|
||||
.x6_parse = CONNMARK_parse,
|
||||
.x6_fcheck = connmark_tg_check,
|
||||
.x6_options = CONNMARK_opts,
|
||||
},
|
||||
{
|
||||
.version = XTABLES_VERSION,
|
||||
.name = "CONNMARK",
|
||||
.revision = 1,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.size = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
|
||||
.help = connmark_tg_help,
|
||||
.init = connmark_tg_init,
|
||||
.print = connmark_tg_print,
|
||||
.save = connmark_tg_save,
|
||||
.x6_parse = connmark_tg_parse,
|
||||
.x6_fcheck = connmark_tg_check,
|
||||
.x6_options = connmark_tg_opts,
|
||||
},
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_targets(connmark_tg_reg, ARRAY_SIZE(connmark_tg_reg));
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
This module sets the netfilter mark value associated with a connection. The
|
||||
mark is 32 bits wide.
|
||||
.TP
|
||||
\fB\-\-set\-xmark\fP \fIvalue\fP[\fB/\fP\fImask\fP]
|
||||
Zero out the bits given by \fImask\fP and XOR \fIvalue\fP into the ctmark.
|
||||
.TP
|
||||
\fB\-\-save\-mark\fP [\fB\-\-nfmask\fP \fInfmask\fP] [\fB\-\-ctmask\fP \fIctmask\fP]
|
||||
Copy the packet mark (nfmark) to the connection mark (ctmark) using the given
|
||||
masks. The new nfmark value is determined as follows:
|
||||
.IP
|
||||
ctmark = (ctmark & ~ctmask) ^ (nfmark & nfmask)
|
||||
.IP
|
||||
i.e. \fIctmask\fP defines what bits to clear and \fInfmask\fP what bits of the
|
||||
nfmark to XOR into the ctmark. \fIctmask\fP and \fInfmask\fP default to
|
||||
0xFFFFFFFF.
|
||||
.TP
|
||||
\fB\-\-restore\-mark\fP [\fB\-\-nfmask\fP \fInfmask\fP] [\fB\-\-ctmask\fP \fIctmask\fP]
|
||||
Copy the connection mark (ctmark) to the packet mark (nfmark) using the given
|
||||
masks. The new ctmark value is determined as follows:
|
||||
.IP
|
||||
nfmark = (nfmark & ~\fInfmask\fP) ^ (ctmark & \fIctmask\fP);
|
||||
.IP
|
||||
i.e. \fInfmask\fP defines what bits to clear and \fIctmask\fP what bits of the
|
||||
ctmark to XOR into the nfmark. \fIctmask\fP and \fInfmask\fP default to
|
||||
0xFFFFFFFF.
|
||||
.IP
|
||||
\fB\-\-restore\-mark\fP is only valid in the \fBmangle\fP table.
|
||||
.PP
|
||||
The following mnemonics are available for \fB\-\-set\-xmark\fP:
|
||||
.TP
|
||||
\fB\-\-and\-mark\fP \fIbits\fP
|
||||
Binary AND the ctmark with \fIbits\fP. (Mnemonic for \fB\-\-set\-xmark
|
||||
0/\fP\fIinvbits\fP, where \fIinvbits\fP is the binary negation of \fIbits\fP.)
|
||||
.TP
|
||||
\fB\-\-or\-mark\fP \fIbits\fP
|
||||
Binary OR the ctmark with \fIbits\fP. (Mnemonic for \fB\-\-set\-xmark\fP
|
||||
\fIbits\fP\fB/\fP\fIbits\fP.)
|
||||
.TP
|
||||
\fB\-\-xor\-mark\fP \fIbits\fP
|
||||
Binary XOR the ctmark with \fIbits\fP. (Mnemonic for \fB\-\-set\-xmark\fP
|
||||
\fIbits\fP\fB/0\fP.)
|
||||
.TP
|
||||
\fB\-\-set\-mark\fP \fIvalue\fP[\fB/\fP\fImask\fP]
|
||||
Set the connection mark. If a mask is specified then only those bits set in the
|
||||
mask are modified.
|
||||
.TP
|
||||
\fB\-\-save\-mark\fP [\fB\-\-mask\fP \fImask\fP]
|
||||
Copy the nfmark to the ctmark. If a mask is specified, only those bits are
|
||||
copied.
|
||||
.TP
|
||||
\fB\-\-restore\-mark\fP [\fB\-\-mask\fP \fImask\fP]
|
||||
Copy the ctmark to the nfmark. If a mask is specified, only those bits are
|
||||
copied. This is only valid in the \fBmangle\fP table.
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Shared library add-on to iptables to add CONNSECMARK target support.
|
||||
*
|
||||
* Based on the MARK and CONNMARK targets.
|
||||
*
|
||||
* Copyright (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com>
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter/xt_CONNSECMARK.h>
|
||||
|
||||
#define PFX "CONNSECMARK target: "
|
||||
|
||||
enum {
|
||||
O_SAVE = 0,
|
||||
O_RESTORE,
|
||||
F_SAVE = 1 << O_SAVE,
|
||||
F_RESTORE = 1 << O_RESTORE,
|
||||
};
|
||||
|
||||
static void CONNSECMARK_help(void)
|
||||
{
|
||||
printf(
|
||||
"CONNSECMARK target options:\n"
|
||||
" --save Copy security mark from packet to conntrack\n"
|
||||
" --restore Copy security mark from connection to packet\n");
|
||||
}
|
||||
|
||||
static const struct xt_option_entry CONNSECMARK_opts[] = {
|
||||
{.name = "save", .id = O_SAVE, .excl = F_RESTORE, .type = XTTYPE_NONE},
|
||||
{.name = "restore", .id = O_RESTORE, .excl = F_SAVE,
|
||||
.type = XTTYPE_NONE},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void CONNSECMARK_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct xt_connsecmark_target_info *info = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_SAVE:
|
||||
info->mode = CONNSECMARK_SAVE;
|
||||
break;
|
||||
case O_RESTORE:
|
||||
info->mode = CONNSECMARK_RESTORE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void CONNSECMARK_check(struct xt_fcheck_call *cb)
|
||||
{
|
||||
if (cb->xflags == 0)
|
||||
xtables_error(PARAMETER_PROBLEM, PFX "parameter required");
|
||||
}
|
||||
|
||||
static void print_connsecmark(const struct xt_connsecmark_target_info *info)
|
||||
{
|
||||
switch (info->mode) {
|
||||
case CONNSECMARK_SAVE:
|
||||
printf("save");
|
||||
break;
|
||||
|
||||
case CONNSECMARK_RESTORE:
|
||||
printf("restore");
|
||||
break;
|
||||
|
||||
default:
|
||||
xtables_error(OTHER_PROBLEM, PFX "invalid mode %hhu\n", info->mode);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
CONNSECMARK_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_connsecmark_target_info *info =
|
||||
(struct xt_connsecmark_target_info*)(target)->data;
|
||||
|
||||
printf(" CONNSECMARK ");
|
||||
print_connsecmark(info);
|
||||
}
|
||||
|
||||
static void
|
||||
CONNSECMARK_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct xt_connsecmark_target_info *info =
|
||||
(struct xt_connsecmark_target_info*)target->data;
|
||||
|
||||
printf(" --");
|
||||
print_connsecmark(info);
|
||||
}
|
||||
|
||||
static struct xtables_target connsecmark_target = {
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.name = "CONNSECMARK",
|
||||
.version = XTABLES_VERSION,
|
||||
.revision = 0,
|
||||
.size = XT_ALIGN(sizeof(struct xt_connsecmark_target_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_connsecmark_target_info)),
|
||||
.help = CONNSECMARK_help,
|
||||
.print = CONNSECMARK_print,
|
||||
.save = CONNSECMARK_save,
|
||||
.x6_parse = CONNSECMARK_parse,
|
||||
.x6_fcheck = CONNSECMARK_check,
|
||||
.x6_options = CONNSECMARK_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&connsecmark_target);
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
This module copies security markings from packets to connections
|
||||
(if unlabeled), and from connections back to packets (also only
|
||||
if unlabeled). Typically used in conjunction with SECMARK, it is
|
||||
valid in the
|
||||
.B security
|
||||
table (for backwards compatibility with older kernels, it is also
|
||||
valid in the
|
||||
.B mangle
|
||||
table).
|
||||
.TP
|
||||
\fB\-\-save\fP
|
||||
If the packet has a security marking, copy it to the connection
|
||||
if the connection is not marked.
|
||||
.TP
|
||||
\fB\-\-restore\fP
|
||||
If the packet does not have a security marking, and the connection
|
||||
does, copy the security marking from the connection to the packet.
|
||||
|
|
@ -0,0 +1,433 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2013 Patrick McHardy <kaber@trash.net>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter/nf_conntrack_common.h>
|
||||
#include <linux/netfilter/xt_CT.h>
|
||||
|
||||
static void ct_help(void)
|
||||
{
|
||||
printf(
|
||||
"CT target options:\n"
|
||||
" --notrack Don't track connection\n"
|
||||
" --helper name Use conntrack helper 'name' for connection\n"
|
||||
" --ctevents event[,event...] Generate specified conntrack events for connection\n"
|
||||
" --expevents event[,event...] Generate specified expectation events for connection\n"
|
||||
" --zone {ID|mark} Assign/Lookup connection in zone ID/packet nfmark\n"
|
||||
" --zone-orig {ID|mark} Same as 'zone' option, but only applies to ORIGINAL direction\n"
|
||||
" --zone-reply {ID|mark} Same as 'zone' option, but only applies to REPLY direction\n"
|
||||
);
|
||||
}
|
||||
|
||||
static void ct_help_v1(void)
|
||||
{
|
||||
printf(
|
||||
"CT target options:\n"
|
||||
" --notrack Don't track connection\n"
|
||||
" --helper name Use conntrack helper 'name' for connection\n"
|
||||
" --timeout name Use timeout policy 'name' for connection\n"
|
||||
" --ctevents event[,event...] Generate specified conntrack events for connection\n"
|
||||
" --expevents event[,event...] Generate specified expectation events for connection\n"
|
||||
" --zone {ID|mark} Assign/Lookup connection in zone ID/packet nfmark\n"
|
||||
" --zone-orig {ID|mark} Same as 'zone' option, but only applies to ORIGINAL direction\n"
|
||||
" --zone-reply {ID|mark} Same as 'zone' option, but only applies to REPLY direction\n"
|
||||
);
|
||||
}
|
||||
|
||||
enum {
|
||||
O_NOTRACK = 0,
|
||||
O_HELPER,
|
||||
O_TIMEOUT,
|
||||
O_CTEVENTS,
|
||||
O_EXPEVENTS,
|
||||
O_ZONE,
|
||||
O_ZONE_ORIG,
|
||||
O_ZONE_REPLY,
|
||||
};
|
||||
|
||||
#define s struct xt_ct_target_info
|
||||
static const struct xt_option_entry ct_opts[] = {
|
||||
{.name = "notrack", .id = O_NOTRACK, .type = XTTYPE_NONE},
|
||||
{.name = "helper", .id = O_HELPER, .type = XTTYPE_STRING,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(s, helper)},
|
||||
{.name = "ctevents", .id = O_CTEVENTS, .type = XTTYPE_STRING},
|
||||
{.name = "expevents", .id = O_EXPEVENTS, .type = XTTYPE_STRING},
|
||||
{.name = "zone-orig", .id = O_ZONE_ORIG, .type = XTTYPE_STRING},
|
||||
{.name = "zone-reply", .id = O_ZONE_REPLY, .type = XTTYPE_STRING},
|
||||
{.name = "zone", .id = O_ZONE, .type = XTTYPE_STRING},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
#undef s
|
||||
|
||||
#define s struct xt_ct_target_info_v1
|
||||
static const struct xt_option_entry ct_opts_v1[] = {
|
||||
{.name = "notrack", .id = O_NOTRACK, .type = XTTYPE_NONE},
|
||||
{.name = "helper", .id = O_HELPER, .type = XTTYPE_STRING,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(s, helper)},
|
||||
{.name = "timeout", .id = O_TIMEOUT, .type = XTTYPE_STRING,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(s, timeout)},
|
||||
{.name = "ctevents", .id = O_CTEVENTS, .type = XTTYPE_STRING},
|
||||
{.name = "expevents", .id = O_EXPEVENTS, .type = XTTYPE_STRING},
|
||||
{.name = "zone-orig", .id = O_ZONE_ORIG, .type = XTTYPE_STRING},
|
||||
{.name = "zone-reply", .id = O_ZONE_REPLY, .type = XTTYPE_STRING},
|
||||
{.name = "zone", .id = O_ZONE, .type = XTTYPE_STRING},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
#undef s
|
||||
|
||||
struct event_tbl {
|
||||
const char *name;
|
||||
unsigned int event;
|
||||
};
|
||||
|
||||
static const struct event_tbl ct_event_tbl[] = {
|
||||
{ "new", IPCT_NEW },
|
||||
{ "related", IPCT_RELATED },
|
||||
{ "destroy", IPCT_DESTROY },
|
||||
{ "reply", IPCT_REPLY },
|
||||
{ "assured", IPCT_ASSURED },
|
||||
{ "protoinfo", IPCT_PROTOINFO },
|
||||
{ "helper", IPCT_HELPER },
|
||||
{ "mark", IPCT_MARK },
|
||||
{ "natseqinfo", IPCT_NATSEQADJ },
|
||||
{ "secmark", IPCT_SECMARK },
|
||||
};
|
||||
|
||||
static const struct event_tbl exp_event_tbl[] = {
|
||||
{ "new", IPEXP_NEW },
|
||||
};
|
||||
|
||||
static void ct_parse_zone_id(const char *opt, unsigned int opt_id,
|
||||
uint16_t *zone_id, uint16_t *flags)
|
||||
{
|
||||
if (opt_id == O_ZONE_ORIG)
|
||||
*flags |= XT_CT_ZONE_DIR_ORIG;
|
||||
if (opt_id == O_ZONE_REPLY)
|
||||
*flags |= XT_CT_ZONE_DIR_REPL;
|
||||
|
||||
*zone_id = 0;
|
||||
|
||||
if (strcasecmp(opt, "mark") == 0) {
|
||||
*flags |= XT_CT_ZONE_MARK;
|
||||
} else {
|
||||
uintmax_t val;
|
||||
|
||||
if (!xtables_strtoul(opt, NULL, &val, 0, UINT16_MAX))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Cannot parse %s as a zone ID\n", opt);
|
||||
|
||||
*zone_id = (uint16_t)val;
|
||||
}
|
||||
}
|
||||
|
||||
static void ct_print_zone_id(const char *pfx, uint16_t zone_id, uint16_t flags)
|
||||
{
|
||||
printf(" %s", pfx);
|
||||
|
||||
if ((flags & (XT_CT_ZONE_DIR_ORIG |
|
||||
XT_CT_ZONE_DIR_REPL)) == XT_CT_ZONE_DIR_ORIG)
|
||||
printf("-orig");
|
||||
if ((flags & (XT_CT_ZONE_DIR_ORIG |
|
||||
XT_CT_ZONE_DIR_REPL)) == XT_CT_ZONE_DIR_REPL)
|
||||
printf("-reply");
|
||||
if (flags & XT_CT_ZONE_MARK)
|
||||
printf(" mark");
|
||||
else
|
||||
printf(" %u", zone_id);
|
||||
}
|
||||
|
||||
static uint32_t ct_parse_events(const struct event_tbl *tbl, unsigned int size,
|
||||
const char *events)
|
||||
{
|
||||
char str[strlen(events) + 1], *e = str, *t;
|
||||
unsigned int mask = 0, i;
|
||||
|
||||
strcpy(str, events);
|
||||
while ((t = strsep(&e, ","))) {
|
||||
for (i = 0; i < size; i++) {
|
||||
if (strcmp(t, tbl[i].name))
|
||||
continue;
|
||||
mask |= 1 << tbl[i].event;
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == size)
|
||||
xtables_error(PARAMETER_PROBLEM, "Unknown event type \"%s\"", t);
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
static void ct_print_events(const char *pfx, const struct event_tbl *tbl,
|
||||
unsigned int size, uint32_t mask)
|
||||
{
|
||||
const char *sep = "";
|
||||
unsigned int i;
|
||||
|
||||
printf(" %s ", pfx);
|
||||
for (i = 0; i < size; i++) {
|
||||
if (mask & (1 << tbl[i].event)) {
|
||||
printf("%s%s", sep, tbl[i].name);
|
||||
sep = ",";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ct_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct xt_ct_target_info *info = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_NOTRACK:
|
||||
info->flags |= XT_CT_NOTRACK;
|
||||
break;
|
||||
case O_ZONE_ORIG:
|
||||
case O_ZONE_REPLY:
|
||||
case O_ZONE:
|
||||
ct_parse_zone_id(cb->arg, cb->entry->id, &info->zone,
|
||||
&info->flags);
|
||||
break;
|
||||
case O_CTEVENTS:
|
||||
info->ct_events = ct_parse_events(ct_event_tbl, ARRAY_SIZE(ct_event_tbl), cb->arg);
|
||||
break;
|
||||
case O_EXPEVENTS:
|
||||
info->exp_events = ct_parse_events(exp_event_tbl, ARRAY_SIZE(exp_event_tbl), cb->arg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ct_parse_v1(struct xt_option_call *cb)
|
||||
{
|
||||
struct xt_ct_target_info_v1 *info = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_NOTRACK:
|
||||
info->flags |= XT_CT_NOTRACK;
|
||||
break;
|
||||
case O_ZONE_ORIG:
|
||||
case O_ZONE_REPLY:
|
||||
case O_ZONE:
|
||||
ct_parse_zone_id(cb->arg, cb->entry->id, &info->zone,
|
||||
&info->flags);
|
||||
break;
|
||||
case O_CTEVENTS:
|
||||
info->ct_events = ct_parse_events(ct_event_tbl,
|
||||
ARRAY_SIZE(ct_event_tbl),
|
||||
cb->arg);
|
||||
break;
|
||||
case O_EXPEVENTS:
|
||||
info->exp_events = ct_parse_events(exp_event_tbl,
|
||||
ARRAY_SIZE(exp_event_tbl),
|
||||
cb->arg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ct_print(const void *ip, const struct xt_entry_target *target, int numeric)
|
||||
{
|
||||
const struct xt_ct_target_info *info =
|
||||
(const struct xt_ct_target_info *)target->data;
|
||||
|
||||
printf(" CT");
|
||||
if (info->flags & XT_CT_NOTRACK)
|
||||
printf(" notrack");
|
||||
if (info->helper[0])
|
||||
printf(" helper %s", info->helper);
|
||||
if (info->ct_events)
|
||||
ct_print_events("ctevents", ct_event_tbl,
|
||||
ARRAY_SIZE(ct_event_tbl), info->ct_events);
|
||||
if (info->exp_events)
|
||||
ct_print_events("expevents", exp_event_tbl,
|
||||
ARRAY_SIZE(exp_event_tbl), info->exp_events);
|
||||
if (info->flags & XT_CT_ZONE_MARK || info->zone)
|
||||
ct_print_zone_id("zone", info->zone, info->flags);
|
||||
}
|
||||
|
||||
static void
|
||||
ct_print_v1(const void *ip, const struct xt_entry_target *target, int numeric)
|
||||
{
|
||||
const struct xt_ct_target_info_v1 *info =
|
||||
(const struct xt_ct_target_info_v1 *)target->data;
|
||||
|
||||
if (info->flags & XT_CT_NOTRACK_ALIAS) {
|
||||
printf (" NOTRACK");
|
||||
return;
|
||||
}
|
||||
printf(" CT");
|
||||
if (info->flags & XT_CT_NOTRACK)
|
||||
printf(" notrack");
|
||||
if (info->helper[0])
|
||||
printf(" helper %s", info->helper);
|
||||
if (info->timeout[0])
|
||||
printf(" timeout %s", info->timeout);
|
||||
if (info->ct_events)
|
||||
ct_print_events("ctevents", ct_event_tbl,
|
||||
ARRAY_SIZE(ct_event_tbl), info->ct_events);
|
||||
if (info->exp_events)
|
||||
ct_print_events("expevents", exp_event_tbl,
|
||||
ARRAY_SIZE(exp_event_tbl), info->exp_events);
|
||||
if (info->flags & XT_CT_ZONE_MARK || info->zone)
|
||||
ct_print_zone_id("zone", info->zone, info->flags);
|
||||
}
|
||||
|
||||
static void ct_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct xt_ct_target_info *info =
|
||||
(const struct xt_ct_target_info *)target->data;
|
||||
|
||||
if (info->flags & XT_CT_NOTRACK_ALIAS)
|
||||
return;
|
||||
if (info->flags & XT_CT_NOTRACK)
|
||||
printf(" --notrack");
|
||||
if (info->helper[0])
|
||||
printf(" --helper %s", info->helper);
|
||||
if (info->ct_events)
|
||||
ct_print_events("--ctevents", ct_event_tbl,
|
||||
ARRAY_SIZE(ct_event_tbl), info->ct_events);
|
||||
if (info->exp_events)
|
||||
ct_print_events("--expevents", exp_event_tbl,
|
||||
ARRAY_SIZE(exp_event_tbl), info->exp_events);
|
||||
if (info->flags & XT_CT_ZONE_MARK || info->zone)
|
||||
ct_print_zone_id("--zone", info->zone, info->flags);
|
||||
}
|
||||
|
||||
static void ct_save_v1(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct xt_ct_target_info_v1 *info =
|
||||
(const struct xt_ct_target_info_v1 *)target->data;
|
||||
|
||||
if (info->flags & XT_CT_NOTRACK_ALIAS)
|
||||
return;
|
||||
if (info->flags & XT_CT_NOTRACK)
|
||||
printf(" --notrack");
|
||||
if (info->helper[0])
|
||||
printf(" --helper %s", info->helper);
|
||||
if (info->timeout[0])
|
||||
printf(" --timeout %s", info->timeout);
|
||||
if (info->ct_events)
|
||||
ct_print_events("--ctevents", ct_event_tbl,
|
||||
ARRAY_SIZE(ct_event_tbl), info->ct_events);
|
||||
if (info->exp_events)
|
||||
ct_print_events("--expevents", exp_event_tbl,
|
||||
ARRAY_SIZE(exp_event_tbl), info->exp_events);
|
||||
if (info->flags & XT_CT_ZONE_MARK || info->zone)
|
||||
ct_print_zone_id("--zone", info->zone, info->flags);
|
||||
}
|
||||
|
||||
static const char *
|
||||
ct_print_name_alias(const struct xt_entry_target *target)
|
||||
{
|
||||
struct xt_ct_target_info *info = (void *)target->data;
|
||||
|
||||
return info->flags & XT_CT_NOTRACK_ALIAS ? "NOTRACK" : "CT";
|
||||
}
|
||||
|
||||
static void notrack_ct0_tg_init(struct xt_entry_target *target)
|
||||
{
|
||||
struct xt_ct_target_info *info = (void *)target->data;
|
||||
|
||||
info->flags = XT_CT_NOTRACK;
|
||||
}
|
||||
|
||||
static void notrack_ct1_tg_init(struct xt_entry_target *target)
|
||||
{
|
||||
struct xt_ct_target_info_v1 *info = (void *)target->data;
|
||||
|
||||
info->flags = XT_CT_NOTRACK;
|
||||
}
|
||||
|
||||
static void notrack_ct2_tg_init(struct xt_entry_target *target)
|
||||
{
|
||||
struct xt_ct_target_info_v1 *info = (void *)target->data;
|
||||
|
||||
info->flags = XT_CT_NOTRACK | XT_CT_NOTRACK_ALIAS;
|
||||
}
|
||||
|
||||
static struct xtables_target ct_target_reg[] = {
|
||||
{
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.name = "CT",
|
||||
.version = XTABLES_VERSION,
|
||||
.size = XT_ALIGN(sizeof(struct xt_ct_target_info)),
|
||||
.userspacesize = offsetof(struct xt_ct_target_info, ct),
|
||||
.help = ct_help,
|
||||
.print = ct_print,
|
||||
.save = ct_save,
|
||||
.x6_parse = ct_parse,
|
||||
.x6_options = ct_opts,
|
||||
},
|
||||
{
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.name = "CT",
|
||||
.revision = 1,
|
||||
.version = XTABLES_VERSION,
|
||||
.size = XT_ALIGN(sizeof(struct xt_ct_target_info_v1)),
|
||||
.userspacesize = offsetof(struct xt_ct_target_info_v1, ct),
|
||||
.help = ct_help_v1,
|
||||
.print = ct_print_v1,
|
||||
.save = ct_save_v1,
|
||||
.x6_parse = ct_parse_v1,
|
||||
.x6_options = ct_opts_v1,
|
||||
},
|
||||
{
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.name = "CT",
|
||||
.revision = 2,
|
||||
.version = XTABLES_VERSION,
|
||||
.size = XT_ALIGN(sizeof(struct xt_ct_target_info_v1)),
|
||||
.userspacesize = offsetof(struct xt_ct_target_info_v1, ct),
|
||||
.help = ct_help_v1,
|
||||
.print = ct_print_v1,
|
||||
.save = ct_save_v1,
|
||||
.alias = ct_print_name_alias,
|
||||
.x6_parse = ct_parse_v1,
|
||||
.x6_options = ct_opts_v1,
|
||||
},
|
||||
{
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.name = "NOTRACK",
|
||||
.real_name = "CT",
|
||||
.revision = 0,
|
||||
.version = XTABLES_VERSION,
|
||||
.size = XT_ALIGN(sizeof(struct xt_ct_target_info)),
|
||||
.userspacesize = offsetof(struct xt_ct_target_info, ct),
|
||||
.init = notrack_ct0_tg_init,
|
||||
},
|
||||
{
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.name = "NOTRACK",
|
||||
.real_name = "CT",
|
||||
.revision = 1,
|
||||
.version = XTABLES_VERSION,
|
||||
.size = XT_ALIGN(sizeof(struct xt_ct_target_info_v1)),
|
||||
.userspacesize = offsetof(struct xt_ct_target_info_v1, ct),
|
||||
.init = notrack_ct1_tg_init,
|
||||
},
|
||||
{
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.name = "NOTRACK",
|
||||
.real_name = "CT",
|
||||
.revision = 2,
|
||||
.ext_flags = XTABLES_EXT_ALIAS,
|
||||
.version = XTABLES_VERSION,
|
||||
.size = XT_ALIGN(sizeof(struct xt_ct_target_info_v1)),
|
||||
.userspacesize = offsetof(struct xt_ct_target_info_v1, ct),
|
||||
.init = notrack_ct2_tg_init,
|
||||
},
|
||||
{
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.name = "NOTRACK",
|
||||
.revision = 0,
|
||||
.version = XTABLES_VERSION,
|
||||
},
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_targets(ct_target_reg, ARRAY_SIZE(ct_target_reg));
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
The CT target allows to set parameters for a packet or its associated
|
||||
connection. The target attaches a "template" connection tracking entry to
|
||||
the packet, which is then used by the conntrack core when initializing
|
||||
a new ct entry. This target is thus only valid in the "raw" table.
|
||||
.TP
|
||||
\fB\-\-notrack\fP
|
||||
Disables connection tracking for this packet.
|
||||
.TP
|
||||
\fB\-\-helper\fP \fIname\fP
|
||||
Use the helper identified by \fIname\fP for the connection. This is more
|
||||
flexible than loading the conntrack helper modules with preset ports.
|
||||
.TP
|
||||
\fB\-\-ctevents\fP \fIevent\fP[\fB,\fP...]
|
||||
Only generate the specified conntrack events for this connection. Possible
|
||||
event types are: \fBnew\fP, \fBrelated\fP, \fBdestroy\fP, \fBreply\fP,
|
||||
\fBassured\fP, \fBprotoinfo\fP, \fBhelper\fP, \fBmark\fP (this refers to
|
||||
the ctmark, not nfmark), \fBnatseqinfo\fP, \fBsecmark\fP (ctsecmark).
|
||||
.TP
|
||||
\fB\-\-expevents\fP \fIevent\fP[\fB,\fP...]
|
||||
Only generate the specified expectation events for this connection.
|
||||
Possible event types are: \fBnew\fP.
|
||||
.TP
|
||||
\fB\-\-zone-orig\fP {\fIid\fP|\fBmark\fP}
|
||||
For traffic coming from ORIGINAL direction, assign this packet to zone
|
||||
\fIid\fP and only have lookups done in that zone. If \fBmark\fP is used
|
||||
instead of \fIid\fP, the zone is derived from the packet nfmark.
|
||||
.TP
|
||||
\fB\-\-zone-reply\fP {\fIid\fP|\fBmark\fP}
|
||||
For traffic coming from REPLY direction, assign this packet to zone
|
||||
\fIid\fP and only have lookups done in that zone. If \fBmark\fP is used
|
||||
instead of \fIid\fP, the zone is derived from the packet nfmark.
|
||||
.TP
|
||||
\fB\-\-zone\fP {\fIid\fP|\fBmark\fP}
|
||||
Assign this packet to zone \fIid\fP and only have lookups done in that zone.
|
||||
If \fBmark\fP is used instead of \fIid\fP, the zone is derived from the
|
||||
packet nfmark. By default, packets have zone 0. This option applies to both
|
||||
directions.
|
||||
.TP
|
||||
\fB\-\-timeout\fP \fIname\fP
|
||||
Use the timeout policy identified by \fIname\fP for the connection. This is
|
||||
provides more flexible timeout policy definition than global timeout values
|
||||
available at /proc/sys/net/netfilter/nf_conntrack_*_timeout_*.
|
|
@ -0,0 +1,38 @@
|
|||
This target is only valid in the
|
||||
.B nat
|
||||
table, in the
|
||||
.B PREROUTING
|
||||
and
|
||||
.B OUTPUT
|
||||
chains, and user-defined chains which are only called from those
|
||||
chains. It specifies that the destination address of the packet
|
||||
should be modified (and all future packets in this connection will
|
||||
also be mangled), and rules should cease being examined. It takes the
|
||||
following options:
|
||||
.TP
|
||||
\fB\-\-to\-destination\fP [\fIipaddr\fP[\fB\-\fP\fIipaddr\fP]][\fB:\fP\fIport\fP[\fB\-\fP\fIport\fP]]
|
||||
which can specify a single new destination IP address, an inclusive
|
||||
range of IP addresses. Optionally a port range,
|
||||
if the rule also specifies one of the following protocols:
|
||||
\fBtcp\fP, \fBudp\fP, \fBdccp\fP or \fBsctp\fP.
|
||||
If no port range is specified, then the destination port will never be
|
||||
modified. If no IP address is specified then only the destination port
|
||||
will be modified.
|
||||
In Kernels up to 2.6.10 you can add several \-\-to\-destination options. For
|
||||
those kernels, if you specify more than one destination address, either via an
|
||||
address range or multiple \-\-to\-destination options, a simple round-robin (one
|
||||
after another in cycle) load balancing takes place between these addresses.
|
||||
Later Kernels (>= 2.6.11-rc1) don't have the ability to NAT to multiple ranges
|
||||
anymore.
|
||||
.TP
|
||||
\fB\-\-random\fP
|
||||
If option
|
||||
\fB\-\-random\fP
|
||||
is used then port mapping will be randomized (kernel >= 2.6.22).
|
||||
.TP
|
||||
\fB\-\-persistent\fP
|
||||
Gives a client the same source-/destination-address for each connection.
|
||||
This supersedes the SAME target. Support for persistent mappings is available
|
||||
from 2.6.29-rc2.
|
||||
.TP
|
||||
IPv6 support available since Linux kernels >= 3.7.
|
|
@ -0,0 +1,112 @@
|
|||
/* Shared library add-on to iptables for DSCP
|
||||
*
|
||||
* (C) 2000- 2002 by Matthew G. Marsh <mgm@paktronix.com>,
|
||||
* Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* This program is distributed under the terms of GNU GPL v2, 1991
|
||||
*
|
||||
* libipt_DSCP.c borrowed heavily from libipt_TOS.c
|
||||
*
|
||||
* --set-class added by Iain Barnes
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter/xt_DSCP.h>
|
||||
|
||||
/* This is evil, but it's my code - HW*/
|
||||
#include "dscp_helper.c"
|
||||
|
||||
enum {
|
||||
O_SET_DSCP = 0,
|
||||
O_SET_DSCP_CLASS,
|
||||
F_SET_DSCP = 1 << O_SET_DSCP,
|
||||
F_SET_DSCP_CLASS = 1 << O_SET_DSCP_CLASS,
|
||||
};
|
||||
|
||||
static void DSCP_help(void)
|
||||
{
|
||||
printf(
|
||||
"DSCP target options\n"
|
||||
" --set-dscp value Set DSCP field in packet header to value\n"
|
||||
" This value can be in decimal (ex: 32)\n"
|
||||
" or in hex (ex: 0x20)\n"
|
||||
" --set-dscp-class class Set the DSCP field in packet header to the\n"
|
||||
" value represented by the DiffServ class value.\n"
|
||||
" This class may be EF,BE or any of the CSxx\n"
|
||||
" or AFxx classes.\n"
|
||||
"\n"
|
||||
" These two options are mutually exclusive !\n"
|
||||
);
|
||||
}
|
||||
|
||||
static const struct xt_option_entry DSCP_opts[] = {
|
||||
{.name = "set-dscp", .id = O_SET_DSCP, .excl = F_SET_DSCP_CLASS,
|
||||
.type = XTTYPE_UINT8, .min = 0, .max = XT_DSCP_MAX,
|
||||
.flags = XTOPT_PUT,
|
||||
XTOPT_POINTER(struct xt_DSCP_info, dscp)},
|
||||
{.name = "set-dscp-class", .id = O_SET_DSCP_CLASS, .excl = F_SET_DSCP,
|
||||
.type = XTTYPE_STRING},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static void DSCP_parse(struct xt_option_call *cb)
|
||||
{
|
||||
struct xt_DSCP_info *dinfo = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
switch (cb->entry->id) {
|
||||
case O_SET_DSCP_CLASS:
|
||||
dinfo->dscp = class_to_dscp(cb->arg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void DSCP_check(struct xt_fcheck_call *cb)
|
||||
{
|
||||
if (cb->xflags == 0)
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"DSCP target: Parameter --set-dscp is required");
|
||||
}
|
||||
|
||||
static void
|
||||
print_dscp(uint8_t dscp, int numeric)
|
||||
{
|
||||
printf(" 0x%02x", dscp);
|
||||
}
|
||||
|
||||
static void DSCP_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_DSCP_info *dinfo =
|
||||
(const struct xt_DSCP_info *)target->data;
|
||||
printf(" DSCP set");
|
||||
print_dscp(dinfo->dscp, numeric);
|
||||
}
|
||||
|
||||
static void DSCP_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct xt_DSCP_info *dinfo =
|
||||
(const struct xt_DSCP_info *)target->data;
|
||||
|
||||
printf(" --set-dscp 0x%02x", dinfo->dscp);
|
||||
}
|
||||
|
||||
static struct xtables_target dscp_target = {
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.name = "DSCP",
|
||||
.version = XTABLES_VERSION,
|
||||
.size = XT_ALIGN(sizeof(struct xt_DSCP_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_DSCP_info)),
|
||||
.help = DSCP_help,
|
||||
.print = DSCP_print,
|
||||
.save = DSCP_save,
|
||||
.x6_parse = DSCP_parse,
|
||||
.x6_fcheck = DSCP_check,
|
||||
.x6_options = DSCP_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&dscp_target);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
This target allows to alter the value of the DSCP bits within the TOS
|
||||
header of the IPv4 packet. As this manipulates a packet, it can only
|
||||
be used in the mangle table.
|
||||
.TP
|
||||
\fB\-\-set\-dscp\fP \fIvalue\fP
|
||||
Set the DSCP field to a numerical value (can be decimal or hex)
|
||||
.TP
|
||||
\fB\-\-set\-dscp\-class\fP \fIclass\fP
|
||||
Set the DSCP field to a DiffServ class.
|
|
@ -0,0 +1,450 @@
|
|||
/*
|
||||
* (C) 2012 by Hans Schillstrom <hans.schillstrom@ericsson.com>
|
||||
* (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Description: shared library add-on to iptables to add HMARK target support
|
||||
*
|
||||
* Initial development by Hans Schillstrom. Pablo's improvements to this piece
|
||||
* of software has been sponsored by Sophos Astaro <http://www.sophos.com>.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "xtables.h"
|
||||
#include <linux/netfilter/xt_HMARK.h>
|
||||
|
||||
static void HMARK_help(void)
|
||||
{
|
||||
printf(
|
||||
"HMARK target options, i.e. modify hash calculation by:\n"
|
||||
" --hmark-tuple [src|dst|sport|dport|spi|proto|ct][,...]\n"
|
||||
" --hmark-mod value nfmark modulus value\n"
|
||||
" --hmark-offset value Last action add value to nfmark\n\n"
|
||||
" --hmark-rnd Random see for hashing\n"
|
||||
" Alternatively, fine tuning of what will be included in hash calculation\n"
|
||||
" --hmark-src-prefix length Source address mask CIDR prefix\n"
|
||||
" --hmark-dst-prefix length Dest address mask CIDR prefix\n"
|
||||
" --hmark-sport-mask value Mask src port with value\n"
|
||||
" --hmark-dport-mask value Mask dst port with value\n"
|
||||
" --hmark-spi-mask value For esp and ah AND spi with value\n"
|
||||
" --hmark-sport value OR src port with value\n"
|
||||
" --hmark-dport value OR dst port with value\n"
|
||||
" --hmark-spi value For esp and ah OR spi with value\n"
|
||||
" --hmark-proto-mask value Mask Protocol with value\n");
|
||||
}
|
||||
|
||||
#define hi struct xt_hmark_info
|
||||
|
||||
enum {
|
||||
O_HMARK_SADDR_MASK,
|
||||
O_HMARK_DADDR_MASK,
|
||||
O_HMARK_SPI,
|
||||
O_HMARK_SPI_MASK,
|
||||
O_HMARK_SPORT,
|
||||
O_HMARK_DPORT,
|
||||
O_HMARK_SPORT_MASK,
|
||||
O_HMARK_DPORT_MASK,
|
||||
O_HMARK_PROTO_MASK,
|
||||
O_HMARK_RND,
|
||||
O_HMARK_MODULUS,
|
||||
O_HMARK_OFFSET,
|
||||
O_HMARK_CT,
|
||||
O_HMARK_TYPE,
|
||||
};
|
||||
|
||||
#define HMARK_OPT_PKT_MASK \
|
||||
((1 << O_HMARK_SADDR_MASK) | \
|
||||
(1 << O_HMARK_DADDR_MASK) | \
|
||||
(1 << O_HMARK_SPI_MASK) | \
|
||||
(1 << O_HMARK_SPORT_MASK) | \
|
||||
(1 << O_HMARK_DPORT_MASK) | \
|
||||
(1 << O_HMARK_PROTO_MASK) | \
|
||||
(1 << O_HMARK_SPI_MASK) | \
|
||||
(1 << O_HMARK_SPORT) | \
|
||||
(1 << O_HMARK_DPORT) | \
|
||||
(1 << O_HMARK_SPI))
|
||||
|
||||
static const struct xt_option_entry HMARK_opts[] = {
|
||||
{ .name = "hmark-tuple",
|
||||
.type = XTTYPE_STRING,
|
||||
.id = O_HMARK_TYPE,
|
||||
},
|
||||
{ .name = "hmark-src-prefix",
|
||||
.type = XTTYPE_PLENMASK,
|
||||
.id = O_HMARK_SADDR_MASK,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(hi, src_mask)
|
||||
},
|
||||
{ .name = "hmark-dst-prefix",
|
||||
.type = XTTYPE_PLENMASK,
|
||||
.id = O_HMARK_DADDR_MASK,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(hi, dst_mask)
|
||||
},
|
||||
{ .name = "hmark-sport-mask",
|
||||
.type = XTTYPE_UINT16,
|
||||
.id = O_HMARK_SPORT_MASK,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(hi, port_mask.p16.src)
|
||||
},
|
||||
{ .name = "hmark-dport-mask",
|
||||
.type = XTTYPE_UINT16,
|
||||
.id = O_HMARK_DPORT_MASK,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(hi, port_mask.p16.dst)
|
||||
},
|
||||
{ .name = "hmark-spi-mask",
|
||||
.type = XTTYPE_UINT32,
|
||||
.id = O_HMARK_SPI_MASK,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(hi, port_mask.v32)
|
||||
},
|
||||
{ .name = "hmark-sport",
|
||||
.type = XTTYPE_UINT16,
|
||||
.id = O_HMARK_SPORT,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(hi, port_set.p16.src)
|
||||
},
|
||||
{ .name = "hmark-dport",
|
||||
.type = XTTYPE_UINT16,
|
||||
.id = O_HMARK_DPORT,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(hi, port_set.p16.dst)
|
||||
},
|
||||
{ .name = "hmark-spi",
|
||||
.type = XTTYPE_UINT32,
|
||||
.id = O_HMARK_SPI,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(hi, port_set.v32)
|
||||
},
|
||||
{ .name = "hmark-proto-mask",
|
||||
.type = XTTYPE_UINT16,
|
||||
.id = O_HMARK_PROTO_MASK,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(hi, proto_mask)
|
||||
},
|
||||
{ .name = "hmark-rnd",
|
||||
.type = XTTYPE_UINT32,
|
||||
.id = O_HMARK_RND,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(hi, hashrnd)
|
||||
},
|
||||
{ .name = "hmark-mod",
|
||||
.type = XTTYPE_UINT32,
|
||||
.id = O_HMARK_MODULUS,
|
||||
.min = 1,
|
||||
.flags = XTOPT_PUT | XTOPT_MAND, XTOPT_POINTER(hi, hmodulus)
|
||||
},
|
||||
{ .name = "hmark-offset",
|
||||
.type = XTTYPE_UINT32,
|
||||
.id = O_HMARK_OFFSET,
|
||||
.flags = XTOPT_PUT, XTOPT_POINTER(hi, hoffset)
|
||||
},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
|
||||
static int
|
||||
hmark_parse(const char *type, size_t len, struct xt_hmark_info *info,
|
||||
unsigned int *xflags)
|
||||
{
|
||||
if (strncasecmp(type, "ct", len) == 0) {
|
||||
info->flags |= XT_HMARK_FLAG(XT_HMARK_CT);
|
||||
*xflags |= (1 << O_HMARK_CT);
|
||||
} else if (strncasecmp(type, "src", len) == 0) {
|
||||
memset(&info->src_mask, 0xff, sizeof(info->src_mask));
|
||||
info->flags |= XT_HMARK_FLAG(XT_HMARK_SADDR_MASK);
|
||||
*xflags |= (1 << O_HMARK_SADDR_MASK);
|
||||
} else if (strncasecmp(type, "dst", len) == 0) {
|
||||
memset(&info->dst_mask, 0xff, sizeof(info->dst_mask));
|
||||
info->flags |= XT_HMARK_FLAG(XT_HMARK_DADDR_MASK);
|
||||
*xflags |= (1 << O_HMARK_DADDR_MASK);
|
||||
} else if (strncasecmp(type, "sport", len) == 0) {
|
||||
memset(&info->port_mask.p16.src, 0xff,
|
||||
sizeof(info->port_mask.p16.src));
|
||||
info->flags |= XT_HMARK_FLAG(XT_HMARK_SPORT_MASK);
|
||||
*xflags |= (1 << O_HMARK_SPORT_MASK);
|
||||
} else if (strncasecmp(type, "dport", len) == 0) {
|
||||
memset(&info->port_mask.p16.dst, 0xff,
|
||||
sizeof(info->port_mask.p16.dst));
|
||||
info->flags |= XT_HMARK_FLAG(XT_HMARK_DPORT_MASK);
|
||||
*xflags |= (1 << O_HMARK_DPORT_MASK);
|
||||
} else if (strncasecmp(type, "proto", len) == 0) {
|
||||
memset(&info->proto_mask, 0xff, sizeof(info->proto_mask));
|
||||
info->flags |= XT_HMARK_FLAG(XT_HMARK_PROTO_MASK);
|
||||
*xflags |= (1 << O_HMARK_PROTO_MASK);
|
||||
} else if (strncasecmp(type, "spi", len) == 0) {
|
||||
memset(&info->port_mask.v32, 0xff, sizeof(info->port_mask.v32));
|
||||
info->flags |= XT_HMARK_FLAG(XT_HMARK_SPI_MASK);
|
||||
*xflags |= (1 << O_HMARK_SPI_MASK);
|
||||
} else
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
hmark_parse_type(struct xt_option_call *cb)
|
||||
{
|
||||
const char *arg = cb->arg;
|
||||
struct xt_hmark_info *info = cb->data;
|
||||
const char *comma;
|
||||
|
||||
while ((comma = strchr(arg, ',')) != NULL) {
|
||||
if (comma == arg ||
|
||||
!hmark_parse(arg, comma-arg, info, &cb->xflags))
|
||||
xtables_error(PARAMETER_PROBLEM, "Bad type \"%s\"", arg);
|
||||
arg = comma+1;
|
||||
}
|
||||
if (!*arg)
|
||||
xtables_error(PARAMETER_PROBLEM, "\"--hmark-tuple\" requires "
|
||||
"a list of types with no "
|
||||
"spaces, e.g. "
|
||||
"src,dst,sport,dport,proto");
|
||||
if (strlen(arg) == 0 ||
|
||||
!hmark_parse(arg, strlen(arg), info, &cb->xflags))
|
||||
xtables_error(PARAMETER_PROBLEM, "Bad type \"%s\"", arg);
|
||||
}
|
||||
|
||||
static void HMARK_parse(struct xt_option_call *cb, int plen)
|
||||
{
|
||||
struct xt_hmark_info *info = cb->data;
|
||||
|
||||
xtables_option_parse(cb);
|
||||
|
||||
switch (cb->entry->id) {
|
||||
case O_HMARK_TYPE:
|
||||
hmark_parse_type(cb);
|
||||
break;
|
||||
case O_HMARK_SADDR_MASK:
|
||||
info->flags |= XT_HMARK_FLAG(XT_HMARK_SADDR_MASK);
|
||||
break;
|
||||
case O_HMARK_DADDR_MASK:
|
||||
info->flags |= XT_HMARK_FLAG(XT_HMARK_DADDR_MASK);
|
||||
break;
|
||||
case O_HMARK_SPI:
|
||||
info->port_set.v32 = htonl(cb->val.u32);
|
||||
info->flags |= XT_HMARK_FLAG(XT_HMARK_SPI);
|
||||
break;
|
||||
case O_HMARK_SPORT:
|
||||
info->port_set.p16.src = htons(cb->val.u16);
|
||||
info->flags |= XT_HMARK_FLAG(XT_HMARK_SPORT);
|
||||
break;
|
||||
case O_HMARK_DPORT:
|
||||
info->port_set.p16.dst = htons(cb->val.u16);
|
||||
info->flags |= XT_HMARK_FLAG(XT_HMARK_DPORT);
|
||||
break;
|
||||
case O_HMARK_SPORT_MASK:
|
||||
info->port_mask.p16.src = htons(cb->val.u16);
|
||||
info->flags |= XT_HMARK_FLAG(XT_HMARK_SPORT_MASK);
|
||||
break;
|
||||
case O_HMARK_DPORT_MASK:
|
||||
info->port_mask.p16.dst = htons(cb->val.u16);
|
||||
info->flags |= XT_HMARK_FLAG(XT_HMARK_DPORT_MASK);
|
||||
break;
|
||||
case O_HMARK_SPI_MASK:
|
||||
info->port_mask.v32 = htonl(cb->val.u32);
|
||||
info->flags |= XT_HMARK_FLAG(XT_HMARK_SPI_MASK);
|
||||
break;
|
||||
case O_HMARK_PROTO_MASK:
|
||||
info->flags |= XT_HMARK_FLAG(XT_HMARK_PROTO_MASK);
|
||||
break;
|
||||
case O_HMARK_RND:
|
||||
info->flags |= XT_HMARK_FLAG(XT_HMARK_RND);
|
||||
break;
|
||||
case O_HMARK_MODULUS:
|
||||
info->flags |= XT_HMARK_FLAG(XT_HMARK_MODULUS);
|
||||
break;
|
||||
case O_HMARK_OFFSET:
|
||||
info->flags |= XT_HMARK_FLAG(XT_HMARK_OFFSET);
|
||||
break;
|
||||
case O_HMARK_CT:
|
||||
info->flags |= XT_HMARK_FLAG(XT_HMARK_CT);
|
||||
break;
|
||||
}
|
||||
cb->xflags |= (1 << cb->entry->id);
|
||||
}
|
||||
|
||||
static void HMARK_ip4_parse(struct xt_option_call *cb)
|
||||
{
|
||||
HMARK_parse(cb, 32);
|
||||
}
|
||||
static void HMARK_ip6_parse(struct xt_option_call *cb)
|
||||
{
|
||||
HMARK_parse(cb, 128);
|
||||
}
|
||||
|
||||
static void HMARK_check(struct xt_fcheck_call *cb)
|
||||
{
|
||||
if (!(cb->xflags & (1 << O_HMARK_MODULUS)))
|
||||
xtables_error(PARAMETER_PROBLEM, "--hmark-mod is mandatory");
|
||||
if (!(cb->xflags & (1 << O_HMARK_RND)))
|
||||
xtables_error(PARAMETER_PROBLEM, "--hmark-rnd is mandatory");
|
||||
if (cb->xflags & (1 << O_HMARK_SPI_MASK) &&
|
||||
(cb->xflags & ((1 << O_HMARK_SPORT_MASK) |
|
||||
(1 << O_HMARK_DPORT_MASK))))
|
||||
xtables_error(PARAMETER_PROBLEM, "you cannot use "
|
||||
"--hmark-spi-mask and --hmark-?port-mask,"
|
||||
"at the same time");
|
||||
if (!((cb->xflags & HMARK_OPT_PKT_MASK) ||
|
||||
cb->xflags & (1 << O_HMARK_CT)))
|
||||
xtables_error(PARAMETER_PROBLEM, "you have to specify "
|
||||
"--hmark-tuple at least");
|
||||
}
|
||||
|
||||
static void HMARK_print(const struct xt_hmark_info *info)
|
||||
{
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT_MASK))
|
||||
printf("sport-mask 0x%x ", htons(info->port_mask.p16.src));
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT_MASK))
|
||||
printf("dport-mask 0x%x ", htons(info->port_mask.p16.dst));
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI_MASK))
|
||||
printf("spi-mask 0x%x ", htonl(info->port_mask.v32));
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT))
|
||||
printf("sport 0x%x ", htons(info->port_set.p16.src));
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT))
|
||||
printf("dport 0x%x ", htons(info->port_set.p16.dst));
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI))
|
||||
printf("spi 0x%x ", htonl(info->port_set.v32));
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_PROTO_MASK))
|
||||
printf("proto-mask 0x%x ", info->proto_mask);
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_RND))
|
||||
printf("rnd 0x%x ", info->hashrnd);
|
||||
}
|
||||
|
||||
static void HMARK_ip6_print(const void *ip,
|
||||
const struct xt_entry_target *target, int numeric)
|
||||
{
|
||||
const struct xt_hmark_info *info =
|
||||
(const struct xt_hmark_info *)target->data;
|
||||
|
||||
printf(" HMARK ");
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_MODULUS))
|
||||
printf("mod %u ", info->hmodulus);
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_OFFSET))
|
||||
printf("+ 0x%x ", info->hoffset);
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_CT))
|
||||
printf("ct, ");
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK))
|
||||
printf("src-prefix %s ",
|
||||
xtables_ip6mask_to_numeric(&info->src_mask.in6) + 1);
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK))
|
||||
printf("dst-prefix %s ",
|
||||
xtables_ip6mask_to_numeric(&info->dst_mask.in6) + 1);
|
||||
HMARK_print(info);
|
||||
}
|
||||
static void HMARK_ip4_print(const void *ip,
|
||||
const struct xt_entry_target *target, int numeric)
|
||||
{
|
||||
const struct xt_hmark_info *info =
|
||||
(const struct xt_hmark_info *)target->data;
|
||||
|
||||
printf(" HMARK ");
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_MODULUS))
|
||||
printf("mod %u ", info->hmodulus);
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_OFFSET))
|
||||
printf("+ 0x%x ", info->hoffset);
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_CT))
|
||||
printf("ct, ");
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK))
|
||||
printf("src-prefix %u ",
|
||||
xtables_ipmask_to_cidr(&info->src_mask.in));
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK))
|
||||
printf("dst-prefix %u ",
|
||||
xtables_ipmask_to_cidr(&info->dst_mask.in));
|
||||
HMARK_print(info);
|
||||
}
|
||||
|
||||
static void HMARK_save(const struct xt_hmark_info *info)
|
||||
{
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT_MASK))
|
||||
printf(" --hmark-sport-mask 0x%04x",
|
||||
htons(info->port_mask.p16.src));
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT_MASK))
|
||||
printf(" --hmark-dport-mask 0x%04x",
|
||||
htons(info->port_mask.p16.dst));
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI_MASK))
|
||||
printf(" --hmark-spi-mask 0x%08x",
|
||||
htonl(info->port_mask.v32));
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT))
|
||||
printf(" --hmark-sport 0x%04x",
|
||||
htons(info->port_set.p16.src));
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT))
|
||||
printf(" --hmark-dport 0x%04x",
|
||||
htons(info->port_set.p16.dst));
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI))
|
||||
printf(" --hmark-spi 0x%08x", htonl(info->port_set.v32));
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_PROTO_MASK))
|
||||
printf(" --hmark-proto-mask 0x%02x", info->proto_mask);
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_RND))
|
||||
printf(" --hmark-rnd 0x%08x", info->hashrnd);
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_MODULUS))
|
||||
printf(" --hmark-mod %u", info->hmodulus);
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_OFFSET))
|
||||
printf(" --hmark-offset %u", info->hoffset);
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_CT))
|
||||
printf(" --hmark-tuple ct");
|
||||
}
|
||||
|
||||
static void HMARK_ip6_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct xt_hmark_info *info =
|
||||
(const struct xt_hmark_info *)target->data;
|
||||
int ret;
|
||||
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK)) {
|
||||
ret = xtables_ip6mask_to_cidr(&info->src_mask.in6);
|
||||
printf(" --hmark-src-prefix %d", ret);
|
||||
}
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK)) {
|
||||
ret = xtables_ip6mask_to_cidr(&info->dst_mask.in6);
|
||||
printf(" --hmark-dst-prefix %d", ret);
|
||||
}
|
||||
HMARK_save(info);
|
||||
}
|
||||
|
||||
static void HMARK_ip4_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct xt_hmark_info *info =
|
||||
(const struct xt_hmark_info *)target->data;
|
||||
int ret;
|
||||
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK)) {
|
||||
ret = xtables_ipmask_to_cidr(&info->src_mask.in);
|
||||
printf(" --hmark-src-prefix %d", ret);
|
||||
}
|
||||
if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK)) {
|
||||
ret = xtables_ipmask_to_cidr(&info->dst_mask.in);
|
||||
printf(" --hmark-dst-prefix %d", ret);
|
||||
}
|
||||
HMARK_save(info);
|
||||
}
|
||||
|
||||
static struct xtables_target mark_tg_reg[] = {
|
||||
{
|
||||
.family = NFPROTO_IPV4,
|
||||
.name = "HMARK",
|
||||
.version = XTABLES_VERSION,
|
||||
.size = XT_ALIGN(sizeof(struct xt_hmark_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_hmark_info)),
|
||||
.help = HMARK_help,
|
||||
.print = HMARK_ip4_print,
|
||||
.save = HMARK_ip4_save,
|
||||
.x6_parse = HMARK_ip4_parse,
|
||||
.x6_fcheck = HMARK_check,
|
||||
.x6_options = HMARK_opts,
|
||||
},
|
||||
{
|
||||
.family = NFPROTO_IPV6,
|
||||
.name = "HMARK",
|
||||
.version = XTABLES_VERSION,
|
||||
.size = XT_ALIGN(sizeof(struct xt_hmark_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_hmark_info)),
|
||||
.help = HMARK_help,
|
||||
.print = HMARK_ip6_print,
|
||||
.save = HMARK_ip6_save,
|
||||
.x6_parse = HMARK_ip6_parse,
|
||||
.x6_fcheck = HMARK_check,
|
||||
.x6_options = HMARK_opts,
|
||||
},
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg));
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
Like MARK, i.e. set the fwmark, but the mark is calculated from hashing
|
||||
packet selector at choice. You have also to specify the mark range and,
|
||||
optionally, the offset to start from. ICMP error messages are inspected
|
||||
and used to calculate the hashing.
|
||||
.PP
|
||||
Existing options are:
|
||||
.TP
|
||||
\fB\-\-hmark\-tuple\fP tuple\fI\fP
|
||||
Possible tuple members are:
|
||||
.B src
|
||||
meaning source address (IPv4, IPv6 address),
|
||||
.B dst
|
||||
meaning destination address (IPv4, IPv6 address),
|
||||
.B sport
|
||||
meaning source port (TCP, UDP, UDPlite, SCTP, DCCP),
|
||||
.B dport
|
||||
meaning destination port (TCP, UDP, UDPlite, SCTP, DCCP),
|
||||
.B spi
|
||||
meaning Security Parameter Index (AH, ESP), and
|
||||
.B ct
|
||||
meaning the usage of the conntrack tuple instead of the packet selectors.
|
||||
.TP
|
||||
\fB\-\-hmark\-mod\fP \fIvalue (must be > 0)\fP
|
||||
Modulus for hash calculation (to limit the range of possible marks)
|
||||
.TP
|
||||
\fB\-\-hmark\-offset\fP \fIvalue\fP
|
||||
Offset to start marks from.
|
||||
.TP
|
||||
For advanced usage, instead of using \-\-hmark\-tuple, you can specify custom
|
||||
prefixes and masks:
|
||||
.TP
|
||||
\fB\-\-hmark\-src\-prefix\fP \fIcidr\fP
|
||||
The source address mask in CIDR notation.
|
||||
.TP
|
||||
\fB\-\-hmark\-dst\-prefix\fP \fIcidr\fP
|
||||
The destination address mask in CIDR notation.
|
||||
.TP
|
||||
\fB\-\-hmark\-sport\-mask\fP \fIvalue\fP
|
||||
A 16 bit source port mask in hexadecimal.
|
||||
.TP
|
||||
\fB\-\-hmark\-dport\-mask\fP \fIvalue\fP
|
||||
A 16 bit destination port mask in hexadecimal.
|
||||
.TP
|
||||
\fB\-\-hmark\-spi\-mask\fP \fIvalue\fP
|
||||
A 32 bit field with spi mask.
|
||||
.TP
|
||||
\fB\-\-hmark\-proto\-mask\fP \fIvalue\fP
|
||||
An 8 bit field with layer 4 protocol number.
|
||||
.TP
|
||||
\fB\-\-hmark\-rnd\fP \fIvalue\fP
|
||||
A 32 bit random custom value to feed hash calculation.
|
||||
.PP
|
||||
\fIExamples:\fP
|
||||
.PP
|
||||
iptables \-t mangle \-A PREROUTING \-m conntrack \-\-ctstate NEW
|
||||
\-j HMARK \-\-hmark-tuple ct,src,dst,proto \-\-hmark-offset 10000
|
||||
\-\-hmark\-mod 10 \-\-hmark\-rnd 0xfeedcafe
|
||||
.PP
|
||||
iptables \-t mangle \-A PREROUTING -j HMARK \-\-hmark\-offset 10000
|
||||
\-\-hmark-tuple src,dst,proto \-\-hmark-mod 10 \-\-hmark\-rnd 0xdeafbeef
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Shared library add-on for iptables to add IDLETIMER support.
|
||||
*
|
||||
* Copyright (C) 2010 Nokia Corporation. All rights reserved.
|
||||
*
|
||||
* Contact: Luciano Coelho <luciano.coelho@nokia.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter/xt_IDLETIMER.h>
|
||||
|
||||
enum {
|
||||
O_TIMEOUT = 0,
|
||||
O_LABEL,
|
||||
};
|
||||
|
||||
#define s struct idletimer_tg_info
|
||||
static const struct xt_option_entry idletimer_tg_opts[] = {
|
||||
{.name = "timeout", .id = O_TIMEOUT, .type = XTTYPE_UINT32,
|
||||
.flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, timeout)},
|
||||
{.name = "label", .id = O_LABEL, .type = XTTYPE_STRING,
|
||||
.flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, label)},
|
||||
XTOPT_TABLEEND,
|
||||
};
|
||||
#undef s
|
||||
|
||||
static void idletimer_tg_help(void)
|
||||
{
|
||||
printf(
|
||||
"IDLETIMER target options:\n"
|
||||
" --timeout time Timeout until the notification is sent (in seconds)\n"
|
||||
" --label string Unique rule identifier\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
static void idletimer_tg_print(const void *ip,
|
||||
const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
struct idletimer_tg_info *info =
|
||||
(struct idletimer_tg_info *) target->data;
|
||||
|
||||
printf(" timeout:%u", info->timeout);
|
||||
printf(" label:%s", info->label);
|
||||
}
|
||||
|
||||
static void idletimer_tg_save(const void *ip,
|
||||
const struct xt_entry_target *target)
|
||||
{
|
||||
struct idletimer_tg_info *info =
|
||||
(struct idletimer_tg_info *) target->data;
|
||||
|
||||
printf(" --timeout %u", info->timeout);
|
||||
printf(" --label %s", info->label);
|
||||
}
|
||||
|
||||
static struct xtables_target idletimer_tg_reg = {
|
||||
.family = NFPROTO_UNSPEC,
|
||||
.name = "IDLETIMER",
|
||||
.version = XTABLES_VERSION,
|
||||
.revision = 0,
|
||||
.size = XT_ALIGN(sizeof(struct idletimer_tg_info)),
|
||||
.userspacesize = offsetof(struct idletimer_tg_info, timer),
|
||||
.help = idletimer_tg_help,
|
||||
.x6_parse = xtables_option_parse,
|
||||
.print = idletimer_tg_print,
|
||||
.save = idletimer_tg_save,
|
||||
.x6_options = idletimer_tg_opts,
|
||||
};
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
xtables_register_target(&idletimer_tg_reg);
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
This target can be used to identify when interfaces have been idle for a
|
||||
certain period of time. Timers are identified by labels and are created when
|
||||
a rule is set with a new label. The rules also take a timeout value (in
|
||||
seconds) as an option. If more than one rule uses the same timer label, the
|
||||
timer will be restarted whenever any of the rules get a hit. One entry for
|
||||
each timer is created in sysfs. This attribute contains the timer remaining
|
||||
for the timer to expire. The attributes are located under the xt_idletimer
|
||||
class:
|
||||
.PP
|
||||
/sys/class/xt_idletimer/timers/<label>
|
||||
.PP
|
||||
When the timer expires, the target module sends a sysfs notification to the
|
||||
userspace, which can then decide what to do (eg. disconnect to save power).
|
||||
.TP
|
||||
\fB\-\-timeout\fP \fIamount\fP
|
||||
This is the time in seconds that will trigger the notification.
|
||||
.TP
|
||||
\fB\-\-label\fP \fIstring\fP
|
||||
This is a unique identifier for the timer. The maximum length for the
|
||||
label string is 27 characters.
|
|
@ -0,0 +1,105 @@
|
|||
/* Shared library add-on to iptables to add IMQ target support. */
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include <xtables.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <linux/netfilter/xt_IMQ.h>
|
||||
|
||||
/* Function which prints out usage message. */
|
||||
static void IMQ_help(void)
|
||||
{
|
||||
printf(
|
||||
"IMQ target options:\n"
|
||||
" --todev <N> enqueue to imq<N>, defaults to 0\n");
|
||||
|
||||
}
|
||||
|
||||
static struct option IMQ_opts[] = {
|
||||
{ "todev", 1, 0, '1' },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/* Initialize the target. */
|
||||
static void IMQ_init(struct xt_entry_target *t)
|
||||
{
|
||||
struct xt_imq_info *mr = (struct xt_imq_info*)t->data;
|
||||
|
||||
mr->todev = 0;
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it
|
||||
ate an option */
|
||||
static int IMQ_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_target **target)
|
||||
{
|
||||
struct xt_imq_info *mr = (struct xt_imq_info*)(*target)->data;
|
||||
|
||||
switch(c) {
|
||||
case '1':
|
||||
/* if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
|
||||
xtables_error(PARAMETER_PROBLEM,
|
||||
"Unexpected `!' after --todev");
|
||||
*/
|
||||
mr->todev=atoi(optarg);
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Prints out the targinfo. */
|
||||
static void IMQ_print(const void *ip,
|
||||
const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
struct xt_imq_info *mr = (struct xt_imq_info*)target->data;
|
||||
|
||||
printf("IMQ: todev %u ", mr->todev);
|
||||
}
|
||||
|
||||
/* Saves the union ipt_targinfo in parsable form to stdout. */
|
||||
static void IMQ_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
struct xt_imq_info *mr = (struct xt_imq_info*)target->data;
|
||||
|
||||
printf(" --todev %u", mr->todev);
|
||||
}
|
||||
|
||||
static struct xtables_target imq_target = {
|
||||
.name = "IMQ",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV4,
|
||||
.size = XT_ALIGN(sizeof(struct xt_imq_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_imq_info)),
|
||||
.help = IMQ_help,
|
||||
.init = IMQ_init,
|
||||
.parse = IMQ_parse,
|
||||
.print = IMQ_print,
|
||||
.save = IMQ_save,
|
||||
.extra_opts = IMQ_opts,
|
||||
};
|
||||
|
||||
static struct xtables_target imq_target6 = {
|
||||
.name = "IMQ",
|
||||
.version = XTABLES_VERSION,
|
||||
.family = NFPROTO_IPV6,
|
||||
.size = XT_ALIGN(sizeof(struct xt_imq_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_imq_info)),
|
||||
.help = IMQ_help,
|
||||
.init = IMQ_init,
|
||||
.parse = IMQ_parse,
|
||||
.print = IMQ_print,
|
||||
.save = IMQ_save,
|
||||
.extra_opts = IMQ_opts,
|
||||
};
|
||||
|
||||
// void __attribute((constructor)) nf_ext_init(void){
|
||||
void _init(void){
|
||||
xtables_register_target(&imq_target);
|
||||
xtables_register_target(&imq_target6);
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
This target is used to redirect the traffic to the IMQ driver and you can apply
|
||||
QoS rules like HTB or CBQ.
|
||||
For example you can select only traffic comming from a specific interface or
|
||||
is going out on a specific interface.
|
||||
Also it permits to capture the traffic BEFORE NAT in the case of outgoing traffic
|
||||
or AFTER NAT in the case of incomming traffic.
|
||||
.TP
|
||||
\fB\-\-to\-dev\fP \fIvalue\fP
|
||||
Set the IMQ interface where to send this traffic
|
||||
.TP
|
||||
Example:
|
||||
.TP
|
||||
Redirect incomming traffic from interface eth0 to imq0 and outgoing traffic to imq1:
|
||||
iptables \-t mangle \-A FORWARD \-i eth0 \-j IMQ \-\-to\-dev 0
|
||||
iptables \-t mangle \-A FORWARD \-o eth0 \-j IMQ \-\-to\-dev 1
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue