mirror of
git://git.code.sf.net/p/xtables-addons/xtables-addons
synced 2025-09-20 19:44:56 +02:00
Compare commits
97 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c168a2f142 | ||
![]() |
68af6989b1 | ||
![]() |
446c67018a | ||
![]() |
0fe8e180c4 | ||
![]() |
7cdfc0ac3d | ||
![]() |
85cab10371 | ||
![]() |
61d8425cb6 | ||
![]() |
d49b6244c1 | ||
![]() |
10c2b97786 | ||
![]() |
9ed364ed36 | ||
![]() |
b95e5f6417 | ||
![]() |
4afebf88eb | ||
![]() |
d523158e92 | ||
![]() |
1fd1787a1c | ||
![]() |
fbbca68790 | ||
![]() |
4cdfd49637 | ||
![]() |
31c01cf107 | ||
![]() |
879e964f60 | ||
![]() |
019c9de291 | ||
![]() |
af370f81f0 | ||
![]() |
598c7ede37 | ||
![]() |
2f66755226 | ||
![]() |
d01a5f3d17 | ||
![]() |
bbda3e53da | ||
![]() |
22e73ea31f | ||
![]() |
6b37f201d7 | ||
![]() |
94ecf3847b | ||
![]() |
ee968691d7 | ||
![]() |
22db3bcb9c | ||
![]() |
7da803e908 | ||
![]() |
4aad07bdc4 | ||
![]() |
7a3f874753 | ||
![]() |
f77a8e2eda | ||
![]() |
bd99e950f5 | ||
![]() |
fdb7f34bc8 | ||
![]() |
85e3c24167 | ||
![]() |
aab8dd360f | ||
![]() |
a8f60d0d4b | ||
![]() |
5b1bfedb82 | ||
![]() |
ee7e4f5a42 | ||
![]() |
d20d1922db | ||
![]() |
be6fbee56a | ||
![]() |
3c0b26c4b9 | ||
![]() |
25e2fbdf7d | ||
![]() |
5bd67db123 | ||
![]() |
f3737502bd | ||
![]() |
74e7eb283a | ||
![]() |
f3f0741469 | ||
![]() |
9c43965a86 | ||
![]() |
3a4e719b8c | ||
![]() |
e87dc5d5e1 | ||
![]() |
a0d3ee45ea | ||
![]() |
38343af9e6 | ||
![]() |
53abb1e735 | ||
![]() |
8a7354d8d5 | ||
![]() |
f30793f591 | ||
![]() |
ab27472eb4 | ||
![]() |
213acdffda | ||
![]() |
a47e6623b8 | ||
![]() |
d894a3dd15 | ||
![]() |
75e9afbc4a | ||
![]() |
003591fe6f | ||
![]() |
fd83fefad1 | ||
![]() |
e601fd61f9 | ||
![]() |
8fe612e43f | ||
![]() |
6737682e82 | ||
![]() |
fd9c6ffb03 | ||
![]() |
4f25eab39d | ||
![]() |
006147a21e | ||
![]() |
c18fae4f2f | ||
![]() |
b4784a48e8 | ||
![]() |
039741e022 | ||
![]() |
74880dd6ca | ||
![]() |
5956a3354e | ||
![]() |
419006eff9 | ||
![]() |
f43ac442e1 | ||
![]() |
1c902893b5 | ||
![]() |
b1b6180e0b | ||
![]() |
5120ab0079 | ||
![]() |
35783b5c51 | ||
![]() |
29aea5a87b | ||
![]() |
e456c864c1 | ||
![]() |
df6d795d22 | ||
![]() |
e987e2118c | ||
![]() |
a1e915a984 | ||
![]() |
74b20f5b73 | ||
![]() |
6d80c3adfe | ||
![]() |
9d696b727a | ||
![]() |
98e88e2d01 | ||
![]() |
a48469ec5b | ||
![]() |
ca482e8add | ||
![]() |
38198b257d | ||
![]() |
0959b60b07 | ||
![]() |
02a65e0af8 | ||
![]() |
84624f66cb | ||
![]() |
5f098b2c5a | ||
![]() |
086c8def12 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,6 +6,7 @@
|
||||
.libs
|
||||
Makefile
|
||||
Makefile.in
|
||||
GNUmakefile
|
||||
|
||||
/downloads
|
||||
|
||||
|
31
INSTALL
31
INSTALL
@@ -12,9 +12,12 @@ in combination with the kernel's Kbuild system.
|
||||
Prerequirements
|
||||
===============
|
||||
|
||||
* xtables(-devel) 1.5.2
|
||||
* iptables 1.4.1
|
||||
|
||||
* kernel-source >= 2.6.18 with prepared build/output directory
|
||||
* kernel-source >= 2.6.17 with prepared build/output directory
|
||||
- CONFIG_NF_CONNTRACK or CONFIG_IP_NF_CONNTRACK
|
||||
- CONFIG_NF_CONNTRACK_MARK or CONFIG_IP_NF_CONNTRACK_MARK
|
||||
enabled =y or as module (=m)
|
||||
|
||||
|
||||
Selecting extensions
|
||||
@@ -36,15 +39,6 @@ Configuring and compiling
|
||||
/lib/modules/$(running version)/build, which usually points to
|
||||
the right directory. (If not, you need to install something.)
|
||||
|
||||
--with-ksource=
|
||||
|
||||
Specifies the path to the kernel source directory. This is
|
||||
currently needed for building the userspace extensions because
|
||||
we use unsanitized kernel headers, but the option MAY
|
||||
DISAPPEAR IN FUTURE.
|
||||
|
||||
--with-ksource=/usr/src/linux
|
||||
|
||||
--with-xtables=
|
||||
|
||||
Specifies the path to the directory where we may find
|
||||
@@ -71,11 +65,24 @@ If you want to enable debugging, use
|
||||
much easier.)
|
||||
|
||||
|
||||
Build-time options
|
||||
==================
|
||||
|
||||
V= controls the kernel's make verbosity.
|
||||
V=0 "silent" (output filename)
|
||||
V=1 "verbose" (entire gcc command line)
|
||||
|
||||
VU= controls the Xt-a make verbosity.
|
||||
VU=0 output filename
|
||||
VU=1 output filename and source file
|
||||
VU=2 entire gcc command line
|
||||
|
||||
|
||||
Note to distribution packagers
|
||||
==============================
|
||||
|
||||
Except for --with-kbuild, distributions should not have a need to
|
||||
supply any other flags (besides --prefix=/usr and perhaps
|
||||
--libdir=/usr/lib64, etc.) to configure when all prerequired packages
|
||||
are installed. If xtables-devel is installed, necessary headers should
|
||||
are installed. If iptables-devel is installed, necessary headers should
|
||||
be in /usr/include, so --with-xtables is not needed.
|
||||
|
339
LICENSE
Normal file
339
LICENSE
Normal file
@@ -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.
|
@@ -1,20 +1,24 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
AUTOMAKE_OPTIONS = foreign subdir-objects
|
||||
SUBDIRS = extensions
|
||||
|
||||
man_MANS := xtables-addons.8
|
||||
|
||||
xtables-addons.8: ${srcdir}/xtables-addons.8.in extensions/matches.man extensions/targets.man
|
||||
${AM_VERBOSE_GEN} sed -e '/@MATCHES@/ r extensions/matches.man' -e '/@TARGET@/ r extensions/targets.man' $< >$@;
|
||||
${am__verbose_GEN}sed -e '/@MATCHES@/ r extensions/matches.man' -e '/@TARGET@/ r extensions/targets.man' $< >$@;
|
||||
|
||||
extensions/%:
|
||||
${MAKE} ${AM_MAKEFLAGS} -C $(@D) $(@F)
|
||||
|
||||
install-exec-local:
|
||||
depmod -a || :;
|
||||
|
||||
.PHONY: tarball
|
||||
tarball:
|
||||
rm -Rf /tmp/xtables-addons-${PACKAGE_VERSION};
|
||||
pushd ${top_srcdir} && git-archive --prefix=xtables-addons-${PACKAGE_VERSION}/ HEAD | tar -C /tmp -x && popd;
|
||||
pushd ${top_srcdir} && git archive --prefix=xtables-addons-${PACKAGE_VERSION}/ HEAD | tar -C /tmp -x && popd;
|
||||
pushd /tmp/xtables-addons-${PACKAGE_VERSION} && ./autogen.sh && popd;
|
||||
tar -C /tmp -cjf xtables-addons-${PACKAGE_VERSION}.tar.bz2 --owner=root --group=root xtables-addons-${PACKAGE_VERSION}/;
|
||||
rm -Rf /tmp/xtables-addons-${PACKAGE_VERSION};
|
||||
|
34
README
34
README
@@ -5,31 +5,43 @@ Xtables-addons is the proclaimed successor to patch-o-matic(-ng). It
|
||||
contains extensions that were not accepted in the main Xtables
|
||||
package.
|
||||
|
||||
Xtables-addons is different from patch-o-matic in that you do not have
|
||||
to patch or recompile either kernel or Xtables(iptables). But please
|
||||
see the INSTALL file for the minimum requirements of this package.
|
||||
Xtables-addons is different from patch-o-matic in that you do not
|
||||
have to patch or recompile either kernel or Xtables(iptables). But
|
||||
please see the INSTALL file for the minimum requirements of this
|
||||
package.
|
||||
|
||||
All code imported from patch-o-matic has been reviewed and all
|
||||
apparent bugs like binary stability across multiarches, missing
|
||||
sanity checks and incorrect endianess handling have been fixed,
|
||||
simplified, and sped up.
|
||||
|
||||
|
||||
Inclusion into a kernel tree
|
||||
============================
|
||||
|
||||
|
||||
|
||||
|
||||
External extensions
|
||||
===================
|
||||
|
||||
The program "xa-download-more" can be used to download more extensions
|
||||
from 3rd parties into the source tree. The URLs are listed in the
|
||||
"sources" file. If the "sources" file contains an entry like
|
||||
The program "xa-download-more" can be used to download more
|
||||
extensions from 3rd parties into the source tree. The URLs are listed
|
||||
in the "sources" file. If the "sources" file contains an entry like
|
||||
|
||||
http://foobar.org/xa/
|
||||
|
||||
xa-download-more will inspect http://foobar.org/xa/xa-index.txt for files
|
||||
to download. That file may contain
|
||||
xa-download-more will inspect http://foobar.org/xa/xa-index.txt for
|
||||
files to download. That file may contain
|
||||
|
||||
foobar.tar.bz2
|
||||
|
||||
and xa-download-more will then retrieve and unpack
|
||||
http://foobar.org/xa/foobar.tar.bz2.
|
||||
|
||||
Files that should be contained in the tarball are an mconfig and Kbuild
|
||||
files to control building the extension, libxt_foobar.c for the userspace
|
||||
extension and xt_foobar.c for the kernel extension.
|
||||
Files that should be contained in the tarball are an mconfig and
|
||||
Kbuild files to control building the extension, libxt_foobar.c for
|
||||
the userspace extension and xt_foobar.c for the kernel extension.
|
||||
|
||||
mconfig.foobar
|
||||
extensions/Kbuild.foobar
|
||||
|
14
configure.ac
14
configure.ac
@@ -1,8 +1,9 @@
|
||||
|
||||
AC_INIT([xtables-addons], [1.5.4])
|
||||
AC_INIT([xtables-addons], [1.9])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_PROG_INSTALL
|
||||
AM_INIT_AUTOMAKE
|
||||
AM_INIT_AUTOMAKE([-Wall])
|
||||
AC_PROG_CC
|
||||
AM_PROG_CC_C_O
|
||||
AC_DISABLE_STATIC
|
||||
@@ -27,8 +28,6 @@ AC_ARG_WITH([xtlibdir],
|
||||
[xtlibdir="$withval"],
|
||||
[xtlibdir='${libexecdir}/xtables'])
|
||||
|
||||
AC_CHECK_HEADER([netinet/ip6.h], [], [AC_MSG_ERROR(but we need that for IPv6)])
|
||||
|
||||
AC_MSG_CHECKING([xtables.h presence])
|
||||
if [[ -n "$xtables_location" ]]; then
|
||||
if [[ -f "$xtables_location/xtables.h" ]]; then
|
||||
@@ -59,8 +58,11 @@ if [[ -n "$ksourcedir" ]]; then
|
||||
kinclude_CFLAGS="$kinclude_CFLAGS -I $ksourcedir/include";
|
||||
fi;
|
||||
|
||||
AC_SUBST([regular_CFLAGS xtables_CFLAGS kinclude_CFLAGS])
|
||||
AC_SUBST([regular_CFLAGS])
|
||||
AC_SUBST([xtables_CFLAGS])
|
||||
AC_SUBST([kinclude_CFLAGS])
|
||||
AC_SUBST([kbuilddir])
|
||||
AC_SUBST([ksourcedir])
|
||||
AC_SUBST([xtlibdir])
|
||||
AC_OUTPUT([Makefile extensions/GNUmakefile])
|
||||
AC_CONFIG_FILES([Makefile extensions/GNUmakefile extensions/ipset/GNUmakefile])
|
||||
AC_OUTPUT
|
||||
|
13
extensions/.gitignore
vendored
13
extensions/.gitignore
vendored
@@ -1,13 +1,14 @@
|
||||
.*.cmd
|
||||
.*.d
|
||||
.manpages.lst
|
||||
.tmp_versions
|
||||
*.ko
|
||||
*.mod.c
|
||||
*.so
|
||||
*.oo
|
||||
GNUmakefile
|
||||
Module.symvers
|
||||
Modules.symvers
|
||||
modules.order
|
||||
matches.man
|
||||
targets.man
|
||||
|
||||
/*.so
|
||||
/*.oo
|
||||
/matches.man
|
||||
/targets.man
|
||||
/.manpages.lst
|
||||
|
@@ -2,8 +2,8 @@
|
||||
|
||||
top_srcdir := @top_srcdir@
|
||||
srcdir := @srcdir@
|
||||
abstop_srcdir := $(shell readlink -e ${top_srcdir})
|
||||
abssrcdir := $(shell readlink -e ${srcdir})
|
||||
abstop_srcdir := $(shell readlink -f ${top_srcdir})
|
||||
abssrcdir := $(shell readlink -f ${srcdir})
|
||||
|
||||
ifeq (${abstop_srcdir},)
|
||||
$(error Path resolution of ${top_srcdir} failed)
|
||||
@@ -30,15 +30,17 @@ xtables_CFLAGS := @xtables_CFLAGS@
|
||||
AM_CFLAGS := ${regular_CFLAGS} -I${top_srcdir}/include ${xtables_CFLAGS} ${kinclude_CFLAGS}
|
||||
AM_DEPFLAGS = -Wp,-MMD,$(@D)/.$(@F).d,-MT,$@
|
||||
|
||||
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
|
||||
VU := 0
|
||||
am__1verbose_CC_0 = @echo " CC " $@;
|
||||
am__1verbose_CCLD_0 = @echo " CCLD " $@;
|
||||
am__1verbose_GEN_0 = @echo " GEN " $@;
|
||||
am__1verbose_CC_1 = @echo " CC " $@ "<-" $<;
|
||||
am__1verbose_CCLD_1 = @echo " CCLD " $@ "<-" $^;
|
||||
am__1verbose_GEN_1 = @echo " GEN " $@ "<-" $<;
|
||||
am__verbose_CC = ${am__1verbose_CC_${VU}}
|
||||
am__verbose_CCLD = ${am__1verbose_CCLD_${VU}}
|
||||
am__verbose_GEN = ${am__1verbose_GEN_${VU}}
|
||||
|
||||
|
||||
#
|
||||
# Wildcard module list
|
||||
@@ -46,25 +48,37 @@ endif
|
||||
include ${top_srcdir}/mconfig
|
||||
-include ${top_srcdir}/mconfig.*
|
||||
include ${srcdir}/Mbuild
|
||||
-include ${srcdir}/Mbuild.*
|
||||
-include ${srcdir}/*.Mbuild
|
||||
|
||||
|
||||
#
|
||||
# Building blocks
|
||||
#
|
||||
targets := ${obj-m}
|
||||
targets_install := ${obj-m}
|
||||
targets := $(filter-out %/,${obj-m})
|
||||
targets_install := ${targets}
|
||||
subdirs_list := $(filter %/,${obj-m})
|
||||
|
||||
.SECONDARY:
|
||||
|
||||
.PHONY: all install clean distclean FORCE
|
||||
|
||||
all: modules ${targets} matches.man targets.man
|
||||
all: subdirs modules user matches.man targets.man
|
||||
|
||||
install: modules_install ${targets_install}
|
||||
subdirs:
|
||||
@for i in ${subdirs_list}; do ${MAKE} -C $$i; done;
|
||||
|
||||
subdirs-install:
|
||||
@for i in ${subdirs_list}; do ${MAKE} -C $$i install; done;
|
||||
|
||||
user: ${targets}
|
||||
|
||||
install: modules_install subdirs-install ${targets_install}
|
||||
@mkdir -p "${DESTDIR}${xtlibdir}";
|
||||
install -pm0755 ${targets_install} "${DESTDIR}${xtlibdir}/";
|
||||
|
||||
clean: clean_modules
|
||||
@for i in ${subdirs_list}; do make -C $$i clean; done;
|
||||
rm -f *.oo *.so;
|
||||
|
||||
distclean: clean
|
||||
@@ -92,10 +106,10 @@ clean_modules:
|
||||
# Shared libraries
|
||||
#
|
||||
lib%.so: lib%.oo
|
||||
${AM_VERBOSE_CCLD} ${CCLD} ${AM_LDFLAGS} -shared ${LDFLAGS} -o $@ $<;
|
||||
${am__verbose_CCLD}${CCLD} ${AM_LDFLAGS} -shared ${LDFLAGS} -o $@ $<;
|
||||
|
||||
lib%.oo: ${srcdir}/lib%.c
|
||||
${AM_VERBOSE_CC} ${CC} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} -o $@ -c $<;
|
||||
${am__verbose_CC}${CC} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} -o $@ -c $<;
|
||||
|
||||
|
||||
#
|
||||
@@ -112,8 +126,7 @@ wlist_targets := $(patsubst ${srcdir}/libxt_%.man,%,${wcman_targets})
|
||||
rm -f $@.tmp;
|
||||
|
||||
man_run = \
|
||||
${AM_VERBOSE_GEN} \
|
||||
for ext in $(1); do \
|
||||
${am__verbose_GEN}for ext in $(1); do \
|
||||
f="${srcdir}/libxt_$$ext.man"; \
|
||||
if [ -f "$$f" ]; then \
|
||||
echo ".SS $$ext"; \
|
||||
|
@@ -3,18 +3,25 @@
|
||||
include ${XA_TOPSRCDIR}/mconfig
|
||||
-include ${XA_TOPSRCDIR}/mconfig.*
|
||||
|
||||
obj-m += compat_xtables.o
|
||||
obj-m += compat_xtables.o
|
||||
|
||||
obj-${build_CHAOS} += xt_CHAOS.o
|
||||
obj-${build_DELUDE} += xt_DELUDE.o
|
||||
obj-${build_ECHO} += xt_ECHO.o
|
||||
obj-${build_IPMARK} += xt_IPMARK.o
|
||||
obj-${build_LOGMARK} += xt_LOGMARK.o
|
||||
obj-${build_TARPIT} += xt_TARPIT.o
|
||||
obj-${build_TEE} += xt_TEE.o
|
||||
obj-${build_condition} += xt_condition.o
|
||||
obj-${build_geoip} += xt_geoip.o
|
||||
obj-${build_ipp2p} += xt_ipp2p.o
|
||||
obj-${build_portscan} += xt_portscan.o
|
||||
obj-${build_CHAOS} += xt_CHAOS.o
|
||||
obj-${build_DELUDE} += xt_DELUDE.o
|
||||
obj-${build_DHCPADDR} += xt_DHCPADDR.o
|
||||
obj-${build_ECHO} += xt_ECHO.o
|
||||
obj-${build_IPMARK} += xt_IPMARK.o
|
||||
obj-${build_LOGMARK} += xt_LOGMARK.o
|
||||
obj-${build_SYSRQ} += xt_SYSRQ.o
|
||||
obj-${build_TARPIT} += xt_TARPIT.o
|
||||
obj-${build_TEE} += xt_TEE.o
|
||||
obj-${build_condition} += xt_condition.o
|
||||
obj-${build_fuzzy} += xt_fuzzy.o
|
||||
obj-${build_geoip} += xt_geoip.o
|
||||
obj-${build_ipp2p} += xt_ipp2p.o
|
||||
obj-${build_ipset} += ipset/
|
||||
obj-${build_length2} += xt_length2.o
|
||||
obj-${build_portscan} += xt_portscan.o
|
||||
obj-${build_quota2} += xt_quota2.o
|
||||
|
||||
-include ${M}/*.Kbuild
|
||||
-include ${M}/Kbuild.*
|
||||
|
@@ -1,11 +1,17 @@
|
||||
obj-${build_CHAOS} += libxt_CHAOS.so
|
||||
obj-${build_DELUDE} += libxt_DELUDE.so
|
||||
obj-${build_ECHO} += libxt_ECHO.so
|
||||
obj-${build_IPMARK} += libxt_IPMARK.so
|
||||
obj-${build_LOGMARK} += libxt_LOGMARK.so
|
||||
obj-${build_TARPIT} += libxt_TARPIT.so
|
||||
obj-${build_TEE} += libxt_TEE.so
|
||||
obj-${build_condition} += libxt_condition.so
|
||||
obj-${build_geoip} += libxt_geoip.so
|
||||
obj-${build_ipp2p} += libxt_ipp2p.so
|
||||
obj-${build_portscan} += libxt_portscan.so
|
||||
obj-${build_CHAOS} += libxt_CHAOS.so
|
||||
obj-${build_DELUDE} += libxt_DELUDE.so
|
||||
obj-${build_DHCPADDR} += libxt_DHCPADDR.so libxt_dhcpaddr.so
|
||||
obj-${build_ECHO} += libxt_ECHO.so
|
||||
obj-${build_IPMARK} += libxt_IPMARK.so
|
||||
obj-${build_LOGMARK} += libxt_LOGMARK.so
|
||||
obj-${build_SYSRQ} += libxt_SYSRQ.so
|
||||
obj-${build_TARPIT} += libxt_TARPIT.so
|
||||
obj-${build_TEE} += libxt_TEE.so
|
||||
obj-${build_condition} += libxt_condition.so
|
||||
obj-${build_fuzzy} += libxt_fuzzy.so
|
||||
obj-${build_geoip} += libxt_geoip.so
|
||||
obj-${build_ipp2p} += libxt_ipp2p.so
|
||||
obj-${build_ipset} += ipset/
|
||||
obj-${build_length2} += libxt_length2.so
|
||||
obj-${build_portscan} += libxt_portscan.so
|
||||
obj-${build_quota2} += libxt_quota2.so
|
||||
|
@@ -10,6 +10,12 @@ struct udphdr;
|
||||
# define skb_nfmark(skb) (((struct sk_buff *)(skb))->mark)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NETWORK_SECMARK
|
||||
# define skb_secmark(skb) ((skb)->secmark)
|
||||
#else
|
||||
# define skb_secmark(skb) 0
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 21)
|
||||
# define ip_hdr(skb) ((skb)->nh.iph)
|
||||
# define ip_hdrlen(skb) (ip_hdr(skb)->ihl * 4)
|
||||
|
@@ -1,3 +1,11 @@
|
||||
/*
|
||||
* API compat layer
|
||||
* written by Jan Engelhardt <jengelh [at] medozas de>, 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License, either
|
||||
* version 2 of the License, or any later version.
|
||||
*/
|
||||
#include <linux/ip.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
@@ -12,27 +20,40 @@
|
||||
#include "compat_skbuff.h"
|
||||
#include "compat_xtnu.h"
|
||||
|
||||
static inline int unable(const char *cause)
|
||||
{
|
||||
if (net_ratelimit())
|
||||
printk(KERN_ERR KBUILD_MODNAME
|
||||
": compat layer limits reached (%s) - dropping packets\n", cause);
|
||||
return -1;
|
||||
}
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19)
|
||||
typedef __u16 __bitwise __sum16;
|
||||
typedef __u32 __bitwise __wsum;
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
|
||||
static int xtnu_match_run(const struct sk_buff *skb,
|
||||
const struct net_device *in, const struct net_device *out,
|
||||
const struct xt_match *cm, const void *matchinfo, int offset,
|
||||
unsigned int protoff, int *hotdrop)
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
static bool xtnu_match_run(const struct sk_buff *skb,
|
||||
const struct net_device *in, const struct net_device *out,
|
||||
const struct xt_match *cm, const void *matchinfo, int offset,
|
||||
unsigned int protoff, bool *hotdrop)
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
{
|
||||
struct xtnu_match *nm = xtcompat_numatch(cm);
|
||||
bool lo_drop, lo_ret;
|
||||
bool lo_drop = false, lo_ret;
|
||||
struct xt_match_param local_par = {
|
||||
.in = in,
|
||||
.out = out,
|
||||
.match = cm,
|
||||
.matchinfo = matchinfo,
|
||||
.fragoff = offset,
|
||||
.thoff = protoff,
|
||||
.hotdrop = &lo_drop,
|
||||
.family = NFPROTO_UNSPEC, /* don't have that info */
|
||||
};
|
||||
|
||||
if (nm == NULL || nm->match == NULL)
|
||||
return false;
|
||||
lo_ret = nm->match(skb, in, out, nm, matchinfo,
|
||||
offset, protoff, &lo_drop);
|
||||
lo_ret = nm->match(skb, &local_par);
|
||||
*hotdrop = lo_drop;
|
||||
return lo_ret;
|
||||
}
|
||||
@@ -45,35 +66,51 @@ static int xtnu_match_check(const char *table, const void *entry,
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
|
||||
static int xtnu_match_check(const char *table, const void *entry,
|
||||
const struct xt_match *cm, void *matchinfo, unsigned int hook_mask)
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
static bool xtnu_match_check(const char *table, const void *entry,
|
||||
const struct xt_match *cm, void *matchinfo, unsigned int hook_mask)
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
{
|
||||
struct xtnu_match *nm = xtcompat_numatch(cm);
|
||||
struct xt_mtchk_param local_par = {
|
||||
.table = table,
|
||||
.entryinfo = entry,
|
||||
.match = cm,
|
||||
.matchinfo = matchinfo,
|
||||
.hook_mask = hook_mask,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
};
|
||||
|
||||
if (nm == NULL)
|
||||
return false;
|
||||
if (nm->checkentry == NULL)
|
||||
return true;
|
||||
return nm->checkentry(table, entry, nm, matchinfo, hook_mask);
|
||||
return nm->checkentry(&local_par);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
|
||||
static void xtnu_match_destroy(const struct xt_match *cm, void *matchinfo,
|
||||
unsigned int matchinfosize)
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
static void xtnu_match_destroy(const struct xt_match *cm, void *matchinfo)
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
{
|
||||
struct xtnu_match *nm = xtcompat_numatch(cm);
|
||||
struct xt_mtdtor_param local_par = {
|
||||
.match = cm,
|
||||
.matchinfo = matchinfo,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
};
|
||||
|
||||
if (nm != NULL && nm->destroy != NULL)
|
||||
nm->destroy(nm, matchinfo);
|
||||
nm->destroy(&local_par);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
int xtnu_register_match(struct xtnu_match *nt)
|
||||
{
|
||||
struct xt_match *ct;
|
||||
@@ -152,15 +189,39 @@ static unsigned int xtnu_target_run(struct sk_buff **pskb,
|
||||
static unsigned int xtnu_target_run(struct sk_buff **pskb,
|
||||
const struct net_device *in, const struct net_device *out,
|
||||
unsigned int hooknum, const struct xt_target *ct, const void *targinfo)
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
static unsigned int xtnu_target_run(struct sk_buff *skb,
|
||||
const struct net_device *in, const struct net_device *out,
|
||||
unsigned int hooknum, const struct xt_target *ct, const void *targinfo)
|
||||
#else
|
||||
static unsigned int
|
||||
xtnu_target_run(struct sk_buff *skb, const struct xt_target_param *par)
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
{
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
struct xtnu_target *nt = xtcompat_nutarget(ct);
|
||||
struct xt_target_param local_par = {
|
||||
.in = in,
|
||||
.out = out,
|
||||
.hooknum = hooknum,
|
||||
.target = ct,
|
||||
.targinfo = targinfo,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
};
|
||||
#else
|
||||
struct xtnu_target *nt = xtcompat_nutarget(par->target);
|
||||
#endif
|
||||
|
||||
if (nt != NULL && nt->target != NULL)
|
||||
return nt->target(*pskb, in, out, hooknum, nt, targinfo);
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
return nt->target(pskb, &local_par);
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
return nt->target(&skb, &local_par);
|
||||
#else
|
||||
return nt->target(&skb, par);
|
||||
#endif
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
|
||||
static int xtnu_target_check(const char *table, const void *entry,
|
||||
@@ -169,37 +230,51 @@ static int xtnu_target_check(const char *table, const void *entry,
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
|
||||
static int xtnu_target_check(const char *table, const void *entry,
|
||||
const struct xt_target *ct, void *targinfo, unsigned int hook_mask)
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
static bool xtnu_target_check(const char *table, const void *entry,
|
||||
const struct xt_target *ct, void *targinfo, unsigned int hook_mask)
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
{
|
||||
struct xtnu_target *nt = xtcompat_nutarget(ct);
|
||||
struct xt_tgchk_param local_par = {
|
||||
.table = table,
|
||||
.entryinfo = entry,
|
||||
.target = ct,
|
||||
.targinfo = targinfo,
|
||||
.hook_mask = hook_mask,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
};
|
||||
|
||||
if (nt == NULL)
|
||||
return false;
|
||||
if (nt->checkentry == NULL)
|
||||
/* this is valid, just like if there was no function */
|
||||
return true;
|
||||
return nt->checkentry(table, entry, nt, targinfo, hook_mask);
|
||||
return nt->checkentry(&local_par);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
|
||||
static void xtnu_target_destroy(const struct xt_target *ct, void *targinfo,
|
||||
unsigned int targinfosize)
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
static void xtnu_target_destroy(const struct xt_target *ct, void *targinfo)
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
{
|
||||
struct xtnu_target *nt = xtcompat_nutarget(ct);
|
||||
struct xt_tgdtor_param local_par = {
|
||||
.target = ct,
|
||||
.targinfo = targinfo,
|
||||
.family = NFPROTO_UNSPEC,
|
||||
};
|
||||
|
||||
if (nt != NULL && nt->destroy != NULL)
|
||||
nt->destroy(nt, targinfo);
|
||||
nt->destroy(&local_par);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
int xtnu_register_target(struct xtnu_target *nt)
|
||||
{
|
||||
struct xt_target *ct;
|
||||
@@ -222,8 +297,13 @@ int xtnu_register_target(struct xtnu_target *nt)
|
||||
ct->hooks = nt->hooks;
|
||||
ct->proto = nt->proto;
|
||||
ct->target = xtnu_target_run;
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
ct->checkentry = xtnu_target_check;
|
||||
ct->destroy = xtnu_target_destroy;
|
||||
#else
|
||||
ct->checkentry = nt->checkentry;
|
||||
ct->destroy = nt->destroy;
|
||||
#endif
|
||||
ct->targetsize = nt->targetsize;
|
||||
ct->me = nt->me;
|
||||
|
||||
@@ -267,7 +347,6 @@ void xtnu_unregister_targets(struct xtnu_target *nt, unsigned int num)
|
||||
xtnu_unregister_target(&nt[i]);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_unregister_targets);
|
||||
#endif
|
||||
|
||||
struct xt_match *xtnu_request_find_match(unsigned int af, const char *name,
|
||||
uint8_t revision)
|
||||
@@ -293,35 +372,28 @@ struct xt_match *xtnu_request_find_match(unsigned int af, const char *name,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_request_find_match);
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
int xtnu_ip_route_me_harder(struct sk_buff *skb, unsigned int addr_type)
|
||||
int xtnu_ip_route_me_harder(struct sk_buff **pskb, unsigned int addr_type)
|
||||
{
|
||||
struct sk_buff *nskb = skb;
|
||||
int ret;
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
|
||||
ret = ip_route_me_harder(&skb);
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 17)
|
||||
/* Actually this one is valid up to 2.6.18.4, but changed in 2.6.18.5 */
|
||||
return ip_route_me_harder(pskb);
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
ret = ip_route_me_harder(&nskb, addr_type);
|
||||
return ip_route_me_harder(pskb, addr_type);
|
||||
#else
|
||||
return ip_route_me_harder(*pskb, addr_type);
|
||||
#endif
|
||||
if (nskb != skb)
|
||||
return unable(__func__);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_ip_route_me_harder);
|
||||
|
||||
int xtnu_skb_make_writable(struct sk_buff *skb, unsigned int len)
|
||||
int xtnu_skb_make_writable(struct sk_buff **pskb, unsigned int len)
|
||||
{
|
||||
struct sk_buff *nskb = skb;
|
||||
int ret;
|
||||
|
||||
ret = skb_make_writable(&skb, len);
|
||||
if (nskb != skb)
|
||||
return unable(__func__);
|
||||
return ret;
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
return skb_make_writable(pskb, len);
|
||||
#else
|
||||
return skb_make_writable(*pskb, len);
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_skb_make_writable);
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 24)
|
||||
static int __xtnu_ip_local_out(struct sk_buff *skb)
|
||||
@@ -390,6 +462,32 @@ int xtnu_neigh_hh_output(struct hh_cache *hh, struct sk_buff *skb)
|
||||
return hh->hh_output(skb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_neigh_hh_output);
|
||||
|
||||
static inline __wsum xtnu_csum_unfold(__sum16 n)
|
||||
{
|
||||
return (__force __wsum)n;
|
||||
}
|
||||
|
||||
static inline void xtnu_csum_replace4(__sum16 *sum, __be32 from, __be32 to)
|
||||
{
|
||||
__be32 diff[] = {~from, to};
|
||||
*sum = csum_fold(csum_partial((char *)diff, sizeof(diff),
|
||||
~xtnu_csum_unfold(*sum)));
|
||||
}
|
||||
|
||||
void xtnu_csum_replace2(__sum16 *sum, __be16 from, __be16 to)
|
||||
{
|
||||
xtnu_csum_replace4(sum, (__force __be32)from, (__force __be32)to);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_csum_replace2);
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 17)
|
||||
int xtnu_skb_linearize(struct sk_buff *skb)
|
||||
{
|
||||
return skb_linearize(skb, GFP_ATOMIC);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xtnu_skb_linearize);
|
||||
#endif
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@@ -5,18 +5,18 @@
|
||||
#include "compat_skbuff.h"
|
||||
#include "compat_xtnu.h"
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
|
||||
# warning Kernels below 2.6.18 not supported.
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 17)
|
||||
# warning Kernels below 2.6.17 not supported.
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
|
||||
# if !defined(CONFIG_NF_CONNTRACK_MARK) || !defined(CONFIG_NF_CONNTRACK_SECMARK)
|
||||
# warning You have CONFIG_NF_CONNTRACK enabled, but CONFIG_NF_CONNTRACK_MARK or CONFIG_NF_CONNTRACK_SECMARK are not (please enable).
|
||||
# if !defined(CONFIG_NF_CONNTRACK_MARK)
|
||||
# warning You have CONFIG_NF_CONNTRACK enabled, but CONFIG_NF_CONNTRACK_MARK is not (please enable).
|
||||
# endif
|
||||
# include <net/netfilter/nf_conntrack.h>
|
||||
#elif defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
|
||||
# if !defined(CONFIG_IP_NF_CONNTRACK_MARK) || !defined(CONFIG_IP_NF_CONNTRACK_SECMARK)
|
||||
# warning You have CONFIG_IP_NF_CONNTRACK enabled, but CONFIG_IP_NF_CONNTRACK_MARK or CONFIG_IP_NF_CONNTRACK_SECMARK are not (please enable).
|
||||
# if !defined(CONFIG_IP_NF_CONNTRACK_MARK)
|
||||
# warning You have CONFIG_IP_NF_CONNTRACK enabled, but CONFIG_IP_NF_CONNTRACK_MARK is not (please enable).
|
||||
# endif
|
||||
# include <linux/netfilter_ipv4/ip_conntrack.h>
|
||||
# define nf_conn ip_conntrack
|
||||
@@ -26,8 +26,14 @@
|
||||
# warning You need either CONFIG_NF_CONNTRACK or CONFIG_IP_NF_CONNTRACK.
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 17)
|
||||
# define skb_init_secmark(skb)
|
||||
# define skb_linearize xtnu_skb_linearize
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19)
|
||||
# define neigh_hh_output xtnu_neigh_hh_output
|
||||
# define IPPROTO_UDPLITE 136
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
|
||||
@@ -44,11 +50,13 @@
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
# define init_net xtnu_ip_route_output_key /* yes */
|
||||
# define init_net__loopback_dev (&loopback_dev)
|
||||
# define init_net__proc_net proc_net
|
||||
#else
|
||||
# define init_net__loopback_dev init_net.loopback_dev
|
||||
# define init_net__proc_net init_net.proc_net
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
# define xt_match xtnu_match
|
||||
# define xt_register_match xtnu_register_match
|
||||
# define xt_unregister_match xtnu_unregister_match
|
||||
@@ -56,16 +64,20 @@
|
||||
# define xt_unregister_matches xtnu_unregister_matches
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
# define xt_target xtnu_target
|
||||
# define ip_route_me_harder xtnu_ip_route_me_harder
|
||||
# define skb_make_writable xtnu_skb_make_writable
|
||||
# define xt_register_target xtnu_register_target
|
||||
# define xt_unregister_target xtnu_unregister_target
|
||||
# define xt_register_targets xtnu_register_targets
|
||||
# define xt_unregister_targets xtnu_unregister_targets
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19)
|
||||
# define csum_replace2 xtnu_csum_replace2
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
|
||||
# define csum_replace2 nf_csum_replace2
|
||||
#endif
|
||||
|
||||
#define ip_route_me_harder xtnu_ip_route_me_harder
|
||||
#define skb_make_writable xtnu_skb_make_writable
|
||||
#define xt_target xtnu_target
|
||||
#define xt_register_target xtnu_register_target
|
||||
#define xt_unregister_target xtnu_unregister_target
|
||||
#define xt_register_targets xtnu_register_targets
|
||||
#define xt_unregister_targets xtnu_unregister_targets
|
||||
|
||||
#define xt_request_find_match xtnu_request_find_match
|
||||
|
||||
#endif /* _XTABLES_COMPAT_H */
|
||||
|
@@ -17,15 +17,72 @@ struct net_device;
|
||||
struct rtable;
|
||||
struct sk_buff;
|
||||
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
enum {
|
||||
NFPROTO_UNSPEC = 0,
|
||||
NFPROTO_IPV4 = 2,
|
||||
NFPROTO_ARP = 3,
|
||||
NFPROTO_BRIDGE = 7,
|
||||
NFPROTO_IPV6 = 10,
|
||||
NFPROTO_DECNET = 12,
|
||||
NFPROTO_NUMPROTO,
|
||||
};
|
||||
|
||||
struct xt_match_param {
|
||||
const struct net_device *in, *out;
|
||||
const struct xt_match *match;
|
||||
const void *matchinfo;
|
||||
int fragoff;
|
||||
unsigned int thoff;
|
||||
bool *hotdrop;
|
||||
u_int8_t family;
|
||||
};
|
||||
|
||||
struct xt_mtchk_param {
|
||||
const char *table;
|
||||
const void *entryinfo;
|
||||
const struct xt_match *match;
|
||||
void *matchinfo;
|
||||
unsigned int hook_mask;
|
||||
u_int8_t family;
|
||||
};
|
||||
|
||||
struct xt_mtdtor_param {
|
||||
const struct xt_match *match;
|
||||
void *matchinfo;
|
||||
u_int8_t family;
|
||||
};
|
||||
|
||||
struct xt_target_param {
|
||||
const struct net_device *in, *out;
|
||||
unsigned int hooknum;
|
||||
const struct xt_target *target;
|
||||
const void *targinfo;
|
||||
u_int8_t family;
|
||||
};
|
||||
|
||||
struct xt_tgchk_param {
|
||||
const char *table;
|
||||
const void *entryinfo;
|
||||
const struct xt_target *target;
|
||||
void *targinfo;
|
||||
unsigned int hook_mask;
|
||||
u_int8_t family;
|
||||
};
|
||||
|
||||
struct xt_tgdtor_param {
|
||||
const struct xt_target *target;
|
||||
void *targinfo;
|
||||
u_int8_t family;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct xtnu_match {
|
||||
struct list_head list;
|
||||
char name[XT_FUNCTION_MAXNAMELEN - 1 - sizeof(void *)];
|
||||
bool (*match)(const struct sk_buff *, const struct net_device *,
|
||||
const struct net_device *, const struct xtnu_match *,
|
||||
const void *, int, unsigned int, bool *);
|
||||
bool (*checkentry)(const char *, const void *,
|
||||
const struct xtnu_match *, void *, unsigned int);
|
||||
void (*destroy)(const struct xtnu_match *, void *);
|
||||
bool (*match)(const struct sk_buff *, const struct xt_match_param *);
|
||||
bool (*checkentry)(const struct xt_mtchk_param *);
|
||||
void (*destroy)(const struct xt_mtdtor_param *);
|
||||
struct module *me;
|
||||
const char *table;
|
||||
unsigned int matchsize, hooks;
|
||||
@@ -38,12 +95,10 @@ struct xtnu_match {
|
||||
struct xtnu_target {
|
||||
struct list_head list;
|
||||
char name[XT_FUNCTION_MAXNAMELEN - 1 - sizeof(void *)];
|
||||
unsigned int (*target)(struct sk_buff *, const struct net_device *,
|
||||
const struct net_device *, unsigned int,
|
||||
const struct xtnu_target *, const void *);
|
||||
bool (*checkentry)(const char *, const void *,
|
||||
const struct xtnu_target *, void *, unsigned int);
|
||||
void (*destroy)(const struct xtnu_target *, void *);
|
||||
unsigned int (*target)(struct sk_buff **,
|
||||
const struct xt_target_param *);
|
||||
bool (*checkentry)(const struct xt_tgchk_param *);
|
||||
void (*destroy)(const struct xt_tgdtor_param *);
|
||||
struct module *me;
|
||||
const char *table;
|
||||
unsigned int targetsize, hooks;
|
||||
@@ -68,8 +123,8 @@ static inline struct xtnu_target *xtcompat_nutarget(const struct xt_target *t)
|
||||
}
|
||||
|
||||
extern int xtnu_ip_local_out(struct sk_buff *);
|
||||
extern int xtnu_ip_route_me_harder(struct sk_buff *, unsigned int);
|
||||
extern int xtnu_skb_make_writable(struct sk_buff *, unsigned int);
|
||||
extern int xtnu_ip_route_me_harder(struct sk_buff **, unsigned int);
|
||||
extern int xtnu_skb_make_writable(struct sk_buff **, unsigned int);
|
||||
extern int xtnu_register_match(struct xtnu_match *);
|
||||
extern int xtnu_ip_route_output_key(void *, struct rtable **, struct flowi *);
|
||||
extern void xtnu_unregister_match(struct xtnu_match *);
|
||||
@@ -82,5 +137,7 @@ extern void xtnu_unregister_targets(struct xtnu_target *, unsigned int);
|
||||
extern struct xt_match *xtnu_request_find_match(unsigned int,
|
||||
const char *, uint8_t);
|
||||
extern int xtnu_neigh_hh_output(struct hh_cache *, struct sk_buff *);
|
||||
extern void xtnu_csum_replace2(__u16 __bitwise *, __be16, __be16);
|
||||
extern int xtnu_skb_linearize(struct sk_buff *);
|
||||
|
||||
#endif /* _COMPAT_XTNU_H */
|
||||
|
3
extensions/ipset/.gitignore
vendored
Normal file
3
extensions/ipset/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
*.oo
|
||||
*.so
|
||||
/ipset
|
84
extensions/ipset/GNUmakefile.in
Normal file
84
extensions/ipset/GNUmakefile.in
Normal file
@@ -0,0 +1,84 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
top_srcdir := @top_srcdir@
|
||||
srcdir := @srcdir@
|
||||
abstop_srcdir := $(shell readlink -e ${top_srcdir})
|
||||
abssrcdir := $(shell readlink -e ${srcdir})
|
||||
|
||||
ifeq (${abstop_srcdir},)
|
||||
$(error Path resolution of ${top_srcdir} failed)
|
||||
endif
|
||||
ifeq (${abssrcdir},)
|
||||
$(error Path resolution of ${srcdir} failed)
|
||||
endif
|
||||
|
||||
prefix := @prefix@
|
||||
exec_prefix := @exec_prefix@
|
||||
sbindir := @sbindir@
|
||||
libdir := @libdir@
|
||||
libexecdir := @libexecdir@
|
||||
xtlibdir := @xtlibdir@
|
||||
kbuilddir := @kbuilddir@
|
||||
man8dir := @mandir@/man8
|
||||
|
||||
CC := @CC@
|
||||
CCLD := ${CC}
|
||||
CFLAGS := @CFLAGS@
|
||||
LDFLAGS := @LDFLAGS@
|
||||
regular_CFLAGS := @regular_CFLAGS@
|
||||
kinclude_CFLAGS := @kinclude_CFLAGS@
|
||||
xtables_CFLAGS := @xtables_CFLAGS@
|
||||
|
||||
AM_CFLAGS := ${regular_CFLAGS} -I${top_srcdir}/include ${xtables_CFLAGS} ${kinclude_CFLAGS} -DIPSET_LIB_DIR=\"${xtlibdir}\"
|
||||
AM_DEPFLAGS = -Wp,-MMD,$(@D)/.$(@F).d,-MT,$@
|
||||
|
||||
VU := 0
|
||||
am__1verbose_CC_0 = @echo " CC " $@;
|
||||
am__1verbose_CCLD_0 = @echo " CCLD " $@;
|
||||
am__1verbose_CC_1 = @echo " CC " $@ "<-" $<;
|
||||
am__1verbose_CCLD_1 = @echo " CCLD " $@ "<-" $^;
|
||||
am__verbose_CC = ${am__1verbose_CC_${VU}}
|
||||
am__verbose_CCLD = ${am__1verbose_CCLD_${VU}}
|
||||
|
||||
#
|
||||
# Building blocks
|
||||
#
|
||||
targets := $(addsuffix .so,$(addprefix libipset_, \
|
||||
iphash ipmap ipporthash ipportiphash ipportnethash iptree \
|
||||
iptreemap macipmap nethash portmap setlist))
|
||||
|
||||
.SECONDARY:
|
||||
|
||||
.PHONY: all install clean distclean FORCE
|
||||
|
||||
all: ipset ${targets}
|
||||
|
||||
install: all
|
||||
@mkdir -p "${DESTDIR}${sbindir}" "${DESTDIR}${xtlibdir}" "${DESTDIR}${man8dir}";
|
||||
install -pm0755 ipset "${DESTDIR}${sbindir}/";
|
||||
install -pm0755 ${targets} "${DESTDIR}${xtlibdir}/";
|
||||
install -pm0644 ipset.8 "${DESTDIR}${man8dir}/";
|
||||
|
||||
clean:
|
||||
rm -f *.oo *.so *.o ipset;
|
||||
|
||||
distclean: clean
|
||||
rm -f .*.d;
|
||||
|
||||
-include .*.d
|
||||
|
||||
|
||||
ipset: ipset.o
|
||||
${am__verbose_CCLD}${CCLD} ${AM_LDFLAGS} ${LDFLAGS} -o $@ $< -ldl -rdynamic;
|
||||
|
||||
#
|
||||
# Shared libraries
|
||||
#
|
||||
lib%.so: lib%.oo
|
||||
${am__verbose_CCLD}${CCLD} ${AM_LDFLAGS} -shared ${LDFLAGS} -o $@ $<;
|
||||
|
||||
libipset_%.oo: ${srcdir}/ipset_%.c
|
||||
${am__verbose_CC}${CC} ${AM_DEPFLAGS} ${AM_CFLAGS} -DPIC -fPIC ${CFLAGS} -o $@ -c $<;
|
||||
|
||||
%.o: %.c
|
||||
${am__verbose_CC}${CC} ${AM_DEPFLAGS} ${AM_CFLAGS} ${CFLAGS} -o $@ -c $<;
|
6
extensions/ipset/Kbuild
Normal file
6
extensions/ipset/Kbuild
Normal file
@@ -0,0 +1,6 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
obj-m += ipt_set.o ipt_SET.o
|
||||
obj-m += ip_set.o ip_set_ipmap.o ip_set_portmap.o ip_set_macipmap.o
|
||||
obj-m += ip_set_iphash.o ip_set_nethash.o ip_set_ipporthash.o
|
||||
obj-m += ip_set_iptree.o ip_set_iptreemap.o
|
2065
extensions/ipset/ip_set.c
Normal file
2065
extensions/ipset/ip_set.c
Normal file
File diff suppressed because it is too large
Load Diff
582
extensions/ipset/ip_set.h
Normal file
582
extensions/ipset/ip_set.h
Normal file
@@ -0,0 +1,582 @@
|
||||
#ifndef _IP_SET_H
|
||||
#define _IP_SET_H
|
||||
|
||||
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
|
||||
* Patrick Schaaf <bof@bof.de>
|
||||
* Martin Josefsson <gandalf@wlug.westbo.se>
|
||||
* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_IP_NF_SET_MAX
|
||||
/* from 2 to 65534 */
|
||||
# define CONFIG_IP_NF_SET_MAX 256
|
||||
#endif
|
||||
#ifndef CONFIG_IP_NF_SET_HASHSIZE
|
||||
# define CONFIG_IP_NF_SET_HASHSIZE 1024
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#define IP_SET_DEBUG
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A sockopt of such quality has hardly ever been seen before on the open
|
||||
* market! This little beauty, hardly ever used: above 64, so it's
|
||||
* traditionally used for firewalling, not touched (even once!) by the
|
||||
* 2.0, 2.2 and 2.4 kernels!
|
||||
*
|
||||
* Comes with its own certificate of authenticity, valid anywhere in the
|
||||
* Free world!
|
||||
*
|
||||
* Rusty, 19.4.2000
|
||||
*/
|
||||
#define SO_IP_SET 83
|
||||
|
||||
/*
|
||||
* Heavily modify by Joakim Axelsson 08.03.2002
|
||||
* - Made it more modulebased
|
||||
*
|
||||
* Additional heavy modifications by Jozsef Kadlecsik 22.02.2004
|
||||
* - bindings added
|
||||
* - in order to "deal with" backward compatibility, renamed to ipset
|
||||
*/
|
||||
|
||||
/*
|
||||
* Used so that the kernel module and ipset-binary can match their versions
|
||||
*/
|
||||
#define IP_SET_PROTOCOL_VERSION 2
|
||||
|
||||
#define IP_SET_MAXNAMELEN 32 /* set names and set typenames */
|
||||
|
||||
/* Lets work with our own typedef for representing an IP address.
|
||||
* We hope to make the code more portable, possibly to IPv6...
|
||||
*
|
||||
* The representation works in HOST byte order, because most set types
|
||||
* will perform arithmetic operations and compare operations.
|
||||
*
|
||||
* For now the type is an uint32_t.
|
||||
*
|
||||
* Make sure to ONLY use the functions when translating and parsing
|
||||
* in order to keep the host byte order and make it more portable:
|
||||
* parse_ip()
|
||||
* parse_mask()
|
||||
* parse_ipandmask()
|
||||
* ip_tostring()
|
||||
* (Joakim: where are they???)
|
||||
*/
|
||||
|
||||
typedef uint32_t ip_set_ip_t;
|
||||
|
||||
/* Sets are identified by an id in kernel space. Tweak with ip_set_id_t
|
||||
* and IP_SET_INVALID_ID if you want to increase the max number of sets.
|
||||
*/
|
||||
typedef uint16_t ip_set_id_t;
|
||||
|
||||
#define IP_SET_INVALID_ID 65535
|
||||
|
||||
/* How deep we follow bindings */
|
||||
#define IP_SET_MAX_BINDINGS 6
|
||||
|
||||
/*
|
||||
* Option flags for kernel operations (ipt_set_info)
|
||||
*/
|
||||
#define IPSET_SRC 0x01 /* Source match/add */
|
||||
#define IPSET_DST 0x02 /* Destination match/add */
|
||||
#define IPSET_MATCH_INV 0x04 /* Inverse matching */
|
||||
|
||||
/*
|
||||
* Set features
|
||||
*/
|
||||
#define IPSET_TYPE_IP 0x01 /* IP address type of set */
|
||||
#define IPSET_TYPE_PORT 0x02 /* Port type of set */
|
||||
#define IPSET_DATA_SINGLE 0x04 /* Single data storage */
|
||||
#define IPSET_DATA_DOUBLE 0x08 /* Double data storage */
|
||||
#define IPSET_DATA_TRIPLE 0x10 /* Triple data storage */
|
||||
#define IPSET_TYPE_IP1 0x20 /* IP address type of set */
|
||||
#define IPSET_TYPE_SETNAME 0x40 /* setname type of set */
|
||||
|
||||
/* Reserved keywords */
|
||||
#define IPSET_TOKEN_DEFAULT ":default:"
|
||||
#define IPSET_TOKEN_ALL ":all:"
|
||||
|
||||
/* SO_IP_SET operation constants, and their request struct types.
|
||||
*
|
||||
* Operation ids:
|
||||
* 0-99: commands with version checking
|
||||
* 100-199: add/del/test/bind/unbind
|
||||
* 200-299: list, save, restore
|
||||
*/
|
||||
|
||||
/* Single shot operations:
|
||||
* version, create, destroy, flush, rename and swap
|
||||
*
|
||||
* Sets are identified by name.
|
||||
*/
|
||||
|
||||
#define IP_SET_REQ_STD \
|
||||
unsigned op; \
|
||||
unsigned version; \
|
||||
char name[IP_SET_MAXNAMELEN]
|
||||
|
||||
#define IP_SET_OP_CREATE 0x00000001 /* Create a new (empty) set */
|
||||
struct ip_set_req_create {
|
||||
IP_SET_REQ_STD;
|
||||
char typename[IP_SET_MAXNAMELEN];
|
||||
};
|
||||
|
||||
#define IP_SET_OP_DESTROY 0x00000002 /* Remove a (empty) set */
|
||||
struct ip_set_req_std {
|
||||
IP_SET_REQ_STD;
|
||||
};
|
||||
|
||||
#define IP_SET_OP_FLUSH 0x00000003 /* Remove all IPs in a set */
|
||||
/* Uses ip_set_req_std */
|
||||
|
||||
#define IP_SET_OP_RENAME 0x00000004 /* Rename a set */
|
||||
/* Uses ip_set_req_create */
|
||||
|
||||
#define IP_SET_OP_SWAP 0x00000005 /* Swap two sets */
|
||||
/* Uses ip_set_req_create */
|
||||
|
||||
union ip_set_name_index {
|
||||
char name[IP_SET_MAXNAMELEN];
|
||||
ip_set_id_t index;
|
||||
};
|
||||
|
||||
#define IP_SET_OP_GET_BYNAME 0x00000006 /* Get set index by name */
|
||||
struct ip_set_req_get_set {
|
||||
unsigned op;
|
||||
unsigned version;
|
||||
union ip_set_name_index set;
|
||||
};
|
||||
|
||||
#define IP_SET_OP_GET_BYINDEX 0x00000007 /* Get set name by index */
|
||||
/* Uses ip_set_req_get_set */
|
||||
|
||||
#define IP_SET_OP_VERSION 0x00000100 /* Ask kernel version */
|
||||
struct ip_set_req_version {
|
||||
unsigned op;
|
||||
unsigned version;
|
||||
};
|
||||
|
||||
/* Double shots operations:
|
||||
* add, del, test, bind and unbind.
|
||||
*
|
||||
* First we query the kernel to get the index and type of the target set,
|
||||
* then issue the command. Validity of IP is checked in kernel in order
|
||||
* to minimalize sockopt operations.
|
||||
*/
|
||||
|
||||
/* Get minimal set data for add/del/test/bind/unbind IP */
|
||||
#define IP_SET_OP_ADT_GET 0x00000010 /* Get set and type */
|
||||
struct ip_set_req_adt_get {
|
||||
unsigned op;
|
||||
unsigned version;
|
||||
union ip_set_name_index set;
|
||||
char typename[IP_SET_MAXNAMELEN];
|
||||
};
|
||||
|
||||
#define IP_SET_REQ_BYINDEX \
|
||||
unsigned op; \
|
||||
ip_set_id_t index;
|
||||
|
||||
struct ip_set_req_adt {
|
||||
IP_SET_REQ_BYINDEX;
|
||||
};
|
||||
|
||||
#define IP_SET_OP_ADD_IP 0x00000101 /* Add an IP to a set */
|
||||
/* Uses ip_set_req_adt, with type specific addage */
|
||||
|
||||
#define IP_SET_OP_DEL_IP 0x00000102 /* Remove an IP from a set */
|
||||
/* Uses ip_set_req_adt, with type specific addage */
|
||||
|
||||
#define IP_SET_OP_TEST_IP 0x00000103 /* Test an IP in a set */
|
||||
/* Uses ip_set_req_adt, with type specific addage */
|
||||
|
||||
#define IP_SET_OP_BIND_SET 0x00000104 /* Bind an IP to a set */
|
||||
/* Uses ip_set_req_bind, with type specific addage */
|
||||
struct ip_set_req_bind {
|
||||
IP_SET_REQ_BYINDEX;
|
||||
char binding[IP_SET_MAXNAMELEN];
|
||||
};
|
||||
|
||||
#define IP_SET_OP_UNBIND_SET 0x00000105 /* Unbind an IP from a set */
|
||||
/* Uses ip_set_req_bind, with type speficic addage
|
||||
* index = 0 means unbinding for all sets */
|
||||
|
||||
#define IP_SET_OP_TEST_BIND_SET 0x00000106 /* Test binding an IP to a set */
|
||||
/* Uses ip_set_req_bind, with type specific addage */
|
||||
|
||||
/* Multiple shots operations: list, save, restore.
|
||||
*
|
||||
* - check kernel version and query the max number of sets
|
||||
* - get the basic information on all sets
|
||||
* and size required for the next step
|
||||
* - get actual set data: header, data, bindings
|
||||
*/
|
||||
|
||||
/* Get max_sets and the index of a queried set
|
||||
*/
|
||||
#define IP_SET_OP_MAX_SETS 0x00000020
|
||||
struct ip_set_req_max_sets {
|
||||
unsigned op;
|
||||
unsigned version;
|
||||
ip_set_id_t max_sets; /* max_sets */
|
||||
ip_set_id_t sets; /* real number of sets */
|
||||
union ip_set_name_index set; /* index of set if name used */
|
||||
};
|
||||
|
||||
/* Get the id and name of the sets plus size for next step */
|
||||
#define IP_SET_OP_LIST_SIZE 0x00000201
|
||||
#define IP_SET_OP_SAVE_SIZE 0x00000202
|
||||
struct ip_set_req_setnames {
|
||||
unsigned op;
|
||||
ip_set_id_t index; /* set to list/save */
|
||||
size_t size; /* size to get setdata/bindings */
|
||||
/* followed by sets number of struct ip_set_name_list */
|
||||
};
|
||||
|
||||
struct ip_set_name_list {
|
||||
char name[IP_SET_MAXNAMELEN];
|
||||
char typename[IP_SET_MAXNAMELEN];
|
||||
ip_set_id_t index;
|
||||
ip_set_id_t id;
|
||||
};
|
||||
|
||||
/* The actual list operation */
|
||||
#define IP_SET_OP_LIST 0x00000203
|
||||
struct ip_set_req_list {
|
||||
IP_SET_REQ_BYINDEX;
|
||||
/* sets number of struct ip_set_list in reply */
|
||||
};
|
||||
|
||||
struct ip_set_list {
|
||||
ip_set_id_t index;
|
||||
ip_set_id_t binding;
|
||||
u_int32_t ref;
|
||||
size_t header_size; /* Set header data of header_size */
|
||||
size_t members_size; /* Set members data of members_size */
|
||||
size_t bindings_size; /* Set bindings data of bindings_size */
|
||||
};
|
||||
|
||||
struct ip_set_hash_list {
|
||||
ip_set_ip_t ip;
|
||||
ip_set_id_t binding;
|
||||
};
|
||||
|
||||
/* The save operation */
|
||||
#define IP_SET_OP_SAVE 0x00000204
|
||||
/* Uses ip_set_req_list, in the reply replaced by
|
||||
* sets number of struct ip_set_save plus a marker
|
||||
* ip_set_save followed by ip_set_hash_save structures.
|
||||
*/
|
||||
struct ip_set_save {
|
||||
ip_set_id_t index;
|
||||
ip_set_id_t binding;
|
||||
size_t header_size; /* Set header data of header_size */
|
||||
size_t members_size; /* Set members data of members_size */
|
||||
};
|
||||
|
||||
/* At restoring, ip == 0 means default binding for the given set: */
|
||||
struct ip_set_hash_save {
|
||||
ip_set_ip_t ip;
|
||||
ip_set_id_t id;
|
||||
ip_set_id_t binding;
|
||||
};
|
||||
|
||||
/* The restore operation */
|
||||
#define IP_SET_OP_RESTORE 0x00000205
|
||||
/* Uses ip_set_req_setnames followed by ip_set_restore structures
|
||||
* plus a marker ip_set_restore, followed by ip_set_hash_save
|
||||
* structures.
|
||||
*/
|
||||
struct ip_set_restore {
|
||||
char name[IP_SET_MAXNAMELEN];
|
||||
char typename[IP_SET_MAXNAMELEN];
|
||||
ip_set_id_t index;
|
||||
size_t header_size; /* Create data of header_size */
|
||||
size_t members_size; /* Set members data of members_size */
|
||||
};
|
||||
|
||||
static inline int bitmap_bytes(ip_set_ip_t a, ip_set_ip_t b)
|
||||
{
|
||||
return 4 * ((((b - a + 8) / 8) + 3) / 4);
|
||||
}
|
||||
|
||||
/* General limit for the elements in a set */
|
||||
#define MAX_RANGE 0x0000FFFF
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include "ip_set_compat.h"
|
||||
#include "ip_set_malloc.h"
|
||||
|
||||
#define ip_set_printk(format, args...) \
|
||||
do { \
|
||||
printk("%s: %s: ", __FILE__, __FUNCTION__); \
|
||||
printk(format "\n" , ## args); \
|
||||
} while (0)
|
||||
|
||||
#if defined(IP_SET_DEBUG)
|
||||
#define DP(format, args...) \
|
||||
do { \
|
||||
printk("%s: %s (DBG): ", __FILE__, __FUNCTION__);\
|
||||
printk(format "\n" , ## args); \
|
||||
} while (0)
|
||||
#define IP_SET_ASSERT(x) \
|
||||
do { \
|
||||
if (!(x)) \
|
||||
printk("IP_SET_ASSERT: %s:%i(%s)\n", \
|
||||
__FILE__, __LINE__, __FUNCTION__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define DP(format, args...)
|
||||
#define IP_SET_ASSERT(x)
|
||||
#endif
|
||||
|
||||
struct ip_set;
|
||||
|
||||
/*
|
||||
* The ip_set_type definition - one per set type, e.g. "ipmap".
|
||||
*
|
||||
* Each individual set has a pointer, set->type, going to one
|
||||
* of these structures. Function pointers inside the structure implement
|
||||
* the real behaviour of the sets.
|
||||
*
|
||||
* If not mentioned differently, the implementation behind the function
|
||||
* pointers of a set_type, is expected to return 0 if ok, and a negative
|
||||
* errno (e.g. -EINVAL) on error.
|
||||
*/
|
||||
struct ip_set_type {
|
||||
struct list_head list; /* next in list of set types */
|
||||
|
||||
/* test for IP in set (kernel: iptables -m set src|dst)
|
||||
* return 0 if not in set, 1 if in set.
|
||||
*/
|
||||
int (*testip_kernel) (struct ip_set *set,
|
||||
const struct sk_buff * skb,
|
||||
ip_set_ip_t *ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index);
|
||||
|
||||
/* test for IP in set (userspace: ipset -T set IP)
|
||||
* return 0 if not in set, 1 if in set.
|
||||
*/
|
||||
int (*testip) (struct ip_set *set,
|
||||
const void *data, size_t size,
|
||||
ip_set_ip_t *ip);
|
||||
|
||||
/*
|
||||
* Size of the data structure passed by when
|
||||
* adding/deletin/testing an entry.
|
||||
*/
|
||||
size_t reqsize;
|
||||
|
||||
/* Add IP into set (userspace: ipset -A set IP)
|
||||
* Return -EEXIST if the address is already in the set,
|
||||
* and -ERANGE if the address lies outside the set bounds.
|
||||
* If the address was not already in the set, 0 is returned.
|
||||
*/
|
||||
int (*addip) (struct ip_set *set,
|
||||
const void *data, size_t size,
|
||||
ip_set_ip_t *ip);
|
||||
|
||||
/* Add IP into set (kernel: iptables ... -j SET set src|dst)
|
||||
* Return -EEXIST if the address is already in the set,
|
||||
* and -ERANGE if the address lies outside the set bounds.
|
||||
* If the address was not already in the set, 0 is returned.
|
||||
*/
|
||||
int (*addip_kernel) (struct ip_set *set,
|
||||
const struct sk_buff * skb,
|
||||
ip_set_ip_t *ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index);
|
||||
|
||||
/* remove IP from set (userspace: ipset -D set --entry x)
|
||||
* Return -EEXIST if the address is NOT in the set,
|
||||
* and -ERANGE if the address lies outside the set bounds.
|
||||
* If the address really was in the set, 0 is returned.
|
||||
*/
|
||||
int (*delip) (struct ip_set *set,
|
||||
const void *data, size_t size,
|
||||
ip_set_ip_t *ip);
|
||||
|
||||
/* remove IP from set (kernel: iptables ... -j SET --entry x)
|
||||
* Return -EEXIST if the address is NOT in the set,
|
||||
* and -ERANGE if the address lies outside the set bounds.
|
||||
* If the address really was in the set, 0 is returned.
|
||||
*/
|
||||
int (*delip_kernel) (struct ip_set *set,
|
||||
const struct sk_buff * skb,
|
||||
ip_set_ip_t *ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index);
|
||||
|
||||
/* new set creation - allocated type specific items
|
||||
*/
|
||||
int (*create) (struct ip_set *set,
|
||||
const void *data, size_t size);
|
||||
|
||||
/* retry the operation after successfully tweaking the set
|
||||
*/
|
||||
int (*retry) (struct ip_set *set);
|
||||
|
||||
/* set destruction - free type specific items
|
||||
* There is no return value.
|
||||
* Can be called only when child sets are destroyed.
|
||||
*/
|
||||
void (*destroy) (struct ip_set *set);
|
||||
|
||||
/* set flushing - reset all bits in the set, or something similar.
|
||||
* There is no return value.
|
||||
*/
|
||||
void (*flush) (struct ip_set *set);
|
||||
|
||||
/* Listing: size needed for header
|
||||
*/
|
||||
size_t header_size;
|
||||
|
||||
/* Listing: Get the header
|
||||
*
|
||||
* Fill in the information in "data".
|
||||
* This function is always run after list_header_size() under a
|
||||
* writelock on the set. Therefor is the length of "data" always
|
||||
* correct.
|
||||
*/
|
||||
void (*list_header) (const struct ip_set *set,
|
||||
void *data);
|
||||
|
||||
/* Listing: Get the size for the set members
|
||||
*/
|
||||
int (*list_members_size) (const struct ip_set *set);
|
||||
|
||||
/* Listing: Get the set members
|
||||
*
|
||||
* Fill in the information in "data".
|
||||
* This function is always run after list_member_size() under a
|
||||
* writelock on the set. Therefor is the length of "data" always
|
||||
* correct.
|
||||
*/
|
||||
void (*list_members) (const struct ip_set *set,
|
||||
void *data);
|
||||
|
||||
char typename[IP_SET_MAXNAMELEN];
|
||||
unsigned char features;
|
||||
int protocol_version;
|
||||
|
||||
/* Set this to THIS_MODULE if you are a module, otherwise NULL */
|
||||
struct module *me;
|
||||
};
|
||||
|
||||
extern int ip_set_register_set_type(struct ip_set_type *set_type);
|
||||
extern void ip_set_unregister_set_type(struct ip_set_type *set_type);
|
||||
|
||||
/* A generic ipset */
|
||||
struct ip_set {
|
||||
char name[IP_SET_MAXNAMELEN]; /* the name of the set */
|
||||
rwlock_t lock; /* lock for concurrency control */
|
||||
ip_set_id_t id; /* set id for swapping */
|
||||
ip_set_id_t binding; /* default binding for the set */
|
||||
atomic_t ref; /* in kernel and in hash references */
|
||||
struct ip_set_type *type; /* the set types */
|
||||
void *data; /* pooltype specific data */
|
||||
};
|
||||
|
||||
/* Structure to bind set elements to sets */
|
||||
struct ip_set_hash {
|
||||
struct list_head list; /* list of clashing entries in hash */
|
||||
ip_set_ip_t ip; /* ip from set */
|
||||
ip_set_id_t id; /* set id */
|
||||
ip_set_id_t binding; /* set we bind the element to */
|
||||
};
|
||||
|
||||
/* register and unregister set references */
|
||||
extern ip_set_id_t ip_set_get_byname(const char name[IP_SET_MAXNAMELEN]);
|
||||
extern ip_set_id_t ip_set_get_byindex(ip_set_id_t index);
|
||||
extern void ip_set_put_byindex(ip_set_id_t index);
|
||||
extern ip_set_id_t ip_set_id(ip_set_id_t index);
|
||||
extern ip_set_id_t __ip_set_get_byname(const char name[IP_SET_MAXNAMELEN],
|
||||
struct ip_set **set);
|
||||
extern void __ip_set_put_byindex(ip_set_id_t index);
|
||||
|
||||
/* API for iptables set match, and SET target */
|
||||
extern int ip_set_addip_kernel(ip_set_id_t id,
|
||||
const struct sk_buff *skb,
|
||||
const u_int32_t *flags);
|
||||
extern int ip_set_delip_kernel(ip_set_id_t id,
|
||||
const struct sk_buff *skb,
|
||||
const u_int32_t *flags);
|
||||
extern int ip_set_testip_kernel(ip_set_id_t id,
|
||||
const struct sk_buff *skb,
|
||||
const u_int32_t *flags);
|
||||
|
||||
/* Macros to generate functions */
|
||||
|
||||
#define STRUCT(pre, type) CONCAT2(pre, type)
|
||||
#define CONCAT2(pre, type) struct pre##type
|
||||
|
||||
#define FNAME(pre, mid, post) CONCAT3(pre, mid, post)
|
||||
#define CONCAT3(pre, mid, post) pre##mid##post
|
||||
|
||||
#define UADT0(type, adt, args...) \
|
||||
static int \
|
||||
FNAME(type,_u,adt)(struct ip_set *set, const void *data, size_t size, \
|
||||
ip_set_ip_t *hash_ip) \
|
||||
{ \
|
||||
const STRUCT(ip_set_req_,type) *req = data; \
|
||||
\
|
||||
return FNAME(type,_,adt)(set, hash_ip , ## args); \
|
||||
}
|
||||
|
||||
#define UADT(type, adt, args...) \
|
||||
UADT0(type, adt, req->ip , ## args)
|
||||
|
||||
#define KADT(type, adt, getfn, args...) \
|
||||
static int \
|
||||
FNAME(type,_k,adt)(struct ip_set *set, \
|
||||
const struct sk_buff *skb, \
|
||||
ip_set_ip_t *hash_ip, \
|
||||
const u_int32_t *flags, \
|
||||
unsigned char index) \
|
||||
{ \
|
||||
ip_set_ip_t ip = getfn(skb, flags[index]); \
|
||||
\
|
||||
KADT_CONDITION \
|
||||
return FNAME(type,_,adt)(set, hash_ip, ip , ##args); \
|
||||
}
|
||||
|
||||
#define REGISTER_MODULE(type) \
|
||||
static int __init ip_set_##type##_init(void) \
|
||||
{ \
|
||||
init_max_page_size(); \
|
||||
return ip_set_register_set_type(&ip_set_##type); \
|
||||
} \
|
||||
\
|
||||
static void __exit ip_set_##type##_fini(void) \
|
||||
{ \
|
||||
/* FIXME: possible race with ip_set_create() */ \
|
||||
ip_set_unregister_set_type(&ip_set_##type); \
|
||||
} \
|
||||
\
|
||||
module_init(ip_set_##type##_init); \
|
||||
module_exit(ip_set_##type##_fini);
|
||||
|
||||
/* Common functions */
|
||||
|
||||
static inline ip_set_ip_t
|
||||
ipaddr(const struct sk_buff *skb, u_int32_t flag)
|
||||
{
|
||||
return ntohl(flag & IPSET_SRC ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr);
|
||||
}
|
||||
|
||||
#define jhash_ip(map, i, ip) jhash_1word(ip, *(map->initval + i))
|
||||
|
||||
#define pack_ip_port(map, ip, port) \
|
||||
(port + ((ip - ((map)->first_ip)) << 16))
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /*_IP_SET_H*/
|
121
extensions/ipset/ip_set_bitmaps.h
Normal file
121
extensions/ipset/ip_set_bitmaps.h
Normal file
@@ -0,0 +1,121 @@
|
||||
#ifndef __IP_SET_BITMAPS_H
|
||||
#define __IP_SET_BITMAPS_H
|
||||
|
||||
/* Macros to generate functions */
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#define BITMAP_CREATE(type) \
|
||||
static int \
|
||||
type##_create(struct ip_set *set, const void *data, size_t size) \
|
||||
{ \
|
||||
int newbytes; \
|
||||
const struct ip_set_req_##type##_create *req = data; \
|
||||
struct ip_set_##type *map; \
|
||||
\
|
||||
if (req->from > req->to) { \
|
||||
DP("bad range"); \
|
||||
return -ENOEXEC; \
|
||||
} \
|
||||
\
|
||||
map = kmalloc(sizeof(struct ip_set_##type), GFP_KERNEL); \
|
||||
if (!map) { \
|
||||
DP("out of memory for %d bytes", \
|
||||
sizeof(struct ip_set_#type)); \
|
||||
return -ENOMEM; \
|
||||
} \
|
||||
map->first_ip = req->from; \
|
||||
map->last_ip = req->to; \
|
||||
\
|
||||
newbytes = __##type##_create(req, map); \
|
||||
if (newbytes < 0) { \
|
||||
kfree(map); \
|
||||
return newbytes; \
|
||||
} \
|
||||
\
|
||||
map->size = newbytes; \
|
||||
map->members = ip_set_malloc(newbytes); \
|
||||
if (!map->members) { \
|
||||
DP("out of memory for %d bytes", newbytes); \
|
||||
kfree(map); \
|
||||
return -ENOMEM; \
|
||||
} \
|
||||
memset(map->members, 0, newbytes); \
|
||||
\
|
||||
set->data = map; \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define BITMAP_DESTROY(type) \
|
||||
static void \
|
||||
type##_destroy(struct ip_set *set) \
|
||||
{ \
|
||||
struct ip_set_##type *map = set->data; \
|
||||
\
|
||||
ip_set_free(map->members, map->size); \
|
||||
kfree(map); \
|
||||
\
|
||||
set->data = NULL; \
|
||||
}
|
||||
|
||||
#define BITMAP_FLUSH(type) \
|
||||
static void \
|
||||
type##_flush(struct ip_set *set) \
|
||||
{ \
|
||||
struct ip_set_##type *map = set->data; \
|
||||
memset(map->members, 0, map->size); \
|
||||
}
|
||||
|
||||
#define BITMAP_LIST_HEADER(type) \
|
||||
static void \
|
||||
type##_list_header(const struct ip_set *set, void *data) \
|
||||
{ \
|
||||
const struct ip_set_##type *map = set->data; \
|
||||
struct ip_set_req_##type##_create *header = data; \
|
||||
\
|
||||
header->from = map->first_ip; \
|
||||
header->to = map->last_ip; \
|
||||
__##type##_list_header(map, header); \
|
||||
}
|
||||
|
||||
#define BITMAP_LIST_MEMBERS_SIZE(type) \
|
||||
static int \
|
||||
type##_list_members_size(const struct ip_set *set) \
|
||||
{ \
|
||||
const struct ip_set_##type *map = set->data; \
|
||||
\
|
||||
return map->size; \
|
||||
}
|
||||
|
||||
#define BITMAP_LIST_MEMBERS(type) \
|
||||
static void \
|
||||
type##_list_members(const struct ip_set *set, void *data) \
|
||||
{ \
|
||||
const struct ip_set_##type *map = set->data; \
|
||||
\
|
||||
memcpy(data, map->members, map->size); \
|
||||
}
|
||||
|
||||
#define IP_SET_TYPE(type, __features) \
|
||||
struct ip_set_type ip_set_##type = { \
|
||||
.typename = #type, \
|
||||
.features = __features, \
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION, \
|
||||
.create = &type##_create, \
|
||||
.destroy = &type##_destroy, \
|
||||
.flush = &type##_flush, \
|
||||
.reqsize = sizeof(struct ip_set_req_##type), \
|
||||
.addip = &type##_uadd, \
|
||||
.addip_kernel = &type##_kadd, \
|
||||
.delip = &type##_udel, \
|
||||
.delip_kernel = &type##_kdel, \
|
||||
.testip = &type##_utest, \
|
||||
.testip_kernel = &type##_ktest, \
|
||||
.header_size = sizeof(struct ip_set_req_##type##_create),\
|
||||
.list_header = &type##_list_header, \
|
||||
.list_members_size = &type##_list_members_size, \
|
||||
.list_members = &type##_list_members, \
|
||||
.me = THIS_MODULE, \
|
||||
};
|
||||
#endif /* __KERNEL */
|
||||
|
||||
#endif /* __IP_SET_BITMAPS_H */
|
70
extensions/ipset/ip_set_compat.h
Normal file
70
extensions/ipset/ip_set_compat.h
Normal file
@@ -0,0 +1,70 @@
|
||||
#ifndef _IP_SET_COMPAT_H
|
||||
#define _IP_SET_COMPAT_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/version.h>
|
||||
|
||||
/* Arrgh */
|
||||
#ifdef MODULE
|
||||
#define __MOD_INC(foo) __MOD_INC_USE_COUNT(foo)
|
||||
#define __MOD_DEC(foo) __MOD_DEC_USE_COUNT(foo)
|
||||
#else
|
||||
#define __MOD_INC(foo) 1
|
||||
#define __MOD_DEC(foo)
|
||||
#endif
|
||||
|
||||
/* Backward compatibility */
|
||||
#ifndef __nocast
|
||||
#define __nocast
|
||||
#endif
|
||||
#ifndef __bitwise__
|
||||
#define __bitwise__
|
||||
#endif
|
||||
|
||||
/* Compatibility glue code */
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
|
||||
#include <linux/interrupt.h>
|
||||
#define DEFINE_RWLOCK(x) rwlock_t x = RW_LOCK_UNLOCKED
|
||||
#define try_module_get(x) __MOD_INC(x)
|
||||
#define module_put(x) __MOD_DEC(x)
|
||||
#define __clear_bit(nr, addr) clear_bit(nr, addr)
|
||||
#define __set_bit(nr, addr) set_bit(nr, addr)
|
||||
#define __test_and_set_bit(nr, addr) test_and_set_bit(nr, addr)
|
||||
#define __test_and_clear_bit(nr, addr) test_and_clear_bit(nr, addr)
|
||||
|
||||
typedef unsigned __bitwise__ gfp_t;
|
||||
|
||||
static inline void *kzalloc(size_t size, gfp_t flags)
|
||||
{
|
||||
void *data = kmalloc(size, flags);
|
||||
|
||||
if (data)
|
||||
memset(data, 0, size);
|
||||
|
||||
return data;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
|
||||
#define __KMEM_CACHE_T__ kmem_cache_t
|
||||
#else
|
||||
#define __KMEM_CACHE_T__ struct kmem_cache
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
|
||||
#define ip_hdr(skb) ((skb)->nh.iph)
|
||||
#define skb_mac_header(skb) ((skb)->mac.raw)
|
||||
#define eth_hdr(skb) ((struct ethhdr *)skb_mac_header(skb))
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
|
||||
#define KMEM_CACHE_CREATE(name, size) \
|
||||
kmem_cache_create(name, size, 0, 0, NULL, NULL)
|
||||
#else
|
||||
#define KMEM_CACHE_CREATE(name, size) \
|
||||
kmem_cache_create(name, size, 0, 0, NULL)
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _IP_SET_COMPAT_H */
|
48
extensions/ipset/ip_set_getport.h
Normal file
48
extensions/ipset/ip_set_getport.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef _IP_SET_GETPORT_H
|
||||
#define _IP_SET_GETPORT_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define INVALID_PORT (MAX_RANGE + 1)
|
||||
|
||||
/* We must handle non-linear skbs */
|
||||
static inline ip_set_ip_t
|
||||
get_port(const struct sk_buff *skb, u_int32_t flags)
|
||||
{
|
||||
struct iphdr *iph = ip_hdr(skb);
|
||||
u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET;
|
||||
switch (iph->protocol) {
|
||||
case IPPROTO_TCP: {
|
||||
struct tcphdr tcph;
|
||||
|
||||
/* See comments at tcp_match in ip_tables.c */
|
||||
if (offset)
|
||||
return INVALID_PORT;
|
||||
|
||||
if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &tcph, sizeof(tcph)) < 0)
|
||||
/* No choice either */
|
||||
return INVALID_PORT;
|
||||
|
||||
return ntohs(flags & IPSET_SRC ?
|
||||
tcph.source : tcph.dest);
|
||||
}
|
||||
case IPPROTO_UDP: {
|
||||
struct udphdr udph;
|
||||
|
||||
if (offset)
|
||||
return INVALID_PORT;
|
||||
|
||||
if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &udph, sizeof(udph)) < 0)
|
||||
/* No choice either */
|
||||
return INVALID_PORT;
|
||||
|
||||
return ntohs(flags & IPSET_SRC ?
|
||||
udph.source : udph.dest);
|
||||
}
|
||||
default:
|
||||
return INVALID_PORT;
|
||||
}
|
||||
}
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /*_IP_SET_GETPORT_H*/
|
304
extensions/ipset/ip_set_hashes.h
Normal file
304
extensions/ipset/ip_set_hashes.h
Normal file
@@ -0,0 +1,304 @@
|
||||
#ifndef __IP_SET_HASHES_H
|
||||
#define __IP_SET_HASHES_H
|
||||
|
||||
#define initval_t uint32_t
|
||||
|
||||
/* Macros to generate functions */
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#define HASH_RETRY0(type, dtype, cond) \
|
||||
static int \
|
||||
type##_retry(struct ip_set *set) \
|
||||
{ \
|
||||
struct ip_set_##type *map = set->data, *tmp; \
|
||||
dtype *elem; \
|
||||
void *members; \
|
||||
u_int32_t i, hashsize = map->hashsize; \
|
||||
int res; \
|
||||
\
|
||||
if (map->resize == 0) \
|
||||
return -ERANGE; \
|
||||
\
|
||||
again: \
|
||||
res = 0; \
|
||||
\
|
||||
/* Calculate new hash size */ \
|
||||
hashsize += (hashsize * map->resize)/100; \
|
||||
if (hashsize == map->hashsize) \
|
||||
hashsize++; \
|
||||
\
|
||||
ip_set_printk("rehashing of set %s triggered: " \
|
||||
"hashsize grows from %u to %u", \
|
||||
set->name, map->hashsize, hashsize); \
|
||||
\
|
||||
tmp = kmalloc(sizeof(struct ip_set_##type) \
|
||||
+ map->probes * sizeof(initval_t), GFP_ATOMIC); \
|
||||
if (!tmp) { \
|
||||
DP("out of memory for %d bytes", \
|
||||
sizeof(struct ip_set_##type) \
|
||||
+ map->probes * sizeof(initval_t)); \
|
||||
return -ENOMEM; \
|
||||
} \
|
||||
tmp->members = harray_malloc(hashsize, sizeof(dtype), GFP_ATOMIC);\
|
||||
if (!tmp->members) { \
|
||||
DP("out of memory for %d bytes", hashsize * sizeof(dtype));\
|
||||
kfree(tmp); \
|
||||
return -ENOMEM; \
|
||||
} \
|
||||
tmp->hashsize = hashsize; \
|
||||
tmp->elements = 0; \
|
||||
tmp->probes = map->probes; \
|
||||
tmp->resize = map->resize; \
|
||||
memcpy(tmp->initval, map->initval, map->probes * sizeof(initval_t));\
|
||||
__##type##_retry(tmp, map); \
|
||||
\
|
||||
write_lock_bh(&set->lock); \
|
||||
map = set->data; /* Play safe */ \
|
||||
for (i = 0; i < map->hashsize && res == 0; i++) { \
|
||||
elem = HARRAY_ELEM(map->members, dtype *, i); \
|
||||
if (cond) \
|
||||
res = __##type##_add(tmp, elem); \
|
||||
} \
|
||||
if (res) { \
|
||||
/* Failure, try again */ \
|
||||
write_unlock_bh(&set->lock); \
|
||||
harray_free(tmp->members); \
|
||||
kfree(tmp); \
|
||||
goto again; \
|
||||
} \
|
||||
\
|
||||
/* Success at resizing! */ \
|
||||
members = map->members; \
|
||||
\
|
||||
map->hashsize = tmp->hashsize; \
|
||||
map->members = tmp->members; \
|
||||
write_unlock_bh(&set->lock); \
|
||||
\
|
||||
harray_free(members); \
|
||||
kfree(tmp); \
|
||||
\
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define HASH_RETRY(type, dtype) \
|
||||
HASH_RETRY0(type, dtype, *elem)
|
||||
|
||||
#define HASH_RETRY2(type, dtype) \
|
||||
HASH_RETRY0(type, dtype, elem->ip || elem->ip1)
|
||||
|
||||
#define HASH_CREATE(type, dtype) \
|
||||
static int \
|
||||
type##_create(struct ip_set *set, const void *data, size_t size) \
|
||||
{ \
|
||||
const struct ip_set_req_##type##_create *req = data; \
|
||||
struct ip_set_##type *map; \
|
||||
uint16_t i; \
|
||||
\
|
||||
if (req->hashsize < 1) { \
|
||||
ip_set_printk("hashsize too small"); \
|
||||
return -ENOEXEC; \
|
||||
} \
|
||||
\
|
||||
if (req->probes < 1) { \
|
||||
ip_set_printk("probes too small"); \
|
||||
return -ENOEXEC; \
|
||||
} \
|
||||
\
|
||||
map = kmalloc(sizeof(struct ip_set_##type) \
|
||||
+ req->probes * sizeof(initval_t), GFP_KERNEL); \
|
||||
if (!map) { \
|
||||
DP("out of memory for %d bytes", \
|
||||
sizeof(struct ip_set_##type) \
|
||||
+ req->probes * sizeof(initval_t)); \
|
||||
return -ENOMEM; \
|
||||
} \
|
||||
for (i = 0; i < req->probes; i++) \
|
||||
get_random_bytes(((initval_t *) map->initval)+i, 4); \
|
||||
map->elements = 0; \
|
||||
map->hashsize = req->hashsize; \
|
||||
map->probes = req->probes; \
|
||||
map->resize = req->resize; \
|
||||
if (__##type##_create(req, map)) { \
|
||||
kfree(map); \
|
||||
return -ENOEXEC; \
|
||||
} \
|
||||
map->members = harray_malloc(map->hashsize, sizeof(dtype), GFP_KERNEL);\
|
||||
if (!map->members) { \
|
||||
DP("out of memory for %d bytes", map->hashsize * sizeof(dtype));\
|
||||
kfree(map); \
|
||||
return -ENOMEM; \
|
||||
} \
|
||||
\
|
||||
set->data = map; \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define HASH_DESTROY(type) \
|
||||
static void \
|
||||
type##_destroy(struct ip_set *set) \
|
||||
{ \
|
||||
struct ip_set_##type *map = set->data; \
|
||||
\
|
||||
harray_free(map->members); \
|
||||
kfree(map); \
|
||||
\
|
||||
set->data = NULL; \
|
||||
}
|
||||
|
||||
#define HASH_FLUSH(type, dtype) \
|
||||
static void \
|
||||
type##_flush(struct ip_set *set) \
|
||||
{ \
|
||||
struct ip_set_##type *map = set->data; \
|
||||
harray_flush(map->members, map->hashsize, sizeof(dtype)); \
|
||||
map->elements = 0; \
|
||||
}
|
||||
|
||||
#define HASH_FLUSH_CIDR(type, dtype) \
|
||||
static void \
|
||||
type##_flush(struct ip_set *set) \
|
||||
{ \
|
||||
struct ip_set_##type *map = set->data; \
|
||||
harray_flush(map->members, map->hashsize, sizeof(dtype)); \
|
||||
memset(map->cidr, 0, sizeof(map->cidr)); \
|
||||
memset(map->nets, 0, sizeof(map->nets)); \
|
||||
map->elements = 0; \
|
||||
}
|
||||
|
||||
#define HASH_LIST_HEADER(type) \
|
||||
static void \
|
||||
type##_list_header(const struct ip_set *set, void *data) \
|
||||
{ \
|
||||
const struct ip_set_##type *map = set->data; \
|
||||
struct ip_set_req_##type##_create *header = data; \
|
||||
\
|
||||
header->hashsize = map->hashsize; \
|
||||
header->probes = map->probes; \
|
||||
header->resize = map->resize; \
|
||||
__##type##_list_header(map, header); \
|
||||
}
|
||||
|
||||
#define HASH_LIST_MEMBERS_SIZE(type, dtype) \
|
||||
static int \
|
||||
type##_list_members_size(const struct ip_set *set) \
|
||||
{ \
|
||||
const struct ip_set_##type *map = set->data; \
|
||||
\
|
||||
return (map->hashsize * sizeof(dtype)); \
|
||||
}
|
||||
|
||||
#define HASH_LIST_MEMBERS(type, dtype) \
|
||||
static void \
|
||||
type##_list_members(const struct ip_set *set, void *data) \
|
||||
{ \
|
||||
const struct ip_set_##type *map = set->data; \
|
||||
dtype *elem; \
|
||||
uint32_t i; \
|
||||
\
|
||||
for (i = 0; i < map->hashsize; i++) { \
|
||||
elem = HARRAY_ELEM(map->members, dtype *, i); \
|
||||
((dtype *)data)[i] = *elem; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define HASH_LIST_MEMBERS_MEMCPY(type, dtype) \
|
||||
static void \
|
||||
type##_list_members(const struct ip_set *set, void *data) \
|
||||
{ \
|
||||
const struct ip_set_##type *map = set->data; \
|
||||
dtype *elem; \
|
||||
uint32_t i; \
|
||||
\
|
||||
for (i = 0; i < map->hashsize; i++) { \
|
||||
elem = HARRAY_ELEM(map->members, dtype *, i); \
|
||||
memcpy((((dtype *)data)+i), elem, sizeof(dtype)); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define IP_SET_RTYPE(type, __features) \
|
||||
struct ip_set_type ip_set_##type = { \
|
||||
.typename = #type, \
|
||||
.features = __features, \
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION, \
|
||||
.create = &type##_create, \
|
||||
.retry = &type##_retry, \
|
||||
.destroy = &type##_destroy, \
|
||||
.flush = &type##_flush, \
|
||||
.reqsize = sizeof(struct ip_set_req_##type), \
|
||||
.addip = &type##_uadd, \
|
||||
.addip_kernel = &type##_kadd, \
|
||||
.delip = &type##_udel, \
|
||||
.delip_kernel = &type##_kdel, \
|
||||
.testip = &type##_utest, \
|
||||
.testip_kernel = &type##_ktest, \
|
||||
.header_size = sizeof(struct ip_set_req_##type##_create),\
|
||||
.list_header = &type##_list_header, \
|
||||
.list_members_size = &type##_list_members_size, \
|
||||
.list_members = &type##_list_members, \
|
||||
.me = THIS_MODULE, \
|
||||
};
|
||||
|
||||
/* Helper functions */
|
||||
static inline void
|
||||
add_cidr_size(uint8_t *cidr, uint8_t size)
|
||||
{
|
||||
uint8_t next;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 30 && cidr[i]; i++) {
|
||||
if (cidr[i] < size) {
|
||||
next = cidr[i];
|
||||
cidr[i] = size;
|
||||
size = next;
|
||||
}
|
||||
}
|
||||
if (i < 30)
|
||||
cidr[i] = size;
|
||||
}
|
||||
|
||||
static inline void
|
||||
del_cidr_size(uint8_t *cidr, uint8_t size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 29 && cidr[i]; i++) {
|
||||
if (cidr[i] == size)
|
||||
cidr[i] = size = cidr[i+1];
|
||||
}
|
||||
cidr[29] = 0;
|
||||
}
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#endif /* __KERNEL */
|
||||
|
||||
#ifndef UINT16_MAX
|
||||
#define UINT16_MAX 65535
|
||||
#endif
|
||||
|
||||
static unsigned char shifts[] = {255, 253, 249, 241, 225, 193, 129, 1};
|
||||
|
||||
static inline ip_set_ip_t
|
||||
pack_ip_cidr(ip_set_ip_t ip, unsigned char cidr)
|
||||
{
|
||||
ip_set_ip_t addr, *paddr = &addr;
|
||||
unsigned char n, t, *a;
|
||||
|
||||
addr = htonl(ip & (0xFFFFFFFF << (32 - (cidr))));
|
||||
#ifdef __KERNEL__
|
||||
DP("ip:%u.%u.%u.%u/%u", NIPQUAD(addr), cidr);
|
||||
#endif
|
||||
n = cidr / 8;
|
||||
t = cidr % 8;
|
||||
a = &((unsigned char *)paddr)[n];
|
||||
*a = *a /(1 << (8 - t)) + shifts[t];
|
||||
#ifdef __KERNEL__
|
||||
DP("n: %u, t: %u, a: %u", n, t, *a);
|
||||
DP("ip:%u.%u.%u.%u/%u, %u.%u.%u.%u",
|
||||
HIPQUAD(ip), cidr, NIPQUAD(addr));
|
||||
#endif
|
||||
|
||||
return ntohl(addr);
|
||||
}
|
||||
|
||||
|
||||
#endif /* __IP_SET_HASHES_H */
|
164
extensions/ipset/ip_set_iphash.c
Normal file
164
extensions/ipset/ip_set_iphash.c
Normal file
@@ -0,0 +1,164 @@
|
||||
/* Copyright (C) 2003-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an ip hash set */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/jhash.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include <net/ip.h>
|
||||
|
||||
#include "ip_set_iphash.h"
|
||||
|
||||
static int limit = MAX_RANGE;
|
||||
|
||||
static inline __u32
|
||||
iphash_id(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_iphash *map = set->data;
|
||||
__u32 id;
|
||||
u_int16_t i;
|
||||
ip_set_ip_t *elem;
|
||||
|
||||
*hash_ip = ip & map->netmask;
|
||||
DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u, %u.%u.%u.%u",
|
||||
set->name, HIPQUAD(ip), HIPQUAD(*hash_ip), HIPQUAD(map->netmask));
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
id = jhash_ip(map, i, *hash_ip) % map->hashsize;
|
||||
DP("hash key: %u", id);
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
|
||||
if (*elem == *hash_ip)
|
||||
return id;
|
||||
/* No shortcut at testing - there can be deleted
|
||||
* entries. */
|
||||
}
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
static inline int
|
||||
iphash_test(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
return (ip && iphash_id(set, hash_ip, ip) != UINT_MAX);
|
||||
}
|
||||
|
||||
#define KADT_CONDITION
|
||||
|
||||
UADT(iphash, test)
|
||||
KADT(iphash, test, ipaddr)
|
||||
|
||||
static inline int
|
||||
__iphash_add(struct ip_set_iphash *map, ip_set_ip_t *ip)
|
||||
{
|
||||
__u32 probe;
|
||||
u_int16_t i;
|
||||
ip_set_ip_t *elem;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
probe = jhash_ip(map, i, *ip) % map->hashsize;
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe);
|
||||
if (*elem == *ip)
|
||||
return -EEXIST;
|
||||
if (!*elem) {
|
||||
*elem = *ip;
|
||||
map->elements++;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Trigger rehashing */
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
static inline int
|
||||
iphash_add(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_iphash *map = set->data;
|
||||
|
||||
if (!ip || map->elements >= limit)
|
||||
return -ERANGE;
|
||||
|
||||
*hash_ip = ip & map->netmask;
|
||||
|
||||
return __iphash_add(map, hash_ip);
|
||||
}
|
||||
|
||||
UADT(iphash, add)
|
||||
KADT(iphash, add, ipaddr)
|
||||
|
||||
static inline void
|
||||
__iphash_retry(struct ip_set_iphash *tmp, struct ip_set_iphash *map)
|
||||
{
|
||||
tmp->netmask = map->netmask;
|
||||
}
|
||||
|
||||
HASH_RETRY(iphash, ip_set_ip_t)
|
||||
|
||||
static inline int
|
||||
iphash_del(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_iphash *map = set->data;
|
||||
ip_set_ip_t id, *elem;
|
||||
|
||||
if (!ip)
|
||||
return -ERANGE;
|
||||
|
||||
id = iphash_id(set, hash_ip, ip);
|
||||
if (id == UINT_MAX)
|
||||
return -EEXIST;
|
||||
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
|
||||
*elem = 0;
|
||||
map->elements--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UADT(iphash, del)
|
||||
KADT(iphash, del, ipaddr)
|
||||
|
||||
static inline int
|
||||
__iphash_create(const struct ip_set_req_iphash_create *req,
|
||||
struct ip_set_iphash *map)
|
||||
{
|
||||
map->netmask = req->netmask;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
HASH_CREATE(iphash, ip_set_ip_t)
|
||||
HASH_DESTROY(iphash)
|
||||
|
||||
HASH_FLUSH(iphash, ip_set_ip_t)
|
||||
|
||||
static inline void
|
||||
__iphash_list_header(const struct ip_set_iphash *map,
|
||||
struct ip_set_req_iphash_create *header)
|
||||
{
|
||||
header->netmask = map->netmask;
|
||||
}
|
||||
|
||||
HASH_LIST_HEADER(iphash)
|
||||
HASH_LIST_MEMBERS_SIZE(iphash, ip_set_ip_t)
|
||||
HASH_LIST_MEMBERS(iphash, ip_set_ip_t)
|
||||
|
||||
IP_SET_RTYPE(iphash, IPSET_TYPE_IP | IPSET_DATA_SINGLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("iphash type of IP sets");
|
||||
module_param(limit, int, 0600);
|
||||
MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
|
||||
|
||||
REGISTER_MODULE(iphash)
|
30
extensions/ipset/ip_set_iphash.h
Normal file
30
extensions/ipset/ip_set_iphash.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef __IP_SET_IPHASH_H
|
||||
#define __IP_SET_IPHASH_H
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_hashes.h"
|
||||
|
||||
#define SETTYPE_NAME "iphash"
|
||||
|
||||
struct ip_set_iphash {
|
||||
ip_set_ip_t *members; /* the iphash proper */
|
||||
uint32_t elements; /* number of elements */
|
||||
uint32_t hashsize; /* hash size */
|
||||
uint16_t probes; /* max number of probes */
|
||||
uint16_t resize; /* resize factor in percent */
|
||||
ip_set_ip_t netmask; /* netmask */
|
||||
initval_t initval[0]; /* initvals for jhash_1word */
|
||||
};
|
||||
|
||||
struct ip_set_req_iphash_create {
|
||||
uint32_t hashsize;
|
||||
uint16_t probes;
|
||||
uint16_t resize;
|
||||
ip_set_ip_t netmask;
|
||||
};
|
||||
|
||||
struct ip_set_req_iphash {
|
||||
ip_set_ip_t ip;
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_IPHASH_H */
|
142
extensions/ipset/ip_set_ipmap.c
Normal file
142
extensions/ipset/ip_set_ipmap.c
Normal file
@@ -0,0 +1,142 @@
|
||||
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
|
||||
* Patrick Schaaf <bof@bof.de>
|
||||
* Copyright (C) 2003-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the single bitmap type */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include "ip_set_ipmap.h"
|
||||
|
||||
static inline ip_set_ip_t
|
||||
ip_to_id(const struct ip_set_ipmap *map, ip_set_ip_t ip)
|
||||
{
|
||||
return (ip - map->first_ip)/map->hosts;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ipmap_test(const struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
const struct ip_set_ipmap *map = set->data;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
*hash_ip = ip & map->netmask;
|
||||
DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u",
|
||||
set->name, HIPQUAD(ip), HIPQUAD(*hash_ip));
|
||||
return !!test_bit(ip_to_id(map, *hash_ip), map->members);
|
||||
}
|
||||
|
||||
#define KADT_CONDITION
|
||||
|
||||
UADT(ipmap, test)
|
||||
KADT(ipmap, test, ipaddr)
|
||||
|
||||
static inline int
|
||||
ipmap_add(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_ipmap *map = set->data;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
*hash_ip = ip & map->netmask;
|
||||
DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip));
|
||||
if (test_and_set_bit(ip_to_id(map, *hash_ip), map->members))
|
||||
return -EEXIST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UADT(ipmap, add)
|
||||
KADT(ipmap, add, ipaddr)
|
||||
|
||||
static inline int
|
||||
ipmap_del(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_ipmap *map = set->data;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
*hash_ip = ip & map->netmask;
|
||||
DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip));
|
||||
if (!test_and_clear_bit(ip_to_id(map, *hash_ip), map->members))
|
||||
return -EEXIST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UADT(ipmap, del)
|
||||
KADT(ipmap, del, ipaddr)
|
||||
|
||||
static inline int
|
||||
__ipmap_create(const struct ip_set_req_ipmap_create *req,
|
||||
struct ip_set_ipmap *map)
|
||||
{
|
||||
map->netmask = req->netmask;
|
||||
|
||||
if (req->netmask == 0xFFFFFFFF) {
|
||||
map->hosts = 1;
|
||||
map->sizeid = map->last_ip - map->first_ip + 1;
|
||||
} else {
|
||||
unsigned int mask_bits, netmask_bits;
|
||||
ip_set_ip_t mask;
|
||||
|
||||
map->first_ip &= map->netmask; /* Should we better bark? */
|
||||
|
||||
mask = range_to_mask(map->first_ip, map->last_ip, &mask_bits);
|
||||
netmask_bits = mask_to_bits(map->netmask);
|
||||
|
||||
if ((!mask && (map->first_ip || map->last_ip != 0xFFFFFFFF))
|
||||
|| netmask_bits <= mask_bits)
|
||||
return -ENOEXEC;
|
||||
|
||||
DP("mask_bits %u, netmask_bits %u",
|
||||
mask_bits, netmask_bits);
|
||||
map->hosts = 2 << (32 - netmask_bits - 1);
|
||||
map->sizeid = 2 << (netmask_bits - mask_bits - 1);
|
||||
}
|
||||
if (map->sizeid > MAX_RANGE + 1) {
|
||||
ip_set_printk("range too big, %d elements (max %d)",
|
||||
map->sizeid, MAX_RANGE+1);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
DP("hosts %u, sizeid %u", map->hosts, map->sizeid);
|
||||
return bitmap_bytes(0, map->sizeid - 1);
|
||||
}
|
||||
|
||||
BITMAP_CREATE(ipmap)
|
||||
BITMAP_DESTROY(ipmap)
|
||||
BITMAP_FLUSH(ipmap)
|
||||
|
||||
static inline void
|
||||
__ipmap_list_header(const struct ip_set_ipmap *map,
|
||||
struct ip_set_req_ipmap_create *header)
|
||||
{
|
||||
header->netmask = map->netmask;
|
||||
}
|
||||
|
||||
BITMAP_LIST_HEADER(ipmap)
|
||||
BITMAP_LIST_MEMBERS_SIZE(ipmap)
|
||||
BITMAP_LIST_MEMBERS(ipmap)
|
||||
|
||||
IP_SET_TYPE(ipmap, IPSET_TYPE_IP | IPSET_DATA_SINGLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("ipmap type of IP sets");
|
||||
|
||||
REGISTER_MODULE(ipmap)
|
57
extensions/ipset/ip_set_ipmap.h
Normal file
57
extensions/ipset/ip_set_ipmap.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#ifndef __IP_SET_IPMAP_H
|
||||
#define __IP_SET_IPMAP_H
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_bitmaps.h"
|
||||
|
||||
#define SETTYPE_NAME "ipmap"
|
||||
|
||||
struct ip_set_ipmap {
|
||||
void *members; /* the ipmap proper */
|
||||
ip_set_ip_t first_ip; /* host byte order, included in range */
|
||||
ip_set_ip_t last_ip; /* host byte order, included in range */
|
||||
ip_set_ip_t netmask; /* subnet netmask */
|
||||
ip_set_ip_t sizeid; /* size of set in IPs */
|
||||
ip_set_ip_t hosts; /* number of hosts in a subnet */
|
||||
size_t size; /* size of the ipmap proper */
|
||||
};
|
||||
|
||||
struct ip_set_req_ipmap_create {
|
||||
ip_set_ip_t from;
|
||||
ip_set_ip_t to;
|
||||
ip_set_ip_t netmask;
|
||||
};
|
||||
|
||||
struct ip_set_req_ipmap {
|
||||
ip_set_ip_t ip;
|
||||
};
|
||||
|
||||
static inline unsigned int
|
||||
mask_to_bits(ip_set_ip_t mask)
|
||||
{
|
||||
unsigned int bits = 32;
|
||||
ip_set_ip_t maskaddr;
|
||||
|
||||
if (mask == 0xFFFFFFFF)
|
||||
return bits;
|
||||
|
||||
maskaddr = 0xFFFFFFFE;
|
||||
while (--bits > 0 && maskaddr != mask)
|
||||
maskaddr <<= 1;
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
static inline ip_set_ip_t
|
||||
range_to_mask(ip_set_ip_t from, ip_set_ip_t to, unsigned int *bits)
|
||||
{
|
||||
ip_set_ip_t mask = 0xFFFFFFFE;
|
||||
|
||||
*bits = 32;
|
||||
while (--(*bits) > 0 && mask && (to & mask) != from)
|
||||
mask <<= 1;
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
#endif /* __IP_SET_IPMAP_H */
|
201
extensions/ipset/ip_set_ipporthash.c
Normal file
201
extensions/ipset/ip_set_ipporthash.c
Normal file
@@ -0,0 +1,201 @@
|
||||
/* Copyright (C) 2003-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an ip+port hash set */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/jhash.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include <net/ip.h>
|
||||
|
||||
#include "ip_set_ipporthash.h"
|
||||
#include "ip_set_getport.h"
|
||||
|
||||
static int limit = MAX_RANGE;
|
||||
|
||||
static inline __u32
|
||||
ipporthash_id(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port)
|
||||
{
|
||||
struct ip_set_ipporthash *map = set->data;
|
||||
__u32 id;
|
||||
u_int16_t i;
|
||||
ip_set_ip_t *elem;
|
||||
|
||||
*hash_ip = pack_ip_port(map, ip, port);
|
||||
|
||||
DP("set: %s, ipport:%u.%u.%u.%u:%u, %u.%u.%u.%u",
|
||||
set->name, HIPQUAD(ip), port, HIPQUAD(*hash_ip));
|
||||
if (!*hash_ip)
|
||||
return UINT_MAX;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
id = jhash_ip(map, i, *hash_ip) % map->hashsize;
|
||||
DP("hash key: %u", id);
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
|
||||
if (*elem == *hash_ip)
|
||||
return id;
|
||||
/* No shortcut at testing - there can be deleted
|
||||
* entries. */
|
||||
}
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ipporthash_test(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port)
|
||||
{
|
||||
struct ip_set_ipporthash *map = set->data;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
return (ipporthash_id(set, hash_ip, ip, port) != UINT_MAX);
|
||||
}
|
||||
|
||||
#define KADT_CONDITION \
|
||||
ip_set_ip_t port; \
|
||||
\
|
||||
if (flags[index+1] == 0) \
|
||||
return 0; \
|
||||
\
|
||||
port = get_port(skb, flags[index+1]); \
|
||||
\
|
||||
if (port == INVALID_PORT) \
|
||||
return 0;
|
||||
|
||||
UADT(ipporthash, test, req->port)
|
||||
KADT(ipporthash, test, ipaddr, port)
|
||||
|
||||
static inline int
|
||||
__ipporthash_add(struct ip_set_ipporthash *map, ip_set_ip_t *ip)
|
||||
{
|
||||
__u32 probe;
|
||||
u_int16_t i;
|
||||
ip_set_ip_t *elem;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
probe = jhash_ip(map, i, *ip) % map->hashsize;
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe);
|
||||
if (*elem == *ip)
|
||||
return -EEXIST;
|
||||
if (!*elem) {
|
||||
*elem = *ip;
|
||||
map->elements++;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Trigger rehashing */
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ipporthash_add(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port)
|
||||
{
|
||||
struct ip_set_ipporthash *map = set->data;
|
||||
if (map->elements > limit)
|
||||
return -ERANGE;
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
*hash_ip = pack_ip_port(map, ip, port);
|
||||
|
||||
if (!*hash_ip)
|
||||
return -ERANGE;
|
||||
|
||||
return __ipporthash_add(map, hash_ip);
|
||||
}
|
||||
|
||||
UADT(ipporthash, add, req->port)
|
||||
KADT(ipporthash, add, ipaddr, port)
|
||||
|
||||
static inline void
|
||||
__ipporthash_retry(struct ip_set_ipporthash *tmp,
|
||||
struct ip_set_ipporthash *map)
|
||||
{
|
||||
tmp->first_ip = map->first_ip;
|
||||
tmp->last_ip = map->last_ip;
|
||||
}
|
||||
|
||||
HASH_RETRY(ipporthash, ip_set_ip_t)
|
||||
|
||||
static inline int
|
||||
ipporthash_del(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port)
|
||||
{
|
||||
struct ip_set_ipporthash *map = set->data;
|
||||
ip_set_ip_t id;
|
||||
ip_set_ip_t *elem;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
id = ipporthash_id(set, hash_ip, ip, port);
|
||||
|
||||
if (id == UINT_MAX)
|
||||
return -EEXIST;
|
||||
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
|
||||
*elem = 0;
|
||||
map->elements--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UADT(ipporthash, del, req->port)
|
||||
KADT(ipporthash, del, ipaddr, port)
|
||||
|
||||
static inline int
|
||||
__ipporthash_create(const struct ip_set_req_ipporthash_create *req,
|
||||
struct ip_set_ipporthash *map)
|
||||
{
|
||||
if (req->to - req->from > MAX_RANGE) {
|
||||
ip_set_printk("range too big, %d elements (max %d)",
|
||||
req->to - req->from + 1, MAX_RANGE+1);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
map->first_ip = req->from;
|
||||
map->last_ip = req->to;
|
||||
return 0;
|
||||
}
|
||||
|
||||
HASH_CREATE(ipporthash, ip_set_ip_t)
|
||||
HASH_DESTROY(ipporthash)
|
||||
HASH_FLUSH(ipporthash, ip_set_ip_t)
|
||||
|
||||
static inline void
|
||||
__ipporthash_list_header(const struct ip_set_ipporthash *map,
|
||||
struct ip_set_req_ipporthash_create *header)
|
||||
{
|
||||
header->from = map->first_ip;
|
||||
header->to = map->last_ip;
|
||||
}
|
||||
|
||||
HASH_LIST_HEADER(ipporthash)
|
||||
HASH_LIST_MEMBERS_SIZE(ipporthash, ip_set_ip_t)
|
||||
HASH_LIST_MEMBERS(ipporthash, ip_set_ip_t)
|
||||
|
||||
IP_SET_RTYPE(ipporthash, IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_DATA_DOUBLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("ipporthash type of IP sets");
|
||||
module_param(limit, int, 0600);
|
||||
MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
|
||||
|
||||
REGISTER_MODULE(ipporthash)
|
33
extensions/ipset/ip_set_ipporthash.h
Normal file
33
extensions/ipset/ip_set_ipporthash.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef __IP_SET_IPPORTHASH_H
|
||||
#define __IP_SET_IPPORTHASH_H
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_hashes.h"
|
||||
|
||||
#define SETTYPE_NAME "ipporthash"
|
||||
|
||||
struct ip_set_ipporthash {
|
||||
ip_set_ip_t *members; /* the ipporthash proper */
|
||||
uint32_t elements; /* number of elements */
|
||||
uint32_t hashsize; /* hash size */
|
||||
uint16_t probes; /* max number of probes */
|
||||
uint16_t resize; /* resize factor in percent */
|
||||
ip_set_ip_t first_ip; /* host byte order, included in range */
|
||||
ip_set_ip_t last_ip; /* host byte order, included in range */
|
||||
initval_t initval[0]; /* initvals for jhash_1word */
|
||||
};
|
||||
|
||||
struct ip_set_req_ipporthash_create {
|
||||
uint32_t hashsize;
|
||||
uint16_t probes;
|
||||
uint16_t resize;
|
||||
ip_set_ip_t from;
|
||||
ip_set_ip_t to;
|
||||
};
|
||||
|
||||
struct ip_set_req_ipporthash {
|
||||
ip_set_ip_t ip;
|
||||
ip_set_ip_t port;
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_IPPORTHASH_H */
|
214
extensions/ipset/ip_set_ipportiphash.c
Normal file
214
extensions/ipset/ip_set_ipportiphash.c
Normal file
@@ -0,0 +1,214 @@
|
||||
/* Copyright (C) 2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an ip+port+ip hash set */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/jhash.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include <net/ip.h>
|
||||
|
||||
#include "ip_set_ipportiphash.h"
|
||||
#include "ip_set_getport.h"
|
||||
|
||||
static int limit = MAX_RANGE;
|
||||
|
||||
#define jhash_ip2(map, i, ipport, ip1) \
|
||||
jhash_2words(ipport, ip1, *(map->initval + i))
|
||||
|
||||
static inline __u32
|
||||
ipportiphash_id(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1)
|
||||
{
|
||||
struct ip_set_ipportiphash *map = set->data;
|
||||
__u32 id;
|
||||
u_int16_t i;
|
||||
struct ipportip *elem;
|
||||
|
||||
*hash_ip = pack_ip_port(map, ip, port);
|
||||
DP("set: %s, ipport:%u.%u.%u.%u:%u, %u.%u.%u.%u",
|
||||
set->name, HIPQUAD(ip), port, HIPQUAD(*hash_ip));
|
||||
if (!(*hash_ip || ip1))
|
||||
return UINT_MAX;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
id = jhash_ip2(map, i, *hash_ip, ip1) % map->hashsize;
|
||||
DP("hash key: %u", id);
|
||||
elem = HARRAY_ELEM(map->members, struct ipportip *, id);
|
||||
if (elem->ip == *hash_ip && elem->ip1 == ip1)
|
||||
return id;
|
||||
/* No shortcut at testing - there can be deleted
|
||||
* entries. */
|
||||
}
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ipportiphash_test(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1)
|
||||
{
|
||||
struct ip_set_ipportiphash *map = set->data;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
return (ipportiphash_id(set, hash_ip, ip, port, ip1) != UINT_MAX);
|
||||
}
|
||||
|
||||
#define KADT_CONDITION \
|
||||
ip_set_ip_t port, ip1; \
|
||||
\
|
||||
if (flags[index+2] == 0) \
|
||||
return 0; \
|
||||
\
|
||||
port = get_port(skb, flags[index+1]); \
|
||||
ip1 = ipaddr(skb, flags[index+2]); \
|
||||
\
|
||||
if (port == INVALID_PORT) \
|
||||
return 0;
|
||||
|
||||
UADT(ipportiphash, test, req->port, req->ip1)
|
||||
KADT(ipportiphash, test, ipaddr, port, ip1)
|
||||
|
||||
static inline int
|
||||
__ipportip_add(struct ip_set_ipportiphash *map,
|
||||
ip_set_ip_t hash_ip, ip_set_ip_t ip1)
|
||||
{
|
||||
__u32 probe;
|
||||
u_int16_t i;
|
||||
struct ipportip *elem;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
probe = jhash_ip2(map, i, hash_ip, ip1) % map->hashsize;
|
||||
elem = HARRAY_ELEM(map->members, struct ipportip *, probe);
|
||||
if (elem->ip == hash_ip && elem->ip1 == ip1)
|
||||
return -EEXIST;
|
||||
if (!(elem->ip || elem->ip1)) {
|
||||
elem->ip = hash_ip;
|
||||
elem->ip1 = ip1;
|
||||
map->elements++;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Trigger rehashing */
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
static inline int
|
||||
__ipportiphash_add(struct ip_set_ipportiphash *map,
|
||||
struct ipportip *elem)
|
||||
{
|
||||
return __ipportip_add(map, elem->ip, elem->ip1);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ipportiphash_add(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1)
|
||||
{
|
||||
struct ip_set_ipportiphash *map = set->data;
|
||||
|
||||
if (map->elements > limit)
|
||||
return -ERANGE;
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
*hash_ip = pack_ip_port(map, ip, port);
|
||||
if (!(*hash_ip || ip1))
|
||||
return -ERANGE;
|
||||
|
||||
return __ipportip_add(map, *hash_ip, ip1);
|
||||
}
|
||||
|
||||
UADT(ipportiphash, add, req->port, req->ip1)
|
||||
KADT(ipportiphash, add, ipaddr, port, ip1)
|
||||
|
||||
static inline void
|
||||
__ipportiphash_retry(struct ip_set_ipportiphash *tmp,
|
||||
struct ip_set_ipportiphash *map)
|
||||
{
|
||||
tmp->first_ip = map->first_ip;
|
||||
tmp->last_ip = map->last_ip;
|
||||
}
|
||||
|
||||
HASH_RETRY2(ipportiphash, struct ipportip)
|
||||
|
||||
static inline int
|
||||
ipportiphash_del(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1)
|
||||
{
|
||||
struct ip_set_ipportiphash *map = set->data;
|
||||
ip_set_ip_t id;
|
||||
struct ipportip *elem;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
id = ipportiphash_id(set, hash_ip, ip, port, ip1);
|
||||
|
||||
if (id == UINT_MAX)
|
||||
return -EEXIST;
|
||||
|
||||
elem = HARRAY_ELEM(map->members, struct ipportip *, id);
|
||||
elem->ip = elem->ip1 = 0;
|
||||
map->elements--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UADT(ipportiphash, del, req->port, req->ip1)
|
||||
KADT(ipportiphash, del, ipaddr, port, ip1)
|
||||
|
||||
static inline int
|
||||
__ipportiphash_create(const struct ip_set_req_ipportiphash_create *req,
|
||||
struct ip_set_ipportiphash *map)
|
||||
{
|
||||
if (req->to - req->from > MAX_RANGE) {
|
||||
ip_set_printk("range too big, %d elements (max %d)",
|
||||
req->to - req->from + 1, MAX_RANGE+1);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
map->first_ip = req->from;
|
||||
map->last_ip = req->to;
|
||||
return 0;
|
||||
}
|
||||
|
||||
HASH_CREATE(ipportiphash, struct ipportip)
|
||||
HASH_DESTROY(ipportiphash)
|
||||
HASH_FLUSH(ipportiphash, struct ipportip)
|
||||
|
||||
static inline void
|
||||
__ipportiphash_list_header(const struct ip_set_ipportiphash *map,
|
||||
struct ip_set_req_ipportiphash_create *header)
|
||||
{
|
||||
header->from = map->first_ip;
|
||||
header->to = map->last_ip;
|
||||
}
|
||||
|
||||
HASH_LIST_HEADER(ipportiphash)
|
||||
HASH_LIST_MEMBERS_SIZE(ipportiphash, struct ipportip)
|
||||
HASH_LIST_MEMBERS_MEMCPY(ipportiphash, struct ipportip)
|
||||
|
||||
IP_SET_RTYPE(ipportiphash, IPSET_TYPE_IP | IPSET_TYPE_PORT
|
||||
| IPSET_TYPE_IP1 | IPSET_DATA_TRIPLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("ipportiphash type of IP sets");
|
||||
module_param(limit, int, 0600);
|
||||
MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
|
||||
|
||||
REGISTER_MODULE(ipportiphash)
|
39
extensions/ipset/ip_set_ipportiphash.h
Normal file
39
extensions/ipset/ip_set_ipportiphash.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef __IP_SET_IPPORTIPHASH_H
|
||||
#define __IP_SET_IPPORTIPHASH_H
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_hashes.h"
|
||||
|
||||
#define SETTYPE_NAME "ipportiphash"
|
||||
|
||||
struct ipportip {
|
||||
ip_set_ip_t ip;
|
||||
ip_set_ip_t ip1;
|
||||
};
|
||||
|
||||
struct ip_set_ipportiphash {
|
||||
struct ipportip *members; /* the ipportip proper */
|
||||
uint32_t elements; /* number of elements */
|
||||
uint32_t hashsize; /* hash size */
|
||||
uint16_t probes; /* max number of probes */
|
||||
uint16_t resize; /* resize factor in percent */
|
||||
ip_set_ip_t first_ip; /* host byte order, included in range */
|
||||
ip_set_ip_t last_ip; /* host byte order, included in range */
|
||||
initval_t initval[0]; /* initvals for jhash_1word */
|
||||
};
|
||||
|
||||
struct ip_set_req_ipportiphash_create {
|
||||
uint32_t hashsize;
|
||||
uint16_t probes;
|
||||
uint16_t resize;
|
||||
ip_set_ip_t from;
|
||||
ip_set_ip_t to;
|
||||
};
|
||||
|
||||
struct ip_set_req_ipportiphash {
|
||||
ip_set_ip_t ip;
|
||||
ip_set_ip_t port;
|
||||
ip_set_ip_t ip1;
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_IPPORTIPHASH_H */
|
302
extensions/ipset/ip_set_ipportnethash.c
Normal file
302
extensions/ipset/ip_set_ipportnethash.c
Normal file
@@ -0,0 +1,302 @@
|
||||
/* Copyright (C) 2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an ip+port+net hash set */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/jhash.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include <net/ip.h>
|
||||
|
||||
#include "ip_set_ipportnethash.h"
|
||||
#include "ip_set_getport.h"
|
||||
|
||||
static int limit = MAX_RANGE;
|
||||
|
||||
#define jhash_ip2(map, i, ipport, ip1) \
|
||||
jhash_2words(ipport, ip1, *(map->initval + i))
|
||||
|
||||
static inline __u32
|
||||
ipportnethash_id_cidr(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port,
|
||||
ip_set_ip_t ip1, uint8_t cidr)
|
||||
{
|
||||
struct ip_set_ipportnethash *map = set->data;
|
||||
__u32 id;
|
||||
u_int16_t i;
|
||||
struct ipportip *elem;
|
||||
|
||||
*hash_ip = pack_ip_port(map, ip, port);
|
||||
DP("set: %s, ipport:%u.%u.%u.%u:%u, %u.%u.%u.%u",
|
||||
set->name, HIPQUAD(ip), port, HIPQUAD(*hash_ip));
|
||||
ip1 = pack_ip_cidr(ip1, cidr);
|
||||
if (!(*hash_ip || ip1))
|
||||
return UINT_MAX;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
id = jhash_ip2(map, i, *hash_ip, ip1) % map->hashsize;
|
||||
DP("hash key: %u", id);
|
||||
elem = HARRAY_ELEM(map->members, struct ipportip *, id);
|
||||
if (elem->ip == *hash_ip && elem->ip1 == ip1)
|
||||
return id;
|
||||
/* No shortcut at testing - there can be deleted
|
||||
* entries. */
|
||||
}
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
static inline __u32
|
||||
ipportnethash_id(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1)
|
||||
{
|
||||
struct ip_set_ipportnethash *map = set->data;
|
||||
__u32 id = UINT_MAX;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 30 && map->cidr[i]; i++) {
|
||||
id = ipportnethash_id_cidr(set, hash_ip, ip, port, ip1,
|
||||
map->cidr[i]);
|
||||
if (id != UINT_MAX)
|
||||
break;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ipportnethash_test_cidr(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port,
|
||||
ip_set_ip_t ip1, uint8_t cidr)
|
||||
{
|
||||
struct ip_set_ipportnethash *map = set->data;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
return (ipportnethash_id_cidr(set, hash_ip, ip, port, ip1,
|
||||
cidr) != UINT_MAX);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ipportnethash_test(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1)
|
||||
{
|
||||
struct ip_set_ipportnethash *map = set->data;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
return (ipportnethash_id(set, hash_ip, ip, port, ip1) != UINT_MAX);
|
||||
}
|
||||
|
||||
static int
|
||||
ipportnethash_utest(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
{
|
||||
const struct ip_set_req_ipportnethash *req = data;
|
||||
|
||||
if (req->cidr <= 0 || req->cidr > 32)
|
||||
return -EINVAL;
|
||||
return (req->cidr == 32
|
||||
? ipportnethash_test(set, hash_ip, req->ip, req->port,
|
||||
req->ip1)
|
||||
: ipportnethash_test_cidr(set, hash_ip, req->ip, req->port,
|
||||
req->ip1, req->cidr));
|
||||
}
|
||||
|
||||
#define KADT_CONDITION \
|
||||
ip_set_ip_t port, ip1; \
|
||||
\
|
||||
if (flags[index+2] == 0) \
|
||||
return 0; \
|
||||
\
|
||||
port = get_port(skb, flags[index+1]); \
|
||||
ip1 = ipaddr(skb, flags[index+2]); \
|
||||
\
|
||||
if (port == INVALID_PORT) \
|
||||
return 0;
|
||||
|
||||
KADT(ipportnethash, test, ipaddr, port, ip1)
|
||||
|
||||
static inline int
|
||||
__ipportnet_add(struct ip_set_ipportnethash *map,
|
||||
ip_set_ip_t hash_ip, ip_set_ip_t ip1)
|
||||
{
|
||||
__u32 probe;
|
||||
u_int16_t i;
|
||||
struct ipportip *elem;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
probe = jhash_ip2(map, i, hash_ip, ip1) % map->hashsize;
|
||||
elem = HARRAY_ELEM(map->members, struct ipportip *, probe);
|
||||
if (elem->ip == hash_ip && elem->ip1 == ip1)
|
||||
return -EEXIST;
|
||||
if (!(elem->ip || elem->ip1)) {
|
||||
elem->ip = hash_ip;
|
||||
elem->ip1 = ip1;
|
||||
map->elements++;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Trigger rehashing */
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
static inline int
|
||||
__ipportnethash_add(struct ip_set_ipportnethash *map,
|
||||
struct ipportip *elem)
|
||||
{
|
||||
return __ipportnet_add(map, elem->ip, elem->ip1);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ipportnethash_add(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port,
|
||||
ip_set_ip_t ip1, uint8_t cidr)
|
||||
{
|
||||
struct ip_set_ipportnethash *map = set->data;
|
||||
struct ipportip;
|
||||
int ret;
|
||||
|
||||
if (map->elements > limit)
|
||||
return -ERANGE;
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
if (cidr <= 0 || cidr >= 32)
|
||||
return -EINVAL;
|
||||
if (map->nets[cidr-1] == UINT16_MAX)
|
||||
return -ERANGE;
|
||||
|
||||
*hash_ip = pack_ip_port(map, ip, port);
|
||||
ip1 = pack_ip_cidr(ip1, cidr);
|
||||
if (!(*hash_ip || ip1))
|
||||
return -ERANGE;
|
||||
|
||||
ret =__ipportnet_add(map, *hash_ip, ip1);
|
||||
if (ret == 0) {
|
||||
if (!map->nets[cidr-1]++)
|
||||
add_cidr_size(map->cidr, cidr);
|
||||
map->elements++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef KADT_CONDITION
|
||||
#define KADT_CONDITION \
|
||||
struct ip_set_ipportnethash *map = set->data; \
|
||||
uint8_t cidr = map->cidr[0] ? map->cidr[0] : 31; \
|
||||
ip_set_ip_t port, ip1; \
|
||||
\
|
||||
if (flags[index+2] == 0) \
|
||||
return 0; \
|
||||
\
|
||||
port = get_port(skb, flags[index+1]); \
|
||||
ip1 = ipaddr(skb, flags[index+2]); \
|
||||
\
|
||||
if (port == INVALID_PORT) \
|
||||
return 0;
|
||||
|
||||
UADT(ipportnethash, add, req->port, req->ip1, req->cidr)
|
||||
KADT(ipportnethash, add, ipaddr, port, ip1, cidr)
|
||||
|
||||
static inline void
|
||||
__ipportnethash_retry(struct ip_set_ipportnethash *tmp,
|
||||
struct ip_set_ipportnethash *map)
|
||||
{
|
||||
tmp->first_ip = map->first_ip;
|
||||
tmp->last_ip = map->last_ip;
|
||||
memcpy(tmp->cidr, map->cidr, sizeof(tmp->cidr));
|
||||
memcpy(tmp->nets, map->nets, sizeof(tmp->nets));
|
||||
}
|
||||
|
||||
HASH_RETRY2(ipportnethash, struct ipportip)
|
||||
|
||||
static inline int
|
||||
ipportnethash_del(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, ip_set_ip_t port,
|
||||
ip_set_ip_t ip1, uint8_t cidr)
|
||||
{
|
||||
struct ip_set_ipportnethash *map = set->data;
|
||||
ip_set_ip_t id;
|
||||
struct ipportip *elem;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
if (!ip)
|
||||
return -ERANGE;
|
||||
if (cidr <= 0 || cidr >= 32)
|
||||
return -EINVAL;
|
||||
|
||||
id = ipportnethash_id_cidr(set, hash_ip, ip, port, ip1, cidr);
|
||||
|
||||
if (id == UINT_MAX)
|
||||
return -EEXIST;
|
||||
|
||||
elem = HARRAY_ELEM(map->members, struct ipportip *, id);
|
||||
elem->ip = elem->ip1 = 0;
|
||||
map->elements--;
|
||||
if (!map->nets[cidr-1]--)
|
||||
del_cidr_size(map->cidr, cidr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UADT(ipportnethash, del, req->port, req->ip1, req->cidr)
|
||||
KADT(ipportnethash, del, ipaddr, port, ip1, cidr)
|
||||
|
||||
static inline int
|
||||
__ipportnethash_create(const struct ip_set_req_ipportnethash_create *req,
|
||||
struct ip_set_ipportnethash *map)
|
||||
{
|
||||
if (req->to - req->from > MAX_RANGE) {
|
||||
ip_set_printk("range too big, %d elements (max %d)",
|
||||
req->to - req->from + 1, MAX_RANGE+1);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
map->first_ip = req->from;
|
||||
map->last_ip = req->to;
|
||||
memset(map->cidr, 0, sizeof(map->cidr));
|
||||
memset(map->nets, 0, sizeof(map->nets));
|
||||
return 0;
|
||||
}
|
||||
|
||||
HASH_CREATE(ipportnethash, struct ipportip)
|
||||
HASH_DESTROY(ipportnethash)
|
||||
HASH_FLUSH_CIDR(ipportnethash, struct ipportip);
|
||||
|
||||
static inline void
|
||||
__ipportnethash_list_header(const struct ip_set_ipportnethash *map,
|
||||
struct ip_set_req_ipportnethash_create *header)
|
||||
{
|
||||
header->from = map->first_ip;
|
||||
header->to = map->last_ip;
|
||||
}
|
||||
|
||||
HASH_LIST_HEADER(ipportnethash)
|
||||
|
||||
HASH_LIST_MEMBERS_SIZE(ipportnethash, struct ipportip)
|
||||
HASH_LIST_MEMBERS_MEMCPY(ipportnethash, struct ipportip)
|
||||
|
||||
IP_SET_RTYPE(ipportnethash, IPSET_TYPE_IP | IPSET_TYPE_PORT
|
||||
| IPSET_TYPE_IP1 | IPSET_DATA_TRIPLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("ipportnethash type of IP sets");
|
||||
module_param(limit, int, 0600);
|
||||
MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
|
||||
|
||||
REGISTER_MODULE(ipportnethash)
|
42
extensions/ipset/ip_set_ipportnethash.h
Normal file
42
extensions/ipset/ip_set_ipportnethash.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#ifndef __IP_SET_IPPORTNETHASH_H
|
||||
#define __IP_SET_IPPORTNETHASH_H
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_hashes.h"
|
||||
|
||||
#define SETTYPE_NAME "ipportnethash"
|
||||
|
||||
struct ipportip {
|
||||
ip_set_ip_t ip;
|
||||
ip_set_ip_t ip1;
|
||||
};
|
||||
|
||||
struct ip_set_ipportnethash {
|
||||
struct ipportip *members; /* the ipportip proper */
|
||||
uint32_t elements; /* number of elements */
|
||||
uint32_t hashsize; /* hash size */
|
||||
uint16_t probes; /* max number of probes */
|
||||
uint16_t resize; /* resize factor in percent */
|
||||
ip_set_ip_t first_ip; /* host byte order, included in range */
|
||||
ip_set_ip_t last_ip; /* host byte order, included in range */
|
||||
uint8_t cidr[30]; /* CIDR sizes */
|
||||
uint16_t nets[30]; /* nr of nets by CIDR sizes */
|
||||
initval_t initval[0]; /* initvals for jhash_1word */
|
||||
};
|
||||
|
||||
struct ip_set_req_ipportnethash_create {
|
||||
uint32_t hashsize;
|
||||
uint16_t probes;
|
||||
uint16_t resize;
|
||||
ip_set_ip_t from;
|
||||
ip_set_ip_t to;
|
||||
};
|
||||
|
||||
struct ip_set_req_ipportnethash {
|
||||
ip_set_ip_t ip;
|
||||
ip_set_ip_t port;
|
||||
ip_set_ip_t ip1;
|
||||
uint8_t cidr;
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_IPPORTNETHASH_H */
|
466
extensions/ipset/ip_set_iptree.c
Normal file
466
extensions/ipset/ip_set_iptree.c
Normal file
@@ -0,0 +1,466 @@
|
||||
/* Copyright (C) 2005-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the iptree type */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/timer.h>
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_bitmaps.h"
|
||||
#include "ip_set_iptree.h"
|
||||
|
||||
static int limit = MAX_RANGE;
|
||||
|
||||
/* Garbage collection interval in seconds: */
|
||||
#define IPTREE_GC_TIME 5*60
|
||||
/* Sleep so many milliseconds before trying again
|
||||
* to delete the gc timer at destroying/flushing a set */
|
||||
#define IPTREE_DESTROY_SLEEP 100
|
||||
|
||||
static __KMEM_CACHE_T__ *branch_cachep;
|
||||
static __KMEM_CACHE_T__ *leaf_cachep;
|
||||
|
||||
|
||||
#if defined(__LITTLE_ENDIAN)
|
||||
#define ABCD(a,b,c,d,addrp) do { \
|
||||
a = ((unsigned char *)addrp)[3]; \
|
||||
b = ((unsigned char *)addrp)[2]; \
|
||||
c = ((unsigned char *)addrp)[1]; \
|
||||
d = ((unsigned char *)addrp)[0]; \
|
||||
} while (0)
|
||||
#elif defined(__BIG_ENDIAN)
|
||||
#define ABCD(a,b,c,d,addrp) do { \
|
||||
a = ((unsigned char *)addrp)[0]; \
|
||||
b = ((unsigned char *)addrp)[1]; \
|
||||
c = ((unsigned char *)addrp)[2]; \
|
||||
d = ((unsigned char *)addrp)[3]; \
|
||||
} while (0)
|
||||
#else
|
||||
#error "Please fix asm/byteorder.h"
|
||||
#endif /* __LITTLE_ENDIAN */
|
||||
|
||||
#define TESTIP_WALK(map, elem, branch) do { \
|
||||
if ((map)->tree[elem]) { \
|
||||
branch = (map)->tree[elem]; \
|
||||
} else \
|
||||
return 0; \
|
||||
} while (0)
|
||||
|
||||
static inline int
|
||||
iptree_test(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_iptree *map = set->data;
|
||||
struct ip_set_iptreeb *btree;
|
||||
struct ip_set_iptreec *ctree;
|
||||
struct ip_set_iptreed *dtree;
|
||||
unsigned char a,b,c,d;
|
||||
|
||||
if (!ip)
|
||||
return -ERANGE;
|
||||
|
||||
*hash_ip = ip;
|
||||
ABCD(a, b, c, d, hash_ip);
|
||||
DP("%u %u %u %u timeout %u", a, b, c, d, map->timeout);
|
||||
TESTIP_WALK(map, a, btree);
|
||||
TESTIP_WALK(btree, b, ctree);
|
||||
TESTIP_WALK(ctree, c, dtree);
|
||||
DP("%lu %lu", dtree->expires[d], jiffies);
|
||||
return dtree->expires[d]
|
||||
&& (!map->timeout
|
||||
|| time_after(dtree->expires[d], jiffies));
|
||||
}
|
||||
|
||||
#define KADT_CONDITION
|
||||
|
||||
UADT(iptree, test)
|
||||
KADT(iptree, test, ipaddr)
|
||||
|
||||
#define ADDIP_WALK(map, elem, branch, type, cachep) do { \
|
||||
if ((map)->tree[elem]) { \
|
||||
DP("found %u", elem); \
|
||||
branch = (map)->tree[elem]; \
|
||||
} else { \
|
||||
branch = (type *) \
|
||||
kmem_cache_alloc(cachep, GFP_ATOMIC); \
|
||||
if (branch == NULL) \
|
||||
return -ENOMEM; \
|
||||
memset(branch, 0, sizeof(*branch)); \
|
||||
(map)->tree[elem] = branch; \
|
||||
DP("alloc %u", elem); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static inline int
|
||||
iptree_add(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, unsigned int timeout)
|
||||
{
|
||||
struct ip_set_iptree *map = set->data;
|
||||
struct ip_set_iptreeb *btree;
|
||||
struct ip_set_iptreec *ctree;
|
||||
struct ip_set_iptreed *dtree;
|
||||
unsigned char a,b,c,d;
|
||||
int ret = 0;
|
||||
|
||||
if (!ip || map->elements >= limit)
|
||||
/* We could call the garbage collector
|
||||
* but it's probably overkill */
|
||||
return -ERANGE;
|
||||
|
||||
*hash_ip = ip;
|
||||
ABCD(a, b, c, d, hash_ip);
|
||||
DP("%u %u %u %u timeout %u", a, b, c, d, timeout);
|
||||
ADDIP_WALK(map, a, btree, struct ip_set_iptreeb, branch_cachep);
|
||||
ADDIP_WALK(btree, b, ctree, struct ip_set_iptreec, branch_cachep);
|
||||
ADDIP_WALK(ctree, c, dtree, struct ip_set_iptreed, leaf_cachep);
|
||||
if (dtree->expires[d]
|
||||
&& (!map->timeout || time_after(dtree->expires[d], jiffies)))
|
||||
ret = -EEXIST;
|
||||
if (map->timeout && timeout == 0)
|
||||
timeout = map->timeout;
|
||||
dtree->expires[d] = map->timeout ? (timeout * HZ + jiffies) : 1;
|
||||
/* Lottery: I won! */
|
||||
if (dtree->expires[d] == 0)
|
||||
dtree->expires[d] = 1;
|
||||
DP("%u %lu", d, dtree->expires[d]);
|
||||
if (ret == 0)
|
||||
map->elements++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
UADT(iptree, add, req->timeout)
|
||||
KADT(iptree, add, ipaddr, 0)
|
||||
|
||||
#define DELIP_WALK(map, elem, branch) do { \
|
||||
if ((map)->tree[elem]) { \
|
||||
branch = (map)->tree[elem]; \
|
||||
} else \
|
||||
return -EEXIST; \
|
||||
} while (0)
|
||||
|
||||
static inline int
|
||||
iptree_del(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_iptree *map = set->data;
|
||||
struct ip_set_iptreeb *btree;
|
||||
struct ip_set_iptreec *ctree;
|
||||
struct ip_set_iptreed *dtree;
|
||||
unsigned char a,b,c,d;
|
||||
|
||||
if (!ip)
|
||||
return -ERANGE;
|
||||
|
||||
*hash_ip = ip;
|
||||
ABCD(a, b, c, d, hash_ip);
|
||||
DELIP_WALK(map, a, btree);
|
||||
DELIP_WALK(btree, b, ctree);
|
||||
DELIP_WALK(ctree, c, dtree);
|
||||
|
||||
if (dtree->expires[d]) {
|
||||
dtree->expires[d] = 0;
|
||||
map->elements--;
|
||||
return 0;
|
||||
}
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
UADT(iptree, del)
|
||||
KADT(iptree, del, ipaddr)
|
||||
|
||||
#define LOOP_WALK_BEGIN(map, i, branch) \
|
||||
for (i = 0; i < 256; i++) { \
|
||||
if (!(map)->tree[i]) \
|
||||
continue; \
|
||||
branch = (map)->tree[i]
|
||||
|
||||
#define LOOP_WALK_END }
|
||||
|
||||
static void
|
||||
ip_tree_gc(unsigned long ul_set)
|
||||
{
|
||||
struct ip_set *set = (struct ip_set *) ul_set;
|
||||
struct ip_set_iptree *map = set->data;
|
||||
struct ip_set_iptreeb *btree;
|
||||
struct ip_set_iptreec *ctree;
|
||||
struct ip_set_iptreed *dtree;
|
||||
unsigned int a,b,c,d;
|
||||
unsigned char i,j,k;
|
||||
|
||||
i = j = k = 0;
|
||||
DP("gc: %s", set->name);
|
||||
write_lock_bh(&set->lock);
|
||||
LOOP_WALK_BEGIN(map, a, btree);
|
||||
LOOP_WALK_BEGIN(btree, b, ctree);
|
||||
LOOP_WALK_BEGIN(ctree, c, dtree);
|
||||
for (d = 0; d < 256; d++) {
|
||||
if (dtree->expires[d]) {
|
||||
DP("gc: %u %u %u %u: expires %lu jiffies %lu",
|
||||
a, b, c, d,
|
||||
dtree->expires[d], jiffies);
|
||||
if (map->timeout
|
||||
&& time_before(dtree->expires[d], jiffies)) {
|
||||
dtree->expires[d] = 0;
|
||||
map->elements--;
|
||||
} else
|
||||
k = 1;
|
||||
}
|
||||
}
|
||||
if (k == 0) {
|
||||
DP("gc: %s: leaf %u %u %u empty",
|
||||
set->name, a, b, c);
|
||||
kmem_cache_free(leaf_cachep, dtree);
|
||||
ctree->tree[c] = NULL;
|
||||
} else {
|
||||
DP("gc: %s: leaf %u %u %u not empty",
|
||||
set->name, a, b, c);
|
||||
j = 1;
|
||||
k = 0;
|
||||
}
|
||||
LOOP_WALK_END;
|
||||
if (j == 0) {
|
||||
DP("gc: %s: branch %u %u empty",
|
||||
set->name, a, b);
|
||||
kmem_cache_free(branch_cachep, ctree);
|
||||
btree->tree[b] = NULL;
|
||||
} else {
|
||||
DP("gc: %s: branch %u %u not empty",
|
||||
set->name, a, b);
|
||||
i = 1;
|
||||
j = k = 0;
|
||||
}
|
||||
LOOP_WALK_END;
|
||||
if (i == 0) {
|
||||
DP("gc: %s: branch %u empty",
|
||||
set->name, a);
|
||||
kmem_cache_free(branch_cachep, btree);
|
||||
map->tree[a] = NULL;
|
||||
} else {
|
||||
DP("gc: %s: branch %u not empty",
|
||||
set->name, a);
|
||||
i = j = k = 0;
|
||||
}
|
||||
LOOP_WALK_END;
|
||||
write_unlock_bh(&set->lock);
|
||||
|
||||
map->gc.expires = jiffies + map->gc_interval * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
static inline void
|
||||
init_gc_timer(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_iptree *map = set->data;
|
||||
|
||||
/* Even if there is no timeout for the entries,
|
||||
* we still have to call gc because delete
|
||||
* do not clean up empty branches */
|
||||
map->gc_interval = IPTREE_GC_TIME;
|
||||
init_timer(&map->gc);
|
||||
map->gc.data = (unsigned long) set;
|
||||
map->gc.function = ip_tree_gc;
|
||||
map->gc.expires = jiffies + map->gc_interval * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
static int
|
||||
iptree_create(struct ip_set *set, const void *data, size_t size)
|
||||
{
|
||||
const struct ip_set_req_iptree_create *req = data;
|
||||
struct ip_set_iptree *map;
|
||||
|
||||
if (size != sizeof(struct ip_set_req_iptree_create)) {
|
||||
ip_set_printk("data length wrong (want %zu, have %zu)",
|
||||
sizeof(struct ip_set_req_iptree_create),
|
||||
size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
map = kmalloc(sizeof(struct ip_set_iptree), GFP_KERNEL);
|
||||
if (!map) {
|
||||
DP("out of memory for %d bytes",
|
||||
sizeof(struct ip_set_iptree));
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(map, 0, sizeof(*map));
|
||||
map->timeout = req->timeout;
|
||||
map->elements = 0;
|
||||
set->data = map;
|
||||
|
||||
init_gc_timer(set);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
__flush(struct ip_set_iptree *map)
|
||||
{
|
||||
struct ip_set_iptreeb *btree;
|
||||
struct ip_set_iptreec *ctree;
|
||||
struct ip_set_iptreed *dtree;
|
||||
unsigned int a,b,c;
|
||||
|
||||
LOOP_WALK_BEGIN(map, a, btree);
|
||||
LOOP_WALK_BEGIN(btree, b, ctree);
|
||||
LOOP_WALK_BEGIN(ctree, c, dtree);
|
||||
kmem_cache_free(leaf_cachep, dtree);
|
||||
LOOP_WALK_END;
|
||||
kmem_cache_free(branch_cachep, ctree);
|
||||
LOOP_WALK_END;
|
||||
kmem_cache_free(branch_cachep, btree);
|
||||
LOOP_WALK_END;
|
||||
map->elements = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
iptree_destroy(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_iptree *map = set->data;
|
||||
|
||||
/* gc might be running */
|
||||
while (!del_timer(&map->gc))
|
||||
msleep(IPTREE_DESTROY_SLEEP);
|
||||
__flush(map);
|
||||
kfree(map);
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
iptree_flush(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_iptree *map = set->data;
|
||||
unsigned int timeout = map->timeout;
|
||||
|
||||
/* gc might be running */
|
||||
while (!del_timer(&map->gc))
|
||||
msleep(IPTREE_DESTROY_SLEEP);
|
||||
__flush(map);
|
||||
memset(map, 0, sizeof(*map));
|
||||
map->timeout = timeout;
|
||||
|
||||
init_gc_timer(set);
|
||||
}
|
||||
|
||||
static void
|
||||
iptree_list_header(const struct ip_set *set, void *data)
|
||||
{
|
||||
const struct ip_set_iptree *map = set->data;
|
||||
struct ip_set_req_iptree_create *header = data;
|
||||
|
||||
header->timeout = map->timeout;
|
||||
}
|
||||
|
||||
static int
|
||||
iptree_list_members_size(const struct ip_set *set)
|
||||
{
|
||||
const struct ip_set_iptree *map = set->data;
|
||||
struct ip_set_iptreeb *btree;
|
||||
struct ip_set_iptreec *ctree;
|
||||
struct ip_set_iptreed *dtree;
|
||||
unsigned int a,b,c,d;
|
||||
unsigned int count = 0;
|
||||
|
||||
LOOP_WALK_BEGIN(map, a, btree);
|
||||
LOOP_WALK_BEGIN(btree, b, ctree);
|
||||
LOOP_WALK_BEGIN(ctree, c, dtree);
|
||||
for (d = 0; d < 256; d++) {
|
||||
if (dtree->expires[d]
|
||||
&& (!map->timeout || time_after(dtree->expires[d], jiffies)))
|
||||
count++;
|
||||
}
|
||||
LOOP_WALK_END;
|
||||
LOOP_WALK_END;
|
||||
LOOP_WALK_END;
|
||||
|
||||
DP("members %u", count);
|
||||
return (count * sizeof(struct ip_set_req_iptree));
|
||||
}
|
||||
|
||||
static void
|
||||
iptree_list_members(const struct ip_set *set, void *data)
|
||||
{
|
||||
const struct ip_set_iptree *map = set->data;
|
||||
struct ip_set_iptreeb *btree;
|
||||
struct ip_set_iptreec *ctree;
|
||||
struct ip_set_iptreed *dtree;
|
||||
unsigned int a,b,c,d;
|
||||
size_t offset = 0;
|
||||
struct ip_set_req_iptree *entry;
|
||||
|
||||
LOOP_WALK_BEGIN(map, a, btree);
|
||||
LOOP_WALK_BEGIN(btree, b, ctree);
|
||||
LOOP_WALK_BEGIN(ctree, c, dtree);
|
||||
for (d = 0; d < 256; d++) {
|
||||
if (dtree->expires[d]
|
||||
&& (!map->timeout || time_after(dtree->expires[d], jiffies))) {
|
||||
entry = data + offset;
|
||||
entry->ip = ((a << 24) | (b << 16) | (c << 8) | d);
|
||||
entry->timeout = !map->timeout ? 0
|
||||
: (dtree->expires[d] - jiffies)/HZ;
|
||||
offset += sizeof(struct ip_set_req_iptree);
|
||||
}
|
||||
}
|
||||
LOOP_WALK_END;
|
||||
LOOP_WALK_END;
|
||||
LOOP_WALK_END;
|
||||
}
|
||||
|
||||
IP_SET_TYPE(iptree, IPSET_TYPE_IP | IPSET_DATA_SINGLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("iptree type of IP sets");
|
||||
module_param(limit, int, 0600);
|
||||
MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
|
||||
|
||||
static int __init ip_set_iptree_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
branch_cachep = KMEM_CACHE_CREATE("ip_set_iptreeb",
|
||||
sizeof(struct ip_set_iptreeb));
|
||||
if (!branch_cachep) {
|
||||
printk(KERN_ERR "Unable to create ip_set_iptreeb slab cache\n");
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
leaf_cachep = KMEM_CACHE_CREATE("ip_set_iptreed",
|
||||
sizeof(struct ip_set_iptreed));
|
||||
if (!leaf_cachep) {
|
||||
printk(KERN_ERR "Unable to create ip_set_iptreed slab cache\n");
|
||||
ret = -ENOMEM;
|
||||
goto free_branch;
|
||||
}
|
||||
ret = ip_set_register_set_type(&ip_set_iptree);
|
||||
if (ret == 0)
|
||||
goto out;
|
||||
|
||||
kmem_cache_destroy(leaf_cachep);
|
||||
free_branch:
|
||||
kmem_cache_destroy(branch_cachep);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit ip_set_iptree_fini(void)
|
||||
{
|
||||
/* FIXME: possible race with ip_set_create() */
|
||||
ip_set_unregister_set_type(&ip_set_iptree);
|
||||
kmem_cache_destroy(leaf_cachep);
|
||||
kmem_cache_destroy(branch_cachep);
|
||||
}
|
||||
|
||||
module_init(ip_set_iptree_init);
|
||||
module_exit(ip_set_iptree_fini);
|
39
extensions/ipset/ip_set_iptree.h
Normal file
39
extensions/ipset/ip_set_iptree.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef __IP_SET_IPTREE_H
|
||||
#define __IP_SET_IPTREE_H
|
||||
|
||||
#include "ip_set.h"
|
||||
|
||||
#define SETTYPE_NAME "iptree"
|
||||
|
||||
struct ip_set_iptreed {
|
||||
unsigned long expires[256]; /* x.x.x.ADDR */
|
||||
};
|
||||
|
||||
struct ip_set_iptreec {
|
||||
struct ip_set_iptreed *tree[256]; /* x.x.ADDR.* */
|
||||
};
|
||||
|
||||
struct ip_set_iptreeb {
|
||||
struct ip_set_iptreec *tree[256]; /* x.ADDR.*.* */
|
||||
};
|
||||
|
||||
struct ip_set_iptree {
|
||||
unsigned int timeout;
|
||||
unsigned int gc_interval;
|
||||
#ifdef __KERNEL__
|
||||
uint32_t elements; /* number of elements */
|
||||
struct timer_list gc;
|
||||
struct ip_set_iptreeb *tree[256]; /* ADDR.*.*.* */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ip_set_req_iptree_create {
|
||||
unsigned int timeout;
|
||||
};
|
||||
|
||||
struct ip_set_req_iptree {
|
||||
ip_set_ip_t ip;
|
||||
unsigned int timeout;
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_IPTREE_H */
|
708
extensions/ipset/ip_set_iptreemap.c
Normal file
708
extensions/ipset/ip_set_iptreemap.c
Normal file
@@ -0,0 +1,708 @@
|
||||
/* Copyright (C) 2007 Sven Wegener <sven.wegener@stealer.net>
|
||||
*
|
||||
* 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 modules implements the iptreemap ipset type. It uses bitmaps to
|
||||
* represent every single IPv4 address as a bit. The bitmaps are managed in a
|
||||
* tree structure, where the first three octets of an address are used as an
|
||||
* index to find the bitmap and the last octet is used as the bit number.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/timer.h>
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_bitmaps.h"
|
||||
#include "ip_set_iptreemap.h"
|
||||
|
||||
#define IPTREEMAP_DEFAULT_GC_TIME (5 * 60)
|
||||
#define IPTREEMAP_DESTROY_SLEEP (100)
|
||||
|
||||
static __KMEM_CACHE_T__ *cachep_b;
|
||||
static __KMEM_CACHE_T__ *cachep_c;
|
||||
static __KMEM_CACHE_T__ *cachep_d;
|
||||
|
||||
static struct ip_set_iptreemap_d *fullbitmap_d;
|
||||
static struct ip_set_iptreemap_c *fullbitmap_c;
|
||||
static struct ip_set_iptreemap_b *fullbitmap_b;
|
||||
|
||||
#if defined(__LITTLE_ENDIAN)
|
||||
#define ABCD(a, b, c, d, addr) \
|
||||
do { \
|
||||
a = ((unsigned char *)addr)[3]; \
|
||||
b = ((unsigned char *)addr)[2]; \
|
||||
c = ((unsigned char *)addr)[1]; \
|
||||
d = ((unsigned char *)addr)[0]; \
|
||||
} while (0)
|
||||
#elif defined(__BIG_ENDIAN)
|
||||
#define ABCD(a,b,c,d,addrp) do { \
|
||||
a = ((unsigned char *)addrp)[0]; \
|
||||
b = ((unsigned char *)addrp)[1]; \
|
||||
c = ((unsigned char *)addrp)[2]; \
|
||||
d = ((unsigned char *)addrp)[3]; \
|
||||
} while (0)
|
||||
#else
|
||||
#error "Please fix asm/byteorder.h"
|
||||
#endif /* __LITTLE_ENDIAN */
|
||||
|
||||
#define TESTIP_WALK(map, elem, branch, full) \
|
||||
do { \
|
||||
branch = (map)->tree[elem]; \
|
||||
if (!branch) \
|
||||
return 0; \
|
||||
else if (branch == full) \
|
||||
return 1; \
|
||||
} while (0)
|
||||
|
||||
#define ADDIP_WALK(map, elem, branch, type, cachep, full) \
|
||||
do { \
|
||||
branch = (map)->tree[elem]; \
|
||||
if (!branch) { \
|
||||
branch = (type *) kmem_cache_alloc(cachep, GFP_ATOMIC); \
|
||||
if (!branch) \
|
||||
return -ENOMEM; \
|
||||
memset(branch, 0, sizeof(*branch)); \
|
||||
(map)->tree[elem] = branch; \
|
||||
} else if (branch == full) { \
|
||||
return -EEXIST; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ADDIP_RANGE_LOOP(map, a, a1, a2, hint, branch, full, cachep, free) \
|
||||
for (a = a1; a <= a2; a++) { \
|
||||
branch = (map)->tree[a]; \
|
||||
if (branch != full) { \
|
||||
if ((a > a1 && a < a2) || (hint)) { \
|
||||
if (branch) \
|
||||
free(branch); \
|
||||
(map)->tree[a] = full; \
|
||||
continue; \
|
||||
} else if (!branch) { \
|
||||
branch = kmem_cache_alloc(cachep, GFP_ATOMIC); \
|
||||
if (!branch) \
|
||||
return -ENOMEM; \
|
||||
memset(branch, 0, sizeof(*branch)); \
|
||||
(map)->tree[a] = branch; \
|
||||
}
|
||||
|
||||
#define ADDIP_RANGE_LOOP_END() \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DELIP_WALK(map, elem, branch, cachep, full, flags) \
|
||||
do { \
|
||||
branch = (map)->tree[elem]; \
|
||||
if (!branch) { \
|
||||
return -EEXIST; \
|
||||
} else if (branch == full) { \
|
||||
branch = kmem_cache_alloc(cachep, flags); \
|
||||
if (!branch) \
|
||||
return -ENOMEM; \
|
||||
memcpy(branch, full, sizeof(*full)); \
|
||||
(map)->tree[elem] = branch; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DELIP_RANGE_LOOP(map, a, a1, a2, hint, branch, full, cachep, free, flags) \
|
||||
for (a = a1; a <= a2; a++) { \
|
||||
branch = (map)->tree[a]; \
|
||||
if (branch) { \
|
||||
if ((a > a1 && a < a2) || (hint)) { \
|
||||
if (branch != full) \
|
||||
free(branch); \
|
||||
(map)->tree[a] = NULL; \
|
||||
continue; \
|
||||
} else if (branch == full) { \
|
||||
branch = kmem_cache_alloc(cachep, flags); \
|
||||
if (!branch) \
|
||||
return -ENOMEM; \
|
||||
memcpy(branch, full, sizeof(*branch)); \
|
||||
(map)->tree[a] = branch; \
|
||||
}
|
||||
|
||||
#define DELIP_RANGE_LOOP_END() \
|
||||
} \
|
||||
}
|
||||
|
||||
#define LOOP_WALK_BEGIN(map, i, branch) \
|
||||
for (i = 0; i < 256; i++) { \
|
||||
branch = (map)->tree[i]; \
|
||||
if (likely(!branch)) \
|
||||
continue;
|
||||
|
||||
#define LOOP_WALK_END() \
|
||||
}
|
||||
|
||||
#define LOOP_WALK_BEGIN_GC(map, i, branch, full, cachep, count) \
|
||||
count = -256; \
|
||||
for (i = 0; i < 256; i++) { \
|
||||
branch = (map)->tree[i]; \
|
||||
if (likely(!branch)) \
|
||||
continue; \
|
||||
count++; \
|
||||
if (branch == full) { \
|
||||
count++; \
|
||||
continue; \
|
||||
}
|
||||
|
||||
#define LOOP_WALK_END_GC(map, i, branch, full, cachep, count) \
|
||||
if (-256 == count) { \
|
||||
kmem_cache_free(cachep, branch); \
|
||||
(map)->tree[i] = NULL; \
|
||||
} else if (256 == count) { \
|
||||
kmem_cache_free(cachep, branch); \
|
||||
(map)->tree[i] = full; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define LOOP_WALK_BEGIN_COUNT(map, i, branch, inrange, count) \
|
||||
for (i = 0; i < 256; i++) { \
|
||||
if (!(map)->tree[i]) { \
|
||||
if (inrange) { \
|
||||
count++; \
|
||||
inrange = 0; \
|
||||
} \
|
||||
continue; \
|
||||
} \
|
||||
branch = (map)->tree[i];
|
||||
|
||||
#define LOOP_WALK_END_COUNT() \
|
||||
}
|
||||
|
||||
#define GETVALUE1(a, a1, b1, r) \
|
||||
(a == a1 ? b1 : r)
|
||||
|
||||
#define GETVALUE2(a, b, a1, b1, c1, r) \
|
||||
(a == a1 && b == b1 ? c1 : r)
|
||||
|
||||
#define GETVALUE3(a, b, c, a1, b1, c1, d1, r) \
|
||||
(a == a1 && b == b1 && c == c1 ? d1 : r)
|
||||
|
||||
#define CHECK1(a, a1, a2, b1, b2, c1, c2, d1, d2) \
|
||||
( \
|
||||
GETVALUE1(a, a1, b1, 0) == 0 \
|
||||
&& GETVALUE1(a, a2, b2, 255) == 255 \
|
||||
&& c1 == 0 \
|
||||
&& c2 == 255 \
|
||||
&& d1 == 0 \
|
||||
&& d2 == 255 \
|
||||
)
|
||||
|
||||
#define CHECK2(a, b, a1, a2, b1, b2, c1, c2, d1, d2) \
|
||||
( \
|
||||
GETVALUE2(a, b, a1, b1, c1, 0) == 0 \
|
||||
&& GETVALUE2(a, b, a2, b2, c2, 255) == 255 \
|
||||
&& d1 == 0 \
|
||||
&& d2 == 255 \
|
||||
)
|
||||
|
||||
#define CHECK3(a, b, c, a1, a2, b1, b2, c1, c2, d1, d2) \
|
||||
( \
|
||||
GETVALUE3(a, b, c, a1, b1, c1, d1, 0) == 0 \
|
||||
&& GETVALUE3(a, b, c, a2, b2, c2, d2, 255) == 255 \
|
||||
)
|
||||
|
||||
|
||||
static inline void
|
||||
free_d(struct ip_set_iptreemap_d *map)
|
||||
{
|
||||
kmem_cache_free(cachep_d, map);
|
||||
}
|
||||
|
||||
static inline void
|
||||
free_c(struct ip_set_iptreemap_c *map)
|
||||
{
|
||||
struct ip_set_iptreemap_d *dtree;
|
||||
unsigned int i;
|
||||
|
||||
LOOP_WALK_BEGIN(map, i, dtree) {
|
||||
if (dtree != fullbitmap_d)
|
||||
free_d(dtree);
|
||||
} LOOP_WALK_END();
|
||||
|
||||
kmem_cache_free(cachep_c, map);
|
||||
}
|
||||
|
||||
static inline void
|
||||
free_b(struct ip_set_iptreemap_b *map)
|
||||
{
|
||||
struct ip_set_iptreemap_c *ctree;
|
||||
unsigned int i;
|
||||
|
||||
LOOP_WALK_BEGIN(map, i, ctree) {
|
||||
if (ctree != fullbitmap_c)
|
||||
free_c(ctree);
|
||||
} LOOP_WALK_END();
|
||||
|
||||
kmem_cache_free(cachep_b, map);
|
||||
}
|
||||
|
||||
static inline int
|
||||
iptreemap_test(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
struct ip_set_iptreemap_b *btree;
|
||||
struct ip_set_iptreemap_c *ctree;
|
||||
struct ip_set_iptreemap_d *dtree;
|
||||
unsigned char a, b, c, d;
|
||||
|
||||
*hash_ip = ip;
|
||||
|
||||
ABCD(a, b, c, d, hash_ip);
|
||||
|
||||
TESTIP_WALK(map, a, btree, fullbitmap_b);
|
||||
TESTIP_WALK(btree, b, ctree, fullbitmap_c);
|
||||
TESTIP_WALK(ctree, c, dtree, fullbitmap_d);
|
||||
|
||||
return !!test_bit(d, (void *) dtree->bitmap);
|
||||
}
|
||||
|
||||
#define KADT_CONDITION
|
||||
|
||||
UADT(iptreemap, test)
|
||||
KADT(iptreemap, test, ipaddr)
|
||||
|
||||
static inline int
|
||||
__addip_single(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data;
|
||||
struct ip_set_iptreemap_b *btree;
|
||||
struct ip_set_iptreemap_c *ctree;
|
||||
struct ip_set_iptreemap_d *dtree;
|
||||
unsigned char a, b, c, d;
|
||||
|
||||
*hash_ip = ip;
|
||||
|
||||
ABCD(a, b, c, d, hash_ip);
|
||||
|
||||
ADDIP_WALK(map, a, btree, struct ip_set_iptreemap_b, cachep_b, fullbitmap_b);
|
||||
ADDIP_WALK(btree, b, ctree, struct ip_set_iptreemap_c, cachep_c, fullbitmap_c);
|
||||
ADDIP_WALK(ctree, c, dtree, struct ip_set_iptreemap_d, cachep_d, fullbitmap_d);
|
||||
|
||||
if (__test_and_set_bit(d, (void *) dtree->bitmap))
|
||||
return -EEXIST;
|
||||
|
||||
__set_bit(b, (void *) btree->dirty);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
iptreemap_add(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t start, ip_set_ip_t end)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
struct ip_set_iptreemap_b *btree;
|
||||
struct ip_set_iptreemap_c *ctree;
|
||||
struct ip_set_iptreemap_d *dtree;
|
||||
unsigned int a, b, c, d;
|
||||
unsigned char a1, b1, c1, d1;
|
||||
unsigned char a2, b2, c2, d2;
|
||||
|
||||
if (start == end)
|
||||
return __addip_single(set, hash_ip, start);
|
||||
|
||||
*hash_ip = start;
|
||||
|
||||
ABCD(a1, b1, c1, d1, &start);
|
||||
ABCD(a2, b2, c2, d2, &end);
|
||||
|
||||
/* This is sooo ugly... */
|
||||
ADDIP_RANGE_LOOP(map, a, a1, a2, CHECK1(a, a1, a2, b1, b2, c1, c2, d1, d2), btree, fullbitmap_b, cachep_b, free_b) {
|
||||
ADDIP_RANGE_LOOP(btree, b, GETVALUE1(a, a1, b1, 0), GETVALUE1(a, a2, b2, 255), CHECK2(a, b, a1, a2, b1, b2, c1, c2, d1, d2), ctree, fullbitmap_c, cachep_c, free_c) {
|
||||
ADDIP_RANGE_LOOP(ctree, c, GETVALUE2(a, b, a1, b1, c1, 0), GETVALUE2(a, b, a2, b2, c2, 255), CHECK3(a, b, c, a1, a2, b1, b2, c1, c2, d1, d2), dtree, fullbitmap_d, cachep_d, free_d) {
|
||||
for (d = GETVALUE3(a, b, c, a1, b1, c1, d1, 0); d <= GETVALUE3(a, b, c, a2, b2, c2, d2, 255); d++)
|
||||
__set_bit(d, (void *) dtree->bitmap);
|
||||
__set_bit(b, (void *) btree->dirty);
|
||||
} ADDIP_RANGE_LOOP_END();
|
||||
} ADDIP_RANGE_LOOP_END();
|
||||
} ADDIP_RANGE_LOOP_END();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UADT0(iptreemap, add, min(req->ip, req->end), max(req->ip, req->end))
|
||||
KADT(iptreemap, add, ipaddr, ip)
|
||||
|
||||
static inline int
|
||||
__delip_single(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, unsigned int __nocast flags)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
struct ip_set_iptreemap_b *btree;
|
||||
struct ip_set_iptreemap_c *ctree;
|
||||
struct ip_set_iptreemap_d *dtree;
|
||||
unsigned char a,b,c,d;
|
||||
|
||||
*hash_ip = ip;
|
||||
|
||||
ABCD(a, b, c, d, hash_ip);
|
||||
|
||||
DELIP_WALK(map, a, btree, cachep_b, fullbitmap_b, flags);
|
||||
DELIP_WALK(btree, b, ctree, cachep_c, fullbitmap_c, flags);
|
||||
DELIP_WALK(ctree, c, dtree, cachep_d, fullbitmap_d, flags);
|
||||
|
||||
if (!__test_and_clear_bit(d, (void *) dtree->bitmap))
|
||||
return -EEXIST;
|
||||
|
||||
__set_bit(b, (void *) btree->dirty);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
iptreemap_del(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t start, ip_set_ip_t end, unsigned int __nocast flags)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
struct ip_set_iptreemap_b *btree;
|
||||
struct ip_set_iptreemap_c *ctree;
|
||||
struct ip_set_iptreemap_d *dtree;
|
||||
unsigned int a, b, c, d;
|
||||
unsigned char a1, b1, c1, d1;
|
||||
unsigned char a2, b2, c2, d2;
|
||||
|
||||
if (start == end)
|
||||
return __delip_single(set, hash_ip, start, flags);
|
||||
|
||||
*hash_ip = start;
|
||||
|
||||
ABCD(a1, b1, c1, d1, &start);
|
||||
ABCD(a2, b2, c2, d2, &end);
|
||||
|
||||
/* This is sooo ugly... */
|
||||
DELIP_RANGE_LOOP(map, a, a1, a2, CHECK1(a, a1, a2, b1, b2, c1, c2, d1, d2), btree, fullbitmap_b, cachep_b, free_b, flags) {
|
||||
DELIP_RANGE_LOOP(btree, b, GETVALUE1(a, a1, b1, 0), GETVALUE1(a, a2, b2, 255), CHECK2(a, b, a1, a2, b1, b2, c1, c2, d1, d2), ctree, fullbitmap_c, cachep_c, free_c, flags) {
|
||||
DELIP_RANGE_LOOP(ctree, c, GETVALUE2(a, b, a1, b1, c1, 0), GETVALUE2(a, b, a2, b2, c2, 255), CHECK3(a, b, c, a1, a2, b1, b2, c1, c2, d1, d2), dtree, fullbitmap_d, cachep_d, free_d, flags) {
|
||||
for (d = GETVALUE3(a, b, c, a1, b1, c1, d1, 0); d <= GETVALUE3(a, b, c, a2, b2, c2, d2, 255); d++)
|
||||
__clear_bit(d, (void *) dtree->bitmap);
|
||||
__set_bit(b, (void *) btree->dirty);
|
||||
} DELIP_RANGE_LOOP_END();
|
||||
} DELIP_RANGE_LOOP_END();
|
||||
} DELIP_RANGE_LOOP_END();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UADT0(iptreemap, del, min(req->ip, req->end), max(req->ip, req->end), GFP_KERNEL)
|
||||
KADT(iptreemap, del, ipaddr, ip, GFP_ATOMIC)
|
||||
|
||||
/* Check the status of the bitmap
|
||||
* -1 == all bits cleared
|
||||
* 1 == all bits set
|
||||
* 0 == anything else
|
||||
*/
|
||||
static inline int
|
||||
bitmap_status(struct ip_set_iptreemap_d *dtree)
|
||||
{
|
||||
unsigned char first = dtree->bitmap[0];
|
||||
int a;
|
||||
|
||||
for (a = 1; a < 32; a++)
|
||||
if (dtree->bitmap[a] != first)
|
||||
return 0;
|
||||
|
||||
return (first == 0 ? -1 : (first == 255 ? 1 : 0));
|
||||
}
|
||||
|
||||
static void
|
||||
gc(unsigned long addr)
|
||||
{
|
||||
struct ip_set *set = (struct ip_set *) addr;
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
struct ip_set_iptreemap_b *btree;
|
||||
struct ip_set_iptreemap_c *ctree;
|
||||
struct ip_set_iptreemap_d *dtree;
|
||||
unsigned int a, b, c;
|
||||
int i, j, k;
|
||||
|
||||
write_lock_bh(&set->lock);
|
||||
|
||||
LOOP_WALK_BEGIN_GC(map, a, btree, fullbitmap_b, cachep_b, i) {
|
||||
LOOP_WALK_BEGIN_GC(btree, b, ctree, fullbitmap_c, cachep_c, j) {
|
||||
if (!__test_and_clear_bit(b, (void *) btree->dirty))
|
||||
continue;
|
||||
LOOP_WALK_BEGIN_GC(ctree, c, dtree, fullbitmap_d, cachep_d, k) {
|
||||
switch (bitmap_status(dtree)) {
|
||||
case -1:
|
||||
kmem_cache_free(cachep_d, dtree);
|
||||
ctree->tree[c] = NULL;
|
||||
k--;
|
||||
break;
|
||||
case 1:
|
||||
kmem_cache_free(cachep_d, dtree);
|
||||
ctree->tree[c] = fullbitmap_d;
|
||||
k++;
|
||||
break;
|
||||
}
|
||||
} LOOP_WALK_END();
|
||||
} LOOP_WALK_END_GC(btree, b, ctree, fullbitmap_c, cachep_c, k);
|
||||
} LOOP_WALK_END_GC(map, a, btree, fullbitmap_b, cachep_b, j);
|
||||
|
||||
write_unlock_bh(&set->lock);
|
||||
|
||||
map->gc.expires = jiffies + map->gc_interval * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
static inline void
|
||||
init_gc_timer(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
|
||||
init_timer(&map->gc);
|
||||
map->gc.data = (unsigned long) set;
|
||||
map->gc.function = gc;
|
||||
map->gc.expires = jiffies + map->gc_interval * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
static int
|
||||
iptreemap_create(struct ip_set *set, const void *data, size_t size)
|
||||
{
|
||||
const struct ip_set_req_iptreemap_create *req = data;
|
||||
struct ip_set_iptreemap *map;
|
||||
|
||||
map = kzalloc(sizeof(*map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
|
||||
map->gc_interval = req->gc_interval ? req->gc_interval : IPTREEMAP_DEFAULT_GC_TIME;
|
||||
set->data = map;
|
||||
|
||||
init_gc_timer(set);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
__flush(struct ip_set_iptreemap *map)
|
||||
{
|
||||
struct ip_set_iptreemap_b *btree;
|
||||
unsigned int a;
|
||||
|
||||
LOOP_WALK_BEGIN(map, a, btree);
|
||||
if (btree != fullbitmap_b)
|
||||
free_b(btree);
|
||||
LOOP_WALK_END();
|
||||
}
|
||||
|
||||
static void
|
||||
iptreemap_destroy(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
|
||||
while (!del_timer(&map->gc))
|
||||
msleep(IPTREEMAP_DESTROY_SLEEP);
|
||||
|
||||
__flush(map);
|
||||
kfree(map);
|
||||
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
iptreemap_flush(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
|
||||
while (!del_timer(&map->gc))
|
||||
msleep(IPTREEMAP_DESTROY_SLEEP);
|
||||
|
||||
__flush(map);
|
||||
|
||||
memset(map, 0, sizeof(*map));
|
||||
|
||||
init_gc_timer(set);
|
||||
}
|
||||
|
||||
static void
|
||||
iptreemap_list_header(const struct ip_set *set, void *data)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
struct ip_set_req_iptreemap_create *header = data;
|
||||
|
||||
header->gc_interval = map->gc_interval;
|
||||
}
|
||||
|
||||
static int
|
||||
iptreemap_list_members_size(const struct ip_set *set)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
struct ip_set_iptreemap_b *btree;
|
||||
struct ip_set_iptreemap_c *ctree;
|
||||
struct ip_set_iptreemap_d *dtree;
|
||||
unsigned int a, b, c, d, inrange = 0, count = 0;
|
||||
|
||||
LOOP_WALK_BEGIN_COUNT(map, a, btree, inrange, count) {
|
||||
LOOP_WALK_BEGIN_COUNT(btree, b, ctree, inrange, count) {
|
||||
LOOP_WALK_BEGIN_COUNT(ctree, c, dtree, inrange, count) {
|
||||
for (d = 0; d < 256; d++) {
|
||||
if (test_bit(d, (void *) dtree->bitmap)) {
|
||||
inrange = 1;
|
||||
} else if (inrange) {
|
||||
count++;
|
||||
inrange = 0;
|
||||
}
|
||||
}
|
||||
} LOOP_WALK_END_COUNT();
|
||||
} LOOP_WALK_END_COUNT();
|
||||
} LOOP_WALK_END_COUNT();
|
||||
|
||||
if (inrange)
|
||||
count++;
|
||||
|
||||
return (count * sizeof(struct ip_set_req_iptreemap));
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
add_member(void *data, size_t offset, ip_set_ip_t start, ip_set_ip_t end)
|
||||
{
|
||||
struct ip_set_req_iptreemap *entry = data + offset;
|
||||
|
||||
entry->ip = start;
|
||||
entry->end = end;
|
||||
|
||||
return sizeof(*entry);
|
||||
}
|
||||
|
||||
static void
|
||||
iptreemap_list_members(const struct ip_set *set, void *data)
|
||||
{
|
||||
struct ip_set_iptreemap *map = set->data;
|
||||
struct ip_set_iptreemap_b *btree;
|
||||
struct ip_set_iptreemap_c *ctree;
|
||||
struct ip_set_iptreemap_d *dtree;
|
||||
unsigned int a, b, c, d, inrange = 0;
|
||||
size_t offset = 0;
|
||||
ip_set_ip_t start = 0, end = 0, ip;
|
||||
|
||||
LOOP_WALK_BEGIN(map, a, btree) {
|
||||
LOOP_WALK_BEGIN(btree, b, ctree) {
|
||||
LOOP_WALK_BEGIN(ctree, c, dtree) {
|
||||
for (d = 0; d < 256; d++) {
|
||||
if (test_bit(d, (void *) dtree->bitmap)) {
|
||||
ip = ((a << 24) | (b << 16) | (c << 8) | d);
|
||||
if (!inrange) {
|
||||
inrange = 1;
|
||||
start = ip;
|
||||
} else if (end < ip - 1) {
|
||||
offset += add_member(data, offset, start, end);
|
||||
start = ip;
|
||||
}
|
||||
end = ip;
|
||||
} else if (inrange) {
|
||||
offset += add_member(data, offset, start, end);
|
||||
inrange = 0;
|
||||
}
|
||||
}
|
||||
} LOOP_WALK_END();
|
||||
} LOOP_WALK_END();
|
||||
} LOOP_WALK_END();
|
||||
|
||||
if (inrange)
|
||||
add_member(data, offset, start, end);
|
||||
}
|
||||
|
||||
IP_SET_TYPE(iptreemap, IPSET_TYPE_IP | IPSET_DATA_SINGLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Sven Wegener <sven.wegener@stealer.net>");
|
||||
MODULE_DESCRIPTION("iptreemap type of IP sets");
|
||||
|
||||
static int __init ip_set_iptreemap_init(void)
|
||||
{
|
||||
int ret = -ENOMEM;
|
||||
int a;
|
||||
|
||||
cachep_b = KMEM_CACHE_CREATE("ip_set_iptreemap_b",
|
||||
sizeof(struct ip_set_iptreemap_b));
|
||||
if (!cachep_b) {
|
||||
ip_set_printk("Unable to create ip_set_iptreemap_b slab cache");
|
||||
goto out;
|
||||
}
|
||||
|
||||
cachep_c = KMEM_CACHE_CREATE("ip_set_iptreemap_c",
|
||||
sizeof(struct ip_set_iptreemap_c));
|
||||
if (!cachep_c) {
|
||||
ip_set_printk("Unable to create ip_set_iptreemap_c slab cache");
|
||||
goto outb;
|
||||
}
|
||||
|
||||
cachep_d = KMEM_CACHE_CREATE("ip_set_iptreemap_d",
|
||||
sizeof(struct ip_set_iptreemap_d));
|
||||
if (!cachep_d) {
|
||||
ip_set_printk("Unable to create ip_set_iptreemap_d slab cache");
|
||||
goto outc;
|
||||
}
|
||||
|
||||
fullbitmap_d = kmem_cache_alloc(cachep_d, GFP_KERNEL);
|
||||
if (!fullbitmap_d)
|
||||
goto outd;
|
||||
|
||||
fullbitmap_c = kmem_cache_alloc(cachep_c, GFP_KERNEL);
|
||||
if (!fullbitmap_c)
|
||||
goto outbitmapd;
|
||||
|
||||
fullbitmap_b = kmem_cache_alloc(cachep_b, GFP_KERNEL);
|
||||
if (!fullbitmap_b)
|
||||
goto outbitmapc;
|
||||
|
||||
ret = ip_set_register_set_type(&ip_set_iptreemap);
|
||||
if (0 > ret)
|
||||
goto outbitmapb;
|
||||
|
||||
/* Now init our global bitmaps */
|
||||
memset(fullbitmap_d->bitmap, 0xff, sizeof(fullbitmap_d->bitmap));
|
||||
|
||||
for (a = 0; a < 256; a++)
|
||||
fullbitmap_c->tree[a] = fullbitmap_d;
|
||||
|
||||
for (a = 0; a < 256; a++)
|
||||
fullbitmap_b->tree[a] = fullbitmap_c;
|
||||
memset(fullbitmap_b->dirty, 0, sizeof(fullbitmap_b->dirty));
|
||||
|
||||
return 0;
|
||||
|
||||
outbitmapb:
|
||||
kmem_cache_free(cachep_b, fullbitmap_b);
|
||||
outbitmapc:
|
||||
kmem_cache_free(cachep_c, fullbitmap_c);
|
||||
outbitmapd:
|
||||
kmem_cache_free(cachep_d, fullbitmap_d);
|
||||
outd:
|
||||
kmem_cache_destroy(cachep_d);
|
||||
outc:
|
||||
kmem_cache_destroy(cachep_c);
|
||||
outb:
|
||||
kmem_cache_destroy(cachep_b);
|
||||
out:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit ip_set_iptreemap_fini(void)
|
||||
{
|
||||
ip_set_unregister_set_type(&ip_set_iptreemap);
|
||||
kmem_cache_free(cachep_d, fullbitmap_d);
|
||||
kmem_cache_free(cachep_c, fullbitmap_c);
|
||||
kmem_cache_free(cachep_b, fullbitmap_b);
|
||||
kmem_cache_destroy(cachep_d);
|
||||
kmem_cache_destroy(cachep_c);
|
||||
kmem_cache_destroy(cachep_b);
|
||||
}
|
||||
|
||||
module_init(ip_set_iptreemap_init);
|
||||
module_exit(ip_set_iptreemap_fini);
|
40
extensions/ipset/ip_set_iptreemap.h
Normal file
40
extensions/ipset/ip_set_iptreemap.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef __IP_SET_IPTREEMAP_H
|
||||
#define __IP_SET_IPTREEMAP_H
|
||||
|
||||
#include "ip_set.h"
|
||||
|
||||
#define SETTYPE_NAME "iptreemap"
|
||||
|
||||
#ifdef __KERNEL__
|
||||
struct ip_set_iptreemap_d {
|
||||
unsigned char bitmap[32]; /* x.x.x.y */
|
||||
};
|
||||
|
||||
struct ip_set_iptreemap_c {
|
||||
struct ip_set_iptreemap_d *tree[256]; /* x.x.y.x */
|
||||
};
|
||||
|
||||
struct ip_set_iptreemap_b {
|
||||
struct ip_set_iptreemap_c *tree[256]; /* x.y.x.x */
|
||||
unsigned char dirty[32];
|
||||
};
|
||||
#endif
|
||||
|
||||
struct ip_set_iptreemap {
|
||||
unsigned int gc_interval;
|
||||
#ifdef __KERNEL__
|
||||
struct timer_list gc;
|
||||
struct ip_set_iptreemap_b *tree[256]; /* y.x.x.x */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ip_set_req_iptreemap_create {
|
||||
unsigned int gc_interval;
|
||||
};
|
||||
|
||||
struct ip_set_req_iptreemap {
|
||||
ip_set_ip_t ip;
|
||||
ip_set_ip_t end;
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_IPTREEMAP_H */
|
148
extensions/ipset/ip_set_jhash.h
Normal file
148
extensions/ipset/ip_set_jhash.h
Normal file
@@ -0,0 +1,148 @@
|
||||
#ifndef _LINUX_IPSET_JHASH_H
|
||||
#define _LINUX_IPSET_JHASH_H
|
||||
|
||||
/* This is a copy of linux/jhash.h but the types u32/u8 are changed
|
||||
* to __u32/__u8 so that the header file can be included into
|
||||
* userspace code as well. Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*/
|
||||
|
||||
/* jhash.h: Jenkins hash support.
|
||||
*
|
||||
* Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
|
||||
*
|
||||
* http://burtleburtle.net/bob/hash/
|
||||
*
|
||||
* These are the credits from Bob's sources:
|
||||
*
|
||||
* lookup2.c, by Bob Jenkins, December 1996, Public Domain.
|
||||
* hash(), hash2(), hash3, and mix() are externally useful functions.
|
||||
* Routines to test the hash are included if SELF_TEST is defined.
|
||||
* You can use this free for any purpose. It has no warranty.
|
||||
*
|
||||
* Copyright (C) 2003 David S. Miller (davem@redhat.com)
|
||||
*
|
||||
* I've modified Bob's hash to be useful in the Linux kernel, and
|
||||
* any bugs present are surely my fault. -DaveM
|
||||
*/
|
||||
|
||||
/* NOTE: Arguments are modified. */
|
||||
#define __jhash_mix(a, b, c) \
|
||||
{ \
|
||||
a -= b; a -= c; a ^= (c>>13); \
|
||||
b -= c; b -= a; b ^= (a<<8); \
|
||||
c -= a; c -= b; c ^= (b>>13); \
|
||||
a -= b; a -= c; a ^= (c>>12); \
|
||||
b -= c; b -= a; b ^= (a<<16); \
|
||||
c -= a; c -= b; c ^= (b>>5); \
|
||||
a -= b; a -= c; a ^= (c>>3); \
|
||||
b -= c; b -= a; b ^= (a<<10); \
|
||||
c -= a; c -= b; c ^= (b>>15); \
|
||||
}
|
||||
|
||||
/* The golden ration: an arbitrary value */
|
||||
#define JHASH_GOLDEN_RATIO 0x9e3779b9
|
||||
|
||||
/* The most generic version, hashes an arbitrary sequence
|
||||
* of bytes. No alignment or length assumptions are made about
|
||||
* the input key.
|
||||
*/
|
||||
static inline __u32 jhash(void *key, __u32 length, __u32 initval)
|
||||
{
|
||||
__u32 a, b, c, len;
|
||||
__u8 *k = key;
|
||||
|
||||
len = length;
|
||||
a = b = JHASH_GOLDEN_RATIO;
|
||||
c = initval;
|
||||
|
||||
while (len >= 12) {
|
||||
a += (k[0] +((__u32)k[1]<<8) +((__u32)k[2]<<16) +((__u32)k[3]<<24));
|
||||
b += (k[4] +((__u32)k[5]<<8) +((__u32)k[6]<<16) +((__u32)k[7]<<24));
|
||||
c += (k[8] +((__u32)k[9]<<8) +((__u32)k[10]<<16)+((__u32)k[11]<<24));
|
||||
|
||||
__jhash_mix(a,b,c);
|
||||
|
||||
k += 12;
|
||||
len -= 12;
|
||||
}
|
||||
|
||||
c += length;
|
||||
switch (len) {
|
||||
case 11: c += ((__u32)k[10]<<24);
|
||||
case 10: c += ((__u32)k[9]<<16);
|
||||
case 9 : c += ((__u32)k[8]<<8);
|
||||
case 8 : b += ((__u32)k[7]<<24);
|
||||
case 7 : b += ((__u32)k[6]<<16);
|
||||
case 6 : b += ((__u32)k[5]<<8);
|
||||
case 5 : b += k[4];
|
||||
case 4 : a += ((__u32)k[3]<<24);
|
||||
case 3 : a += ((__u32)k[2]<<16);
|
||||
case 2 : a += ((__u32)k[1]<<8);
|
||||
case 1 : a += k[0];
|
||||
};
|
||||
|
||||
__jhash_mix(a,b,c);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/* A special optimized version that handles 1 or more of __u32s.
|
||||
* The length parameter here is the number of __u32s in the key.
|
||||
*/
|
||||
static inline __u32 jhash2(__u32 *k, __u32 length, __u32 initval)
|
||||
{
|
||||
__u32 a, b, c, len;
|
||||
|
||||
a = b = JHASH_GOLDEN_RATIO;
|
||||
c = initval;
|
||||
len = length;
|
||||
|
||||
while (len >= 3) {
|
||||
a += k[0];
|
||||
b += k[1];
|
||||
c += k[2];
|
||||
__jhash_mix(a, b, c);
|
||||
k += 3; len -= 3;
|
||||
}
|
||||
|
||||
c += length * 4;
|
||||
|
||||
switch (len) {
|
||||
case 2 : b += k[1];
|
||||
case 1 : a += k[0];
|
||||
};
|
||||
|
||||
__jhash_mix(a,b,c);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/* A special ultra-optimized versions that knows they are hashing exactly
|
||||
* 3, 2 or 1 word(s).
|
||||
*
|
||||
* NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
|
||||
* done at the end is not done here.
|
||||
*/
|
||||
static inline __u32 jhash_3words(__u32 a, __u32 b, __u32 c, __u32 initval)
|
||||
{
|
||||
a += JHASH_GOLDEN_RATIO;
|
||||
b += JHASH_GOLDEN_RATIO;
|
||||
c += initval;
|
||||
|
||||
__jhash_mix(a, b, c);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline __u32 jhash_2words(__u32 a, __u32 b, __u32 initval)
|
||||
{
|
||||
return jhash_3words(a, b, 0, initval);
|
||||
}
|
||||
|
||||
static inline __u32 jhash_1word(__u32 a, __u32 initval)
|
||||
{
|
||||
return jhash_3words(a, 0, 0, initval);
|
||||
}
|
||||
|
||||
#endif /* _LINUX_IPSET_JHASH_H */
|
166
extensions/ipset/ip_set_macipmap.c
Normal file
166
extensions/ipset/ip_set_macipmap.c
Normal file
@@ -0,0 +1,166 @@
|
||||
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
|
||||
* Patrick Schaaf <bof@bof.de>
|
||||
* Martin Josefsson <gandalf@wlug.westbo.se>
|
||||
* Copyright (C) 2003-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the macipmap type */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/if_ether.h>
|
||||
|
||||
#include "ip_set_macipmap.h"
|
||||
|
||||
static int
|
||||
macipmap_utest(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
{
|
||||
const struct ip_set_macipmap *map = set->data;
|
||||
const struct ip_set_macip *table = map->members;
|
||||
const struct ip_set_req_macipmap *req = data;
|
||||
|
||||
if (req->ip < map->first_ip || req->ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
*hash_ip = req->ip;
|
||||
DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u",
|
||||
set->name, HIPQUAD(req->ip), HIPQUAD(*hash_ip));
|
||||
if (test_bit(IPSET_MACIP_ISSET,
|
||||
(void *) &table[req->ip - map->first_ip].flags)) {
|
||||
return (memcmp(req->ethernet,
|
||||
&table[req->ip - map->first_ip].ethernet,
|
||||
ETH_ALEN) == 0);
|
||||
} else {
|
||||
return (map->flags & IPSET_MACIP_MATCHUNSET ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
macipmap_ktest(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
const struct ip_set_macipmap *map = set->data;
|
||||
const struct ip_set_macip *table = map->members;
|
||||
ip_set_ip_t ip;
|
||||
|
||||
ip = ipaddr(skb, flags[index]);
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return 0;
|
||||
|
||||
*hash_ip = ip;
|
||||
DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u",
|
||||
set->name, HIPQUAD(ip), HIPQUAD(*hash_ip));
|
||||
if (test_bit(IPSET_MACIP_ISSET,
|
||||
(void *) &table[ip - map->first_ip].flags)) {
|
||||
/* Is mac pointer valid?
|
||||
* If so, compare... */
|
||||
return (skb_mac_header(skb) >= skb->head
|
||||
&& (skb_mac_header(skb) + ETH_HLEN) <= skb->data
|
||||
&& (memcmp(eth_hdr(skb)->h_source,
|
||||
&table[ip - map->first_ip].ethernet,
|
||||
ETH_ALEN) == 0));
|
||||
} else {
|
||||
return (map->flags & IPSET_MACIP_MATCHUNSET ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* returns 0 on success */
|
||||
static inline int
|
||||
macipmap_add(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, const unsigned char *ethernet)
|
||||
{
|
||||
struct ip_set_macipmap *map = set->data;
|
||||
struct ip_set_macip *table = map->members;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
if (test_and_set_bit(IPSET_MACIP_ISSET,
|
||||
(void *) &table[ip - map->first_ip].flags))
|
||||
return -EEXIST;
|
||||
|
||||
*hash_ip = ip;
|
||||
DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip));
|
||||
memcpy(&table[ip - map->first_ip].ethernet, ethernet, ETH_ALEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define KADT_CONDITION \
|
||||
if (!(skb_mac_header(skb) >= skb->head \
|
||||
&& (skb_mac_header(skb) + ETH_HLEN) <= skb->data))\
|
||||
return -EINVAL;
|
||||
|
||||
UADT(macipmap, add, req->ethernet)
|
||||
KADT(macipmap, add, ipaddr, eth_hdr(skb)->h_source)
|
||||
|
||||
static inline int
|
||||
macipmap_del(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
struct ip_set_macipmap *map = set->data;
|
||||
struct ip_set_macip *table = map->members;
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -ERANGE;
|
||||
if (!test_and_clear_bit(IPSET_MACIP_ISSET,
|
||||
(void *)&table[ip - map->first_ip].flags))
|
||||
return -EEXIST;
|
||||
|
||||
*hash_ip = ip;
|
||||
DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef KADT_CONDITION
|
||||
#define KADT_CONDITION
|
||||
|
||||
UADT(macipmap, del)
|
||||
KADT(macipmap, del, ipaddr)
|
||||
|
||||
static inline int
|
||||
__macipmap_create(const struct ip_set_req_macipmap_create *req,
|
||||
struct ip_set_macipmap *map)
|
||||
{
|
||||
if (req->to - req->from > MAX_RANGE) {
|
||||
ip_set_printk("range too big, %d elements (max %d)",
|
||||
req->to - req->from + 1, MAX_RANGE+1);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
map->flags = req->flags;
|
||||
return (req->to - req->from + 1) * sizeof(struct ip_set_macip);
|
||||
}
|
||||
|
||||
BITMAP_CREATE(macipmap)
|
||||
BITMAP_DESTROY(macipmap)
|
||||
BITMAP_FLUSH(macipmap)
|
||||
|
||||
static inline void
|
||||
__macipmap_list_header(const struct ip_set_macipmap *map,
|
||||
struct ip_set_req_macipmap_create *header)
|
||||
{
|
||||
header->flags = map->flags;
|
||||
}
|
||||
|
||||
BITMAP_LIST_HEADER(macipmap)
|
||||
BITMAP_LIST_MEMBERS_SIZE(macipmap)
|
||||
BITMAP_LIST_MEMBERS(macipmap)
|
||||
|
||||
IP_SET_TYPE(macipmap, IPSET_TYPE_IP | IPSET_DATA_SINGLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("macipmap type of IP sets");
|
||||
|
||||
REGISTER_MODULE(macipmap)
|
39
extensions/ipset/ip_set_macipmap.h
Normal file
39
extensions/ipset/ip_set_macipmap.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef __IP_SET_MACIPMAP_H
|
||||
#define __IP_SET_MACIPMAP_H
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_bitmaps.h"
|
||||
|
||||
#define SETTYPE_NAME "macipmap"
|
||||
|
||||
/* general flags */
|
||||
#define IPSET_MACIP_MATCHUNSET 1
|
||||
|
||||
/* per ip flags */
|
||||
#define IPSET_MACIP_ISSET 1
|
||||
|
||||
struct ip_set_macipmap {
|
||||
void *members; /* the macipmap proper */
|
||||
ip_set_ip_t first_ip; /* host byte order, included in range */
|
||||
ip_set_ip_t last_ip; /* host byte order, included in range */
|
||||
u_int32_t flags;
|
||||
size_t size; /* size of the ipmap proper */
|
||||
};
|
||||
|
||||
struct ip_set_req_macipmap_create {
|
||||
ip_set_ip_t from;
|
||||
ip_set_ip_t to;
|
||||
u_int32_t flags;
|
||||
};
|
||||
|
||||
struct ip_set_req_macipmap {
|
||||
ip_set_ip_t ip;
|
||||
unsigned char ethernet[ETH_ALEN];
|
||||
};
|
||||
|
||||
struct ip_set_macip {
|
||||
unsigned short flags;
|
||||
unsigned char ethernet[ETH_ALEN];
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_MACIPMAP_H */
|
153
extensions/ipset/ip_set_malloc.h
Normal file
153
extensions/ipset/ip_set_malloc.h
Normal file
@@ -0,0 +1,153 @@
|
||||
#ifndef _IP_SET_MALLOC_H
|
||||
#define _IP_SET_MALLOC_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
static size_t max_malloc_size = 0, max_page_size = 0;
|
||||
static size_t default_max_malloc_size = 131072; /* Guaranteed: slab.c */
|
||||
|
||||
static inline int init_max_page_size(void)
|
||||
{
|
||||
/* Compatibility glues to support 2.4.36 */
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
|
||||
#define __GFP_NOWARN 0
|
||||
|
||||
/* Guaranteed: slab.c */
|
||||
max_malloc_size = max_page_size = default_max_malloc_size;
|
||||
#else
|
||||
size_t page_size = 0;
|
||||
|
||||
#define CACHE(x) if (max_page_size == 0 || x < max_page_size) \
|
||||
page_size = x;
|
||||
#include <linux/kmalloc_sizes.h>
|
||||
#undef CACHE
|
||||
if (page_size) {
|
||||
if (max_malloc_size == 0)
|
||||
max_malloc_size = page_size;
|
||||
|
||||
max_page_size = page_size;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct harray {
|
||||
size_t max_elements;
|
||||
void *arrays[0];
|
||||
};
|
||||
|
||||
static inline void *
|
||||
__harray_malloc(size_t hashsize, size_t typesize, int flags)
|
||||
{
|
||||
struct harray *harray;
|
||||
size_t max_elements, size, i, j;
|
||||
|
||||
BUG_ON(max_page_size == 0);
|
||||
|
||||
if (typesize > max_page_size)
|
||||
return NULL;
|
||||
|
||||
max_elements = max_page_size/typesize;
|
||||
size = hashsize/max_elements;
|
||||
if (hashsize % max_elements)
|
||||
size++;
|
||||
|
||||
/* Last pointer signals end of arrays */
|
||||
harray = kmalloc(sizeof(struct harray) + (size + 1) * sizeof(void *),
|
||||
flags);
|
||||
|
||||
if (!harray)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < size - 1; i++) {
|
||||
harray->arrays[i] = kmalloc(max_elements * typesize, flags);
|
||||
if (!harray->arrays[i])
|
||||
goto undo;
|
||||
memset(harray->arrays[i], 0, max_elements * typesize);
|
||||
}
|
||||
harray->arrays[i] = kmalloc((hashsize - i * max_elements) * typesize,
|
||||
flags);
|
||||
if (!harray->arrays[i])
|
||||
goto undo;
|
||||
memset(harray->arrays[i], 0, (hashsize - i * max_elements) * typesize);
|
||||
|
||||
harray->max_elements = max_elements;
|
||||
harray->arrays[size] = NULL;
|
||||
|
||||
return (void *)harray;
|
||||
|
||||
undo:
|
||||
for (j = 0; j < i; j++) {
|
||||
kfree(harray->arrays[j]);
|
||||
}
|
||||
kfree(harray);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void *
|
||||
harray_malloc(size_t hashsize, size_t typesize, int flags)
|
||||
{
|
||||
void *harray;
|
||||
|
||||
do {
|
||||
harray = __harray_malloc(hashsize, typesize, flags|__GFP_NOWARN);
|
||||
} while (harray == NULL && init_max_page_size());
|
||||
|
||||
return harray;
|
||||
}
|
||||
|
||||
static inline void harray_free(void *h)
|
||||
{
|
||||
struct harray *harray = (struct harray *) h;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; harray->arrays[i] != NULL; i++)
|
||||
kfree(harray->arrays[i]);
|
||||
kfree(harray);
|
||||
}
|
||||
|
||||
static inline void harray_flush(void *h, size_t hashsize, size_t typesize)
|
||||
{
|
||||
struct harray *harray = (struct harray *) h;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; harray->arrays[i+1] != NULL; i++)
|
||||
memset(harray->arrays[i], 0, harray->max_elements * typesize);
|
||||
memset(harray->arrays[i], 0,
|
||||
(hashsize - i * harray->max_elements) * typesize);
|
||||
}
|
||||
|
||||
#define HARRAY_ELEM(h, type, which) \
|
||||
({ \
|
||||
struct harray *__h = (struct harray *)(h); \
|
||||
((type)((__h)->arrays[(which)/(__h)->max_elements]) \
|
||||
+ (which)%(__h)->max_elements); \
|
||||
})
|
||||
|
||||
/* General memory allocation and deallocation */
|
||||
static inline void * ip_set_malloc(size_t bytes)
|
||||
{
|
||||
BUG_ON(max_malloc_size == 0);
|
||||
|
||||
if (bytes > default_max_malloc_size)
|
||||
return vmalloc(bytes);
|
||||
else
|
||||
return kmalloc(bytes, GFP_KERNEL | __GFP_NOWARN);
|
||||
}
|
||||
|
||||
static inline void ip_set_free(void * data, size_t bytes)
|
||||
{
|
||||
BUG_ON(max_malloc_size == 0);
|
||||
|
||||
if (bytes > default_max_malloc_size)
|
||||
vfree(data);
|
||||
else
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /*_IP_SET_MALLOC_H*/
|
220
extensions/ipset/ip_set_nethash.c
Normal file
220
extensions/ipset/ip_set_nethash.c
Normal file
@@ -0,0 +1,220 @@
|
||||
/* Copyright (C) 2003-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing a cidr nethash set */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/jhash.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include <net/ip.h>
|
||||
|
||||
#include "ip_set_nethash.h"
|
||||
|
||||
static int limit = MAX_RANGE;
|
||||
|
||||
static inline __u32
|
||||
nethash_id_cidr(const struct ip_set_nethash *map,
|
||||
ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip,
|
||||
uint8_t cidr)
|
||||
{
|
||||
__u32 id;
|
||||
u_int16_t i;
|
||||
ip_set_ip_t *elem;
|
||||
|
||||
*hash_ip = pack_ip_cidr(ip, cidr);
|
||||
if (!*hash_ip)
|
||||
return MAX_RANGE;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
id = jhash_ip(map, i, *hash_ip) % map->hashsize;
|
||||
DP("hash key: %u", id);
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
|
||||
if (*elem == *hash_ip)
|
||||
return id;
|
||||
}
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
static inline __u32
|
||||
nethash_id(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
const struct ip_set_nethash *map = set->data;
|
||||
__u32 id = UINT_MAX;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 30 && map->cidr[i]; i++) {
|
||||
id = nethash_id_cidr(map, hash_ip, ip, map->cidr[i]);
|
||||
if (id != UINT_MAX)
|
||||
break;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
static inline int
|
||||
nethash_test_cidr(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, uint8_t cidr)
|
||||
{
|
||||
const struct ip_set_nethash *map = set->data;
|
||||
|
||||
return (nethash_id_cidr(map, hash_ip, ip, cidr) != UINT_MAX);
|
||||
}
|
||||
|
||||
static inline int
|
||||
nethash_test(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip)
|
||||
{
|
||||
return (nethash_id(set, hash_ip, ip) != UINT_MAX);
|
||||
}
|
||||
|
||||
static int
|
||||
nethash_utest(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
{
|
||||
const struct ip_set_req_nethash *req = data;
|
||||
|
||||
if (req->cidr <= 0 || req->cidr > 32)
|
||||
return -EINVAL;
|
||||
return (req->cidr == 32 ? nethash_test(set, hash_ip, req->ip)
|
||||
: nethash_test_cidr(set, hash_ip, req->ip, req->cidr));
|
||||
}
|
||||
|
||||
#define KADT_CONDITION
|
||||
|
||||
KADT(nethash, test, ipaddr)
|
||||
|
||||
static inline int
|
||||
__nethash_add(struct ip_set_nethash *map, ip_set_ip_t *ip)
|
||||
{
|
||||
__u32 probe;
|
||||
u_int16_t i;
|
||||
ip_set_ip_t *elem;
|
||||
|
||||
for (i = 0; i < map->probes; i++) {
|
||||
probe = jhash_ip(map, i, *ip) % map->hashsize;
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe);
|
||||
if (*elem == *ip)
|
||||
return -EEXIST;
|
||||
if (!*elem) {
|
||||
*elem = *ip;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Trigger rehashing */
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
static inline int
|
||||
nethash_add(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, uint8_t cidr)
|
||||
{
|
||||
struct ip_set_nethash *map = set->data;
|
||||
int ret;
|
||||
|
||||
if (map->elements >= limit || map->nets[cidr-1] == UINT16_MAX)
|
||||
return -ERANGE;
|
||||
if (cidr <= 0 || cidr >= 32)
|
||||
return -EINVAL;
|
||||
|
||||
*hash_ip = pack_ip_cidr(ip, cidr);
|
||||
DP("%u.%u.%u.%u/%u, %u.%u.%u.%u", HIPQUAD(ip), cidr, HIPQUAD(*hash_ip));
|
||||
if (!*hash_ip)
|
||||
return -ERANGE;
|
||||
|
||||
ret = __nethash_add(map, hash_ip);
|
||||
if (ret == 0) {
|
||||
if (!map->nets[cidr-1]++)
|
||||
add_cidr_size(map->cidr, cidr);
|
||||
map->elements++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef KADT_CONDITION
|
||||
#define KADT_CONDITION \
|
||||
struct ip_set_nethash *map = set->data; \
|
||||
uint8_t cidr = map->cidr[0] ? map->cidr[0] : 31;
|
||||
|
||||
UADT(nethash, add, req->cidr)
|
||||
KADT(nethash, add, ipaddr, cidr)
|
||||
|
||||
static inline void
|
||||
__nethash_retry(struct ip_set_nethash *tmp, struct ip_set_nethash *map)
|
||||
{
|
||||
memcpy(tmp->cidr, map->cidr, sizeof(tmp->cidr));
|
||||
memcpy(tmp->nets, map->nets, sizeof(tmp->nets));
|
||||
}
|
||||
|
||||
HASH_RETRY(nethash, ip_set_ip_t)
|
||||
|
||||
static inline int
|
||||
nethash_del(struct ip_set *set, ip_set_ip_t *hash_ip,
|
||||
ip_set_ip_t ip, uint8_t cidr)
|
||||
{
|
||||
struct ip_set_nethash *map = set->data;
|
||||
ip_set_ip_t id, *elem;
|
||||
|
||||
if (cidr <= 0 || cidr >= 32)
|
||||
return -EINVAL;
|
||||
|
||||
id = nethash_id_cidr(map, hash_ip, ip, cidr);
|
||||
if (id == UINT_MAX)
|
||||
return -EEXIST;
|
||||
|
||||
elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
|
||||
*elem = 0;
|
||||
map->elements--;
|
||||
if (!map->nets[cidr-1]--)
|
||||
del_cidr_size(map->cidr, cidr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
UADT(nethash, del, req->cidr)
|
||||
KADT(nethash, del, ipaddr, cidr)
|
||||
|
||||
static inline int
|
||||
__nethash_create(const struct ip_set_req_nethash_create *req,
|
||||
struct ip_set_nethash *map)
|
||||
{
|
||||
memset(map->cidr, 0, sizeof(map->cidr));
|
||||
memset(map->nets, 0, sizeof(map->nets));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
HASH_CREATE(nethash, ip_set_ip_t)
|
||||
HASH_DESTROY(nethash)
|
||||
|
||||
HASH_FLUSH_CIDR(nethash, ip_set_ip_t)
|
||||
|
||||
static inline void
|
||||
__nethash_list_header(const struct ip_set_nethash *map,
|
||||
struct ip_set_req_nethash_create *header)
|
||||
{
|
||||
}
|
||||
|
||||
HASH_LIST_HEADER(nethash)
|
||||
HASH_LIST_MEMBERS_SIZE(nethash, ip_set_ip_t)
|
||||
HASH_LIST_MEMBERS(nethash, ip_set_ip_t)
|
||||
|
||||
IP_SET_RTYPE(nethash, IPSET_TYPE_IP | IPSET_DATA_SINGLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("nethash type of IP sets");
|
||||
module_param(limit, int, 0600);
|
||||
MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
|
||||
|
||||
REGISTER_MODULE(nethash)
|
31
extensions/ipset/ip_set_nethash.h
Normal file
31
extensions/ipset/ip_set_nethash.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef __IP_SET_NETHASH_H
|
||||
#define __IP_SET_NETHASH_H
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_hashes.h"
|
||||
|
||||
#define SETTYPE_NAME "nethash"
|
||||
|
||||
struct ip_set_nethash {
|
||||
ip_set_ip_t *members; /* the nethash proper */
|
||||
uint32_t elements; /* number of elements */
|
||||
uint32_t hashsize; /* hash size */
|
||||
uint16_t probes; /* max number of probes */
|
||||
uint16_t resize; /* resize factor in percent */
|
||||
uint8_t cidr[30]; /* CIDR sizes */
|
||||
uint16_t nets[30]; /* nr of nets by CIDR sizes */
|
||||
initval_t initval[0]; /* initvals for jhash_1word */
|
||||
};
|
||||
|
||||
struct ip_set_req_nethash_create {
|
||||
uint32_t hashsize;
|
||||
uint16_t probes;
|
||||
uint16_t resize;
|
||||
};
|
||||
|
||||
struct ip_set_req_nethash {
|
||||
ip_set_ip_t ip;
|
||||
uint8_t cidr;
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_NETHASH_H */
|
114
extensions/ipset/ip_set_portmap.c
Normal file
114
extensions/ipset/ip_set_portmap.c
Normal file
@@ -0,0 +1,114 @@
|
||||
/* Copyright (C) 2003-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing a port set type as a bitmap */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <net/ip.h>
|
||||
|
||||
#include "ip_set_portmap.h"
|
||||
#include "ip_set_getport.h"
|
||||
|
||||
static inline int
|
||||
portmap_test(const struct ip_set *set, ip_set_ip_t *hash_port,
|
||||
ip_set_ip_t port)
|
||||
{
|
||||
const struct ip_set_portmap *map = set->data;
|
||||
|
||||
if (port < map->first_ip || port > map->last_ip)
|
||||
return -ERANGE;
|
||||
|
||||
*hash_port = port;
|
||||
DP("set: %s, port:%u, %u", set->name, port, *hash_port);
|
||||
return !!test_bit(port - map->first_ip, map->members);
|
||||
}
|
||||
|
||||
#define KADT_CONDITION \
|
||||
if (ip == INVALID_PORT) \
|
||||
return 0;
|
||||
|
||||
UADT(portmap, test)
|
||||
KADT(portmap, test, get_port)
|
||||
|
||||
static inline int
|
||||
portmap_add(struct ip_set *set, ip_set_ip_t *hash_port, ip_set_ip_t port)
|
||||
{
|
||||
struct ip_set_portmap *map = set->data;
|
||||
|
||||
if (port < map->first_ip || port > map->last_ip)
|
||||
return -ERANGE;
|
||||
if (test_and_set_bit(port - map->first_ip, map->members))
|
||||
return -EEXIST;
|
||||
|
||||
*hash_port = port;
|
||||
DP("port %u", port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
UADT(portmap, add)
|
||||
KADT(portmap, add, get_port)
|
||||
|
||||
static inline int
|
||||
portmap_del(struct ip_set *set, ip_set_ip_t *hash_port, ip_set_ip_t port)
|
||||
{
|
||||
struct ip_set_portmap *map = set->data;
|
||||
|
||||
if (port < map->first_ip || port > map->last_ip)
|
||||
return -ERANGE;
|
||||
if (!test_and_clear_bit(port - map->first_ip, map->members))
|
||||
return -EEXIST;
|
||||
|
||||
*hash_port = port;
|
||||
DP("port %u", port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
UADT(portmap, del)
|
||||
KADT(portmap, del, get_port)
|
||||
|
||||
static inline int
|
||||
__portmap_create(const struct ip_set_req_portmap_create *req,
|
||||
struct ip_set_portmap *map)
|
||||
{
|
||||
if (req->to - req->from > MAX_RANGE) {
|
||||
ip_set_printk("range too big, %d elements (max %d)",
|
||||
req->to - req->from + 1, MAX_RANGE+1);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
return bitmap_bytes(req->from, req->to);
|
||||
}
|
||||
|
||||
BITMAP_CREATE(portmap)
|
||||
BITMAP_DESTROY(portmap)
|
||||
BITMAP_FLUSH(portmap)
|
||||
|
||||
static inline void
|
||||
__portmap_list_header(const struct ip_set_portmap *map,
|
||||
struct ip_set_req_portmap_create *header)
|
||||
{
|
||||
}
|
||||
|
||||
BITMAP_LIST_HEADER(portmap)
|
||||
BITMAP_LIST_MEMBERS_SIZE(portmap)
|
||||
BITMAP_LIST_MEMBERS(portmap)
|
||||
|
||||
IP_SET_TYPE(portmap, IPSET_TYPE_PORT | IPSET_DATA_SINGLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("portmap type of IP sets");
|
||||
|
||||
REGISTER_MODULE(portmap)
|
25
extensions/ipset/ip_set_portmap.h
Normal file
25
extensions/ipset/ip_set_portmap.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef __IP_SET_PORTMAP_H
|
||||
#define __IP_SET_PORTMAP_H
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_bitmaps.h"
|
||||
|
||||
#define SETTYPE_NAME "portmap"
|
||||
|
||||
struct ip_set_portmap {
|
||||
void *members; /* the portmap proper */
|
||||
ip_set_ip_t first_ip; /* host byte order, included in range */
|
||||
ip_set_ip_t last_ip; /* host byte order, included in range */
|
||||
size_t size; /* size of the ipmap proper */
|
||||
};
|
||||
|
||||
struct ip_set_req_portmap_create {
|
||||
ip_set_ip_t from;
|
||||
ip_set_ip_t to;
|
||||
};
|
||||
|
||||
struct ip_set_req_portmap {
|
||||
ip_set_ip_t ip;
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_PORTMAP_H */
|
332
extensions/ipset/ip_set_setlist.c
Normal file
332
extensions/ipset/ip_set_setlist.c
Normal file
@@ -0,0 +1,332 @@
|
||||
/* Copyright (C) 2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the setlist type */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_bitmaps.h"
|
||||
#include "ip_set_setlist.h"
|
||||
|
||||
/*
|
||||
* before ==> index, ref
|
||||
* after ==> ref, index
|
||||
*/
|
||||
|
||||
static inline bool
|
||||
next_index_eq(const struct ip_set_setlist *map, int i, ip_set_id_t index)
|
||||
{
|
||||
return i < map->size && map->index[i] == index;
|
||||
}
|
||||
|
||||
static int
|
||||
setlist_utest(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
{
|
||||
const struct ip_set_setlist *map = set->data;
|
||||
const struct ip_set_req_setlist *req = data;
|
||||
ip_set_id_t index, ref = IP_SET_INVALID_ID;
|
||||
int i, res = 0;
|
||||
struct ip_set *s;
|
||||
|
||||
if (req->before && req->ref[0] == '\0')
|
||||
return -EINVAL;
|
||||
|
||||
index = __ip_set_get_byname(req->name, &s);
|
||||
if (index == IP_SET_INVALID_ID)
|
||||
return -EEXIST;
|
||||
if (req->ref[0] != '\0') {
|
||||
ref = __ip_set_get_byname(req->ref, &s);
|
||||
if (ref == IP_SET_INVALID_ID) {
|
||||
res = -EEXIST;
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < map->size
|
||||
&& map->index[i] != IP_SET_INVALID_ID; i++) {
|
||||
if (req->before && map->index[i] == index) {
|
||||
res = next_index_eq(map, i + 1, ref);
|
||||
break;
|
||||
} else if (!req->before) {
|
||||
if ((ref == IP_SET_INVALID_ID
|
||||
&& map->index[i] == index)
|
||||
|| (map->index[i] == ref
|
||||
&& next_index_eq(map, i + 1, index))) {
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ref != IP_SET_INVALID_ID)
|
||||
__ip_set_put_byindex(ref);
|
||||
finish:
|
||||
__ip_set_put_byindex(index);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
setlist_ktest(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
struct ip_set_setlist *map = set->data;
|
||||
int i, res = 0;
|
||||
|
||||
for (i = 0; i < map->size
|
||||
&& map->index[i] != IP_SET_INVALID_ID
|
||||
&& res == 0; i++)
|
||||
res = ip_set_testip_kernel(map->index[i], skb, flags);
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline int
|
||||
insert_setlist(struct ip_set_setlist *map, int i, ip_set_id_t index)
|
||||
{
|
||||
ip_set_id_t tmp;
|
||||
int j;
|
||||
|
||||
DP("i: %u, last %u\n", i, map->index[map->size - 1]);
|
||||
if (i >= map->size || map->index[map->size - 1] != IP_SET_INVALID_ID)
|
||||
return -ERANGE;
|
||||
|
||||
for (j = i; j < map->size
|
||||
&& index != IP_SET_INVALID_ID; j++) {
|
||||
tmp = map->index[j];
|
||||
map->index[j] = index;
|
||||
index = tmp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
setlist_uadd(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
{
|
||||
struct ip_set_setlist *map = set->data;
|
||||
const struct ip_set_req_setlist *req = data;
|
||||
ip_set_id_t index, ref = IP_SET_INVALID_ID;
|
||||
int i, res = -ERANGE;
|
||||
struct ip_set *s;
|
||||
|
||||
if (req->before && req->ref[0] == '\0')
|
||||
return -EINVAL;
|
||||
|
||||
index = __ip_set_get_byname(req->name, &s);
|
||||
if (index == IP_SET_INVALID_ID)
|
||||
return -EEXIST;
|
||||
/* "Loop detection" */
|
||||
if (strcmp(s->type->typename, "setlist") == 0)
|
||||
goto finish;
|
||||
|
||||
if (req->ref[0] != '\0') {
|
||||
ref = __ip_set_get_byname(req->ref, &s);
|
||||
if (ref == IP_SET_INVALID_ID) {
|
||||
res = -EEXIST;
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < map->size; i++) {
|
||||
if (map->index[i] != ref)
|
||||
continue;
|
||||
if (req->before)
|
||||
res = insert_setlist(map, i, index);
|
||||
else
|
||||
res = insert_setlist(map,
|
||||
ref == IP_SET_INVALID_ID ? i : i + 1,
|
||||
index);
|
||||
break;
|
||||
}
|
||||
if (ref != IP_SET_INVALID_ID)
|
||||
__ip_set_put_byindex(ref);
|
||||
/* In case of success, we keep the reference to the set */
|
||||
finish:
|
||||
if (res != 0)
|
||||
__ip_set_put_byindex(index);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
setlist_kadd(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
struct ip_set_setlist *map = set->data;
|
||||
int i, res = -EINVAL;
|
||||
|
||||
for (i = 0; i < map->size
|
||||
&& map->index[i] != IP_SET_INVALID_ID
|
||||
&& res != 0; i++)
|
||||
res = ip_set_addip_kernel(map->index[i], skb, flags);
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
unshift_setlist(struct ip_set_setlist *map, int i)
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = i; j < map->size - 1; j++)
|
||||
map->index[j] = map->index[j+1];
|
||||
map->index[map->size-1] = IP_SET_INVALID_ID;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
setlist_udel(struct ip_set *set, const void *data, size_t size,
|
||||
ip_set_ip_t *hash_ip)
|
||||
{
|
||||
struct ip_set_setlist *map = set->data;
|
||||
const struct ip_set_req_setlist *req = data;
|
||||
ip_set_id_t index, ref = IP_SET_INVALID_ID;
|
||||
int i, res = -EEXIST;
|
||||
struct ip_set *s;
|
||||
|
||||
if (req->before && req->ref[0] == '\0')
|
||||
return -EINVAL;
|
||||
|
||||
index = __ip_set_get_byname(req->name, &s);
|
||||
if (index == IP_SET_INVALID_ID)
|
||||
return -EEXIST;
|
||||
if (req->ref[0] != '\0') {
|
||||
ref = __ip_set_get_byname(req->ref, &s);
|
||||
if (ref == IP_SET_INVALID_ID)
|
||||
goto finish;
|
||||
}
|
||||
for (i = 0; i < map->size
|
||||
&& map->index[i] != IP_SET_INVALID_ID; i++) {
|
||||
if (req->before) {
|
||||
if (map->index[i] == index
|
||||
&& next_index_eq(map, i + 1, ref)) {
|
||||
res = unshift_setlist(map, i);
|
||||
break;
|
||||
}
|
||||
} else if (ref == IP_SET_INVALID_ID) {
|
||||
if (map->index[i] == index) {
|
||||
res = unshift_setlist(map, i);
|
||||
break;
|
||||
}
|
||||
} else if (map->index[i] == ref
|
||||
&& next_index_eq(map, i + 1, index)) {
|
||||
res = unshift_setlist(map, i + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ref != IP_SET_INVALID_ID)
|
||||
__ip_set_put_byindex(ref);
|
||||
finish:
|
||||
__ip_set_put_byindex(index);
|
||||
/* In case of success, release the reference to the set */
|
||||
if (res == 0)
|
||||
__ip_set_put_byindex(index);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
setlist_kdel(struct ip_set *set,
|
||||
const struct sk_buff *skb,
|
||||
ip_set_ip_t *hash_ip,
|
||||
const u_int32_t *flags,
|
||||
unsigned char index)
|
||||
{
|
||||
struct ip_set_setlist *map = set->data;
|
||||
int i, res = -EINVAL;
|
||||
|
||||
for (i = 0; i < map->size
|
||||
&& map->index[i] != IP_SET_INVALID_ID
|
||||
&& res != 0; i++)
|
||||
res = ip_set_delip_kernel(map->index[i], skb, flags);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
setlist_create(struct ip_set *set, const void *data, size_t size)
|
||||
{
|
||||
struct ip_set_setlist *map;
|
||||
const struct ip_set_req_setlist_create *req = data;
|
||||
int i;
|
||||
|
||||
map = kmalloc(sizeof(struct ip_set_setlist) +
|
||||
req->size * sizeof(ip_set_id_t), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
map->size = req->size;
|
||||
for (i = 0; i < map->size; i++)
|
||||
map->index[i] = IP_SET_INVALID_ID;
|
||||
|
||||
set->data = map;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
setlist_destroy(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_setlist *map = set->data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < map->size
|
||||
&& map->index[i] != IP_SET_INVALID_ID; i++)
|
||||
__ip_set_put_byindex(map->index[i]);
|
||||
|
||||
kfree(map);
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
setlist_flush(struct ip_set *set)
|
||||
{
|
||||
struct ip_set_setlist *map = set->data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < map->size
|
||||
&& map->index[i] != IP_SET_INVALID_ID; i++) {
|
||||
__ip_set_put_byindex(map->index[i]);
|
||||
map->index[i] = IP_SET_INVALID_ID;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
setlist_list_header(const struct ip_set *set, void *data)
|
||||
{
|
||||
const struct ip_set_setlist *map = set->data;
|
||||
struct ip_set_req_setlist_create *header = data;
|
||||
|
||||
header->size = map->size;
|
||||
}
|
||||
|
||||
static int
|
||||
setlist_list_members_size(const struct ip_set *set)
|
||||
{
|
||||
const struct ip_set_setlist *map = set->data;
|
||||
|
||||
return map->size * sizeof(ip_set_id_t);
|
||||
}
|
||||
|
||||
static void
|
||||
setlist_list_members(const struct ip_set *set, void *data)
|
||||
{
|
||||
struct ip_set_setlist *map = set->data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < map->size; i++)
|
||||
*((ip_set_id_t *)data + i) = ip_set_id(map->index[i]);
|
||||
}
|
||||
|
||||
IP_SET_TYPE(setlist, IPSET_TYPE_SETNAME | IPSET_DATA_SINGLE)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("setlist type of IP sets");
|
||||
|
||||
REGISTER_MODULE(setlist)
|
26
extensions/ipset/ip_set_setlist.h
Normal file
26
extensions/ipset/ip_set_setlist.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef __IP_SET_SETLIST_H
|
||||
#define __IP_SET_SETLIST_H
|
||||
|
||||
#include "ip_set.h"
|
||||
|
||||
#define SETTYPE_NAME "setlist"
|
||||
|
||||
#define IP_SET_SETLIST_ADD_AFTER 0
|
||||
#define IP_SET_SETLIST_ADD_BEFORE 1
|
||||
|
||||
struct ip_set_setlist {
|
||||
uint8_t size;
|
||||
ip_set_id_t index[0];
|
||||
};
|
||||
|
||||
struct ip_set_req_setlist_create {
|
||||
uint8_t size;
|
||||
};
|
||||
|
||||
struct ip_set_req_setlist {
|
||||
char name[IP_SET_MAXNAMELEN];
|
||||
char ref[IP_SET_MAXNAMELEN];
|
||||
uint8_t before;
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_SETLIST_H */
|
609
extensions/ipset/ipset.8
Normal file
609
extensions/ipset/ipset.8
Normal file
@@ -0,0 +1,609 @@
|
||||
.TH IPSET 8 "Feb 05, 2004" "" ""
|
||||
.\"
|
||||
.\" Man page written by Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
.\"
|
||||
.\" 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
.\"
|
||||
.\"
|
||||
.SH NAME
|
||||
ipset \- administration tool for IP sets
|
||||
.SH SYNOPSIS
|
||||
.BR "ipset -N " "set type-specification [options]"
|
||||
.br
|
||||
.BR "ipset -[XFLSHh] " "[set] [options]"
|
||||
.br
|
||||
.BR "ipset -[EW] " "from-set to-set"
|
||||
.br
|
||||
.BR "ipset -[ADU] " "set entry"
|
||||
.br
|
||||
.BR "ipset -B " "set entry -b binding"
|
||||
.br
|
||||
.BR "ipset -T " "set entry [-b binding]"
|
||||
.br
|
||||
.BR "ipset -R "
|
||||
.SH DESCRIPTION
|
||||
.B ipset
|
||||
is used to set up, maintain and inspect so called IP sets in the Linux
|
||||
kernel. Depending on the type, an IP set may store IP addresses, (TCP/UDP)
|
||||
port numbers or additional informations besides IP addresses: the word IP
|
||||
means a general term here. See the set type definitions below.
|
||||
.P
|
||||
Any entry in a set can be bound to another set, which forms a relationship
|
||||
between a set element and the set it is bound to. In order to define a
|
||||
binding it is not required that the entry be already added to the set.
|
||||
The sets may have a default binding, which is valid for every set element
|
||||
for which there is no binding defined at all.
|
||||
.P
|
||||
IP set bindings pointing to sets and iptables matches and targets
|
||||
referring to sets creates references, which protects the given sets in
|
||||
the kernel. A set cannot be removed (destroyed) while there is a single
|
||||
reference pointing to it.
|
||||
.SH OPTIONS
|
||||
The options that are recognized by
|
||||
.B ipset
|
||||
can be divided into several different groups.
|
||||
.SS COMMANDS
|
||||
These options specify the specific action to perform. Only one of them
|
||||
can be specified on the command line unless otherwise specified
|
||||
below. For all the long versions of the command and option names, you
|
||||
need to use only enough letters to ensure that
|
||||
.B ipset
|
||||
can differentiate it from all other options.
|
||||
.TP
|
||||
.BI "-N, --create " "\fIsetname\fP type type-specific-options"
|
||||
Create a set identified with setname and specified type.
|
||||
Type-specific options must be supplied.
|
||||
.TP
|
||||
.BI "-X, --destroy " "[\fIsetname\fP]"
|
||||
Destroy the specified set, or all sets if none or the keyword
|
||||
.B
|
||||
:all:
|
||||
is specified.
|
||||
Before destroying the set, all bindings belonging to the
|
||||
set elements and the default binding of the set are removed.
|
||||
|
||||
If the set has got references, nothing is done.
|
||||
.TP
|
||||
.BI "-F, --flush " "[\fIsetname\fP]"
|
||||
Delete all entries from the specified set, or flush
|
||||
all sets if none or the keyword
|
||||
.B
|
||||
:all:
|
||||
is given. Bindings are not affected by the flush operation.
|
||||
.TP
|
||||
.BI "-E, --rename " "\fIfrom-setname\fP \fIto-setname\fP"
|
||||
Rename a set. Set identified by to-setname must not exist.
|
||||
.TP
|
||||
.BI "-W, --swap " "\fIfrom-setname\fP \fIto-setname\fP"
|
||||
Swap the content of two sets, or in another words,
|
||||
exchange the name of two sets. The referred sets must exist and
|
||||
identical type of sets can be swapped only.
|
||||
.TP
|
||||
.BI "-L, --list " "[\fIsetname\fP]"
|
||||
List the entries and bindings for the specified set, or for
|
||||
all sets if none or the keyword
|
||||
.B
|
||||
:all:
|
||||
is given. The
|
||||
.B "-n, --numeric"
|
||||
option can be used to suppress name lookups and generate numeric
|
||||
output. When the
|
||||
.B "-s, --sorted"
|
||||
option is given, the entries are listed sorted (if the given set
|
||||
type supports the operation).
|
||||
.TP
|
||||
.BI "-S, --save " "[\fIsetname\fP]"
|
||||
Save the given set, or all sets if none or the keyword
|
||||
.B
|
||||
:all:
|
||||
is specified to stdout in a format that --restore can read.
|
||||
.TP
|
||||
.BI "-R, --restore "
|
||||
Restore a saved session generated by --save. The saved session
|
||||
can be fed from stdin.
|
||||
|
||||
When generating a session file please note that the supported commands
|
||||
(create set, add element, bind) must appear in a strict order: first create
|
||||
the set, then add all elements. Then create the next set, add all its elements
|
||||
and so on. Finally you can list all binding commands. Also, it is a restore
|
||||
operation, so the sets being restored must not exist.
|
||||
.TP
|
||||
.BI "-A, --add " "\fIsetname\fP \fIIP\fP"
|
||||
Add an IP to a set.
|
||||
.TP
|
||||
.BI "-D, --del " "\fIsetname\fP \fIIP\fP"
|
||||
Delete an IP from a set.
|
||||
.TP
|
||||
.BI "-T, --test " "\fIsetname\fP \fIIP
|
||||
Test wether an IP is in a set or not. Exit status number is zero
|
||||
if the tested IP is in the set and nonzero if it is missing from
|
||||
the set.
|
||||
.TP
|
||||
.BI "-T, --test " "\fIsetname\fP \fIIP\fP \fI--binding\fP \fIto-setname\fP"
|
||||
Test wether the IP belonging to the set points to the specified binding.
|
||||
Exit status number is zero if the binding points to the specified set,
|
||||
otherwise it is nonzero. The keyword
|
||||
.B
|
||||
:default:
|
||||
can be used to test the default binding of the set.
|
||||
.TP
|
||||
.BI "-B, --bind " "\fIsetname\fP \fIIP\fP \fI--binding\fP \fIto-setname\fP"
|
||||
Bind the IP in setname to to-setname.
|
||||
.TP
|
||||
.BI "-U, --unbind " "\fIsetname\fP \fIIP\fP"
|
||||
Delete the binding belonging to IP in set setname.
|
||||
.TP
|
||||
.BI "-H, --help " "[settype]"
|
||||
Print help and settype specific help if settype specified.
|
||||
.P
|
||||
At the
|
||||
.B
|
||||
-B, -U
|
||||
and
|
||||
.B
|
||||
-T
|
||||
commands you can use the token
|
||||
.B
|
||||
:default:
|
||||
to bind, unbind or test the default binding of a set instead
|
||||
of an IP. At the
|
||||
.B
|
||||
-U
|
||||
command you can use the token
|
||||
.B
|
||||
:all:
|
||||
to destroy the bindings of all elements of a set.
|
||||
.SS "OTHER OPTIONS"
|
||||
The following additional options can be specified:
|
||||
.TP
|
||||
.B "-b, --binding setname"
|
||||
The option specifies the value of the binding for the
|
||||
.B "-B"
|
||||
binding command, for which it is a mandatory option.
|
||||
You can use it in the
|
||||
.B "-T"
|
||||
test command as well to test bindings.
|
||||
.TP
|
||||
.B "-s, --sorted"
|
||||
Sorted output. When listing sets, entries are listed sorted.
|
||||
.TP
|
||||
.B "-n, --numeric"
|
||||
Numeric output. When listing sets, bindings, IP addresses and
|
||||
port numbers will be printed in numeric format. By default the
|
||||
program will try to display them as host names, network names
|
||||
or services (whenever applicable), which can trigger
|
||||
.B
|
||||
slow
|
||||
DNS
|
||||
lookups.
|
||||
.TP
|
||||
.B "-q, --quiet"
|
||||
Suppress any output to stdout and stderr. ipset will still return
|
||||
possible errors.
|
||||
.SH SET TYPES
|
||||
ipset supports the following set types:
|
||||
.SS ipmap
|
||||
The ipmap set type uses a memory range, where each bit represents
|
||||
one IP address. An ipmap set can store up to 65536 (B-class network)
|
||||
IP addresses. The ipmap set type is very fast and memory cheap, great
|
||||
for use when one want to match certain IPs in a range. If the optional
|
||||
.B "--netmask"
|
||||
parameter is specified with a CIDR netmask value between 1-31 then
|
||||
network addresses are stored in the given set: i.e an
|
||||
IP address will be in the set if the network address, which is resulted
|
||||
by masking the address with the specified netmask, can be found in the set.
|
||||
.P
|
||||
Options to use when creating an ipmap set:
|
||||
.TP
|
||||
.BR "--from " from-IP
|
||||
.TP
|
||||
.BR "--to " to-IP
|
||||
Create an ipmap set from the specified range.
|
||||
.TP
|
||||
.BR "--network " IP/mask
|
||||
Create an ipmap set from the specified network.
|
||||
.TP
|
||||
.BR "--netmask " CIDR-netmask
|
||||
When the optional
|
||||
.B "--netmask"
|
||||
parameter specified, network addresses will be
|
||||
stored in the set instead of IP addresses, and the from-IP parameter
|
||||
must be a network address. The CIDR-netmask value must be between 1-31.
|
||||
.SS macipmap
|
||||
The macipmap set type uses a memory range, where each 8 bytes
|
||||
represents one IP and a MAC addresses. A macipmap set type can store
|
||||
up to 65536 (B-class network) IP addresses with MAC.
|
||||
When adding an entry to a macipmap set, you must specify the entry as
|
||||
.I IP,MAC.
|
||||
When deleting or testing macipmap entries, the
|
||||
.I ,MAC
|
||||
part is not mandatory.
|
||||
.P
|
||||
Options to use when creating an macipmap set:
|
||||
.TP
|
||||
.BR "--from " from-IP
|
||||
.TP
|
||||
.BR "--to " to-IP
|
||||
Create a macipmap set from the specified range.
|
||||
.TP
|
||||
.BR "--network " IP/mask
|
||||
Create a macipmap set from the specified network.
|
||||
.TP
|
||||
.BR "--matchunset"
|
||||
When the optional
|
||||
.B "--matchunset"
|
||||
parameter specified, IP addresses which could be stored
|
||||
in the set but not set yet, will always match.
|
||||
.P
|
||||
Please note, the
|
||||
.I
|
||||
set
|
||||
and
|
||||
.I
|
||||
SET
|
||||
netfilter kernel modules
|
||||
.B
|
||||
always
|
||||
use the source MAC address from the packet to match, add or delete
|
||||
entries from a macipmap type of set.
|
||||
.SS portmap
|
||||
The portmap set type uses a memory range, where each bit represents
|
||||
one port. A portmap set type can store up to 65536 ports.
|
||||
The portmap set type is very fast and memory cheap.
|
||||
.P
|
||||
Options to use when creating an portmap set:
|
||||
.TP
|
||||
.BR "--from " from-port
|
||||
.TP
|
||||
.BR "--to " to-port
|
||||
Create a portmap set from the specified range.
|
||||
.SS iphash
|
||||
The iphash set type uses a hash to store IP addresses.
|
||||
In order to avoid clashes in the hash double-hashing, and as a last
|
||||
resort, dynamic growing of the hash performed. The iphash set type is
|
||||
great to store random addresses. If the optional
|
||||
.B "--netmask"
|
||||
parameter is specified with a CIDR netmask value between 1-31 then
|
||||
network addresses are stored in the given set: i.e an
|
||||
IP address will be in the set if the network address, which is resulted
|
||||
by masking the address with the specified netmask, can be found in the set.
|
||||
.P
|
||||
Options to use when creating an iphash set:
|
||||
.TP
|
||||
.BR "--hashsize " hashsize
|
||||
The initial hash size (default 1024)
|
||||
.TP
|
||||
.BR "--probes " probes
|
||||
How many times try to resolve clashing at adding an IP to the hash
|
||||
by double-hashing (default 8).
|
||||
.TP
|
||||
.BR "--resize " percent
|
||||
Increase the hash size by this many percent (default 50) when adding
|
||||
an IP to the hash could not be performed after
|
||||
.B
|
||||
probes
|
||||
number of double-hashing.
|
||||
.TP
|
||||
.BR "--netmask " CIDR-netmask
|
||||
When the optional
|
||||
.B "--netmask"
|
||||
parameter specified, network addresses will be
|
||||
stored in the set instead of IP addresses. The CIDR-netmask value must
|
||||
be between 1-31.
|
||||
.P
|
||||
The iphash type of sets can store up to 65536 entries. If a set is full,
|
||||
no new entries can be added to it.
|
||||
.P
|
||||
Sets created by zero valued resize parameter won't be resized at all.
|
||||
The lookup time in an iphash type of set grows approximately linearly with
|
||||
the value of the
|
||||
.B
|
||||
probes
|
||||
parameter. In general higher
|
||||
.B
|
||||
probe
|
||||
value results better utilized hash while smaller value
|
||||
produces larger, sparser hash.
|
||||
.SS nethash
|
||||
The nethash set type uses a hash to store different size of
|
||||
network addresses. The
|
||||
.I
|
||||
IP
|
||||
"address" used in the ipset commands must be in the form
|
||||
.I
|
||||
IP-address/cidr-size
|
||||
where the CIDR block size must be in the inclusive range of 1-31.
|
||||
In order to avoid clashes in the hash
|
||||
double-hashing, and as a last resort, dynamic growing of the hash performed.
|
||||
.P
|
||||
Options to use when creating an nethash set:
|
||||
.TP
|
||||
.BR "--hashsize " hashsize
|
||||
The initial hash size (default 1024)
|
||||
.TP
|
||||
.BR "--probes " probes
|
||||
How many times try to resolve clashing at adding an IP to the hash
|
||||
by double-hashing (default 4).
|
||||
.TP
|
||||
.BR "--resize " percent
|
||||
Increase the hash size by this many percent (default 50) when adding
|
||||
an IP to the hash could not be performed after
|
||||
.P
|
||||
The nethash type of sets can store up to 65536 entries. If a set is full,
|
||||
no new entries can be added to it.
|
||||
.P
|
||||
An IP address will be in a nethash type of set if it belongs to any of the
|
||||
netblocks added to the set. The matching always start from the smallest
|
||||
size of netblock (most specific netmask) to the largest ones (least
|
||||
specific netmasks). When adding/deleting IP addresses
|
||||
to a nethash set by the
|
||||
.I
|
||||
SET
|
||||
netfilter kernel module, it will be added/deleted by the smallest
|
||||
netblock size which can be found in the set, or by /31 if the set is empty.
|
||||
.P
|
||||
The lookup time in a nethash type of set grows approximately linearly
|
||||
with the times of the
|
||||
.B
|
||||
probes
|
||||
parameter and the number of different mask parameters in the hash.
|
||||
Otherwise the same speed and memory efficiency comments applies here
|
||||
as at the iphash type.
|
||||
.SS ipporthash
|
||||
The ipporthash set type uses a hash to store IP address and port pairs.
|
||||
In order to avoid clashes in the hash double-hashing, and as a last
|
||||
resort, dynamic growing of the hash performed. An ipporthash set can
|
||||
store up to 65536 (B-class network) IP addresses with all possible port
|
||||
values. When adding, deleting and testing values in an ipporthash type of
|
||||
set, the entries must be specified as
|
||||
.B
|
||||
"IP,port".
|
||||
.P
|
||||
The ipporthash types of sets evaluates two src/dst parameters of the
|
||||
.I
|
||||
set
|
||||
match and
|
||||
.I
|
||||
SET
|
||||
target.
|
||||
.P
|
||||
Options to use when creating an ipporthash set:
|
||||
.TP
|
||||
.BR "--from " from-IP
|
||||
.TP
|
||||
.BR "--to " to-IP
|
||||
Create an ipporthash set from the specified range.
|
||||
.TP
|
||||
.BR "--network " IP/mask
|
||||
Create an ipporthash set from the specified network.
|
||||
.TP
|
||||
.BR "--hashsize " hashsize
|
||||
The initial hash size (default 1024)
|
||||
.TP
|
||||
.BR "--probes " probes
|
||||
How many times try to resolve clashing at adding an IP to the hash
|
||||
by double-hashing (default 8).
|
||||
.TP
|
||||
.BR "--resize " percent
|
||||
Increase the hash size by this many percent (default 50) when adding
|
||||
an IP to the hash could not be performed after
|
||||
.B
|
||||
probes
|
||||
number of double-hashing.
|
||||
.P
|
||||
The same resizing, speed and memory efficiency comments applies here
|
||||
as at the iphash type.
|
||||
.SS ipportiphash
|
||||
The ipportiphash set type uses a hash to store IP address,port and IP
|
||||
address triples. The first IP address must come form a maximum /16
|
||||
sized network or range while the port number and the second IP address
|
||||
parameters are arbitrary. When adding, deleting and testing values in an
|
||||
ipportiphash type of set, the entries must be specified as
|
||||
.B
|
||||
"IP,port,IP".
|
||||
.P
|
||||
The ipportiphash types of sets evaluates three src/dst parameters of the
|
||||
.I
|
||||
set
|
||||
match and
|
||||
.I
|
||||
SET
|
||||
target.
|
||||
.P
|
||||
Options to use when creating an ipportiphash set:
|
||||
.TP
|
||||
.BR "--from " from-IP
|
||||
.TP
|
||||
.BR "--to " to-IP
|
||||
Create an ipportiphash set from the specified range.
|
||||
.TP
|
||||
.BR "--network " IP/mask
|
||||
Create an ipportiphash set from the specified network.
|
||||
.TP
|
||||
.BR "--hashsize " hashsize
|
||||
The initial hash size (default 1024)
|
||||
.TP
|
||||
.BR "--probes " probes
|
||||
How many times try to resolve clashing at adding an IP to the hash
|
||||
by double-hashing (default 8).
|
||||
.TP
|
||||
.BR "--resize " percent
|
||||
Increase the hash size by this many percent (default 50) when adding
|
||||
an IP to the hash could not be performed after
|
||||
.B
|
||||
probes
|
||||
number of double-hashing.
|
||||
.P
|
||||
The same resizing, speed and memory efficiency comments applies here
|
||||
as at the iphash type.
|
||||
.SS ipportnethash
|
||||
The ipportnethash set type uses a hash to store IP address, port, and
|
||||
network address triples. The IP address must come form a maximum /16
|
||||
sized network or range while the port number and the network address
|
||||
parameters are arbitrary, but the size of the network address must be
|
||||
between /1-/31. When adding, deleting
|
||||
and testing values in an ipportnethash type of set, the entries must be
|
||||
specified as
|
||||
.B
|
||||
"IP,port,IP/cidr-size".
|
||||
.P
|
||||
The ipportnethash types of sets evaluates three src/dst parameters of the
|
||||
.I
|
||||
set
|
||||
match and
|
||||
.I
|
||||
SET
|
||||
target.
|
||||
.P
|
||||
Options to use when creating an ipportnethash set:
|
||||
.TP
|
||||
.BR "--from " from-IP
|
||||
.TP
|
||||
.BR "--to " to-IP
|
||||
Create an ipporthash set from the specified range.
|
||||
.TP
|
||||
.BR "--network " IP/mask
|
||||
Create an ipporthash set from the specified network.
|
||||
.TP
|
||||
.BR "--hashsize " hashsize
|
||||
The initial hash size (default 1024)
|
||||
.TP
|
||||
.BR "--probes " probes
|
||||
How many times try to resolve clashing at adding an IP to the hash
|
||||
by double-hashing (default 8).
|
||||
.TP
|
||||
.BR "--resize " percent
|
||||
Increase the hash size by this many percent (default 50) when adding
|
||||
an IP to the hash could not be performed after
|
||||
.B
|
||||
probes
|
||||
number of double-hashing.
|
||||
.P
|
||||
The same resizing, speed and memory efficiency comments applies here
|
||||
as at the iphash type.
|
||||
.SS iptree
|
||||
The iptree set type uses a tree to store IP addresses, optionally
|
||||
with timeout values.
|
||||
.P
|
||||
Options to use when creating an iptree set:
|
||||
.TP
|
||||
.BR "--timeout " value
|
||||
The timeout value for the entries in seconds (default 0)
|
||||
.P
|
||||
If a set was created with a nonzero valued
|
||||
.B "--timeout"
|
||||
parameter then one may add IP addresses to the set with a specific
|
||||
timeout value using the syntax
|
||||
.I IP,timeout-value.
|
||||
Similarly to the hash types, the iptree type of sets can store up to 65536
|
||||
entries.
|
||||
.SS iptreemap
|
||||
The iptreemap set type uses a tree to store IP addresses or networks,
|
||||
where the last octet of an IP address are stored in a bitmap.
|
||||
As input entry, you can add IP addresses, CIDR blocks or network ranges
|
||||
to the set. Network ranges can be specified in the format
|
||||
.I IP1-IP2
|
||||
.P
|
||||
Options to use when creating an iptreemap set:
|
||||
.TP
|
||||
.BR "--gc " value
|
||||
How often the garbage collection should be called, in seconds (default 300)
|
||||
.SS setlist
|
||||
The setlist type uses a simple list in which you can store sets. By the
|
||||
.I
|
||||
ipset
|
||||
command you can add, delete and test sets in a setlist type of set.
|
||||
You can specify the sets as
|
||||
.B
|
||||
"setname[,after|before,setname]".
|
||||
By default new sets are added after (appended to) the existing
|
||||
elements. Setlist type of sets cannot be added to a setlist type of set.
|
||||
.P
|
||||
Options to use when creating a setlist type of set:
|
||||
.TP
|
||||
.BR "--size " size
|
||||
Create a setlist type of set with the given size (default 8).
|
||||
.P
|
||||
By the
|
||||
.I
|
||||
set
|
||||
match or
|
||||
.I
|
||||
SET
|
||||
target of
|
||||
.I
|
||||
iptables
|
||||
you can test, add or delete entries in the sets. The match
|
||||
will try to find a matching IP address/port in the sets and
|
||||
the target will try to add the IP address/port to the first set
|
||||
to which it can be added. The number of src,dst options of
|
||||
the match and target are important: sets which eats more src,dst
|
||||
parameters than specified are skipped, while sets with equal
|
||||
or less parameters are checked, elements added. For example
|
||||
if
|
||||
.I
|
||||
a
|
||||
and
|
||||
.I
|
||||
b
|
||||
are setlist type of sets then in the command
|
||||
.TP
|
||||
iptables -m set --match-set a src,dst -j SET --add-set b src,dst
|
||||
the match and target will skip any set in
|
||||
.I a
|
||||
and
|
||||
.I b
|
||||
which stores
|
||||
data triples, but will check all sets with single or double
|
||||
data storage in
|
||||
.I a
|
||||
set and add src to the first single or src,dst to the first double
|
||||
data storage set in
|
||||
.I b.
|
||||
.P
|
||||
You can imagine a setlist type of set as an ordered union of
|
||||
the set elements.
|
||||
.SH GENERAL RESTRICTIONS
|
||||
Setnames starting with colon (:) cannot be defined. Zero valued set
|
||||
entries cannot be used with hash type of sets.
|
||||
.SH COMMENTS
|
||||
If you want to store same size subnets from a given network
|
||||
(say /24 blocks from a /8 network), use the ipmap set type.
|
||||
If you want to store random same size networks (say random /24 blocks),
|
||||
use the iphash set type. If you have got random size of netblocks,
|
||||
use nethash.
|
||||
.P
|
||||
Old separator tokens (':' and '%") are still accepted.
|
||||
.SH DIAGNOSTICS
|
||||
Various error messages are printed to standard error. The exit code
|
||||
is 0 for correct functioning. Errors which appear to be caused by
|
||||
invalid or abused command line parameters cause an exit code of 2, and
|
||||
other errors cause an exit code of 1.
|
||||
.SH BUGS
|
||||
Bugs? No, just funny features. :-)
|
||||
OK, just kidding...
|
||||
.SH SEE ALSO
|
||||
.BR iptables (8),
|
||||
.SH AUTHORS
|
||||
Jozsef Kadlecsik wrote ipset, which is based on ippool by
|
||||
Joakim Axelsson, Patrick Schaaf and Martin Josefsson.
|
||||
.P
|
||||
Sven Wegener wrote the iptreemap type.
|
||||
.SH LAST REMARK
|
||||
.BR "I stand on the shoulder of giants."
|
||||
.\" .. and did I mention that we are incredibly cool people?
|
||||
.\" .. sexy, too ..
|
||||
.\" .. witty, charming, powerful ..
|
||||
.\" .. and most of all, modest ..
|
2340
extensions/ipset/ipset.c
Normal file
2340
extensions/ipset/ipset.c
Normal file
File diff suppressed because it is too large
Load Diff
202
extensions/ipset/ipset.h
Normal file
202
extensions/ipset/ipset.h
Normal file
@@ -0,0 +1,202 @@
|
||||
#ifndef __IPSET_H
|
||||
#define __IPSET_H
|
||||
|
||||
/* Copyright 2000-2004 Joakim Axelsson (gozem@linux.nu)
|
||||
* Patrick Schaaf (bof@bof.de)
|
||||
* Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <getopt.h> /* struct option */
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "ip_set.h"
|
||||
|
||||
#define IPSET_LIB_NAME "/libipset_%s.so"
|
||||
#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"
|
||||
|
||||
#define LIST_TRIES 5
|
||||
|
||||
#ifdef IPSET_DEBUG
|
||||
extern int option_debug;
|
||||
#define DP(format, args...) if (option_debug) \
|
||||
do { \
|
||||
fprintf(stderr, "%s: %s (DBG): ", __FILE__, __FUNCTION__);\
|
||||
fprintf(stderr, format "\n" , ## args); \
|
||||
} while (0)
|
||||
#else
|
||||
#define DP(format, args...)
|
||||
#endif
|
||||
|
||||
/* Commands */
|
||||
enum set_commands {
|
||||
CMD_NONE,
|
||||
CMD_CREATE, /* -N */
|
||||
CMD_DESTROY, /* -X */
|
||||
CMD_FLUSH, /* -F */
|
||||
CMD_RENAME, /* -E */
|
||||
CMD_SWAP, /* -W */
|
||||
CMD_LIST, /* -L */
|
||||
CMD_SAVE, /* -S */
|
||||
CMD_RESTORE, /* -R */
|
||||
CMD_ADD, /* -A */
|
||||
CMD_DEL, /* -D */
|
||||
CMD_TEST, /* -T */
|
||||
CMD_BIND, /* -B */
|
||||
CMD_UNBIND, /* -U */
|
||||
CMD_HELP, /* -H */
|
||||
CMD_VERSION, /* -V */
|
||||
NUMBER_OF_CMD = CMD_VERSION,
|
||||
/* Internal commands */
|
||||
CMD_MAX_SETS,
|
||||
CMD_LIST_SIZE,
|
||||
CMD_SAVE_SIZE,
|
||||
CMD_ADT_GET,
|
||||
};
|
||||
|
||||
enum exittype {
|
||||
OTHER_PROBLEM = 1,
|
||||
PARAMETER_PROBLEM,
|
||||
VERSION_PROBLEM
|
||||
};
|
||||
|
||||
/* The view of an ipset in userspace */
|
||||
struct set {
|
||||
char name[IP_SET_MAXNAMELEN]; /* Name of the set */
|
||||
ip_set_id_t id; /* Unique set id */
|
||||
ip_set_id_t index; /* Array index */
|
||||
unsigned ref; /* References in kernel */
|
||||
struct settype *settype; /* Pointer to set type functions */
|
||||
};
|
||||
|
||||
struct settype {
|
||||
struct settype *next;
|
||||
|
||||
char typename[IP_SET_MAXNAMELEN];
|
||||
|
||||
int protocol_version;
|
||||
|
||||
/*
|
||||
* Create set
|
||||
*/
|
||||
|
||||
/* Size of create data. Will be sent to kernel */
|
||||
size_t create_size;
|
||||
|
||||
/* Initialize the create. */
|
||||
void (*create_init) (void *data);
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
int (*create_parse) (int c, char *argv[], void *data,
|
||||
unsigned *flags);
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
void (*create_final) (void *data, unsigned int flags);
|
||||
|
||||
/* Pointer to list of extra command-line options for create */
|
||||
const struct option *create_opts;
|
||||
|
||||
/*
|
||||
* Add/del/test IP
|
||||
*/
|
||||
|
||||
/* Size of data. Will be sent to kernel */
|
||||
size_t adt_size;
|
||||
|
||||
/* Function which parses command options */
|
||||
ip_set_ip_t (*adt_parser) (int cmd, const char *optarg, void *data);
|
||||
|
||||
/*
|
||||
* Printing
|
||||
*/
|
||||
|
||||
/* Size of header. */
|
||||
size_t header_size;
|
||||
|
||||
/* Initialize the type-header */
|
||||
void (*initheader) (struct set *set, const void *data);
|
||||
|
||||
/* Pretty print the type-header */
|
||||
void (*printheader) (struct set *set, unsigned options);
|
||||
|
||||
/* Pretty print all IPs */
|
||||
void (*printips) (struct set *set, void *data, size_t len, unsigned options);
|
||||
|
||||
/* Pretty print all IPs sorted */
|
||||
void (*printips_sorted) (struct set *set, void *data, size_t len, unsigned options);
|
||||
|
||||
/* Print save arguments for creating the set */
|
||||
void (*saveheader) (struct set *set, unsigned options);
|
||||
|
||||
/* Print save for all IPs */
|
||||
void (*saveips) (struct set *set, void *data, size_t len, unsigned options);
|
||||
|
||||
/* Conver a single IP (binding) to string */
|
||||
char * (*bindip_tostring)(struct set *set, ip_set_ip_t ip, unsigned options);
|
||||
|
||||
/* Parse an IP at restoring bindings. FIXME */
|
||||
void (*bindip_parse) (const char *str, ip_set_ip_t * ip);
|
||||
|
||||
/* Print usage */
|
||||
void (*usage) (void);
|
||||
|
||||
/* Internal data */
|
||||
void *header;
|
||||
void *data;
|
||||
int option_offset;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
extern void settype_register(struct settype *settype);
|
||||
|
||||
/* extern void unregister_settype(set_type_t *set_type); */
|
||||
|
||||
extern void exit_error(int status, const char *msg, ...);
|
||||
|
||||
extern char *binding_ip_tostring(struct set *set,
|
||||
ip_set_ip_t ip, unsigned options);
|
||||
extern char *ip_tostring(ip_set_ip_t ip, unsigned options);
|
||||
extern char *ip_tostring_numeric(ip_set_ip_t ip);
|
||||
extern void parse_ip(const char *str, ip_set_ip_t * ip);
|
||||
extern void parse_mask(const char *str, ip_set_ip_t * mask);
|
||||
extern void parse_ipandmask(const char *str, ip_set_ip_t * ip,
|
||||
ip_set_ip_t * mask);
|
||||
extern char *port_tostring(ip_set_ip_t port, unsigned options);
|
||||
extern void parse_port(const char *str, ip_set_ip_t * port);
|
||||
extern int string_to_number(const char *str, unsigned int min, unsigned int max,
|
||||
ip_set_ip_t *port);
|
||||
|
||||
extern void *ipset_malloc(size_t size);
|
||||
extern char *ipset_strdup(const char *);
|
||||
extern void ipset_free(void *data);
|
||||
|
||||
extern struct set *set_find_byname(const char *name);
|
||||
extern struct set *set_find_byid(ip_set_id_t id);
|
||||
|
||||
extern unsigned warn_once;
|
||||
|
||||
#define BITSPERBYTE (8*sizeof(char))
|
||||
#define ID2BYTE(id) ((id)/BITSPERBYTE)
|
||||
#define ID2MASK(id) (1 << ((id)%BITSPERBYTE))
|
||||
#define test_bit(id, heap) ((((char *)(heap))[ID2BYTE(id)] & ID2MASK(id)) != 0)
|
||||
|
||||
#define UNUSED __attribute__ ((unused))
|
||||
#define CONSTRUCTOR(module) \
|
||||
void __attribute__ ((constructor)) module##_init(void); \
|
||||
void module##_init(void)
|
||||
|
||||
#endif /* __IPSET_H */
|
283
extensions/ipset/ipset_iphash.c
Normal file
283
extensions/ipset/ipset_iphash.c
Normal file
@@ -0,0 +1,283 @@
|
||||
/* Copyright 2004 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <limits.h> /* UINT_MAX */
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem* */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_iphash.h"
|
||||
|
||||
#define BUFLEN 30;
|
||||
|
||||
#define OPT_CREATE_HASHSIZE 0x01U
|
||||
#define OPT_CREATE_PROBES 0x02U
|
||||
#define OPT_CREATE_RESIZE 0x04U
|
||||
#define OPT_CREATE_NETMASK 0x08U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void
|
||||
create_init(void *data)
|
||||
{
|
||||
struct ip_set_req_iphash_create *mydata = data;
|
||||
|
||||
DP("create INIT");
|
||||
|
||||
/* Default create parameters */
|
||||
mydata->hashsize = 1024;
|
||||
mydata->probes = 8;
|
||||
mydata->resize = 50;
|
||||
|
||||
mydata->netmask = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int
|
||||
create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_iphash_create *mydata =
|
||||
(struct ip_set_req_iphash_create *) data;
|
||||
unsigned int bits;
|
||||
ip_set_ip_t value;
|
||||
|
||||
DP("create_parse");
|
||||
|
||||
switch (c) {
|
||||
case '1':
|
||||
|
||||
if (string_to_number(optarg, 1, UINT_MAX - 1, &mydata->hashsize))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid hashsize `%s' specified", optarg);
|
||||
|
||||
*flags |= OPT_CREATE_HASHSIZE;
|
||||
|
||||
DP("--hashsize %u", mydata->hashsize);
|
||||
|
||||
break;
|
||||
|
||||
case '2':
|
||||
|
||||
if (string_to_number(optarg, 1, 65535, &value))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid probes `%s' specified", optarg);
|
||||
|
||||
mydata->probes = value;
|
||||
*flags |= OPT_CREATE_PROBES;
|
||||
|
||||
DP("--probes %u", mydata->probes);
|
||||
|
||||
break;
|
||||
|
||||
case '3':
|
||||
|
||||
if (string_to_number(optarg, 0, 65535, &value))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid resize `%s' specified", optarg);
|
||||
|
||||
mydata->resize = value;
|
||||
*flags |= OPT_CREATE_RESIZE;
|
||||
|
||||
DP("--resize %u", mydata->resize);
|
||||
|
||||
break;
|
||||
|
||||
case '4':
|
||||
|
||||
if (string_to_number(optarg, 0, 32, &bits))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Invalid netmask `%s' specified", optarg);
|
||||
|
||||
if (bits != 0)
|
||||
mydata->netmask = 0xFFFFFFFF << (32 - bits);
|
||||
|
||||
*flags |= OPT_CREATE_NETMASK;
|
||||
|
||||
DP("--netmask %x", mydata->netmask);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void
|
||||
create_final(void *data UNUSED, unsigned int flags UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{.name = "hashsize", .has_arg = required_argument, .val = '1'},
|
||||
{.name = "probes", .has_arg = required_argument, .val = '2'},
|
||||
{.name = "resize", .has_arg = required_argument, .val = '3'},
|
||||
{.name = "netmask", .has_arg = required_argument, .val = '4'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t
|
||||
adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_iphash *mydata = data;
|
||||
|
||||
parse_ip(arg, &mydata->ip);
|
||||
if (!mydata->ip)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Zero valued IP address `%s' specified", arg);
|
||||
|
||||
return mydata->ip;
|
||||
};
|
||||
|
||||
/*
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void
|
||||
initheader(struct set *set, const void *data)
|
||||
{
|
||||
const struct ip_set_req_iphash_create *header = data;
|
||||
struct ip_set_iphash *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_iphash));
|
||||
map->hashsize = header->hashsize;
|
||||
map->probes = header->probes;
|
||||
map->resize = header->resize;
|
||||
map->netmask = header->netmask;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
mask_to_bits(ip_set_ip_t mask)
|
||||
{
|
||||
unsigned int bits = 32;
|
||||
ip_set_ip_t maskaddr;
|
||||
|
||||
if (mask == 0xFFFFFFFF)
|
||||
return bits;
|
||||
|
||||
maskaddr = 0xFFFFFFFE;
|
||||
while (--bits > 0 && maskaddr != mask)
|
||||
maskaddr <<= 1;
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
static void
|
||||
printheader(struct set *set, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_iphash *mysetdata = set->settype->header;
|
||||
|
||||
printf(" hashsize: %u", mysetdata->hashsize);
|
||||
printf(" probes: %u", mysetdata->probes);
|
||||
printf(" resize: %u", mysetdata->resize);
|
||||
if (mysetdata->netmask == 0xFFFFFFFF)
|
||||
printf("\n");
|
||||
else
|
||||
printf(" netmask: %d\n", mask_to_bits(mysetdata->netmask));
|
||||
}
|
||||
|
||||
static void
|
||||
printips(struct set *set UNUSED, void *data, size_t len, unsigned options)
|
||||
{
|
||||
size_t offset = 0;
|
||||
ip_set_ip_t *ip;
|
||||
|
||||
while (offset < len) {
|
||||
ip = data + offset;
|
||||
if (*ip)
|
||||
printf("%s\n", ip_tostring(*ip, options));
|
||||
offset += sizeof(ip_set_ip_t);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
saveheader(struct set *set, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_iphash *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --hashsize %u --probes %u --resize %u",
|
||||
set->name, set->settype->typename,
|
||||
mysetdata->hashsize, mysetdata->probes, mysetdata->resize);
|
||||
if (mysetdata->netmask == 0xFFFFFFFF)
|
||||
printf("\n");
|
||||
else
|
||||
printf(" --netmask %d\n", mask_to_bits(mysetdata->netmask));
|
||||
}
|
||||
|
||||
/* Print save for an IP */
|
||||
static void
|
||||
saveips(struct set *set UNUSED, void *data, size_t len, unsigned options)
|
||||
{
|
||||
size_t offset = 0;
|
||||
ip_set_ip_t *ip;
|
||||
|
||||
while (offset < len) {
|
||||
ip = data + offset;
|
||||
if (*ip)
|
||||
printf("-A %s %s\n", set->name,
|
||||
ip_tostring(*ip, options));
|
||||
offset += sizeof(ip_set_ip_t);
|
||||
}
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf
|
||||
("-N set iphash [--hashsize hashsize] [--probes probes ]\n"
|
||||
" [--resize resize] [--netmask CIDR-netmask]\n"
|
||||
"-A set IP\n"
|
||||
"-D set IP\n"
|
||||
"-T set IP\n");
|
||||
}
|
||||
|
||||
static struct settype settype_iphash = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
|
||||
/* Create */
|
||||
.create_size = sizeof(struct ip_set_req_iphash_create),
|
||||
.create_init = &create_init,
|
||||
.create_parse = &create_parse,
|
||||
.create_final = &create_final,
|
||||
.create_opts = create_opts,
|
||||
|
||||
/* Add/del/test */
|
||||
.adt_size = sizeof(struct ip_set_req_iphash),
|
||||
.adt_parser = &adt_parser,
|
||||
|
||||
/* Printing */
|
||||
.header_size = sizeof(struct ip_set_iphash),
|
||||
.initheader = &initheader,
|
||||
.printheader = &printheader,
|
||||
.printips = &printips, /* We only have the unsorted version */
|
||||
.printips_sorted = &printips,
|
||||
.saveheader = &saveheader,
|
||||
.saveips = &saveips,
|
||||
|
||||
/* Bindings */
|
||||
.bindip_tostring = &binding_ip_tostring,
|
||||
.bindip_parse = &parse_ip,
|
||||
|
||||
.usage = &usage,
|
||||
};
|
||||
|
||||
CONSTRUCTOR(iphash)
|
||||
{
|
||||
settype_register(&settype_iphash);
|
||||
|
||||
}
|
342
extensions/ipset/ipset_ipmap.c
Normal file
342
extensions/ipset/ipset_ipmap.c
Normal file
@@ -0,0 +1,342 @@
|
||||
/* Copyright 2000-2004 Joakim Axelsson (gozem@linux.nu)
|
||||
* Patrick Schaaf (bof@bof.de)
|
||||
* Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem* */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_ipmap.h"
|
||||
|
||||
#define BUFLEN 30;
|
||||
|
||||
#define OPT_CREATE_FROM 0x01U
|
||||
#define OPT_CREATE_TO 0x02U
|
||||
#define OPT_CREATE_NETWORK 0x04U
|
||||
#define OPT_CREATE_NETMASK 0x08U
|
||||
|
||||
#define OPT_ADDDEL_IP 0x01U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void
|
||||
create_init(void *data)
|
||||
{
|
||||
struct ip_set_req_ipmap_create *mydata = data;
|
||||
|
||||
DP("create INIT");
|
||||
mydata->netmask = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int
|
||||
create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_ipmap_create *mydata = data;
|
||||
unsigned int bits;
|
||||
|
||||
DP("create_parse");
|
||||
|
||||
switch (c) {
|
||||
case '1':
|
||||
parse_ip(optarg, &mydata->from);
|
||||
|
||||
*flags |= OPT_CREATE_FROM;
|
||||
|
||||
DP("--from %x (%s)", mydata->from,
|
||||
ip_tostring_numeric(mydata->from));
|
||||
|
||||
break;
|
||||
|
||||
case '2':
|
||||
parse_ip(optarg, &mydata->to);
|
||||
|
||||
*flags |= OPT_CREATE_TO;
|
||||
|
||||
DP("--to %x (%s)", mydata->to,
|
||||
ip_tostring_numeric(mydata->to));
|
||||
|
||||
break;
|
||||
|
||||
case '3':
|
||||
parse_ipandmask(optarg, &mydata->from, &mydata->to);
|
||||
|
||||
/* Make to the last of from + mask */
|
||||
if (mydata->to)
|
||||
mydata->to = mydata->from | ~(mydata->to);
|
||||
else {
|
||||
mydata->from = 0x00000000;
|
||||
mydata->to = 0xFFFFFFFF;
|
||||
}
|
||||
*flags |= OPT_CREATE_NETWORK;
|
||||
|
||||
DP("--network from %x (%s)",
|
||||
mydata->from, ip_tostring_numeric(mydata->from));
|
||||
DP("--network to %x (%s)",
|
||||
mydata->to, ip_tostring_numeric(mydata->to));
|
||||
|
||||
break;
|
||||
|
||||
case '4':
|
||||
if (string_to_number(optarg, 0, 32, &bits))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Invalid netmask `%s' specified", optarg);
|
||||
|
||||
if (bits != 0)
|
||||
mydata->netmask = 0xFFFFFFFF << (32 - bits);
|
||||
|
||||
*flags |= OPT_CREATE_NETMASK;
|
||||
|
||||
DP("--netmask %x", mydata->netmask);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void
|
||||
create_final(void *data, unsigned int flags)
|
||||
{
|
||||
struct ip_set_req_ipmap_create *mydata = data;
|
||||
ip_set_ip_t range;
|
||||
|
||||
if (flags == 0)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify --from and --to, or --network\n");
|
||||
|
||||
if (flags & OPT_CREATE_NETWORK) {
|
||||
/* --network */
|
||||
if ((flags & OPT_CREATE_FROM) || (flags & OPT_CREATE_TO))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Can't specify --from or --to with --network\n");
|
||||
} else {
|
||||
/* --from --to */
|
||||
if ((flags & OPT_CREATE_FROM) == 0
|
||||
|| (flags & OPT_CREATE_TO) == 0)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify both --from and --to\n");
|
||||
}
|
||||
|
||||
DP("from : %x to: %x diff: %x",
|
||||
mydata->from, mydata->to,
|
||||
mydata->to - mydata->from);
|
||||
|
||||
if (mydata->from > mydata->to)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"From can't be lower than to.\n");
|
||||
|
||||
if (flags & OPT_CREATE_NETMASK) {
|
||||
unsigned int mask_bits, netmask_bits;
|
||||
ip_set_ip_t mask;
|
||||
|
||||
if ((mydata->from & mydata->netmask) != mydata->from)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"%s is not a network address according to netmask %d\n",
|
||||
ip_tostring_numeric(mydata->from),
|
||||
mask_to_bits(mydata->netmask));
|
||||
|
||||
mask = range_to_mask(mydata->from, mydata->to, &mask_bits);
|
||||
if (!mask
|
||||
&& (mydata->from || mydata->to != 0xFFFFFFFF)) {
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"You have to define a full network with --from"
|
||||
" and --to if you specify the --network option\n");
|
||||
}
|
||||
netmask_bits = mask_to_bits(mydata->netmask);
|
||||
if (netmask_bits <= mask_bits) {
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"%d netmask specifies larger or equal netblock than the network itself\n");
|
||||
}
|
||||
range = (1<<(netmask_bits - mask_bits)) - 1;
|
||||
} else {
|
||||
range = mydata->to - mydata->from;
|
||||
}
|
||||
if (range > MAX_RANGE)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Range too large. Max is %d IPs in range\n",
|
||||
MAX_RANGE+1);
|
||||
}
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{.name = "from", .has_arg = required_argument, .val = '1'},
|
||||
{.name = "to", .has_arg = required_argument, .val = '2'},
|
||||
{.name = "network", .has_arg = required_argument, .val = '3'},
|
||||
{.name = "netmask", .has_arg = required_argument, .val = '4'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t
|
||||
adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_ipmap *mydata = data;
|
||||
|
||||
DP("ipmap: %p %p", arg, data);
|
||||
|
||||
parse_ip(arg, &mydata->ip);
|
||||
DP("%s", ip_tostring_numeric(mydata->ip));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void
|
||||
initheader(struct set *set, const void *data)
|
||||
{
|
||||
const struct ip_set_req_ipmap_create *header = data;
|
||||
struct ip_set_ipmap *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_ipmap));
|
||||
map->first_ip = header->from;
|
||||
map->last_ip = header->to;
|
||||
map->netmask = header->netmask;
|
||||
|
||||
if (map->netmask == 0xFFFFFFFF) {
|
||||
map->hosts = 1;
|
||||
map->sizeid = map->last_ip - map->first_ip + 1;
|
||||
} else {
|
||||
unsigned int mask_bits, netmask_bits;
|
||||
ip_set_ip_t mask;
|
||||
|
||||
mask = range_to_mask(header->from, header->to, &mask_bits);
|
||||
netmask_bits = mask_to_bits(header->netmask);
|
||||
|
||||
DP("bits: %i %i", mask_bits, netmask_bits);
|
||||
map->hosts = 2 << (32 - netmask_bits - 1);
|
||||
map->sizeid = 2 << (netmask_bits - mask_bits - 1);
|
||||
}
|
||||
|
||||
DP("%i %i", map->hosts, map->sizeid );
|
||||
}
|
||||
|
||||
static void
|
||||
printheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_ipmap *mysetdata = set->settype->header;
|
||||
|
||||
printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
|
||||
if (mysetdata->netmask == 0xFFFFFFFF)
|
||||
printf("\n");
|
||||
else
|
||||
printf(" netmask: %d\n", mask_to_bits(mysetdata->netmask));
|
||||
}
|
||||
|
||||
static void
|
||||
printips_sorted(struct set *set, void *data,
|
||||
size_t len UNUSED, unsigned options)
|
||||
{
|
||||
struct ip_set_ipmap *mysetdata = set->settype->header;
|
||||
ip_set_ip_t id;
|
||||
|
||||
for (id = 0; id < mysetdata->sizeid; id++)
|
||||
if (test_bit(id, data))
|
||||
printf("%s\n",
|
||||
ip_tostring(mysetdata->first_ip
|
||||
+ id * mysetdata->hosts,
|
||||
options));
|
||||
}
|
||||
|
||||
static void
|
||||
saveheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_ipmap *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --from %s",
|
||||
set->name, set->settype->typename,
|
||||
ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" --to %s",
|
||||
ip_tostring(mysetdata->last_ip, options));
|
||||
if (mysetdata->netmask == 0xFFFFFFFF)
|
||||
printf("\n");
|
||||
else
|
||||
printf(" --netmask %d\n",
|
||||
mask_to_bits(mysetdata->netmask));
|
||||
}
|
||||
|
||||
static void
|
||||
saveips(struct set *set, void *data, size_t len UNUSED, unsigned options)
|
||||
{
|
||||
struct ip_set_ipmap *mysetdata = set->settype->header;
|
||||
ip_set_ip_t id;
|
||||
|
||||
DP("%s", set->name);
|
||||
for (id = 0; id < mysetdata->sizeid; id++)
|
||||
if (test_bit(id, data))
|
||||
printf("-A %s %s\n",
|
||||
set->name,
|
||||
ip_tostring(mysetdata->first_ip
|
||||
+ id * mysetdata->hosts,
|
||||
options));
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf
|
||||
("-N set ipmap --from IP --to IP [--netmask CIDR-netmask]\n"
|
||||
"-N set ipmap --network IP/mask [--netmask CIDR-netmask]\n"
|
||||
"-A set IP\n"
|
||||
"-D set IP\n"
|
||||
"-T set IP\n");
|
||||
}
|
||||
|
||||
static struct settype settype_ipmap = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
|
||||
/* Create */
|
||||
.create_size = sizeof(struct ip_set_req_ipmap_create),
|
||||
.create_init = &create_init,
|
||||
.create_parse = &create_parse,
|
||||
.create_final = &create_final,
|
||||
.create_opts = create_opts,
|
||||
|
||||
/* Add/del/test */
|
||||
.adt_size = sizeof(struct ip_set_req_ipmap),
|
||||
.adt_parser = &adt_parser,
|
||||
|
||||
/* Printing */
|
||||
.header_size = sizeof(struct ip_set_ipmap),
|
||||
.initheader = &initheader,
|
||||
.printheader = &printheader,
|
||||
.printips = &printips_sorted, /* We only have sorted version */
|
||||
.printips_sorted = &printips_sorted,
|
||||
.saveheader = &saveheader,
|
||||
.saveips = &saveips,
|
||||
|
||||
/* Bindings */
|
||||
.bindip_tostring = &binding_ip_tostring,
|
||||
.bindip_parse = &parse_ip,
|
||||
|
||||
.usage = &usage,
|
||||
};
|
||||
|
||||
CONSTRUCTOR(ipmap)
|
||||
{
|
||||
settype_register(&settype_ipmap);
|
||||
|
||||
}
|
370
extensions/ipset/ipset_ipporthash.c
Normal file
370
extensions/ipset/ipset_ipporthash.c
Normal file
@@ -0,0 +1,370 @@
|
||||
/* Copyright 2004 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <limits.h> /* UINT_MAX */
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem*, str* */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_ipporthash.h"
|
||||
|
||||
#define OPT_CREATE_HASHSIZE 0x01U
|
||||
#define OPT_CREATE_PROBES 0x02U
|
||||
#define OPT_CREATE_RESIZE 0x04U
|
||||
#define OPT_CREATE_NETWORK 0x08U
|
||||
#define OPT_CREATE_FROM 0x10U
|
||||
#define OPT_CREATE_TO 0x20U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void
|
||||
create_init(void *data)
|
||||
{
|
||||
struct ip_set_req_ipporthash_create *mydata = data;
|
||||
|
||||
DP("create INIT");
|
||||
|
||||
/* Default create parameters */
|
||||
mydata->hashsize = 1024;
|
||||
mydata->probes = 8;
|
||||
mydata->resize = 50;
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int
|
||||
create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_ipporthash_create *mydata = data;
|
||||
ip_set_ip_t value;
|
||||
|
||||
DP("create_parse");
|
||||
|
||||
switch (c) {
|
||||
case '1':
|
||||
|
||||
if (string_to_number(optarg, 1, UINT_MAX - 1, &mydata->hashsize))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid hashsize `%s' specified", optarg);
|
||||
|
||||
*flags |= OPT_CREATE_HASHSIZE;
|
||||
|
||||
DP("--hashsize %u", mydata->hashsize);
|
||||
|
||||
break;
|
||||
|
||||
case '2':
|
||||
|
||||
if (string_to_number(optarg, 1, 65535, &value))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid probes `%s' specified", optarg);
|
||||
|
||||
mydata->probes = value;
|
||||
*flags |= OPT_CREATE_PROBES;
|
||||
|
||||
DP("--probes %u", mydata->probes);
|
||||
|
||||
break;
|
||||
|
||||
case '3':
|
||||
|
||||
if (string_to_number(optarg, 0, 65535, &value))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid resize `%s' specified", optarg);
|
||||
|
||||
mydata->resize = value;
|
||||
*flags |= OPT_CREATE_RESIZE;
|
||||
|
||||
DP("--resize %u", mydata->resize);
|
||||
|
||||
break;
|
||||
|
||||
case '4':
|
||||
parse_ip(optarg, &mydata->from);
|
||||
|
||||
*flags |= OPT_CREATE_FROM;
|
||||
|
||||
DP("--from %x (%s)", mydata->from,
|
||||
ip_tostring_numeric(mydata->from));
|
||||
|
||||
break;
|
||||
|
||||
case '5':
|
||||
parse_ip(optarg, &mydata->to);
|
||||
|
||||
*flags |= OPT_CREATE_TO;
|
||||
|
||||
DP("--to %x (%s)", mydata->to,
|
||||
ip_tostring_numeric(mydata->to));
|
||||
|
||||
break;
|
||||
|
||||
case '6':
|
||||
parse_ipandmask(optarg, &mydata->from, &mydata->to);
|
||||
|
||||
/* Make to the last of from + mask */
|
||||
if (mydata->to)
|
||||
mydata->to = mydata->from | ~(mydata->to);
|
||||
else {
|
||||
mydata->from = 0x00000000;
|
||||
mydata->to = 0xFFFFFFFF;
|
||||
}
|
||||
*flags |= OPT_CREATE_NETWORK;
|
||||
|
||||
DP("--network from %x (%s)",
|
||||
mydata->from, ip_tostring_numeric(mydata->from));
|
||||
DP("--network to %x (%s)",
|
||||
mydata->to, ip_tostring_numeric(mydata->to));
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void
|
||||
create_final(void *data, unsigned int flags)
|
||||
{
|
||||
struct ip_set_req_ipporthash_create *mydata = data;
|
||||
|
||||
#ifdef IPSET_DEBUG
|
||||
DP("hashsize %u probes %u resize %u",
|
||||
mydata->hashsize, mydata->probes, mydata->resize);
|
||||
#endif
|
||||
|
||||
if (flags & OPT_CREATE_NETWORK) {
|
||||
/* --network */
|
||||
if ((flags & OPT_CREATE_FROM) || (flags & OPT_CREATE_TO))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Can't specify --from or --to with --network\n");
|
||||
} else if (flags & (OPT_CREATE_FROM | OPT_CREATE_TO)) {
|
||||
/* --from --to */
|
||||
if (!(flags & OPT_CREATE_FROM) || !(flags & OPT_CREATE_TO))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify both --from and --to\n");
|
||||
} else {
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify --from and --to, or --network\n");
|
||||
|
||||
}
|
||||
|
||||
DP("from : %x to: %x diff: %x",
|
||||
mydata->from, mydata->to,
|
||||
mydata->to - mydata->from);
|
||||
|
||||
if (mydata->from > mydata->to)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"From can't be higher than to.\n");
|
||||
|
||||
if (mydata->to - mydata->from > MAX_RANGE)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Range too large. Max is %d IPs in range\n",
|
||||
MAX_RANGE+1);
|
||||
}
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{.name = "hashsize", .has_arg = required_argument, .val = '1'},
|
||||
{.name = "probes", .has_arg = required_argument, .val = '2'},
|
||||
{.name = "resize", .has_arg = required_argument, .val = '3'},
|
||||
{.name = "from", .has_arg = required_argument, .val = '4'},
|
||||
{.name = "to", .has_arg = required_argument, .val = '5'},
|
||||
{.name = "network", .has_arg = required_argument, .val = '6'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t
|
||||
adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_ipporthash *mydata = data;
|
||||
char *saved = ipset_strdup(arg);
|
||||
char *ptr, *tmp = saved;
|
||||
|
||||
DP("ipporthash: %p %p", arg, data);
|
||||
|
||||
if (((ptr = strchr(tmp, ':')) || (ptr = strchr(tmp, '%'))) && ++warn_once == 1)
|
||||
fprintf(stderr, "Warning: please use ',' separator token between ip,port.\n"
|
||||
"Next release won't support old separator tokens.\n");
|
||||
|
||||
ptr = strsep(&tmp, ":%,");
|
||||
parse_ip(ptr, &mydata->ip);
|
||||
|
||||
if (tmp)
|
||||
parse_port(tmp, &mydata->port);
|
||||
else
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"IP address and port must be specified: ip,port");
|
||||
|
||||
if (!(mydata->ip || mydata->port))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Zero valued IP address and port `%s' specified", arg);
|
||||
ipset_free(saved);
|
||||
return 1;
|
||||
};
|
||||
|
||||
/*
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void
|
||||
initheader(struct set *set, const void *data)
|
||||
{
|
||||
const struct ip_set_req_ipporthash_create *header = data;
|
||||
struct ip_set_ipporthash *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_ipporthash));
|
||||
map->hashsize = header->hashsize;
|
||||
map->probes = header->probes;
|
||||
map->resize = header->resize;
|
||||
map->first_ip = header->from;
|
||||
map->last_ip = header->to;
|
||||
}
|
||||
|
||||
static void
|
||||
printheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_ipporthash *mysetdata = set->settype->header;
|
||||
|
||||
printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
|
||||
printf(" hashsize: %u", mysetdata->hashsize);
|
||||
printf(" probes: %u", mysetdata->probes);
|
||||
printf(" resize: %u\n", mysetdata->resize);
|
||||
}
|
||||
|
||||
static void
|
||||
printips(struct set *set, void *data, size_t len, unsigned options)
|
||||
{
|
||||
struct ip_set_ipporthash *mysetdata = set->settype->header;
|
||||
size_t offset = 0;
|
||||
ip_set_ip_t *ipptr, ip;
|
||||
uint16_t port;
|
||||
|
||||
while (offset < len) {
|
||||
ipptr = data + offset;
|
||||
if (*ipptr) {
|
||||
ip = (*ipptr>>16) + mysetdata->first_ip;
|
||||
port = (uint16_t) *ipptr;
|
||||
printf("%s,%s\n",
|
||||
ip_tostring(ip, options),
|
||||
port_tostring(port, options));
|
||||
}
|
||||
offset += sizeof(ip_set_ip_t);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
saveheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_ipporthash *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --from %s",
|
||||
set->name, set->settype->typename,
|
||||
ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" --to %s",
|
||||
ip_tostring(mysetdata->last_ip, options));
|
||||
printf(" --hashsize %u --probes %u --resize %u\n",
|
||||
mysetdata->hashsize, mysetdata->probes, mysetdata->resize);
|
||||
}
|
||||
|
||||
/* Print save for an IP */
|
||||
static void
|
||||
saveips(struct set *set, void *data, size_t len, unsigned options)
|
||||
{
|
||||
struct ip_set_ipporthash *mysetdata = set->settype->header;
|
||||
size_t offset = 0;
|
||||
ip_set_ip_t *ipptr, ip;
|
||||
uint16_t port;
|
||||
|
||||
while (offset < len) {
|
||||
ipptr = data + offset;
|
||||
if (*ipptr) {
|
||||
ip = (*ipptr>>16) + mysetdata->first_ip;
|
||||
port = (uint16_t) *ipptr;
|
||||
printf("-A %s %s,%s\n", set->name,
|
||||
ip_tostring(ip, options),
|
||||
port_tostring(port, options));
|
||||
}
|
||||
offset += sizeof(ip_set_ip_t);
|
||||
}
|
||||
}
|
||||
|
||||
static char buffer[22];
|
||||
|
||||
static char *
|
||||
unpack_ipport_tostring(struct set *set, ip_set_ip_t bip, unsigned options)
|
||||
{
|
||||
struct ip_set_ipporthash *mysetdata = set->settype->header;
|
||||
ip_set_ip_t ip, port;
|
||||
|
||||
ip = (bip>>16) + mysetdata->first_ip;
|
||||
port = (uint16_t) bip;
|
||||
sprintf(buffer, "%s,%s",
|
||||
ip_tostring(ip, options), port_tostring(port, options));
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf
|
||||
("-N set ipporthash --from IP --to IP\n"
|
||||
" [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
|
||||
"-N set ipporthash --network IP/mask\n"
|
||||
" [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
|
||||
"-A set IP,port\n"
|
||||
"-D set IP,port\n"
|
||||
"-T set IP,port\n");
|
||||
}
|
||||
|
||||
static struct settype settype_ipporthash = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
|
||||
/* Create */
|
||||
.create_size = sizeof(struct ip_set_req_ipporthash_create),
|
||||
.create_init = &create_init,
|
||||
.create_parse = &create_parse,
|
||||
.create_final = &create_final,
|
||||
.create_opts = create_opts,
|
||||
|
||||
/* Add/del/test */
|
||||
.adt_size = sizeof(struct ip_set_req_ipporthash),
|
||||
.adt_parser = &adt_parser,
|
||||
|
||||
/* Printing */
|
||||
.header_size = sizeof(struct ip_set_ipporthash),
|
||||
.initheader = &initheader,
|
||||
.printheader = &printheader,
|
||||
.printips = &printips, /* We only have the unsorted version */
|
||||
.printips_sorted = &printips,
|
||||
.saveheader = &saveheader,
|
||||
.saveips = &saveips,
|
||||
|
||||
/* Bindings */
|
||||
.bindip_tostring = &unpack_ipport_tostring,
|
||||
.bindip_parse = &parse_ip,
|
||||
|
||||
.usage = &usage,
|
||||
};
|
||||
|
||||
CONSTRUCTOR(ipporthash)
|
||||
{
|
||||
settype_register(&settype_ipporthash);
|
||||
|
||||
}
|
361
extensions/ipset/ipset_ipportiphash.c
Normal file
361
extensions/ipset/ipset_ipportiphash.c
Normal file
@@ -0,0 +1,361 @@
|
||||
/* Copyright 2008 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <limits.h> /* UINT_MAX */
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem*, str* */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_ipportiphash.h"
|
||||
|
||||
#define OPT_CREATE_HASHSIZE 0x01U
|
||||
#define OPT_CREATE_PROBES 0x02U
|
||||
#define OPT_CREATE_RESIZE 0x04U
|
||||
#define OPT_CREATE_NETWORK 0x08U
|
||||
#define OPT_CREATE_FROM 0x10U
|
||||
#define OPT_CREATE_TO 0x20U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void
|
||||
create_init(void *data)
|
||||
{
|
||||
struct ip_set_req_ipportiphash_create *mydata = data;
|
||||
|
||||
DP("create INIT");
|
||||
|
||||
/* Default create parameters */
|
||||
mydata->hashsize = 1024;
|
||||
mydata->probes = 8;
|
||||
mydata->resize = 50;
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int
|
||||
create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_ipportiphash_create *mydata = data;
|
||||
ip_set_ip_t value;
|
||||
|
||||
DP("create_parse");
|
||||
|
||||
switch (c) {
|
||||
case '1':
|
||||
|
||||
if (string_to_number(optarg, 1, UINT_MAX - 1, &mydata->hashsize))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid hashsize `%s' specified", optarg);
|
||||
|
||||
*flags |= OPT_CREATE_HASHSIZE;
|
||||
|
||||
DP("--hashsize %u", mydata->hashsize);
|
||||
|
||||
break;
|
||||
|
||||
case '2':
|
||||
|
||||
if (string_to_number(optarg, 1, 65535, &value))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid probes `%s' specified", optarg);
|
||||
|
||||
mydata->probes = value;
|
||||
*flags |= OPT_CREATE_PROBES;
|
||||
|
||||
DP("--probes %u", mydata->probes);
|
||||
|
||||
break;
|
||||
|
||||
case '3':
|
||||
|
||||
if (string_to_number(optarg, 0, 65535, &value))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid resize `%s' specified", optarg);
|
||||
|
||||
mydata->resize = value;
|
||||
*flags |= OPT_CREATE_RESIZE;
|
||||
|
||||
DP("--resize %u", mydata->resize);
|
||||
|
||||
break;
|
||||
|
||||
case '4':
|
||||
parse_ip(optarg, &mydata->from);
|
||||
|
||||
*flags |= OPT_CREATE_FROM;
|
||||
|
||||
DP("--from %x (%s)", mydata->from,
|
||||
ip_tostring_numeric(mydata->from));
|
||||
|
||||
break;
|
||||
|
||||
case '5':
|
||||
parse_ip(optarg, &mydata->to);
|
||||
|
||||
*flags |= OPT_CREATE_TO;
|
||||
|
||||
DP("--to %x (%s)", mydata->to,
|
||||
ip_tostring_numeric(mydata->to));
|
||||
|
||||
break;
|
||||
|
||||
case '6':
|
||||
parse_ipandmask(optarg, &mydata->from, &mydata->to);
|
||||
|
||||
/* Make to the last of from + mask */
|
||||
if (mydata->to)
|
||||
mydata->to = mydata->from | ~(mydata->to);
|
||||
else {
|
||||
mydata->from = 0x00000000;
|
||||
mydata->to = 0xFFFFFFFF;
|
||||
}
|
||||
*flags |= OPT_CREATE_NETWORK;
|
||||
|
||||
DP("--network from %x (%s)",
|
||||
mydata->from, ip_tostring_numeric(mydata->from));
|
||||
DP("--network to %x (%s)",
|
||||
mydata->to, ip_tostring_numeric(mydata->to));
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void
|
||||
create_final(void *data, unsigned int flags)
|
||||
{
|
||||
struct ip_set_req_ipportiphash_create *mydata = data;
|
||||
|
||||
#ifdef IPSET_DEBUG
|
||||
DP("hashsize %u probes %u resize %u",
|
||||
mydata->hashsize, mydata->probes, mydata->resize);
|
||||
#endif
|
||||
|
||||
if (flags & OPT_CREATE_NETWORK) {
|
||||
/* --network */
|
||||
if ((flags & OPT_CREATE_FROM) || (flags & OPT_CREATE_TO))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Can't specify --from or --to with --network\n");
|
||||
} else if (flags & (OPT_CREATE_FROM | OPT_CREATE_TO)) {
|
||||
/* --from --to */
|
||||
if (!(flags & OPT_CREATE_FROM) || !(flags & OPT_CREATE_TO))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify both --from and --to\n");
|
||||
} else {
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify --from and --to, or --network\n");
|
||||
|
||||
}
|
||||
|
||||
DP("from : %x to: %x diff: %x",
|
||||
mydata->from, mydata->to,
|
||||
mydata->to - mydata->from);
|
||||
|
||||
if (mydata->from > mydata->to)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"From can't be higher than to.\n");
|
||||
|
||||
if (mydata->to - mydata->from > MAX_RANGE)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Range too large. Max is %d IPs in range\n",
|
||||
MAX_RANGE+1);
|
||||
}
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{.name = "hashsize", .has_arg = required_argument, .val = '1'},
|
||||
{.name = "probes", .has_arg = required_argument, .val = '2'},
|
||||
{.name = "resize", .has_arg = required_argument, .val = '3'},
|
||||
{.name = "from", .has_arg = required_argument, .val = '4'},
|
||||
{.name = "to", .has_arg = required_argument, .val = '5'},
|
||||
{.name = "network", .has_arg = required_argument, .val = '6'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t
|
||||
adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_ipportiphash *mydata = data;
|
||||
char *saved = ipset_strdup(arg);
|
||||
char *ptr, *tmp = saved;
|
||||
|
||||
DP("ipportiphash: %p %p", arg, data);
|
||||
|
||||
if (((ptr = strchr(tmp, ':')) || (ptr = strchr(tmp, '%'))) && ++warn_once == 1)
|
||||
fprintf(stderr, "Warning: please use ',' separator token between ip,port,ip.\n"
|
||||
"Next release won't support old separator tokens.\n");
|
||||
|
||||
ptr = strsep(&tmp, ":%,");
|
||||
parse_ip(ptr, &mydata->ip);
|
||||
|
||||
if (!tmp)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"IP address, port and IP address must be specified: ip,port,ip");
|
||||
|
||||
ptr = strsep(&tmp, ":%,");
|
||||
parse_port(ptr, &mydata->port);
|
||||
if (tmp)
|
||||
parse_ip(tmp, &mydata->ip1);
|
||||
else
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"IP address, port and IP address must be specified: ip,port,ip");
|
||||
if (!(mydata->ip || mydata->port || mydata->ip1))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Zero valued IP address, port and IP address `%s' specified", arg);
|
||||
ipset_free(saved);
|
||||
return 1;
|
||||
};
|
||||
|
||||
/*
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void
|
||||
initheader(struct set *set, const void *data)
|
||||
{
|
||||
const struct ip_set_req_ipportiphash_create *header = data;
|
||||
struct ip_set_ipportiphash *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_ipportiphash));
|
||||
map->hashsize = header->hashsize;
|
||||
map->probes = header->probes;
|
||||
map->resize = header->resize;
|
||||
map->first_ip = header->from;
|
||||
map->last_ip = header->to;
|
||||
}
|
||||
|
||||
static void
|
||||
printheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_ipportiphash *mysetdata = set->settype->header;
|
||||
|
||||
printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
|
||||
printf(" hashsize: %u", mysetdata->hashsize);
|
||||
printf(" probes: %u", mysetdata->probes);
|
||||
printf(" resize: %u\n", mysetdata->resize);
|
||||
}
|
||||
|
||||
static void
|
||||
printips(struct set *set, void *data, size_t len, unsigned options)
|
||||
{
|
||||
struct ip_set_ipportiphash *mysetdata = set->settype->header;
|
||||
size_t offset = 0;
|
||||
struct ipportip *ipptr;
|
||||
ip_set_ip_t ip;
|
||||
uint16_t port;
|
||||
|
||||
while (offset < len) {
|
||||
ipptr = data + offset;
|
||||
if (ipptr->ip && ipptr->ip1) {
|
||||
ip = (ipptr->ip>>16) + mysetdata->first_ip;
|
||||
port = (uint16_t) ipptr->ip;
|
||||
printf("%s,%s,",
|
||||
ip_tostring(ip, options),
|
||||
port_tostring(port, options));
|
||||
printf("%s\n",
|
||||
ip_tostring(ipptr->ip1, options));
|
||||
}
|
||||
offset += sizeof(struct ipportip);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
saveheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_ipportiphash *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --from %s",
|
||||
set->name, set->settype->typename,
|
||||
ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" --to %s",
|
||||
ip_tostring(mysetdata->last_ip, options));
|
||||
printf(" --hashsize %u --probes %u --resize %u\n",
|
||||
mysetdata->hashsize, mysetdata->probes, mysetdata->resize);
|
||||
}
|
||||
|
||||
/* Print save for an IP */
|
||||
static void
|
||||
saveips(struct set *set, void *data, size_t len, unsigned options)
|
||||
{
|
||||
struct ip_set_ipportiphash *mysetdata = set->settype->header;
|
||||
size_t offset = 0;
|
||||
struct ipportip *ipptr;
|
||||
ip_set_ip_t ip;
|
||||
uint16_t port;
|
||||
|
||||
while (offset < len) {
|
||||
ipptr = data + offset;
|
||||
if (ipptr->ip && ipptr->ip1) {
|
||||
ip = (ipptr->ip>>16) + mysetdata->first_ip;
|
||||
port = (uint16_t) ipptr->ip;
|
||||
printf("-A %s %s,%s,", set->name,
|
||||
ip_tostring(ip, options),
|
||||
port_tostring(port, options));
|
||||
printf("%s\n",
|
||||
ip_tostring(ipptr->ip1, options));
|
||||
}
|
||||
offset += sizeof(struct ipportip);
|
||||
}
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf
|
||||
("-N set ipportiphash --from IP --to IP\n"
|
||||
" [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
|
||||
"-N set ipportiphash --network IP/mask\n"
|
||||
" [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
|
||||
"-A set IP,port,IP\n"
|
||||
"-D set IP,port,IP\n"
|
||||
"-T set IP,port,IP\n");
|
||||
}
|
||||
|
||||
static struct settype settype_ipportiphash = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
|
||||
/* Create */
|
||||
.create_size = sizeof(struct ip_set_req_ipportiphash_create),
|
||||
.create_init = &create_init,
|
||||
.create_parse = &create_parse,
|
||||
.create_final = &create_final,
|
||||
.create_opts = create_opts,
|
||||
|
||||
/* Add/del/test */
|
||||
.adt_size = sizeof(struct ip_set_req_ipportiphash),
|
||||
.adt_parser = &adt_parser,
|
||||
|
||||
/* Printing */
|
||||
.header_size = sizeof(struct ip_set_ipportiphash),
|
||||
.initheader = &initheader,
|
||||
.printheader = &printheader,
|
||||
.printips = &printips, /* We only have the unsorted version */
|
||||
.printips_sorted = &printips,
|
||||
.saveheader = &saveheader,
|
||||
.saveips = &saveips,
|
||||
|
||||
.usage = &usage,
|
||||
};
|
||||
|
||||
CONSTRUCTOR(ipportiphash)
|
||||
{
|
||||
settype_register(&settype_ipportiphash);
|
||||
|
||||
}
|
426
extensions/ipset/ipset_ipportnethash.c
Normal file
426
extensions/ipset/ipset_ipportnethash.c
Normal file
@@ -0,0 +1,426 @@
|
||||
/* Copyright 2008 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <limits.h> /* UINT_MAX */
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem*, str* */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_ipportnethash.h"
|
||||
|
||||
#define OPT_CREATE_HASHSIZE 0x01U
|
||||
#define OPT_CREATE_PROBES 0x02U
|
||||
#define OPT_CREATE_RESIZE 0x04U
|
||||
#define OPT_CREATE_NETWORK 0x08U
|
||||
#define OPT_CREATE_FROM 0x10U
|
||||
#define OPT_CREATE_TO 0x20U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void
|
||||
create_init(void *data)
|
||||
{
|
||||
struct ip_set_req_ipportnethash_create *mydata = data;
|
||||
|
||||
DP("create INIT");
|
||||
|
||||
/* Default create parameters */
|
||||
mydata->hashsize = 1024;
|
||||
mydata->probes = 8;
|
||||
mydata->resize = 50;
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int
|
||||
create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_ipportnethash_create *mydata = data;
|
||||
ip_set_ip_t value;
|
||||
|
||||
DP("create_parse");
|
||||
|
||||
switch (c) {
|
||||
case '1':
|
||||
|
||||
if (string_to_number(optarg, 1, UINT_MAX - 1, &mydata->hashsize))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid hashsize `%s' specified", optarg);
|
||||
|
||||
*flags |= OPT_CREATE_HASHSIZE;
|
||||
|
||||
DP("--hashsize %u", mydata->hashsize);
|
||||
|
||||
break;
|
||||
|
||||
case '2':
|
||||
|
||||
if (string_to_number(optarg, 1, 65535, &value))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid probes `%s' specified", optarg);
|
||||
|
||||
mydata->probes = value;
|
||||
*flags |= OPT_CREATE_PROBES;
|
||||
|
||||
DP("--probes %u", mydata->probes);
|
||||
|
||||
break;
|
||||
|
||||
case '3':
|
||||
|
||||
if (string_to_number(optarg, 0, 65535, &value))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid resize `%s' specified", optarg);
|
||||
|
||||
mydata->resize = value;
|
||||
*flags |= OPT_CREATE_RESIZE;
|
||||
|
||||
DP("--resize %u", mydata->resize);
|
||||
|
||||
break;
|
||||
|
||||
case '4':
|
||||
parse_ip(optarg, &mydata->from);
|
||||
|
||||
*flags |= OPT_CREATE_FROM;
|
||||
|
||||
DP("--from %x (%s)", mydata->from,
|
||||
ip_tostring_numeric(mydata->from));
|
||||
|
||||
break;
|
||||
|
||||
case '5':
|
||||
parse_ip(optarg, &mydata->to);
|
||||
|
||||
*flags |= OPT_CREATE_TO;
|
||||
|
||||
DP("--to %x (%s)", mydata->to,
|
||||
ip_tostring_numeric(mydata->to));
|
||||
|
||||
break;
|
||||
|
||||
case '6':
|
||||
parse_ipandmask(optarg, &mydata->from, &mydata->to);
|
||||
|
||||
/* Make to the last of from + mask */
|
||||
if (mydata->to)
|
||||
mydata->to = mydata->from | ~(mydata->to);
|
||||
else {
|
||||
mydata->from = 0x00000000;
|
||||
mydata->to = 0xFFFFFFFF;
|
||||
}
|
||||
*flags |= OPT_CREATE_NETWORK;
|
||||
|
||||
DP("--network from %x (%s)",
|
||||
mydata->from, ip_tostring_numeric(mydata->from));
|
||||
DP("--network to %x (%s)",
|
||||
mydata->to, ip_tostring_numeric(mydata->to));
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void
|
||||
create_final(void *data, unsigned int flags)
|
||||
{
|
||||
struct ip_set_req_ipportnethash_create *mydata = data;
|
||||
|
||||
#ifdef IPSET_DEBUG
|
||||
DP("hashsize %u probes %u resize %u",
|
||||
mydata->hashsize, mydata->probes, mydata->resize);
|
||||
#endif
|
||||
|
||||
if (flags & OPT_CREATE_NETWORK) {
|
||||
/* --network */
|
||||
if ((flags & OPT_CREATE_FROM) || (flags & OPT_CREATE_TO))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Can't specify --from or --to with --network\n");
|
||||
} else if (flags & (OPT_CREATE_FROM | OPT_CREATE_TO)) {
|
||||
/* --from --to */
|
||||
if (!(flags & OPT_CREATE_FROM) || !(flags & OPT_CREATE_TO))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify both --from and --to\n");
|
||||
} else {
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify --from and --to, or --network\n");
|
||||
|
||||
}
|
||||
|
||||
DP("from : %x to: %x diff: %x",
|
||||
mydata->from, mydata->to,
|
||||
mydata->to - mydata->from);
|
||||
|
||||
if (mydata->from > mydata->to)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"From can't be higher than to.\n");
|
||||
|
||||
if (mydata->to - mydata->from > MAX_RANGE)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Range too large. Max is %d IPs in range\n",
|
||||
MAX_RANGE+1);
|
||||
}
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{.name = "hashsize", .has_arg = required_argument, .val = '1'},
|
||||
{.name = "probes", .has_arg = required_argument, .val = '2'},
|
||||
{.name = "resize", .has_arg = required_argument, .val = '3'},
|
||||
{.name = "from", .has_arg = required_argument, .val = '4'},
|
||||
{.name = "to", .has_arg = required_argument, .val = '5'},
|
||||
{.name = "network", .has_arg = required_argument, .val = '6'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t
|
||||
adt_parser(int cmd, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_ipportnethash *mydata = data;
|
||||
char *saved = ipset_strdup(arg);
|
||||
char *ptr, *tmp = saved;
|
||||
ip_set_ip_t cidr;
|
||||
|
||||
DP("ipportnethash: %p %p", arg, data);
|
||||
|
||||
if (((ptr = strchr(tmp, ':')) || (ptr = strchr(tmp, '%'))) && ++warn_once == 1)
|
||||
fprintf(stderr, "Warning: please use ',' separator token between ip,port,net.\n"
|
||||
"Next release won't support old separator tokens.\n");
|
||||
|
||||
ptr = strsep(&tmp, ":%,");
|
||||
parse_ip(ptr, &mydata->ip);
|
||||
if (!tmp)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"IP address, port and network address must be specified: ip,port,net");
|
||||
|
||||
ptr = strsep(&tmp, ":%,");
|
||||
parse_port(ptr, &mydata->port);
|
||||
if (!tmp)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"IP address, port and network address must be specified: ip,port,net");
|
||||
|
||||
ptr = strsep(&tmp, "/");
|
||||
if (tmp == NULL)
|
||||
if (cmd == CMD_TEST)
|
||||
cidr = 32;
|
||||
else
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Missing /cidr from `%s'", arg);
|
||||
else
|
||||
if (string_to_number(tmp, 1, 31, &cidr))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Out of range cidr `%s' specified", arg);
|
||||
|
||||
mydata->cidr = cidr;
|
||||
|
||||
parse_ip(ptr, &mydata->ip1);
|
||||
ipset_free(saved);
|
||||
return 1;
|
||||
};
|
||||
|
||||
/*
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void
|
||||
initheader(struct set *set, const void *data)
|
||||
{
|
||||
const struct ip_set_req_ipportnethash_create *header = data;
|
||||
struct ip_set_ipportnethash *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_ipportnethash));
|
||||
map->hashsize = header->hashsize;
|
||||
map->probes = header->probes;
|
||||
map->resize = header->resize;
|
||||
map->first_ip = header->from;
|
||||
map->last_ip = header->to;
|
||||
}
|
||||
|
||||
static void
|
||||
printheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_ipportnethash *mysetdata = set->settype->header;
|
||||
|
||||
printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
|
||||
printf(" hashsize: %u", mysetdata->hashsize);
|
||||
printf(" probes: %u", mysetdata->probes);
|
||||
printf(" resize: %u\n", mysetdata->resize);
|
||||
}
|
||||
|
||||
static char buf[20];
|
||||
|
||||
static char *
|
||||
unpack_ip_tostring(ip_set_ip_t ip, unsigned options UNUSED)
|
||||
{
|
||||
int i, j = 3;
|
||||
unsigned char a, b;
|
||||
|
||||
ip = htonl(ip);
|
||||
for (i = 3; i >= 0; i--)
|
||||
if (((unsigned char *)&ip)[i] != 0) {
|
||||
j = i;
|
||||
break;
|
||||
}
|
||||
|
||||
a = ((unsigned char *)&ip)[j];
|
||||
if (a <= 128) {
|
||||
a = (a - 1) * 2;
|
||||
b = 7;
|
||||
} else if (a <= 192) {
|
||||
a = (a - 129) * 4;
|
||||
b = 6;
|
||||
} else if (a <= 224) {
|
||||
a = (a - 193) * 8;
|
||||
b = 5;
|
||||
} else if (a <= 240) {
|
||||
a = (a - 225) * 16;
|
||||
b = 4;
|
||||
} else if (a <= 248) {
|
||||
a = (a - 241) * 32;
|
||||
b = 3;
|
||||
} else if (a <= 252) {
|
||||
a = (a - 249) * 64;
|
||||
b = 2;
|
||||
} else if (a <= 254) {
|
||||
a = (a - 253) * 128;
|
||||
b = 1;
|
||||
} else {
|
||||
a = b = 0;
|
||||
}
|
||||
((unsigned char *)&ip)[j] = a;
|
||||
b += j * 8;
|
||||
|
||||
sprintf(buf, "%u.%u.%u.%u/%u",
|
||||
((unsigned char *)&ip)[0],
|
||||
((unsigned char *)&ip)[1],
|
||||
((unsigned char *)&ip)[2],
|
||||
((unsigned char *)&ip)[3],
|
||||
b);
|
||||
|
||||
DP("%s %s", ip_tostring(ntohl(ip), 0), buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void
|
||||
printips(struct set *set, void *data, size_t len, unsigned options)
|
||||
{
|
||||
struct ip_set_ipportnethash *mysetdata = set->settype->header;
|
||||
size_t offset = 0;
|
||||
struct ipportip *ipptr;
|
||||
ip_set_ip_t ip;
|
||||
uint16_t port;
|
||||
|
||||
while (offset < len) {
|
||||
ipptr = data + offset;
|
||||
if (ipptr->ip || ipptr->ip1) {
|
||||
ip = (ipptr->ip>>16) + mysetdata->first_ip;
|
||||
port = (uint16_t) ipptr->ip;
|
||||
printf("%s,%s,",
|
||||
ip_tostring(ip, options),
|
||||
port_tostring(port, options));
|
||||
printf("%s\n",
|
||||
unpack_ip_tostring(ipptr->ip1, options));
|
||||
}
|
||||
offset += sizeof(struct ipportip);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
saveheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_ipportnethash *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --from %s",
|
||||
set->name, set->settype->typename,
|
||||
ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" --to %s",
|
||||
ip_tostring(mysetdata->last_ip, options));
|
||||
printf(" --hashsize %u --probes %u --resize %u\n",
|
||||
mysetdata->hashsize, mysetdata->probes, mysetdata->resize);
|
||||
}
|
||||
|
||||
/* Print save for an IP */
|
||||
static void
|
||||
saveips(struct set *set, void *data, size_t len, unsigned options)
|
||||
{
|
||||
struct ip_set_ipportnethash *mysetdata = set->settype->header;
|
||||
size_t offset = 0;
|
||||
struct ipportip *ipptr;
|
||||
ip_set_ip_t ip;
|
||||
uint16_t port;
|
||||
|
||||
while (offset < len) {
|
||||
ipptr = data + offset;
|
||||
if (ipptr) {
|
||||
ip = (ipptr->ip>>16) + mysetdata->first_ip;
|
||||
port = (uint16_t) ipptr->ip;
|
||||
printf("-A %s %s,%s,", set->name,
|
||||
ip_tostring(ip, options),
|
||||
port_tostring(port, options));
|
||||
printf("%s\n",
|
||||
unpack_ip_tostring(ipptr->ip, options));
|
||||
}
|
||||
offset += sizeof(struct ipportip);
|
||||
}
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf
|
||||
("-N set ipportnethash --from IP --to IP\n"
|
||||
" [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
|
||||
"-N set ipportnethash --network IP/mask\n"
|
||||
" [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
|
||||
"-A set IP,port,IP/net\n"
|
||||
"-D set IP,port,IP/net\n"
|
||||
"-T set IP,port,IP[/net]\n");
|
||||
}
|
||||
|
||||
static struct settype settype_ipportnethash = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
|
||||
/* Create */
|
||||
.create_size = sizeof(struct ip_set_req_ipportnethash_create),
|
||||
.create_init = &create_init,
|
||||
.create_parse = &create_parse,
|
||||
.create_final = &create_final,
|
||||
.create_opts = create_opts,
|
||||
|
||||
/* Add/del/test */
|
||||
.adt_size = sizeof(struct ip_set_req_ipportnethash),
|
||||
.adt_parser = &adt_parser,
|
||||
|
||||
/* Printing */
|
||||
.header_size = sizeof(struct ip_set_ipportnethash),
|
||||
.initheader = &initheader,
|
||||
.printheader = &printheader,
|
||||
.printips = &printips, /* We only have the unsorted version */
|
||||
.printips_sorted = &printips,
|
||||
.saveheader = &saveheader,
|
||||
.saveips = &saveips,
|
||||
|
||||
.usage = &usage,
|
||||
};
|
||||
|
||||
CONSTRUCTOR(ipportnethash)
|
||||
{
|
||||
settype_register(&settype_ipportnethash);
|
||||
|
||||
}
|
225
extensions/ipset/ipset_iptree.c
Normal file
225
extensions/ipset/ipset_iptree.c
Normal file
@@ -0,0 +1,225 @@
|
||||
/* Copyright 2005 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <limits.h> /* UINT_MAX */
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem* */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_iptree.h"
|
||||
|
||||
#define BUFLEN 30;
|
||||
|
||||
#define OPT_CREATE_TIMEOUT 0x01U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void
|
||||
create_init(void *data)
|
||||
{
|
||||
struct ip_set_req_iptree_create *mydata = data;
|
||||
|
||||
DP("create INIT");
|
||||
mydata->timeout = 0;
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int
|
||||
create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_iptree_create *mydata = data;
|
||||
|
||||
DP("create_parse");
|
||||
|
||||
switch (c) {
|
||||
case '1':
|
||||
string_to_number(optarg, 0, UINT_MAX, &mydata->timeout);
|
||||
|
||||
*flags |= OPT_CREATE_TIMEOUT;
|
||||
|
||||
DP("--timeout %u", mydata->timeout);
|
||||
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void
|
||||
create_final(void *data UNUSED, unsigned int flags UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{.name = "timeout", .has_arg = required_argument, .val = '1'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t
|
||||
adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_iptree *mydata = data;
|
||||
char *saved = ipset_strdup(arg);
|
||||
char *ptr, *tmp = saved;
|
||||
|
||||
DP("iptree: %p %p", arg, data);
|
||||
|
||||
if (((ptr = strchr(tmp, ':')) || (ptr = strchr(tmp, '%'))) && ++warn_once == 1)
|
||||
fprintf(stderr, "Warning: please use ',' separator token between ip,timeout.\n"
|
||||
"Next release won't support old separator tokens.\n");
|
||||
|
||||
ptr = strsep(&tmp, ":%,");
|
||||
parse_ip(ptr, &mydata->ip);
|
||||
|
||||
if (tmp)
|
||||
string_to_number(tmp, 0, UINT_MAX, &mydata->timeout);
|
||||
else
|
||||
mydata->timeout = 0;
|
||||
|
||||
ipset_free(saved);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void
|
||||
initheader(struct set *set, const void *data)
|
||||
{
|
||||
const struct ip_set_req_iptree_create *header = data;
|
||||
struct ip_set_iptree *map = set->settype->header;
|
||||
|
||||
map->timeout = header->timeout;
|
||||
}
|
||||
|
||||
static void
|
||||
printheader(struct set *set, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_iptree *mysetdata = set->settype->header;
|
||||
|
||||
if (mysetdata->timeout)
|
||||
printf(" timeout: %u", mysetdata->timeout);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
printips_sorted(struct set *set, void *data, size_t len, unsigned options)
|
||||
{
|
||||
struct ip_set_iptree *mysetdata = set->settype->header;
|
||||
struct ip_set_req_iptree *req;
|
||||
size_t offset = 0;
|
||||
|
||||
while (len >= offset + sizeof(struct ip_set_req_iptree)) {
|
||||
req = (struct ip_set_req_iptree *)(data + offset);
|
||||
if (mysetdata->timeout)
|
||||
printf("%s,%u\n", ip_tostring(req->ip, options),
|
||||
req->timeout);
|
||||
else
|
||||
printf("%s\n", ip_tostring(req->ip, options));
|
||||
offset += sizeof(struct ip_set_req_iptree);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
saveheader(struct set *set, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_iptree *mysetdata = set->settype->header;
|
||||
|
||||
if (mysetdata->timeout)
|
||||
printf("-N %s %s --timeout %u\n",
|
||||
set->name, set->settype->typename,
|
||||
mysetdata->timeout);
|
||||
else
|
||||
printf("-N %s %s\n",
|
||||
set->name, set->settype->typename);
|
||||
}
|
||||
|
||||
static void
|
||||
saveips(struct set *set, void *data, size_t len, unsigned options)
|
||||
{
|
||||
struct ip_set_iptree *mysetdata = set->settype->header;
|
||||
struct ip_set_req_iptree *req;
|
||||
size_t offset = 0;
|
||||
|
||||
DP("%s", set->name);
|
||||
|
||||
while (len >= offset + sizeof(struct ip_set_req_iptree)) {
|
||||
req = (struct ip_set_req_iptree *)(data + offset);
|
||||
if (mysetdata->timeout)
|
||||
printf("-A %s %s,%u\n",
|
||||
set->name,
|
||||
ip_tostring(req->ip, options),
|
||||
req->timeout);
|
||||
else
|
||||
printf("-A %s %s\n",
|
||||
set->name,
|
||||
ip_tostring(req->ip, options));
|
||||
offset += sizeof(struct ip_set_req_iptree);
|
||||
}
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf
|
||||
("-N set iptree [--timeout value]\n"
|
||||
"-A set IP[,timeout]\n"
|
||||
"-D set IP\n"
|
||||
"-T set IP\n");
|
||||
}
|
||||
|
||||
static struct settype settype_iptree = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
|
||||
/* Create */
|
||||
.create_size = sizeof(struct ip_set_req_iptree_create),
|
||||
.create_init = &create_init,
|
||||
.create_parse = &create_parse,
|
||||
.create_final = &create_final,
|
||||
.create_opts = create_opts,
|
||||
|
||||
/* Add/del/test */
|
||||
.adt_size = sizeof(struct ip_set_req_iptree),
|
||||
.adt_parser = &adt_parser,
|
||||
|
||||
/* Printing */
|
||||
.header_size = sizeof(struct ip_set_iptree),
|
||||
.initheader = &initheader,
|
||||
.printheader = &printheader,
|
||||
.printips = &printips_sorted, /* We only have sorted version */
|
||||
.printips_sorted = &printips_sorted,
|
||||
.saveheader = &saveheader,
|
||||
.saveips = &saveips,
|
||||
|
||||
/* Bindings */
|
||||
.bindip_tostring = &binding_ip_tostring,
|
||||
.bindip_parse = &parse_ip,
|
||||
|
||||
.usage = &usage,
|
||||
};
|
||||
|
||||
CONSTRUCTOR(iptree)
|
||||
{
|
||||
settype_register(&settype_iptree);
|
||||
|
||||
}
|
210
extensions/ipset/ipset_iptreemap.c
Normal file
210
extensions/ipset/ipset_iptreemap.c
Normal file
@@ -0,0 +1,210 @@
|
||||
/* Copyright 2007 Sven Wegener <sven.wegener@stealer.net>
|
||||
*
|
||||
* 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., 59 Temple
|
||||
* Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <limits.h> /* UINT_MAX */
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem* */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_iptreemap.h"
|
||||
|
||||
#define OPT_CREATE_GC 0x1
|
||||
|
||||
static void
|
||||
create_init(void *data)
|
||||
{
|
||||
struct ip_set_req_iptreemap_create *mydata = data;
|
||||
|
||||
mydata->gc_interval = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
create_parse(int c, char *argv[] UNUSED, void *data, unsigned int *flags)
|
||||
{
|
||||
struct ip_set_req_iptreemap_create *mydata = data;
|
||||
|
||||
switch (c) {
|
||||
case 'g':
|
||||
string_to_number(optarg, 0, UINT_MAX, &mydata->gc_interval);
|
||||
|
||||
*flags |= OPT_CREATE_GC;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
create_final(void *data UNUSED, unsigned int flags UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct option create_opts[] = {
|
||||
{.name = "gc", .has_arg = required_argument, .val = 'g'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static ip_set_ip_t
|
||||
adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_iptreemap *mydata = data;
|
||||
ip_set_ip_t mask;
|
||||
|
||||
char *saved = ipset_strdup(arg);
|
||||
char *ptr, *tmp = saved;
|
||||
|
||||
if (strchr(tmp, '/')) {
|
||||
parse_ipandmask(tmp, &mydata->ip, &mask);
|
||||
mydata->end = mydata->ip | ~mask;
|
||||
} else {
|
||||
if ((ptr = strchr(tmp, ':')) != NULL && ++warn_once == 1)
|
||||
fprintf(stderr, "Warning: please use '-' separator token between IP range.\n"
|
||||
"Next release won't support old separator token.\n");
|
||||
ptr = strsep(&tmp, "-:");
|
||||
parse_ip(ptr, &mydata->ip);
|
||||
|
||||
if (tmp) {
|
||||
parse_ip(tmp, &mydata->end);
|
||||
} else {
|
||||
mydata->end = mydata->ip;
|
||||
}
|
||||
}
|
||||
|
||||
ipset_free(saved);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
initheader(struct set *set, const void *data)
|
||||
{
|
||||
const struct ip_set_req_iptreemap_create *header = data;
|
||||
struct ip_set_iptreemap *map = set->settype->header;
|
||||
|
||||
map->gc_interval = header->gc_interval;
|
||||
}
|
||||
|
||||
static void
|
||||
printheader(struct set *set, unsigned int options UNUSED)
|
||||
{
|
||||
struct ip_set_iptreemap *mysetdata = set->settype->header;
|
||||
|
||||
if (mysetdata->gc_interval)
|
||||
printf(" gc: %u", mysetdata->gc_interval);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
printips_sorted(struct set *set UNUSED, void *data,
|
||||
size_t len, unsigned int options)
|
||||
{
|
||||
struct ip_set_req_iptreemap *req;
|
||||
size_t offset = 0;
|
||||
|
||||
while (len >= offset + sizeof(struct ip_set_req_iptreemap)) {
|
||||
req = data + offset;
|
||||
|
||||
printf("%s", ip_tostring(req->ip, options));
|
||||
if (req->ip != req->end)
|
||||
printf("-%s", ip_tostring(req->end, options));
|
||||
printf("\n");
|
||||
|
||||
offset += sizeof(struct ip_set_req_iptreemap);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
saveheader(struct set *set, unsigned int options UNUSED)
|
||||
{
|
||||
struct ip_set_iptreemap *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s", set->name, set->settype->typename);
|
||||
|
||||
if (mysetdata->gc_interval)
|
||||
printf(" --gc %u", mysetdata->gc_interval);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
saveips(struct set *set UNUSED, void *data,
|
||||
size_t len, unsigned int options)
|
||||
{
|
||||
struct ip_set_req_iptreemap *req;
|
||||
size_t offset = 0;
|
||||
|
||||
while (len >= offset + sizeof(struct ip_set_req_iptreemap)) {
|
||||
req = data + offset;
|
||||
|
||||
printf("-A %s %s", set->name, ip_tostring(req->ip, options));
|
||||
|
||||
if (req->ip != req->end)
|
||||
printf("-%s", ip_tostring(req->end, options));
|
||||
|
||||
printf("\n");
|
||||
|
||||
offset += sizeof(struct ip_set_req_iptreemap);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf(
|
||||
"-N set iptreemap --gc interval\n"
|
||||
"-A set IP\n"
|
||||
"-D set IP\n"
|
||||
"-T set IP\n"
|
||||
);
|
||||
}
|
||||
|
||||
static struct settype settype_iptreemap = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
|
||||
.create_size = sizeof(struct ip_set_req_iptreemap_create),
|
||||
.create_init = &create_init,
|
||||
.create_parse = &create_parse,
|
||||
.create_final = &create_final,
|
||||
.create_opts = create_opts,
|
||||
|
||||
.adt_size = sizeof(struct ip_set_req_iptreemap),
|
||||
.adt_parser = &adt_parser,
|
||||
|
||||
.header_size = sizeof(struct ip_set_iptreemap),
|
||||
.initheader = &initheader,
|
||||
.printheader = &printheader,
|
||||
.printips = &printips_sorted,
|
||||
.printips_sorted = &printips_sorted,
|
||||
.saveheader = &saveheader,
|
||||
.saveips = &saveips,
|
||||
|
||||
.bindip_tostring = &binding_ip_tostring,
|
||||
.bindip_parse = &parse_ip,
|
||||
|
||||
.usage = &usage,
|
||||
};
|
||||
|
||||
CONSTRUCTOR(iptreemap)
|
||||
{
|
||||
settype_register(&settype_iptreemap);
|
||||
}
|
347
extensions/ipset/ipset_macipmap.c
Normal file
347
extensions/ipset/ipset_macipmap.c
Normal file
@@ -0,0 +1,347 @@
|
||||
/* Copyright 2000, 2001, 2002 Joakim Axelsson (gozem@linux.nu)
|
||||
* Patrick Schaaf (bof@bof.de)
|
||||
* Martin Josefsson (gandalf@wlug.westbo.se)
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <stdlib.h> /* mem* */
|
||||
#include <string.h> /* str* */
|
||||
#include <net/ethernet.h> /* ETH_ALEN */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_macipmap.h"
|
||||
|
||||
#define BUFLEN 30;
|
||||
|
||||
#define OPT_CREATE_FROM 0x01U
|
||||
#define OPT_CREATE_TO 0x02U
|
||||
#define OPT_CREATE_NETWORK 0x04U
|
||||
#define OPT_CREATE_MATCHUNSET 0x08U
|
||||
|
||||
#define OPT_ADDDEL_IP 0x01U
|
||||
#define OPT_ADDDEL_MAC 0x02U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void
|
||||
create_init(void *data UNUSED)
|
||||
{
|
||||
DP("create INIT");
|
||||
/* Nothing */
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int
|
||||
create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_macipmap_create *mydata = data;
|
||||
|
||||
DP("create_parse");
|
||||
|
||||
switch (c) {
|
||||
case '1':
|
||||
parse_ip(optarg, &mydata->from);
|
||||
|
||||
*flags |= OPT_CREATE_FROM;
|
||||
|
||||
DP("--from %x (%s)", mydata->from,
|
||||
ip_tostring_numeric(mydata->from));
|
||||
|
||||
break;
|
||||
|
||||
case '2':
|
||||
parse_ip(optarg, &mydata->to);
|
||||
|
||||
*flags |= OPT_CREATE_TO;
|
||||
|
||||
DP("--to %x (%s)", mydata->to,
|
||||
ip_tostring_numeric(mydata->to));
|
||||
|
||||
break;
|
||||
|
||||
case '3':
|
||||
parse_ipandmask(optarg, &mydata->from, &mydata->to);
|
||||
|
||||
/* Make to the last of from + mask */
|
||||
mydata->to = mydata->from | (~mydata->to);
|
||||
|
||||
*flags |= OPT_CREATE_NETWORK;
|
||||
|
||||
DP("--network from %x (%s)",
|
||||
mydata->from, ip_tostring_numeric(mydata->from));
|
||||
DP("--network to %x (%s)",
|
||||
mydata->to, ip_tostring_numeric(mydata->to));
|
||||
|
||||
break;
|
||||
|
||||
case '4':
|
||||
mydata->flags |= IPSET_MACIP_MATCHUNSET;
|
||||
|
||||
*flags |= OPT_CREATE_MATCHUNSET;
|
||||
|
||||
DP("--matchunset");
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void
|
||||
create_final(void *data, unsigned int flags)
|
||||
{
|
||||
struct ip_set_req_macipmap_create *mydata = data;
|
||||
|
||||
if (flags == 0)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify --from and --to, or --network\n");
|
||||
|
||||
if (flags & OPT_CREATE_NETWORK) {
|
||||
/* --network */
|
||||
if ((flags & OPT_CREATE_FROM) || (flags & OPT_CREATE_TO))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Can't specify --from or --to with --network\n");
|
||||
} else {
|
||||
/* --from --to */
|
||||
if ((flags & OPT_CREATE_FROM) == 0
|
||||
|| (flags & OPT_CREATE_TO) == 0)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify both --from and --to\n");
|
||||
}
|
||||
|
||||
|
||||
DP("from : %x to: %x diff: %d match unset: %d", mydata->from,
|
||||
mydata->to, mydata->to - mydata->from,
|
||||
flags & OPT_CREATE_MATCHUNSET);
|
||||
|
||||
if (mydata->from > mydata->to)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"From can't be lower than to.\n");
|
||||
|
||||
if (mydata->to - mydata->from > MAX_RANGE)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Range too large. Max is %d IPs in range\n",
|
||||
MAX_RANGE+1);
|
||||
}
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{.name = "from", .has_arg = required_argument, .val = '1'},
|
||||
{.name = "to", .has_arg = required_argument, .val = '2'},
|
||||
{.name = "network", .has_arg = required_argument, .val = '3'},
|
||||
{.name = "matchunset", .has_arg = no_argument, .val = '4'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static void
|
||||
parse_mac(const char *mac, unsigned char *ethernet)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
if (strlen(mac) != ETH_ALEN * 3 - 1)
|
||||
exit_error(PARAMETER_PROBLEM, "Bad mac address `%s'", mac);
|
||||
|
||||
for (i = 0; i < ETH_ALEN; i++) {
|
||||
long number;
|
||||
char *end;
|
||||
|
||||
number = strtol(mac + i * 3, &end, 16);
|
||||
|
||||
if (end == mac + i * 3 + 2 && number >= 0 && number <= 255)
|
||||
ethernet[i] = number;
|
||||
else
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Bad mac address `%s'", mac);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t
|
||||
adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_macipmap *mydata = data;
|
||||
char *saved = ipset_strdup(arg);
|
||||
char *ptr, *tmp = saved;
|
||||
|
||||
DP("macipmap: %p %p", arg, data);
|
||||
|
||||
ptr = strsep(&tmp, ",");
|
||||
if (!tmp) {
|
||||
tmp = saved;
|
||||
ptr = strsep(&tmp, ":%");
|
||||
if (tmp && ++warn_once == 1)
|
||||
fprintf(stderr, "Warning: please use ',' separator token between ip,mac.\n"
|
||||
"Next release won't support old separator tokens.\n");
|
||||
}
|
||||
parse_ip(ptr, &mydata->ip);
|
||||
|
||||
if (tmp)
|
||||
parse_mac(tmp, mydata->ethernet);
|
||||
else
|
||||
memset(mydata->ethernet, 0, ETH_ALEN);
|
||||
|
||||
free(saved);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void
|
||||
initheader(struct set *set, const void *data)
|
||||
{
|
||||
const struct ip_set_req_macipmap_create *header = data;
|
||||
struct ip_set_macipmap *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_macipmap));
|
||||
map->first_ip = header->from;
|
||||
map->last_ip = header->to;
|
||||
map->flags = header->flags;
|
||||
}
|
||||
|
||||
static void
|
||||
printheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_macipmap *mysetdata = set->settype->header;
|
||||
|
||||
printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
|
||||
|
||||
if (mysetdata->flags & IPSET_MACIP_MATCHUNSET)
|
||||
printf(" matchunset");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
print_mac(unsigned char macaddress[ETH_ALEN])
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
printf("%02X", macaddress[0]);
|
||||
for (i = 1; i < ETH_ALEN; i++)
|
||||
printf(":%02X", macaddress[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
printips_sorted(struct set *set, void *data,
|
||||
size_t len UNUSED, unsigned options)
|
||||
{
|
||||
struct ip_set_macipmap *mysetdata = set->settype->header;
|
||||
struct ip_set_macip *table = data;
|
||||
u_int32_t addr = mysetdata->first_ip;
|
||||
|
||||
while (addr <= mysetdata->last_ip) {
|
||||
if (test_bit(IPSET_MACIP_ISSET,
|
||||
(void *)&table[addr - mysetdata->first_ip].flags)) {
|
||||
printf("%s,", ip_tostring(addr, options));
|
||||
print_mac(table[addr - mysetdata->first_ip].
|
||||
ethernet);
|
||||
printf("\n");
|
||||
}
|
||||
addr++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
saveheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_macipmap *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --from %s",
|
||||
set->name, set->settype->typename,
|
||||
ip_tostring(mysetdata->first_ip, options));
|
||||
printf(" --to %s", ip_tostring(mysetdata->last_ip, options));
|
||||
|
||||
if (mysetdata->flags & IPSET_MACIP_MATCHUNSET)
|
||||
printf(" --matchunset");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
saveips(struct set *set, void *data,
|
||||
size_t len UNUSED, unsigned options)
|
||||
{
|
||||
struct ip_set_macipmap *mysetdata = set->settype->header;
|
||||
struct ip_set_macip *table = data;
|
||||
u_int32_t addr = mysetdata->first_ip;
|
||||
|
||||
while (addr <= mysetdata->last_ip) {
|
||||
if (test_bit(IPSET_MACIP_ISSET,
|
||||
(void *)&table[addr - mysetdata->first_ip].flags)) {
|
||||
printf("-A %s %s,",
|
||||
set->name, ip_tostring(addr, options));
|
||||
print_mac(table[addr - mysetdata->first_ip].
|
||||
ethernet);
|
||||
printf("\n");
|
||||
}
|
||||
addr++;
|
||||
}
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf
|
||||
("-N set macipmap --from IP --to IP [--matchunset]\n"
|
||||
"-N set macipmap --network IP/mask [--matchunset]\n"
|
||||
"-A set IP[,MAC]\n"
|
||||
"-D set IP[,MAC]\n"
|
||||
"-T set IP[,MAC]\n");
|
||||
}
|
||||
|
||||
static struct settype settype_macipmap = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
|
||||
/* Create */
|
||||
.create_size = sizeof(struct ip_set_req_macipmap_create),
|
||||
.create_init = &create_init,
|
||||
.create_parse = &create_parse,
|
||||
.create_final = &create_final,
|
||||
.create_opts = create_opts,
|
||||
|
||||
/* Add/del/test */
|
||||
.adt_size = sizeof(struct ip_set_req_macipmap),
|
||||
.adt_parser = &adt_parser,
|
||||
|
||||
/* Printing */
|
||||
.header_size = sizeof(struct ip_set_macipmap),
|
||||
.initheader = &initheader,
|
||||
.printheader = &printheader,
|
||||
.printips = &printips_sorted, /* We only have sorted version */
|
||||
.printips_sorted = &printips_sorted,
|
||||
.saveheader = &saveheader,
|
||||
.saveips = &saveips,
|
||||
|
||||
/* Bindings */
|
||||
.bindip_tostring = &binding_ip_tostring,
|
||||
.bindip_parse = &parse_ip,
|
||||
|
||||
.usage = &usage,
|
||||
};
|
||||
|
||||
CONSTRUCTOR(macipmap)
|
||||
{
|
||||
settype_register(&settype_macipmap);
|
||||
|
||||
}
|
340
extensions/ipset/ipset_nethash.c
Normal file
340
extensions/ipset/ipset_nethash.c
Normal file
@@ -0,0 +1,340 @@
|
||||
/* Copyright 2004 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <limits.h> /* UINT_MAX */
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem*, str* */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_nethash.h"
|
||||
|
||||
#define BUFLEN 30;
|
||||
|
||||
#define OPT_CREATE_HASHSIZE 0x01U
|
||||
#define OPT_CREATE_PROBES 0x02U
|
||||
#define OPT_CREATE_RESIZE 0x04U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void
|
||||
create_init(void *data)
|
||||
{
|
||||
struct ip_set_req_nethash_create *mydata = data;
|
||||
|
||||
DP("create INIT");
|
||||
|
||||
/* Default create parameters */
|
||||
mydata->hashsize = 1024;
|
||||
mydata->probes = 4;
|
||||
mydata->resize = 50;
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int
|
||||
create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_nethash_create *mydata = data;
|
||||
ip_set_ip_t value;
|
||||
|
||||
DP("create_parse");
|
||||
|
||||
switch (c) {
|
||||
case '1':
|
||||
|
||||
if (string_to_number(optarg, 1, UINT_MAX - 1, &mydata->hashsize))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid hashsize `%s' specified", optarg);
|
||||
|
||||
*flags |= OPT_CREATE_HASHSIZE;
|
||||
|
||||
DP("--hashsize %u", mydata->hashsize);
|
||||
|
||||
break;
|
||||
|
||||
case '2':
|
||||
|
||||
if (string_to_number(optarg, 1, 65535, &value))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid probes `%s' specified", optarg);
|
||||
|
||||
mydata->probes = value;
|
||||
*flags |= OPT_CREATE_PROBES;
|
||||
|
||||
DP("--probes %u", mydata->probes);
|
||||
|
||||
break;
|
||||
|
||||
case '3':
|
||||
|
||||
if (string_to_number(optarg, 0, 65535, &value))
|
||||
exit_error(PARAMETER_PROBLEM, "Invalid resize `%s' specified", optarg);
|
||||
|
||||
mydata->resize = value;
|
||||
*flags |= OPT_CREATE_RESIZE;
|
||||
|
||||
DP("--resize %u", mydata->resize);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void
|
||||
create_final(void *data UNUSED, unsigned int flags UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{.name = "hashsize", .has_arg = required_argument, .val = '1'},
|
||||
{.name = "probes", .has_arg = required_argument, .val = '2'},
|
||||
{.name = "resize", .has_arg = required_argument, .val = '3'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t
|
||||
adt_parser(int cmd, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_nethash *mydata = data;
|
||||
char *saved = ipset_strdup(arg);
|
||||
char *ptr, *tmp = saved;
|
||||
ip_set_ip_t cidr;
|
||||
|
||||
ptr = strsep(&tmp, "/");
|
||||
|
||||
if (tmp == NULL) {
|
||||
if (cmd == CMD_TEST)
|
||||
cidr = 32;
|
||||
else
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Missing cidr from `%s'", arg);
|
||||
} else
|
||||
if (string_to_number(tmp, 1, 31, &cidr))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Out of range cidr `%s' specified", arg);
|
||||
|
||||
mydata->cidr = cidr;
|
||||
parse_ip(ptr, &mydata->ip);
|
||||
#if 0
|
||||
if (!mydata->ip)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Zero valued IP address `%s' specified", ptr);
|
||||
#endif
|
||||
ipset_free(saved);
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
||||
/*
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void
|
||||
initheader(struct set *set, const void *data)
|
||||
{
|
||||
const struct ip_set_req_nethash_create *header = data;
|
||||
struct ip_set_nethash *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_nethash));
|
||||
map->hashsize = header->hashsize;
|
||||
map->probes = header->probes;
|
||||
map->resize = header->resize;
|
||||
}
|
||||
|
||||
static void
|
||||
printheader(struct set *set, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_nethash *mysetdata = set->settype->header;
|
||||
|
||||
printf(" hashsize: %u", mysetdata->hashsize);
|
||||
printf(" probes: %u", mysetdata->probes);
|
||||
printf(" resize: %u\n", mysetdata->resize);
|
||||
}
|
||||
|
||||
static char buf[20];
|
||||
|
||||
static char *
|
||||
unpack_ip_tostring(ip_set_ip_t ip, unsigned options UNUSED)
|
||||
{
|
||||
int i, j = 3;
|
||||
unsigned char a, b;
|
||||
|
||||
ip = htonl(ip);
|
||||
for (i = 3; i >= 0; i--)
|
||||
if (((unsigned char *)&ip)[i] != 0) {
|
||||
j = i;
|
||||
break;
|
||||
}
|
||||
|
||||
a = ((unsigned char *)&ip)[j];
|
||||
if (a <= 128) {
|
||||
a = (a - 1) * 2;
|
||||
b = 7;
|
||||
} else if (a <= 192) {
|
||||
a = (a - 129) * 4;
|
||||
b = 6;
|
||||
} else if (a <= 224) {
|
||||
a = (a - 193) * 8;
|
||||
b = 5;
|
||||
} else if (a <= 240) {
|
||||
a = (a - 225) * 16;
|
||||
b = 4;
|
||||
} else if (a <= 248) {
|
||||
a = (a - 241) * 32;
|
||||
b = 3;
|
||||
} else if (a <= 252) {
|
||||
a = (a - 249) * 64;
|
||||
b = 2;
|
||||
} else if (a <= 254) {
|
||||
a = (a - 253) * 128;
|
||||
b = 1;
|
||||
} else {
|
||||
a = b = 0;
|
||||
}
|
||||
((unsigned char *)&ip)[j] = a;
|
||||
b += j * 8;
|
||||
|
||||
sprintf(buf, "%u.%u.%u.%u/%u",
|
||||
((unsigned char *)&ip)[0],
|
||||
((unsigned char *)&ip)[1],
|
||||
((unsigned char *)&ip)[2],
|
||||
((unsigned char *)&ip)[3],
|
||||
b);
|
||||
|
||||
DP("%s %s", ip_tostring(ntohl(ip), 0), buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void
|
||||
printips(struct set *set UNUSED, void *data, size_t len, unsigned options)
|
||||
{
|
||||
size_t offset = 0;
|
||||
ip_set_ip_t *ip;
|
||||
|
||||
while (offset < len) {
|
||||
ip = data + offset;
|
||||
if (*ip)
|
||||
printf("%s\n", unpack_ip_tostring(*ip, options));
|
||||
offset += sizeof(ip_set_ip_t);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
saveheader(struct set *set, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_nethash *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --hashsize %u --probes %u --resize %u\n",
|
||||
set->name, set->settype->typename,
|
||||
mysetdata->hashsize, mysetdata->probes, mysetdata->resize);
|
||||
}
|
||||
|
||||
/* Print save for an IP */
|
||||
static void
|
||||
saveips(struct set *set UNUSED, void *data, size_t len, unsigned options)
|
||||
{
|
||||
size_t offset = 0;
|
||||
ip_set_ip_t *ip;
|
||||
|
||||
while (offset < len) {
|
||||
ip = data + offset;
|
||||
if (*ip)
|
||||
printf("-A %s %s\n", set->name,
|
||||
unpack_ip_tostring(*ip, options));
|
||||
offset += sizeof(ip_set_ip_t);
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
net_tostring(struct set *set UNUSED, ip_set_ip_t ip, unsigned options)
|
||||
{
|
||||
return unpack_ip_tostring(ip, options);
|
||||
}
|
||||
|
||||
static void
|
||||
parse_net(const char *str, ip_set_ip_t *ip)
|
||||
{
|
||||
char *saved = ipset_strdup(str);
|
||||
char *ptr, *tmp = saved;
|
||||
ip_set_ip_t cidr;
|
||||
|
||||
ptr = strsep(&tmp, "/");
|
||||
|
||||
if (tmp == NULL)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Missing cidr from `%s'", str);
|
||||
|
||||
if (string_to_number(tmp, 1, 31, &cidr))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Out of range cidr `%s' specified", str);
|
||||
|
||||
parse_ip(ptr, ip);
|
||||
ipset_free(saved);
|
||||
|
||||
*ip = pack_ip_cidr(*ip, cidr);
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf
|
||||
("-N set nethash [--hashsize hashsize] [--probes probes ]\n"
|
||||
" [--resize resize]\n"
|
||||
"-A set IP/cidr\n"
|
||||
"-D set IP/cidr\n"
|
||||
"-T set IP/cidr\n");
|
||||
}
|
||||
|
||||
static struct settype settype_nethash = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
|
||||
/* Create */
|
||||
.create_size = sizeof(struct ip_set_req_nethash_create),
|
||||
.create_init = &create_init,
|
||||
.create_parse = &create_parse,
|
||||
.create_final = &create_final,
|
||||
.create_opts = create_opts,
|
||||
|
||||
/* Add/del/test */
|
||||
.adt_size = sizeof(struct ip_set_req_nethash),
|
||||
.adt_parser = &adt_parser,
|
||||
|
||||
/* Printing */
|
||||
.header_size = sizeof(struct ip_set_nethash),
|
||||
.initheader = &initheader,
|
||||
.printheader = &printheader,
|
||||
.printips = &printips, /* We only have the unsorted version */
|
||||
.printips_sorted = &printips,
|
||||
.saveheader = &saveheader,
|
||||
.saveips = &saveips,
|
||||
|
||||
/* Bindings */
|
||||
.bindip_tostring = &net_tostring,
|
||||
.bindip_parse = &parse_net,
|
||||
|
||||
.usage = &usage,
|
||||
};
|
||||
|
||||
CONSTRUCTOR(nethash)
|
||||
{
|
||||
settype_register(&settype_nethash);
|
||||
|
||||
}
|
245
extensions/ipset/ipset_portmap.c
Normal file
245
extensions/ipset/ipset_portmap.c
Normal file
@@ -0,0 +1,245 @@
|
||||
/* Copyright 2004 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h> /* *printf */
|
||||
#include <string.h> /* mem* */
|
||||
|
||||
#include "ipset.h"
|
||||
|
||||
#include "ip_set_portmap.h"
|
||||
|
||||
#define BUFLEN 30;
|
||||
|
||||
#define OPT_CREATE_FROM 0x01U
|
||||
#define OPT_CREATE_TO 0x02U
|
||||
|
||||
#define OPT_ADDDEL_PORT 0x01U
|
||||
|
||||
/* Initialize the create. */
|
||||
static void
|
||||
create_init(void *data UNUSED)
|
||||
{
|
||||
DP("create INIT");
|
||||
/* Nothing */
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int
|
||||
create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
|
||||
{
|
||||
struct ip_set_req_portmap_create *mydata = data;
|
||||
|
||||
DP("create_parse");
|
||||
|
||||
switch (c) {
|
||||
case '1':
|
||||
parse_port(optarg, &mydata->from);
|
||||
|
||||
*flags |= OPT_CREATE_FROM;
|
||||
|
||||
DP("--from %x (%s)", mydata->from,
|
||||
port_tostring(mydata->from, 0));
|
||||
|
||||
break;
|
||||
|
||||
case '2':
|
||||
parse_port(optarg, &mydata->to);
|
||||
|
||||
*flags |= OPT_CREATE_TO;
|
||||
|
||||
DP("--to %x (%s)", mydata->to,
|
||||
port_tostring(mydata->to, 0));
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void
|
||||
create_final(void *data, unsigned int flags)
|
||||
{
|
||||
struct ip_set_req_portmap_create *mydata = data;
|
||||
|
||||
if (flags == 0) {
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify --from and --to\n");
|
||||
} else {
|
||||
/* --from --to */
|
||||
if ((flags & OPT_CREATE_FROM) == 0
|
||||
|| (flags & OPT_CREATE_TO) == 0)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Need to specify both --from and --to\n");
|
||||
}
|
||||
|
||||
DP("from : %x to: %x diff: %d", mydata->from, mydata->to,
|
||||
mydata->to - mydata->from);
|
||||
|
||||
if (mydata->from > mydata->to)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"From can't be lower than to.\n");
|
||||
|
||||
if (mydata->to - mydata->from > MAX_RANGE)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Range too large. Max is %d ports in range\n",
|
||||
MAX_RANGE+1);
|
||||
}
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{.name = "from", .has_arg = required_argument, .val = '1'},
|
||||
{.name = "to", .has_arg = required_argument, .val = '2'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t
|
||||
adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_portmap *mydata = data;
|
||||
|
||||
parse_port(arg, &mydata->ip);
|
||||
DP("%s", port_tostring(mydata->ip, 0));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void
|
||||
initheader(struct set *set, const void *data)
|
||||
{
|
||||
const struct ip_set_req_portmap_create *header = data;
|
||||
struct ip_set_portmap *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_portmap));
|
||||
map->first_ip = header->from;
|
||||
map->last_ip = header->to;
|
||||
}
|
||||
|
||||
static void
|
||||
printheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_portmap *mysetdata = set->settype->header;
|
||||
|
||||
printf(" from: %s", port_tostring(mysetdata->first_ip, options));
|
||||
printf(" to: %s\n", port_tostring(mysetdata->last_ip, options));
|
||||
}
|
||||
|
||||
static void
|
||||
printports_sorted(struct set *set, void *data,
|
||||
size_t len UNUSED, unsigned options)
|
||||
{
|
||||
struct ip_set_portmap *mysetdata = set->settype->header;
|
||||
u_int32_t addr = mysetdata->first_ip;
|
||||
|
||||
DP("%u -- %u", mysetdata->first_ip, mysetdata->last_ip);
|
||||
while (addr <= mysetdata->last_ip) {
|
||||
if (test_bit(addr - mysetdata->first_ip, data))
|
||||
printf("%s\n", port_tostring(addr, options));
|
||||
addr++;
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
binding_port_tostring(struct set *set UNUSED,
|
||||
ip_set_ip_t ip, unsigned options)
|
||||
{
|
||||
return port_tostring(ip, options);
|
||||
}
|
||||
|
||||
static void
|
||||
saveheader(struct set *set, unsigned options)
|
||||
{
|
||||
struct ip_set_portmap *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --from %s",
|
||||
set->name,
|
||||
set->settype->typename,
|
||||
port_tostring(mysetdata->first_ip, options));
|
||||
printf(" --to %s\n",
|
||||
port_tostring(mysetdata->last_ip, options));
|
||||
}
|
||||
|
||||
static void
|
||||
saveports(struct set *set, void *data,
|
||||
size_t len UNUSED, unsigned options)
|
||||
{
|
||||
struct ip_set_portmap *mysetdata = set->settype->header;
|
||||
u_int32_t addr = mysetdata->first_ip;
|
||||
|
||||
while (addr <= mysetdata->last_ip) {
|
||||
if (test_bit(addr - mysetdata->first_ip, data))
|
||||
printf("-A %s %s\n",
|
||||
set->name,
|
||||
port_tostring(addr, options));
|
||||
addr++;
|
||||
}
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf
|
||||
("-N set portmap --from PORT --to PORT\n"
|
||||
"-A set PORT\n"
|
||||
"-D set PORT\n"
|
||||
"-T set PORT\n");
|
||||
}
|
||||
|
||||
static struct settype settype_portmap = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
|
||||
/* Create */
|
||||
.create_size = sizeof(struct ip_set_req_portmap_create),
|
||||
.create_init = &create_init,
|
||||
.create_parse = &create_parse,
|
||||
.create_final = &create_final,
|
||||
.create_opts = create_opts,
|
||||
|
||||
/* Add/del/test */
|
||||
.adt_size = sizeof(struct ip_set_req_portmap),
|
||||
.adt_parser = &adt_parser,
|
||||
|
||||
/* Printing */
|
||||
.header_size = sizeof(struct ip_set_portmap),
|
||||
.initheader = &initheader,
|
||||
.printheader = &printheader,
|
||||
.printips = &printports_sorted, /* We only have sorted version */
|
||||
.printips_sorted = &printports_sorted,
|
||||
.saveheader = &saveheader,
|
||||
.saveips = &saveports,
|
||||
|
||||
/* Bindings */
|
||||
.bindip_tostring = &binding_port_tostring,
|
||||
.bindip_parse = &parse_port,
|
||||
|
||||
.usage = &usage,
|
||||
};
|
||||
|
||||
CONSTRUCTOR(portmap)
|
||||
{
|
||||
settype_register(&settype_portmap);
|
||||
|
||||
}
|
221
extensions/ipset/ipset_setlist.c
Normal file
221
extensions/ipset/ipset_setlist.c
Normal file
@@ -0,0 +1,221 @@
|
||||
/* Copyright 2008 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "ip_set_setlist.h"
|
||||
#include "ipset.h"
|
||||
|
||||
/* Initialize the create. */
|
||||
static void
|
||||
create_init(void *data)
|
||||
{
|
||||
struct ip_set_req_setlist_create *mydata = data;
|
||||
|
||||
mydata->size = 8;
|
||||
}
|
||||
|
||||
/* Function which parses command options; returns true if it ate an option */
|
||||
static int
|
||||
create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags UNUSED)
|
||||
{
|
||||
struct ip_set_req_setlist_create *mydata = data;
|
||||
unsigned int size;
|
||||
|
||||
switch (c) {
|
||||
case '1':
|
||||
if (string_to_number(optarg, 1, 255, &size))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Invalid size '%s specified: must be "
|
||||
"between 1-255", optarg);
|
||||
mydata->size = size;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Final check; exit if not ok. */
|
||||
static void
|
||||
create_final(void *data UNUSED, unsigned int flags UNUSED)
|
||||
{
|
||||
}
|
||||
|
||||
/* Create commandline options */
|
||||
static const struct option create_opts[] = {
|
||||
{.name = "size", .has_arg = required_argument, .val = '1'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static void check_setname(const char *name)
|
||||
{
|
||||
if (strlen(name) > IP_SET_MAXNAMELEN - 1)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Setname %s is longer than %d characters.",
|
||||
name, IP_SET_MAXNAMELEN - 1);
|
||||
}
|
||||
|
||||
/* Add, del, test parser */
|
||||
static ip_set_ip_t
|
||||
adt_parser(int cmd UNUSED, const char *arg, void *data)
|
||||
{
|
||||
struct ip_set_req_setlist *mydata = data;
|
||||
char *saved = ipset_strdup(arg);
|
||||
char *ptr, *tmp = saved;
|
||||
|
||||
DP("setlist: %p %p", arg, data);
|
||||
|
||||
ptr = strsep(&tmp, ",");
|
||||
check_setname(ptr);
|
||||
strcpy(mydata->name, ptr);
|
||||
|
||||
if (!tmp) {
|
||||
mydata->before = 0;
|
||||
mydata->ref[0] = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
ptr = strsep(&tmp, ",");
|
||||
|
||||
if (tmp == NULL || !(strcmp(ptr, "before") == 0 || strcmp(ptr, "after") == 0))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Syntax error, you must specify elements as setname,[before|after],setname");
|
||||
|
||||
check_setname(tmp);
|
||||
strcpy(mydata->ref, tmp);
|
||||
mydata->before = !strcmp(ptr, "before");
|
||||
|
||||
free(saved);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print and save
|
||||
*/
|
||||
|
||||
static void
|
||||
initheader(struct set *set, const void *data)
|
||||
{
|
||||
const struct ip_set_req_setlist_create *header = data;
|
||||
struct ip_set_setlist *map = set->settype->header;
|
||||
|
||||
memset(map, 0, sizeof(struct ip_set_setlist));
|
||||
map->size = header->size;
|
||||
}
|
||||
|
||||
static void
|
||||
printheader(struct set *set, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_setlist *mysetdata = set->settype->header;
|
||||
|
||||
printf(" size: %u\n", mysetdata->size);
|
||||
}
|
||||
|
||||
static void
|
||||
printips_sorted(struct set *set, void *data,
|
||||
size_t len UNUSED, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_setlist *mysetdata = set->settype->header;
|
||||
int i;
|
||||
ip_set_id_t id;
|
||||
struct set *elem;
|
||||
|
||||
for (i = 0; i < mysetdata->size; i++ ) {
|
||||
id = *((ip_set_id_t *)data + i);
|
||||
if (id == IP_SET_INVALID_ID)
|
||||
return;
|
||||
elem = set_find_byid(id);
|
||||
printf("%s\n", elem->name);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
saveheader(struct set *set, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_setlist *mysetdata = set->settype->header;
|
||||
|
||||
printf("-N %s %s --size %u\n",
|
||||
set->name, set->settype->typename,
|
||||
mysetdata->size);
|
||||
}
|
||||
|
||||
static void
|
||||
saveips(struct set *set, void *data,
|
||||
size_t len UNUSED, unsigned options UNUSED)
|
||||
{
|
||||
struct ip_set_setlist *mysetdata = set->settype->header;
|
||||
int i;
|
||||
ip_set_id_t id;
|
||||
struct set *elem;
|
||||
|
||||
for (i = 0; i < mysetdata->size; i++ ) {
|
||||
id = *((ip_set_id_t *)data + i);
|
||||
if (id == IP_SET_INVALID_ID)
|
||||
return;
|
||||
elem = set_find_byid(id);
|
||||
printf("-A %s %s\n", set->name, elem->name);
|
||||
}
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf
|
||||
("-N set setlist --size size\n"
|
||||
"-A set setname[,before|after,setname]\n"
|
||||
"-D set setname\n"
|
||||
"-T set setname\n");
|
||||
}
|
||||
|
||||
static struct settype settype_setlist = {
|
||||
.typename = SETTYPE_NAME,
|
||||
.protocol_version = IP_SET_PROTOCOL_VERSION,
|
||||
|
||||
/* Create */
|
||||
.create_size = sizeof(struct ip_set_req_setlist_create),
|
||||
.create_init = &create_init,
|
||||
.create_parse = &create_parse,
|
||||
.create_final = &create_final,
|
||||
.create_opts = create_opts,
|
||||
|
||||
/* Add/del/test */
|
||||
.adt_size = sizeof(struct ip_set_req_setlist),
|
||||
.adt_parser = &adt_parser,
|
||||
|
||||
/* Printing */
|
||||
.header_size = sizeof(struct ip_set_setlist),
|
||||
.initheader = &initheader,
|
||||
.printheader = &printheader,
|
||||
.printips = &printips_sorted, /* We only have sorted version */
|
||||
.printips_sorted = &printips_sorted,
|
||||
.saveheader = &saveheader,
|
||||
.saveips = &saveips,
|
||||
|
||||
.usage = &usage,
|
||||
};
|
||||
|
||||
CONSTRUCTOR(setlist)
|
||||
{
|
||||
settype_register(&settype_setlist);
|
||||
|
||||
}
|
138
extensions/ipset/ipt_SET.c
Normal file
138
extensions/ipset/ipt_SET.c
Normal file
@@ -0,0 +1,138 @@
|
||||
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
|
||||
* Patrick Schaaf <bof@bof.de>
|
||||
* Martin Josefsson <gandalf@wlug.westbo.se>
|
||||
* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* ipt_SET.c - netfilter target to manipulate IP sets */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include <linux/netfilter_ipv4.h>
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#define xt_register_target ipt_register_target
|
||||
#define xt_unregister_target ipt_unregister_target
|
||||
#define xt_target ipt_target
|
||||
#define XT_CONTINUE IPT_CONTINUE
|
||||
#else
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#endif
|
||||
#include "ipt_set.h"
|
||||
#include "../compat_xtables.h"
|
||||
|
||||
static unsigned int
|
||||
target(struct sk_buff **pskb, const struct xt_target_param *par)
|
||||
{
|
||||
const struct ipt_set_info_target *info = par->targinfo;
|
||||
|
||||
if (info->add_set.index != IP_SET_INVALID_ID)
|
||||
ip_set_addip_kernel(info->add_set.index,
|
||||
*pskb,
|
||||
info->add_set.flags);
|
||||
if (info->del_set.index != IP_SET_INVALID_ID)
|
||||
ip_set_delip_kernel(info->del_set.index,
|
||||
*pskb,
|
||||
info->del_set.flags);
|
||||
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
|
||||
static bool
|
||||
checkentry(const struct xt_tgchk_param *par)
|
||||
{
|
||||
struct ipt_set_info_target *info = par->targinfo;
|
||||
ip_set_id_t index;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
|
||||
if (targinfosize != IPT_ALIGN(sizeof(*info))) {
|
||||
DP("bad target info size %u", targinfosize);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (info->add_set.index != IP_SET_INVALID_ID) {
|
||||
index = ip_set_get_byindex(info->add_set.index);
|
||||
if (index == IP_SET_INVALID_ID) {
|
||||
ip_set_printk("cannot find add_set index %u as target",
|
||||
info->add_set.index);
|
||||
return 0; /* error */
|
||||
}
|
||||
}
|
||||
|
||||
if (info->del_set.index != IP_SET_INVALID_ID) {
|
||||
index = ip_set_get_byindex(info->del_set.index);
|
||||
if (index == IP_SET_INVALID_ID) {
|
||||
ip_set_printk("cannot find del_set index %u as target",
|
||||
info->del_set.index);
|
||||
return 0; /* error */
|
||||
}
|
||||
}
|
||||
if (info->add_set.flags[IP_SET_MAX_BINDINGS] != 0
|
||||
|| info->del_set.flags[IP_SET_MAX_BINDINGS] != 0) {
|
||||
ip_set_printk("That's nasty!");
|
||||
return 0; /* error */
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void destroy(const struct xt_tgdtor_param *par)
|
||||
{
|
||||
struct ipt_set_info_target *info = par->targinfo;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
|
||||
if (targetsize != IPT_ALIGN(sizeof(struct ipt_set_info_target))) {
|
||||
ip_set_printk("invalid targetsize %d", targetsize);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (info->add_set.index != IP_SET_INVALID_ID)
|
||||
ip_set_put_byindex(info->add_set.index);
|
||||
if (info->del_set.index != IP_SET_INVALID_ID)
|
||||
ip_set_put_byindex(info->del_set.index);
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
|
||||
static struct xt_target SET_target = {
|
||||
.name = "SET",
|
||||
.target = target,
|
||||
.checkentry = checkentry,
|
||||
.destroy = destroy,
|
||||
.me = THIS_MODULE
|
||||
};
|
||||
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) */
|
||||
static struct xt_target SET_target = {
|
||||
.name = "SET",
|
||||
.family = AF_INET,
|
||||
.target = target,
|
||||
.targetsize = sizeof(struct ipt_set_info_target),
|
||||
.checkentry = checkentry,
|
||||
.destroy = destroy,
|
||||
.me = THIS_MODULE
|
||||
};
|
||||
#endif
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("iptables IP set target module");
|
||||
|
||||
static int __init ipt_SET_init(void)
|
||||
{
|
||||
return xt_register_target(&SET_target);
|
||||
}
|
||||
|
||||
static void __exit ipt_SET_fini(void)
|
||||
{
|
||||
xt_unregister_target(&SET_target);
|
||||
}
|
||||
|
||||
module_init(ipt_SET_init);
|
||||
module_exit(ipt_SET_fini);
|
126
extensions/ipset/ipt_set.c
Normal file
126
extensions/ipset/ipt_set.c
Normal file
@@ -0,0 +1,126 @@
|
||||
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
|
||||
* Patrick Schaaf <bof@bof.de>
|
||||
* Martin Josefsson <gandalf@wlug.westbo.se>
|
||||
* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Kernel module to match an IP set. */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#define xt_register_match ipt_register_match
|
||||
#define xt_unregister_match ipt_unregister_match
|
||||
#define xt_match ipt_match
|
||||
#else
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#endif
|
||||
#include "ip_set.h"
|
||||
#include "ipt_set.h"
|
||||
#include "../compat_xtables.h"
|
||||
|
||||
static inline int
|
||||
match_set(const struct ipt_set_info *info,
|
||||
const struct sk_buff *skb,
|
||||
int inv)
|
||||
{
|
||||
if (ip_set_testip_kernel(info->index, skb, info->flags))
|
||||
inv = !inv;
|
||||
return inv;
|
||||
}
|
||||
|
||||
static bool
|
||||
match(const struct sk_buff *skb, const struct xt_match_param *par)
|
||||
{
|
||||
const struct ipt_set_info_match *info = par->matchinfo;
|
||||
|
||||
return match_set(&info->match_set,
|
||||
skb,
|
||||
info->match_set.flags[0] & IPSET_MATCH_INV);
|
||||
}
|
||||
|
||||
static bool
|
||||
checkentry(const struct xt_mtchk_param *par)
|
||||
{
|
||||
struct ipt_set_info_match *info = par->matchinfo;
|
||||
ip_set_id_t index;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
|
||||
if (matchsize != IPT_ALIGN(sizeof(struct ipt_set_info_match))) {
|
||||
ip_set_printk("invalid matchsize %d", matchsize);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
index = ip_set_get_byindex(info->match_set.index);
|
||||
|
||||
if (index == IP_SET_INVALID_ID) {
|
||||
ip_set_printk("Cannot find set indentified by id %u to match",
|
||||
info->match_set.index);
|
||||
return 0; /* error */
|
||||
}
|
||||
if (info->match_set.flags[IP_SET_MAX_BINDINGS] != 0) {
|
||||
ip_set_printk("That's nasty!");
|
||||
return 0; /* error */
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void destroy(const struct xt_mtdtor_param *par)
|
||||
{
|
||||
struct ipt_set_info_match *info = par->matchinfo;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
|
||||
if (matchsize != IPT_ALIGN(sizeof(struct ipt_set_info_match))) {
|
||||
ip_set_printk("invalid matchsize %d", matchsize);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
ip_set_put_byindex(info->match_set.index);
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
|
||||
static struct xt_match set_match = {
|
||||
.name = "set",
|
||||
.match = &match,
|
||||
.checkentry = &checkentry,
|
||||
.destroy = &destroy,
|
||||
.me = THIS_MODULE
|
||||
};
|
||||
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) */
|
||||
static struct xt_match set_match = {
|
||||
.name = "set",
|
||||
.family = AF_INET,
|
||||
.match = &match,
|
||||
.matchsize = sizeof(struct ipt_set_info_match),
|
||||
.checkentry = &checkentry,
|
||||
.destroy = &destroy,
|
||||
.me = THIS_MODULE
|
||||
};
|
||||
#endif
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("iptables IP set match module");
|
||||
|
||||
static int __init ipt_ipset_init(void)
|
||||
{
|
||||
return xt_register_match(&set_match);
|
||||
}
|
||||
|
||||
static void __exit ipt_ipset_fini(void)
|
||||
{
|
||||
xt_unregister_match(&set_match);
|
||||
}
|
||||
|
||||
module_init(ipt_ipset_init);
|
||||
module_exit(ipt_ipset_fini);
|
21
extensions/ipset/ipt_set.h
Normal file
21
extensions/ipset/ipt_set.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef _IPT_SET_H
|
||||
#define _IPT_SET_H
|
||||
|
||||
#include "ip_set.h"
|
||||
|
||||
struct ipt_set_info {
|
||||
ip_set_id_t index;
|
||||
u_int32_t flags[IP_SET_MAX_BINDINGS + 1];
|
||||
};
|
||||
|
||||
/* match info */
|
||||
struct ipt_set_info_match {
|
||||
struct ipt_set_info match_set;
|
||||
};
|
||||
|
||||
struct ipt_set_info_target {
|
||||
struct ipt_set_info add_set;
|
||||
struct ipt_set_info del_set;
|
||||
};
|
||||
|
||||
#endif /*_IPT_SET_H*/
|
@@ -1,13 +1,15 @@
|
||||
/*
|
||||
* CHAOS target for Xtables
|
||||
* Copyright © CC Computer Consultants GmbH, 2006 - 2008
|
||||
* "CHAOS" target extension for iptables
|
||||
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2006 - 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License; either version
|
||||
* 2 or 3 as published by the Free Software Foundation.
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
* version 2 of the License, or any later version, as published by the
|
||||
* Free Software Foundation.
|
||||
*/
|
||||
#include <getopt.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -23,7 +25,7 @@ enum {
|
||||
static const struct option chaos_tg_opts[] = {
|
||||
{.name = "delude", .has_arg = false, .val = 'd'},
|
||||
{.name = "tarpit", .has_arg = false, .val = 't'},
|
||||
{},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static void chaos_tg_help(void)
|
||||
@@ -74,7 +76,6 @@ static void chaos_tg_print(const void *ip,
|
||||
printf("TARPIT ");
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void chaos_tg_save(const void *ip, const struct xt_entry_target *target)
|
||||
@@ -89,7 +90,6 @@ static void chaos_tg_save(const void *ip, const struct xt_entry_target *target)
|
||||
printf("--tarpit ");
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static struct xtables_target chaos_tg_reg = {
|
||||
@@ -106,8 +106,7 @@ static struct xtables_target chaos_tg_reg = {
|
||||
.extra_opts = chaos_tg_opts,
|
||||
};
|
||||
|
||||
void _init(void);
|
||||
void _init(void)
|
||||
static __attribute__((constructor)) void chaos_tg_ldr(void)
|
||||
{
|
||||
xtables_register_target(&chaos_tg_reg);
|
||||
}
|
||||
|
@@ -16,3 +16,6 @@ connections than they can.
|
||||
.PP
|
||||
The randomness factor of not replying vs. replying can be set during load-time
|
||||
of the xt_CHAOS module or during runtime in /sys/modules/xt_CHAOS/parameters.
|
||||
.PP
|
||||
See http://jengelh.medozas.de/projects/chaostables/ for more information
|
||||
about CHAOS, DELUDE and portscan.
|
||||
|
@@ -1,10 +1,11 @@
|
||||
/*
|
||||
* DELUDE target for Xtables
|
||||
* Copyright © CC Computer Consultants GmbH, 2006 - 2008
|
||||
* "DELUDE" target extension for iptables
|
||||
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2006 - 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License; either version
|
||||
* 2 or 3 as published by the Free Software Foundation.
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
* version 2 of the License, or any later version, as published by the
|
||||
* Free Software Foundation.
|
||||
*/
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
@@ -40,8 +41,7 @@ static struct xtables_target delude_tg_reg = {
|
||||
.final_check = delude_tg_check,
|
||||
};
|
||||
|
||||
void _init(void);
|
||||
void _init(void)
|
||||
static __attribute__((constructor)) void delude_tg_ldr(void)
|
||||
{
|
||||
xtables_register_target(&delude_tg_reg);
|
||||
}
|
||||
|
101
extensions/libxt_DHCPADDR.c
Normal file
101
extensions/libxt_DHCPADDR.c
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* "DHCPADDR" target extension for iptables
|
||||
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
* version 2 of the License, or any later version, as published by the
|
||||
* Free Software Foundation.
|
||||
*/
|
||||
#include <getopt.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <netinet/ether.h>
|
||||
#include <xtables.h>
|
||||
#include "xt_DHCPADDR.h"
|
||||
#include "mac.c"
|
||||
|
||||
enum {
|
||||
F_MAC = 1 << 0,
|
||||
};
|
||||
|
||||
static const struct option dhcpaddr_tg_opts[] = {
|
||||
{.name = "set-mac", .has_arg = true, .val = 'M'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static void dhcpaddr_tg_help(void)
|
||||
{
|
||||
printf(
|
||||
"DHCPADDDR target options:\n"
|
||||
" --set-mac lladdr[/mask] Set MAC address in DHCP Client Host field\n"
|
||||
);
|
||||
}
|
||||
|
||||
static int dhcpaddr_tg_parse(int c, char **argv, int invert,
|
||||
unsigned int *flags, const void *entry, struct xt_entry_target **target)
|
||||
{
|
||||
struct dhcpaddr_info *info = (void *)(*target)->data;
|
||||
|
||||
switch (c) {
|
||||
case 'M':
|
||||
param_act(P_ONLY_ONCE, "DHCPADDR", "--set-mac", *flags & F_MAC);
|
||||
param_act(P_NO_INVERT, "DHCPADDR", "--set-mac", invert);
|
||||
if (!mac_parse(optarg, info->addr, &info->mask))
|
||||
param_act(P_BAD_VALUE, "DHCPADDR", "--set-mac", optarg);
|
||||
*flags |= F_MAC;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void dhcpaddr_tg_check(unsigned int flags)
|
||||
{
|
||||
if (flags == 0)
|
||||
exit_error(PARAMETER_PROBLEM, "DHCPADDR target: "
|
||||
"--set-mac parameter required");
|
||||
}
|
||||
|
||||
static void dhcpaddr_tg_print(const void *ip,
|
||||
const struct xt_entry_target *target, int numeric)
|
||||
{
|
||||
const struct dhcpaddr_info *info = (void *)target->data;
|
||||
|
||||
printf("DHCPADDR %s" DH_MAC_FMT "/%u ",
|
||||
info->invert ? "!" : "", DH_MAC_HEX(info->addr), info->mask);
|
||||
}
|
||||
|
||||
static void dhcpaddr_tg_save(const void *ip,
|
||||
const struct xt_entry_target *target)
|
||||
{
|
||||
const struct dhcpaddr_info *info = (const void *)target->data;
|
||||
|
||||
if (info->invert)
|
||||
printf("! ");
|
||||
printf("--set-mac " DH_MAC_FMT "/%u ",
|
||||
DH_MAC_HEX(info->addr), info->mask);
|
||||
}
|
||||
|
||||
static struct xtables_target dhcpaddr_tg_reg = {
|
||||
.version = XTABLES_VERSION,
|
||||
.name = "DHCPADDR",
|
||||
.revision = 0,
|
||||
.family = PF_INET,
|
||||
.size = XT_ALIGN(sizeof(struct dhcpaddr_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct dhcpaddr_info)),
|
||||
.help = dhcpaddr_tg_help,
|
||||
.parse = dhcpaddr_tg_parse,
|
||||
.final_check = dhcpaddr_tg_check,
|
||||
.print = dhcpaddr_tg_print,
|
||||
.save = dhcpaddr_tg_save,
|
||||
.extra_opts = dhcpaddr_tg_opts,
|
||||
};
|
||||
|
||||
static __attribute__((constructor)) void dhcpaddr_tg_ldr(void)
|
||||
{
|
||||
xtables_register_target(&dhcpaddr_tg_reg);
|
||||
}
|
25
extensions/libxt_DHCPADDR.man
Normal file
25
extensions/libxt_DHCPADDR.man
Normal file
@@ -0,0 +1,25 @@
|
||||
In conjunction with ebtables, DHCPADDR can be used to completely change all MAC
|
||||
addresses from and to a VMware-based virtual machine. This is needed because
|
||||
VMware does not allow to set a non-VMware MAC address before an operating
|
||||
system is booted (and the MAC be changed with `ip link set eth0 address
|
||||
aa:bb..`).
|
||||
.TP
|
||||
\fB--set-mac\fP \fIaa:bb:cc:dd:ee:ff\fP[\fB/\fP\fImask\fP]
|
||||
Replace the client host MAC address field in the DHCP message with the given
|
||||
MAC address. This option is mandatory. The \fImask\fP parameter specifies the
|
||||
prefix length of bits to change.
|
||||
.PP
|
||||
EXAMPLE, replacing all addresses from one of VMware's assigned vendor IDs
|
||||
(00:50:56) addresses with something else:
|
||||
.PP
|
||||
iptables -t mangle -A FORWARD -p udp --dport 67 -m physdev --physdev-in vmnet1
|
||||
-m dhcpaddr --mac 00:50:56:00:00:00/24 -j DHCPADDR --set-mac
|
||||
ab:cd:ef:00:00:00/24
|
||||
.PP
|
||||
iptables -t mangle -A FORWARD -p udp --dport 68 -m physdev --physdev-out vmnet1
|
||||
-m dhcpaddr --mac ab:cd:ef:00:00:00/24 -j DHCPADDR --set-mac
|
||||
00:50:56:00:00:00/24
|
||||
.PP
|
||||
(This assumes there is a bridge interface that has vmnet1 as a port. You will
|
||||
also need to add appropriate ebtables rules to change the MAC address of the
|
||||
Ethernet headers.)
|
@@ -1,3 +1,12 @@
|
||||
/*
|
||||
* "ECHO" target extension for iptables
|
||||
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
* version 2 of the License, or any later version, as published by the
|
||||
* Free Software Foundation.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <getopt.h>
|
||||
#include <xtables.h>
|
||||
@@ -28,7 +37,7 @@ static struct xtables_target echo_tg_reg = {
|
||||
.final_check = echo_tg_check,
|
||||
};
|
||||
|
||||
static void _init(void)
|
||||
static __attribute__((constructor)) void echo_tg_ldr(void)
|
||||
{
|
||||
xtables_register_target(&echo_tg_reg);
|
||||
}
|
||||
|
4
extensions/libxt_ECHO.man
Normal file
4
extensions/libxt_ECHO.man
Normal file
@@ -0,0 +1,4 @@
|
||||
The \fBECHO\fP target will send back all packets it received. It serves as an
|
||||
examples for an Xtables target.
|
||||
.PP
|
||||
ECHO takes no options.
|
@@ -1,9 +1,12 @@
|
||||
/* Shared library add-on to iptables to add IPMARK target support.
|
||||
* (C) 2003 by Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>
|
||||
/*
|
||||
* "IPMARK" target extension for iptables
|
||||
* Copyright © Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>, 2003
|
||||
* Jan Engelhardt <jengelh [at] medozas de>, 2008
|
||||
*
|
||||
* based on original MARK target
|
||||
*
|
||||
* This program is distributed under the terms of GNU GPL
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
* version 2 of the License, or any later version, as published by the
|
||||
* Free Software Foundation.
|
||||
*/
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
@@ -65,7 +68,7 @@ static int ipmark_tg_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
exit_error(PARAMETER_PROBLEM, "Bad addr value `%s' - should be `src' or `dst'", optarg);
|
||||
*flags |= FL_ADDR_USED;
|
||||
return true;
|
||||
|
||||
|
||||
case '2':
|
||||
param_act(P_ONLY_ONCE, "IPMARK", "and-mask", *flags & FL_AND_MASK_USED);
|
||||
param_act(P_NO_INVERT, "IPMARK", "and-mask", invert);
|
||||
@@ -172,7 +175,7 @@ static struct xtables_target ipmark_tg6_reg = {
|
||||
.extra_opts = ipmark_tg_opts,
|
||||
};
|
||||
|
||||
static void _init(void)
|
||||
static __attribute__((constructor)) void ipmark_tg_ldr(void)
|
||||
{
|
||||
xtables_register_target(&ipmark_tg4_reg);
|
||||
xtables_register_target(&ipmark_tg6_reg);
|
||||
|
@@ -7,31 +7,31 @@ This target is to be used inside the \fBmangle\fP table.
|
||||
\fB--addr\fP {\fBsrc\fP|\fBdst\fP}
|
||||
Select source or destination IP address as a basis for the mark.
|
||||
.TP
|
||||
.BI "--and-mask " "mask"
|
||||
Perform bitwise `and' on the IP address and this mask.
|
||||
\fB--and-mask\fP \fImask\fP
|
||||
Perform bitwise AND on the IP address and this bitmask.
|
||||
.TP
|
||||
.BI "--or-mask " "mask"
|
||||
Perform bitwise `or' on the IP address and this mask.
|
||||
\fB--or-mask\fP \fImask\fP
|
||||
Perform bitwise OR on the IP address and this bitmask.
|
||||
.TP
|
||||
\fB--shift\fP \fIvalue\fP
|
||||
Shift addresses to the right by the given number of bits before taking it
|
||||
as a mark. (This is done before ANDing or ORing it.) This option is needed
|
||||
to select part of an IPv6 address, because marks are only 32 bits in size.
|
||||
.P
|
||||
.PP
|
||||
The order of IP address bytes is reversed to meet "human order of bytes":
|
||||
192.168.0.1 is 0xc0a80001. At first the `and' operation is performed, then
|
||||
`or'.
|
||||
|
||||
192.168.0.1 is 0xc0a80001. At first the "AND" operation is performed, then
|
||||
"OR".
|
||||
.PP
|
||||
Examples:
|
||||
|
||||
.PP
|
||||
We create a queue for each user, the queue number is adequate
|
||||
to the IP address of the user, e.g.: all packets going to/from 192.168.5.2
|
||||
are directed to 1:0502 queue, 192.168.5.12 -> 1:050c etc.
|
||||
|
||||
.PP
|
||||
We have one classifier rule:
|
||||
.IP
|
||||
tc filter add dev eth3 parent 1:0 protocol ip fw
|
||||
.P
|
||||
.PP
|
||||
Earlier we had many rules just like below:
|
||||
.IP
|
||||
iptables -t mangle -A POSTROUTING -o eth3 -d 192.168.5.2 -j MARK
|
||||
@@ -39,12 +39,12 @@ iptables -t mangle -A POSTROUTING -o eth3 -d 192.168.5.2 -j MARK
|
||||
.IP
|
||||
iptables -t mangle -A POSTROUTING -o eth3 -d 192.168.5.3 -j MARK
|
||||
--set-mark 0x10503
|
||||
.P
|
||||
.PP
|
||||
Using IPMARK target we can replace all the mangle/mark rules with only one:
|
||||
.IP
|
||||
iptables -t mangle -A POSTROUTING -o eth3 -j IPMARK --addr=dst
|
||||
--and-mask=0xffff --or-mask=0x10000
|
||||
.P
|
||||
iptables -t mangle -A POSTROUTING -o eth3 -j IPMARK --addr dst
|
||||
--and-mask 0xffff --or-mask 0x10000
|
||||
.PP
|
||||
On the routers with hundreds of users there should be significant load
|
||||
decrease (e.g. twice).
|
||||
.PP
|
||||
|
@@ -1,3 +1,12 @@
|
||||
/*
|
||||
* "LOGMARK" target extension for iptables
|
||||
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
* version 2 of the License, or any later version, as published by the
|
||||
* Free Software Foundation.
|
||||
*/
|
||||
#include <getopt.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
@@ -13,7 +22,7 @@ enum {
|
||||
static const struct option logmark_tg_opts[] = {
|
||||
{.name = "log-level", .has_arg = true, .val = 'l'},
|
||||
{.name = "log-prefix", .has_arg = true, .val = 'p'},
|
||||
{},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static void logmark_tg_help(void)
|
||||
@@ -102,8 +111,7 @@ static struct xtables_target logmark_tg_reg = {
|
||||
.extra_opts = logmark_tg_opts,
|
||||
};
|
||||
|
||||
void _init(void);
|
||||
void _init(void)
|
||||
static __attribute__((constructor)) void logmark_tg_ldr(void)
|
||||
{
|
||||
xtables_register_target(&logmark_tg_reg);
|
||||
}
|
||||
|
50
extensions/libxt_SYSRQ.c
Normal file
50
extensions/libxt_SYSRQ.c
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* "SYSRQ" target extension to iptables
|
||||
* this file is in the Public Domain
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <getopt.h>
|
||||
#include <xtables.h>
|
||||
|
||||
static void sysrq_tg_help(void)
|
||||
{
|
||||
printf("SYSRQ takes no options\n\n");
|
||||
}
|
||||
|
||||
static int sysrq_tg_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_target **target)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sysrq_tg_check(unsigned int flags)
|
||||
{
|
||||
}
|
||||
|
||||
static struct xtables_target sysrq_tg4_reg = {
|
||||
.version = XTABLES_VERSION,
|
||||
.name = "SYSRQ",
|
||||
.family = PF_INET,
|
||||
.size = XT_ALIGN(0),
|
||||
.userspacesize = XT_ALIGN(0),
|
||||
.help = sysrq_tg_help,
|
||||
.parse = sysrq_tg_parse,
|
||||
.final_check = sysrq_tg_check,
|
||||
};
|
||||
|
||||
static struct xtables_target sysrq_tg6_reg = {
|
||||
.version = XTABLES_VERSION,
|
||||
.name = "SYSRQ",
|
||||
.family = PF_INET6,
|
||||
.size = XT_ALIGN(0),
|
||||
.userspacesize = XT_ALIGN(0),
|
||||
.help = sysrq_tg_help,
|
||||
.parse = sysrq_tg_parse,
|
||||
.final_check = sysrq_tg_check,
|
||||
};
|
||||
|
||||
static __attribute__((constructor)) void sysrq_tg_ldr(void)
|
||||
{
|
||||
xtables_register_target(&sysrq_tg4_reg);
|
||||
xtables_register_target(&sysrq_tg6_reg);
|
||||
}
|
80
extensions/libxt_SYSRQ.man
Normal file
80
extensions/libxt_SYSRQ.man
Normal file
@@ -0,0 +1,80 @@
|
||||
The SYSRQ target allows to remotely trigger sysrq on the local machine over the
|
||||
network. This can be useful when vital parts of the machine hang, for example
|
||||
an oops in a filesystem causing locks to be not released and processes to get
|
||||
stuck as a result - if still possible, use /proc/sysrq-trigger. Even when
|
||||
processes are stuck, interrupts are likely to be still processed, and as such,
|
||||
sysrq can be triggered through incoming network packets.
|
||||
.PP
|
||||
The xt_SYSRQ implementation uses a salted hash and a sequence number to prevent
|
||||
network sniffers from either guessing the password or replaying earlier
|
||||
requests. The initial sequence number comes from the time of day so you will
|
||||
have a small window of vulnerability should time go backwards at a reboot.
|
||||
However, the file /sys/module/xt_SYSREQ/seqno can be used to both query and
|
||||
update the current sequence number. Also, you should limit as to who can issue
|
||||
commands using \fB-s\fP and/or \fB-m mac\fP, and also that the destination is
|
||||
correct using \fB-d\fP (to protect against potential broadcast packets), noting
|
||||
that it is still short of MAC/IP spoofing:
|
||||
.IP
|
||||
-A INPUT -s 10.10.25.1 -m mac --mac-source aa:bb:cc:dd:ee:ff -d 10.10.25.7
|
||||
-p udp --dport 9 -j SYSRQ
|
||||
.IP
|
||||
(with IPsec) -A INPUT -s 10.10.25.1 -d 10.10.25.7 -m policy --dir in --pol
|
||||
ipsec --proto esp --tunnel-src 10.10.25.1 --tunnel-dst 10.10.25.7
|
||||
-p udp --dport 9 -j SYSRQ
|
||||
.PP
|
||||
You should also limit the rate at which connections can be received to limit
|
||||
the CPU time taken by illegal requests, for example:
|
||||
.IP
|
||||
-A INPUT 0s 10.10.25.1 -m mac --mac-source aa:bb:cc:dd:ee:ff -d 10.10.25.7
|
||||
-p udp --dport 9 -m limit --limit 5/minute -j SYSRQ
|
||||
.PP
|
||||
This extension does not take any options. The \fB-p udp\fP options are
|
||||
required.
|
||||
.PP
|
||||
The SYSRQ password can be changed through
|
||||
/sys/module/xt_SYSRQ/parameters/password, for example:
|
||||
.IP
|
||||
echo -n "password" >/sys/module/xt_SYSRQ/parameters/password
|
||||
.PP
|
||||
Alternatively, the password may be specified at modprobe time, but this is
|
||||
insecure as people can possible see it through ps(1). You can use an option
|
||||
line in e.g. /etc/modprobe.d/xt_sysrq if it is properly guarded, that is, only
|
||||
readable by root.
|
||||
.IP
|
||||
options xt_SYSRQ password=cookies
|
||||
.PP
|
||||
The hash algorithm can also be specified as a module option, for example, to
|
||||
use SHA-256 instead of the default SHA-1:
|
||||
.IP
|
||||
options xt_SYSRQ hash=sha256
|
||||
.PP
|
||||
The xt_SYSRQ module is normally silent unless a successful request is received,
|
||||
but the \fIdebug\fP module parameter can be used to find exactly why a
|
||||
seemingly correct request is not being processed.
|
||||
.PP
|
||||
To trigger SYSRQ from a remote host, just use netcat or socat:
|
||||
.PP
|
||||
.nf
|
||||
sysrq_key="s" # the SysRq key(s)
|
||||
password="password"
|
||||
seqno="$(date +%s)"
|
||||
salt="$(dd bs=12 count=1 if=/dev/urandom 2>/dev/null |
|
||||
openssl enc -base64)"
|
||||
req="$sysrq_key,$seqno,$salt"
|
||||
req="$req,$(echo -n "$req,$password" | sha1sum | cut -c1-40)"
|
||||
|
||||
echo "$req" | socat stdin udp-sendto:10.10.25.7:9
|
||||
# or
|
||||
echo "$req" | netcat -uw1 10.10.25.7 9
|
||||
.fi
|
||||
.PP
|
||||
See the Linux docs for possible sysrq keys. Important ones are: re(b)oot,
|
||||
power(o)ff, (s)ync filesystems, (u)mount and remount readonly. More than one
|
||||
sysrq key can be used at once, but bear in mind that, for example, a sync may
|
||||
not complete before a subsequent reboot or poweroff.
|
||||
.PP
|
||||
The hashing scheme should be enough to prevent mis-use of SYSRQ in many
|
||||
environments, but it is not perfect: take reasonable precautions to
|
||||
protect your machines. Most importantly ensure that each machine has a
|
||||
different password; there is scant protection for a SYSRQ packet being
|
||||
applied to a machine that happens to have the same password.
|
@@ -1,3 +1,7 @@
|
||||
/*
|
||||
* "TARPIT" target extension to iptables
|
||||
* this file is in the Public Domain
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <getopt.h>
|
||||
#include <xtables.h>
|
||||
@@ -28,7 +32,7 @@ static struct xtables_target tarpit_tg_reg = {
|
||||
.final_check = tarpit_tg_check,
|
||||
};
|
||||
|
||||
static void _init(void)
|
||||
static __attribute__((constructor)) void tarpit_tg_ldr(void)
|
||||
{
|
||||
xtables_register_target(&tarpit_tg_reg);
|
||||
}
|
||||
|
@@ -1,9 +1,12 @@
|
||||
/*
|
||||
* libxt_TEE
|
||||
* "TEE" target extension for iptables
|
||||
* Copyright © Sebastian Claßen <sebastian.classen [at] freenet.ag>, 2007
|
||||
* Jan Engelhardt <jengelh [at] medozas de>, 2007 - 2009
|
||||
*
|
||||
* Copyright © Sebastian Claßen <sebastian.classen@freenet.ag>, 2007
|
||||
* Copyright © CC Computer Consultants GmbH, 2007 - 2008
|
||||
* Jan Engelhardt <jengelh@computergmbh.de>
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
* version 2 of the License, or any later version, as published by the
|
||||
* Free Software Foundation.
|
||||
*/
|
||||
#include <sys/socket.h>
|
||||
#include <getopt.h>
|
||||
@@ -27,7 +30,7 @@ enum {
|
||||
|
||||
static const struct option tee_tg_opts[] = {
|
||||
{.name = "gateway", .has_arg = true, .val = 'g'},
|
||||
{},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static void tee_tg_help(void)
|
||||
@@ -50,10 +53,6 @@ static int tee_tg_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Cannot specify --gw more than once");
|
||||
|
||||
if (check_inverse(optarg, &invert, NULL, 0))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Unexpected \"!\" after --gateway");
|
||||
|
||||
ia = numeric_to_ipaddr(optarg);
|
||||
if (ia == NULL)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
@@ -67,6 +66,31 @@ static int tee_tg_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
return false;
|
||||
}
|
||||
|
||||
static int tee_tg6_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_target **target)
|
||||
{
|
||||
struct xt_tee_tginfo *info = (void *)(*target)->data;
|
||||
const struct in6_addr *ia;
|
||||
|
||||
switch (c) {
|
||||
case 'g':
|
||||
if (*flags & FLAG_GATEWAY)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Cannot specify --gw more than once");
|
||||
|
||||
ia = numeric_to_ip6addr(optarg);
|
||||
if (ia == NULL)
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Invalid IP address %s", optarg);
|
||||
|
||||
memcpy(&info->gw, ia, sizeof(*ia));
|
||||
*flags |= FLAG_GATEWAY;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void tee_tg_check(unsigned int flags)
|
||||
{
|
||||
if (flags == 0)
|
||||
@@ -80,9 +104,20 @@ static void tee_tg_print(const void *ip, const struct xt_entry_target *target,
|
||||
const struct xt_tee_tginfo *info = (const void *)target->data;
|
||||
|
||||
if (numeric)
|
||||
printf("TEE gw:%s ", ipaddr_to_anyname(&info->gw.in));
|
||||
else
|
||||
printf("TEE gw:%s ", ipaddr_to_numeric(&info->gw.in));
|
||||
else
|
||||
printf("TEE gw:%s ", ipaddr_to_anyname(&info->gw.in));
|
||||
}
|
||||
|
||||
static void tee_tg6_print(const void *ip, const struct xt_entry_target *target,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_tee_tginfo *info = (const void *)target->data;
|
||||
|
||||
if (numeric)
|
||||
printf("TEE gw:%s ", ip6addr_to_numeric(&info->gw.in6));
|
||||
else
|
||||
printf("TEE gw:%s ", ip6addr_to_anyname(&info->gw.in6));
|
||||
}
|
||||
|
||||
static void tee_tg_save(const void *ip, const struct xt_entry_target *target)
|
||||
@@ -92,9 +127,18 @@ static void tee_tg_save(const void *ip, const struct xt_entry_target *target)
|
||||
printf("--gateway %s ", ipaddr_to_numeric(&info->gw.in));
|
||||
}
|
||||
|
||||
static void tee_tg6_save(const void *ip, const struct xt_entry_target *target)
|
||||
{
|
||||
const struct xt_tee_tginfo *info = (const void *)target->data;
|
||||
|
||||
printf("--gateway %s ", ip6addr_to_numeric(&info->gw.in6));
|
||||
}
|
||||
|
||||
static struct xtables_target tee_tg_reg = {
|
||||
.name = "TEE",
|
||||
.version = XTABLES_VERSION,
|
||||
.revision = 0,
|
||||
.family = PF_INET,
|
||||
.size = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
|
||||
.help = tee_tg_help,
|
||||
@@ -105,7 +149,23 @@ static struct xtables_target tee_tg_reg = {
|
||||
.extra_opts = tee_tg_opts,
|
||||
};
|
||||
|
||||
static void _init(void)
|
||||
static struct xtables_target tee_tg6_reg = {
|
||||
.name = "TEE",
|
||||
.version = XTABLES_VERSION,
|
||||
.revision = 0,
|
||||
.family = PF_INET6,
|
||||
.size = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
|
||||
.help = tee_tg_help,
|
||||
.parse = tee_tg6_parse,
|
||||
.final_check = tee_tg_check,
|
||||
.print = tee_tg6_print,
|
||||
.save = tee_tg6_save,
|
||||
.extra_opts = tee_tg_opts,
|
||||
};
|
||||
|
||||
static __attribute__((constructor)) void tee_tg_ldr(void)
|
||||
{
|
||||
xtables_register_target(&tee_tg_reg);
|
||||
xtables_register_target(&tee_tg6_reg);
|
||||
}
|
||||
|
8
extensions/libxt_TEE.man
Normal file
8
extensions/libxt_TEE.man
Normal file
@@ -0,0 +1,8 @@
|
||||
The \fBTEE\fP target will clone a packet and redirect this clone to another
|
||||
machine on the \fBlocal\fP network segment. In other words, the nexthop
|
||||
must be the target, or you will have to configure the nexthop to forward it
|
||||
further if so desired.
|
||||
.TP
|
||||
\fB--gw\fP \fIipaddr\fP
|
||||
Send the cloned packet to the host reachable at the given IP address.
|
||||
Use of 0.0.0.0 (for IPv4 packets) or :: (IPv6) is invalid.
|
@@ -1,4 +1,13 @@
|
||||
/* Shared library add-on to iptables for condition match */
|
||||
/*
|
||||
* "condition" match extension for iptables
|
||||
* Stephane Ouellette <ouellettes [at] videotron ca>, 2002-10-22
|
||||
* Massimiliano Hofer <max [at] nucleus it>, 2006-05-15
|
||||
* Jan Engelhardt <jengelh [at] medozas de>, 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License; either version 2
|
||||
* or 3 of the License, as published by the Free Software Foundation.
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
@@ -68,10 +77,10 @@ static void condition_save(const void *ip, const struct xt_entry_match *match)
|
||||
printf("--condition %s\"%s\" ", (info->invert) ? "! " : "", info->name);
|
||||
}
|
||||
|
||||
static struct xtables_match condition_mt4_reg = {
|
||||
static struct xtables_match condition_mt_reg = {
|
||||
.name = "condition",
|
||||
.revision = 0,
|
||||
.family = PF_INET,
|
||||
.family = PF_UNSPEC,
|
||||
.version = XTABLES_VERSION,
|
||||
.size = XT_ALIGN(sizeof(struct xt_condition_mtinfo)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_condition_mtinfo)),
|
||||
@@ -83,23 +92,7 @@ static struct xtables_match condition_mt4_reg = {
|
||||
.extra_opts = condition_opts,
|
||||
};
|
||||
|
||||
static struct xtables_match condition_mt6_reg = {
|
||||
.name = "condition",
|
||||
.revision = 0,
|
||||
.family = PF_INET6,
|
||||
.version = XTABLES_VERSION,
|
||||
.size = XT_ALIGN(sizeof(struct xt_condition_mtinfo)),
|
||||
.userspacesize = offsetof(struct xt_condition_mtinfo, condvar),
|
||||
.help = condition_help,
|
||||
.parse = condition_parse,
|
||||
.final_check = condition_check,
|
||||
.print = condition_print,
|
||||
.save = condition_save,
|
||||
.extra_opts = condition_opts,
|
||||
};
|
||||
|
||||
static void _init(void)
|
||||
static __attribute__((constructor)) void condition_mt_ldr(void)
|
||||
{
|
||||
xtables_register_match(&condition_mt4_reg);
|
||||
xtables_register_match(&condition_mt6_reg);
|
||||
xtables_register_match(&condition_mt_reg);
|
||||
}
|
||||
|
102
extensions/libxt_dhcpaddr.c
Normal file
102
extensions/libxt_dhcpaddr.c
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* "dhcpaddr" match extension for iptables
|
||||
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
* version 2 of the License, or any later version, as published by the
|
||||
* Free Software Foundation.
|
||||
*/
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <netdb.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <xtables.h>
|
||||
#include "xt_DHCPADDR.h"
|
||||
#include "mac.c"
|
||||
|
||||
enum {
|
||||
F_MAC = 1 << 0,
|
||||
};
|
||||
|
||||
static const struct option dhcpaddr_mt_opts[] = {
|
||||
{.name = "mac", .has_arg = true, .val = 'M'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static void dhcpaddr_mt_help(void)
|
||||
{
|
||||
printf(
|
||||
"dhcpaddr match options:\n"
|
||||
"[!] --mac lladdr[/mask] Match on MAC address in DHCP Client Host field\n"
|
||||
);
|
||||
}
|
||||
|
||||
static int dhcpaddr_mt_parse(int c, char **argv, int invert,
|
||||
unsigned int *flags, const void *entry, struct xt_entry_match **match)
|
||||
{
|
||||
struct dhcpaddr_info *info = (void *)(*match)->data;
|
||||
|
||||
switch (c) {
|
||||
case 'M':
|
||||
param_act(P_ONLY_ONCE, "dhcpaddr", "--mac", *flags & F_MAC);
|
||||
param_act(P_NO_INVERT, "dhcpaddr", "--mac", invert);
|
||||
if (!mac_parse(optarg, info->addr, &info->mask))
|
||||
param_act(P_BAD_VALUE, "dhcpaddr", "--mac", optarg);
|
||||
if (invert)
|
||||
info->invert = true;
|
||||
*flags |= F_MAC;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void dhcpaddr_mt_check(unsigned int flags)
|
||||
{
|
||||
if (flags == 0)
|
||||
exit_error(PARAMETER_PROBLEM, "dhcpaddr match: "
|
||||
"--mac parameter required");
|
||||
}
|
||||
|
||||
static void dhcpaddr_mt_print(const void *ip,
|
||||
const struct xt_entry_match *match, int numeric)
|
||||
{
|
||||
const struct dhcpaddr_info *info = (void *)match->data;
|
||||
|
||||
printf("dhcpaddr %s" DH_MAC_FMT "/%u ",
|
||||
info->invert ? "!" : "", DH_MAC_HEX(info->addr), info->mask);
|
||||
}
|
||||
|
||||
static void dhcpaddr_mt_save(const void *ip,
|
||||
const struct xt_entry_match *match)
|
||||
{
|
||||
const struct dhcpaddr_info *info = (void *)match->data;
|
||||
|
||||
if (info->invert)
|
||||
printf("! ");
|
||||
printf("--mac " DH_MAC_FMT "/%u ",
|
||||
DH_MAC_HEX(info->addr), info->mask);
|
||||
}
|
||||
|
||||
static struct xtables_match dhcpaddr_mt_reg = {
|
||||
.version = XTABLES_VERSION,
|
||||
.name = "dhcpaddr",
|
||||
.revision = 0,
|
||||
.family = PF_INET,
|
||||
.size = XT_ALIGN(sizeof(struct dhcpaddr_info)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct dhcpaddr_info)),
|
||||
.help = dhcpaddr_mt_help,
|
||||
.parse = dhcpaddr_mt_parse,
|
||||
.final_check = dhcpaddr_mt_check,
|
||||
.print = dhcpaddr_mt_print,
|
||||
.save = dhcpaddr_mt_save,
|
||||
.extra_opts = dhcpaddr_mt_opts,
|
||||
};
|
||||
|
||||
static __attribute__((constructor)) void dhcpaddr_mt_ldr(void)
|
||||
{
|
||||
xtables_register_match(&dhcpaddr_mt_reg);
|
||||
}
|
4
extensions/libxt_dhcpaddr.man
Normal file
4
extensions/libxt_dhcpaddr.man
Normal file
@@ -0,0 +1,4 @@
|
||||
.TP
|
||||
\fB--mac\fP \fIaa:bb:cc:dd:ee:ff\fP[\fB/\fP\fImask\fP]
|
||||
Matches the DHCP Client Host address in a DHCP message. \fImask\fP specifies
|
||||
the prefix length of the initial portion to match.
|
118
extensions/libxt_fuzzy.c
Normal file
118
extensions/libxt_fuzzy.c
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* "fuzzy" match extension for iptables
|
||||
* Hime Aguiar e Oliveira Jr. <hime@engineer.com>, 2002 - 2003
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License;
|
||||
* either version 2 of the License, or any later version, as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <getopt.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <xtables.h>
|
||||
#include "xt_fuzzy.h"
|
||||
|
||||
static void fuzzy_mt_help(void)
|
||||
{
|
||||
printf(
|
||||
"fuzzy match options:\n"
|
||||
" --lower-limit number (in packets per second)\n"
|
||||
" --upper-limit number\n");
|
||||
};
|
||||
|
||||
static const struct option fuzzy_mt_opts[] = {
|
||||
{.name = "lower-limit", .has_arg = true, .val = '1'},
|
||||
{.name = "upper-limit", .has_arg = true, .val = '2'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
/* Initialize data structures */
|
||||
static void fuzzy_mt_init(struct xt_entry_match *m)
|
||||
{
|
||||
struct xt_fuzzy_mtinfo *info = (void *)m->data;
|
||||
|
||||
/*
|
||||
* Default rates (I will improve this very soon with something based
|
||||
* on real statistics of the running machine).
|
||||
*/
|
||||
info->minimum_rate = 1000;
|
||||
info->maximum_rate = 2000;
|
||||
}
|
||||
|
||||
#define IPT_FUZZY_OPT_MINIMUM 0x01
|
||||
#define IPT_FUZZY_OPT_MAXIMUM 0x02
|
||||
|
||||
static int fuzzy_mt_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_match **match)
|
||||
{
|
||||
struct xt_fuzzy_mtinfo *info = (void *)(*match)->data;
|
||||
uint32_t num;
|
||||
|
||||
switch (c) {
|
||||
case '1':
|
||||
if (invert)
|
||||
exit_error(PARAMETER_PROBLEM,"Can't specify ! --lower-limit");
|
||||
if (*flags & IPT_FUZZY_OPT_MINIMUM)
|
||||
exit_error(PARAMETER_PROBLEM,"Can't specify --lower-limit twice");
|
||||
if (string_to_number(optarg,1,FUZZY_MAX_RATE,&num) == -1 || num < 1)
|
||||
exit_error(PARAMETER_PROBLEM,"BAD --lower-limit");
|
||||
info->minimum_rate = num;
|
||||
*flags |= IPT_FUZZY_OPT_MINIMUM;
|
||||
return true;
|
||||
|
||||
case '2':
|
||||
if (invert)
|
||||
exit_error(PARAMETER_PROBLEM,"Can't specify ! --upper-limit");
|
||||
if (*flags & IPT_FUZZY_OPT_MAXIMUM)
|
||||
exit_error(PARAMETER_PROBLEM,"Can't specify --upper-limit twice");
|
||||
if (string_to_number(optarg,1,FUZZY_MAX_RATE,&num) == -1 || num < 1)
|
||||
exit_error(PARAMETER_PROBLEM,"BAD --upper-limit");
|
||||
info->maximum_rate = num;
|
||||
*flags |= IPT_FUZZY_OPT_MAXIMUM;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void fuzzy_mt_check(unsigned int flags)
|
||||
{
|
||||
}
|
||||
|
||||
static void fuzzy_mt_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_fuzzy_mtinfo *info = (const void *)match->data;
|
||||
|
||||
printf("fuzzy: lower limit = %u pps - upper limit = %u pps ",
|
||||
info->minimum_rate, info->maximum_rate);
|
||||
}
|
||||
|
||||
static void fuzzy_mt_save(const void *ip, const struct xt_entry_match *match)
|
||||
{
|
||||
const struct xt_fuzzy_mtinfo *info = (const void *)match->data;
|
||||
|
||||
printf("--lower-limit %u ", info->minimum_rate);
|
||||
printf("--upper-limit %u ", info->maximum_rate);
|
||||
}
|
||||
|
||||
static struct xtables_match fuzzy_mt_reg = {
|
||||
.name = "fuzzy",
|
||||
.version = XTABLES_VERSION,
|
||||
.size = XT_ALIGN(sizeof(struct xt_fuzzy_mtinfo)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_fuzzy_mtinfo)),
|
||||
.help = fuzzy_mt_help,
|
||||
.init = fuzzy_mt_init,
|
||||
.parse = fuzzy_mt_parse,
|
||||
.final_check = fuzzy_mt_check,
|
||||
.print = fuzzy_mt_print,
|
||||
.save = fuzzy_mt_save,
|
||||
.extra_opts = fuzzy_mt_opts,
|
||||
};
|
||||
|
||||
static __attribute__((constructor)) void fuzzy_mt_ldr(void)
|
||||
{
|
||||
xtables_register_match(&fuzzy_mt_reg);
|
||||
}
|
7
extensions/libxt_fuzzy.man
Normal file
7
extensions/libxt_fuzzy.man
Normal file
@@ -0,0 +1,7 @@
|
||||
This module matches a rate limit based on a fuzzy logic controller (FLC).
|
||||
.TP
|
||||
\fB--lower-limit\fP \fInumber\fP
|
||||
Specifies the lower limit, in packets per second.
|
||||
.TP
|
||||
\fB--upper-limit\fP \fInumber\fP
|
||||
Specifies the upper limit, also in packets per second.
|
@@ -1,16 +1,13 @@
|
||||
/* Shared library add-on to iptables to add geoip match support.
|
||||
/*
|
||||
* "geoip" match extension for iptables
|
||||
* Copyright © Samuel Jean <peejix [at] people netfilter org>, 2004 - 2008
|
||||
* Copyright © Nicolas Bouliane <acidfu [at] people netfilter org>, 2004 - 2008
|
||||
* Jan Engelhardt <jengelh [at] medozas de>, 2008
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Copyright (c) 2004, 2005, 2006, 2007, 2008
|
||||
* Samuel Jean & Nicolas Bouliane
|
||||
*
|
||||
* For comments, bugs or suggestions, please contact
|
||||
* Samuel Jean <peejix@people.netfilter.org>
|
||||
* Nicolas Bouliane <peejix@people.netfilter.org>
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
* version 2 of the License, or any later version, as published by the
|
||||
* Free Software Foundation.
|
||||
*/
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
@@ -20,6 +17,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -175,35 +173,37 @@ static int geoip_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
{
|
||||
struct xt_geoip_match_info *info = (void *)(*match)->data;
|
||||
|
||||
switch(c) {
|
||||
case '1':
|
||||
// Ensure that XT_GEOIP_SRC *OR* XT_GEOIP_DST haven't been used yet.
|
||||
switch (c) {
|
||||
case '1':
|
||||
if (*flags & (XT_GEOIP_SRC | XT_GEOIP_DST))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"geoip: only use --source-country *OR* --destination-country once!");
|
||||
"geoip: Only exactly one of --source-country "
|
||||
"or --destination-country must be specified!");
|
||||
|
||||
*flags |= XT_GEOIP_SRC;
|
||||
break;
|
||||
if (invert)
|
||||
*flags |= XT_GEOIP_INV;
|
||||
|
||||
info->count = parse_geoip_cc(argv[optind-1], info->cc, info->mem);
|
||||
info->flags = *flags;
|
||||
return true;
|
||||
|
||||
case '2':
|
||||
// Ensure that XT_GEOIP_SRC *OR* XT_GEOIP_DST haven't been used yet.
|
||||
if (*flags & (XT_GEOIP_SRC | XT_GEOIP_DST))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"geoip: only use --source-country *OR* --destination-country once!");
|
||||
"geoip: Only exactly one of --source-country "
|
||||
"or --destination-country must be specified!");
|
||||
|
||||
*flags |= XT_GEOIP_DST;
|
||||
break;
|
||||
if (invert)
|
||||
*flags |= XT_GEOIP_INV;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
info->count = parse_geoip_cc(argv[optind-1], info->cc, info->mem);
|
||||
info->flags = *flags;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (invert)
|
||||
*flags |= XT_GEOIP_INV;
|
||||
|
||||
info->count = parse_geoip_cc(argv[optind-1], info->cc, info->mem);
|
||||
info->flags = *flags;
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -272,7 +272,7 @@ static struct xtables_match geoip_match = {
|
||||
.extra_opts = geoip_opts,
|
||||
};
|
||||
|
||||
static void _init(void)
|
||||
static __attribute__((constructor)) void geoip_mt_ldr(void)
|
||||
{
|
||||
xtables_register_match(&geoip_match);
|
||||
}
|
||||
|
@@ -1,3 +1,13 @@
|
||||
/*
|
||||
* "ipp2p" match extension for iptables
|
||||
* Eicke Friedrich/Klaus Degner <ipp2p@ipp2p.org>, 2005 - 2006
|
||||
* Jan Engelhardt <jengelh [at] medozas de>, 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
* version 2 of the License, or any later version, as published by the
|
||||
* Free Software Foundation.
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
@@ -12,7 +22,7 @@
|
||||
static void ipp2p_mt_help(void)
|
||||
{
|
||||
printf(
|
||||
"IPP2P v%s options:\n"
|
||||
"ipp2p v%s match options:\n"
|
||||
" --edk [tcp,udp] All known eDonkey/eMule/Overnet packets\n"
|
||||
" --dc [tcp] All known Direct Connect packets\n"
|
||||
" --kazaa [tcp,udp] All known KaZaA packets\n"
|
||||
@@ -22,19 +32,10 @@ static void ipp2p_mt_help(void)
|
||||
" --winmx [tcp] All known WinMX\n"
|
||||
" --soul [tcp] All known SoulSeek\n"
|
||||
" --ares [tcp] All known Ares\n\n"
|
||||
"EXPERIMENTAL protocols (please send feedback to: ipp2p@ipp2p.org) :\n"
|
||||
"EXPERIMENTAL protocols:\n"
|
||||
" --mute [tcp] All known Mute packets\n"
|
||||
" --waste [tcp] All known Waste packets\n"
|
||||
" --xdcc [tcp] All known XDCC packets (only xdcc login)\n\n"
|
||||
"DEBUG SUPPPORT, use only if you know why\n"
|
||||
" --debug Generate kernel debug output, THIS WILL SLOW DOWN THE FILTER\n"
|
||||
"\nIPP2P was intended for TCP only. Due to increasing usage of UDP we needed to change this.\n"
|
||||
"You can now use -p udp to search UDP packets only or without -p switch to search UDP and TCP packets.\n"
|
||||
"\nSee README included with this package for more details or visit http://www.ipp2p.org\n"
|
||||
"\nExamples:\n"
|
||||
" iptables -A FORWARD -m ipp2p --ipp2p -j MARK --set-mark 0x01\n"
|
||||
" iptables -A FORWARD -p udp -m ipp2p --kazaa --bit -j DROP\n"
|
||||
" iptables -A FORWARD -p tcp -m ipp2p --edk --soul -j DROP\n\n"
|
||||
, IPP2P_VERSION);
|
||||
}
|
||||
|
||||
@@ -232,7 +233,7 @@ static struct xtables_match ipp2p_mt_reg = {
|
||||
.extra_opts = ipp2p_mt_opts,
|
||||
};
|
||||
|
||||
static void _init(void)
|
||||
static __attribute__((constructor)) void ipp2p_mt_ldr(void)
|
||||
{
|
||||
xtables_register_match(&ipp2p_mt_reg);
|
||||
}
|
||||
|
@@ -1,12 +1,12 @@
|
||||
This module matches certain packets in P2P flows. It is not
|
||||
designed to match all packets belonging to a P2P connection -
|
||||
use IPP2P together with CONNMARK for this purpose. Also visit
|
||||
http://www.ipp2p.org for detailed information.
|
||||
|
||||
use IPP2P together with CONNMARK for this purpose.
|
||||
.PP
|
||||
Use it together with -p tcp or -p udp to search these protocols
|
||||
only or without -p switch to search packets of both protocols.
|
||||
|
||||
IPP2P provides the following options:
|
||||
.PP
|
||||
IPP2P provides the following options, of which one or more may be specified
|
||||
on the command line:
|
||||
.TP
|
||||
.B "--edk "
|
||||
Matches as many eDonkey/eMule packets as possible.
|
||||
@@ -38,3 +38,11 @@ Matches Ares and AresLite packets. Use together with -j DROP only.
|
||||
.B "--debug "
|
||||
Prints some information about each hit into kernel logfile. May
|
||||
produce huge logfiles so beware!
|
||||
.PP
|
||||
Note that ipp2p may not (and often, does not) identify all packets that are
|
||||
exchanged as a result of running filesharing programs.
|
||||
.PP
|
||||
There is more information on http://ipp2p.org/ , but it has not been updated
|
||||
since September 2006, and the syntax there is different from the ipp2p.c
|
||||
provided in Xtables-addons; most importantly, the --ipp2p flag was removed due
|
||||
to its ambiguity to match "all known" protocols.
|
||||
|
18
extensions/libxt_length.man
Normal file
18
extensions/libxt_length.man
Normal file
@@ -0,0 +1,18 @@
|
||||
This module matches the length of a packet against a specific value or range of
|
||||
values.
|
||||
.TP
|
||||
[\fB!\fR] \fB--length\fR \fIlength\fR[\fB:\fR\fIlength\fR]
|
||||
Match exact length or length range.
|
||||
.TP
|
||||
\fB--layer3\fR
|
||||
Match the layer3 frame size (e.g. IPv4/v6 header plus payload).
|
||||
.TP
|
||||
\fB--layer4\fR
|
||||
Match the layer4 frame size (e.g. TCP/UDP header plus payload).
|
||||
.TP
|
||||
\fB--layer5\fR
|
||||
Match the layer5 frame size (e.g. TCP/UDP payload, often called layer7).
|
||||
.PP
|
||||
If no --layer* option is given, --layer3 is assumed by default. Note that using
|
||||
--layer5 may not match a packet if it is not one of the recognized types
|
||||
(currently TCP, UDP, UDPLite, ICMP, AH and ESP) or which has no 5th layer.
|
173
extensions/libxt_length2.c
Normal file
173
extensions/libxt_length2.c
Normal file
@@ -0,0 +1,173 @@
|
||||
#include <getopt.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <xtables.h>
|
||||
#include "xt_length2.h"
|
||||
|
||||
enum {
|
||||
F_LAYER = 1 << 0,
|
||||
F_LENGTH = 1 << 1,
|
||||
|
||||
XT_LENGTH_LAYER_MASK = XT_LENGTH_LAYER3 | XT_LENGTH_LAYER4 |
|
||||
XT_LENGTH_LAYER5 | XT_LENGTH_LAYER7,
|
||||
};
|
||||
|
||||
static void length_mt_help(void)
|
||||
{
|
||||
printf(
|
||||
"length match options:\n"
|
||||
" --layer3 Match against layer3 size (e.g. L4 + IPv6 header)\n"
|
||||
" --layer4 Match against layer4 size (e.g. L5 + SCTP header)\n"
|
||||
" --layer5 Match against layer5 size (e.g. L7 + chunk headers)\n"
|
||||
" --layer7 Match against layer7 payload (e.g. SCTP payload)\n"
|
||||
"[!] --length n[:n] Match packet length against value or range\n"
|
||||
" of values (inclusive)\n"
|
||||
);
|
||||
}
|
||||
|
||||
static const struct option length_mt_opts[] = {
|
||||
{.name = "layer3", .has_arg = false, .val = '3'},
|
||||
{.name = "layer4", .has_arg = false, .val = '4'},
|
||||
{.name = "layer5", .has_arg = false, .val = '5'},
|
||||
{.name = "layer7", .has_arg = false, .val = '7'},
|
||||
{.name = "length", .has_arg = true, .val = '='},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static void length_mt_init(struct xt_entry_match *match)
|
||||
{
|
||||
struct xt_length_mtinfo2 *info = (void *)match->data;
|
||||
|
||||
info->flags = XT_LENGTH_LAYER3;
|
||||
}
|
||||
|
||||
static int length_mt_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_match **match)
|
||||
{
|
||||
struct xt_length_mtinfo2 *info = (void *)(*match)->data;
|
||||
unsigned int from, to;
|
||||
char *end;
|
||||
|
||||
switch (c) {
|
||||
case '3': /* --layer3 */
|
||||
param_act(P_ONLY_ONCE, "length", "--layer*", *flags & F_LAYER);
|
||||
info->flags &= ~XT_LENGTH_LAYER_MASK;
|
||||
info->flags |= XT_LENGTH_LAYER3;
|
||||
*flags |= F_LAYER;
|
||||
return true;
|
||||
case '4': /* --layer4 */
|
||||
param_act(P_ONLY_ONCE, "length", "--layer*", *flags & F_LAYER);
|
||||
info->flags &= ~XT_LENGTH_LAYER_MASK;
|
||||
info->flags |= XT_LENGTH_LAYER4;
|
||||
*flags |= F_LAYER;
|
||||
return true;
|
||||
case '5': /* --layer5 */
|
||||
param_act(P_ONLY_ONCE, "length", "--layer*", *flags & F_LAYER);
|
||||
info->flags &= ~XT_LENGTH_LAYER_MASK;
|
||||
info->flags |= XT_LENGTH_LAYER5;
|
||||
*flags |= F_LAYER;
|
||||
return true;
|
||||
case '7': /* --layer7 */
|
||||
param_act(P_ONLY_ONCE, "length", "--layer*", *flags & F_LAYER);
|
||||
info->flags &= ~XT_LENGTH_LAYER_MASK;
|
||||
info->flags |= XT_LENGTH_LAYER7;
|
||||
*flags |= F_LAYER;
|
||||
return true;
|
||||
case '=': /* --length */
|
||||
param_act(P_ONLY_ONCE, "length", "--length", *flags & F_LENGTH);
|
||||
if (invert)
|
||||
info->flags |= XT_LENGTH_INVERT;
|
||||
if (!strtonum(optarg, &end, &from, 0, ~0U))
|
||||
param_act(P_BAD_VALUE, "length", "--length", optarg);
|
||||
to = from;
|
||||
if (*end == ':')
|
||||
if (!strtonum(end + 1, &end, &to, 0, ~0U))
|
||||
param_act(P_BAD_VALUE, "length",
|
||||
"--length", optarg);
|
||||
if (*end != '\0')
|
||||
param_act(P_BAD_VALUE, "length", "--length", optarg);
|
||||
info->min = from;
|
||||
info->max = to;
|
||||
*flags |= F_LENGTH;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void length_mt_check(unsigned int flags)
|
||||
{
|
||||
if (!(flags & F_LENGTH))
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"length: You must specify \"--length\"");
|
||||
if (!(flags & F_LAYER))
|
||||
fprintf(stderr, "iptables: length match: Defaulting to "
|
||||
"--layer3. Consider specifying it explicitly.\n");
|
||||
}
|
||||
|
||||
static void length_mt_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_length_mtinfo2 *info = (const void *)match->data;
|
||||
|
||||
if (info->flags & XT_LENGTH_LAYER3)
|
||||
printf("layer3 ");
|
||||
else if (info->flags & XT_LENGTH_LAYER4)
|
||||
printf("layer4 ");
|
||||
else if (info->flags & XT_LENGTH_LAYER5)
|
||||
printf("layer5 ");
|
||||
else if (info->flags & XT_LENGTH_LAYER7)
|
||||
printf("layer7 ");
|
||||
printf("length ");
|
||||
if (info->flags & XT_LENGTH_INVERT)
|
||||
printf("! ");
|
||||
if (info->min == info->max)
|
||||
printf("%u ", (unsigned int)info->min);
|
||||
else
|
||||
printf("%u-%u ", (unsigned int)info->min,
|
||||
(unsigned int)info->max);
|
||||
}
|
||||
|
||||
static void length_mt_save(const void *ip, const struct xt_entry_match *match)
|
||||
{
|
||||
const struct xt_length_mtinfo2 *info = (const void *)match->data;
|
||||
|
||||
if (info->flags & XT_LENGTH_LAYER3)
|
||||
printf("--layer3 ");
|
||||
else if (info->flags & XT_LENGTH_LAYER4)
|
||||
printf("--layer4 ");
|
||||
else if (info->flags & XT_LENGTH_LAYER5)
|
||||
printf("--layer5 ");
|
||||
else if (info->flags & XT_LENGTH_LAYER7)
|
||||
printf("--layer7 ");
|
||||
if (info->flags & XT_LENGTH_INVERT)
|
||||
printf("! ");
|
||||
printf("--length ");
|
||||
if (info->min == info->max)
|
||||
printf("%u ", (unsigned int)info->min);
|
||||
else
|
||||
printf("%u:%u ", (unsigned int)info->min,
|
||||
(unsigned int)info->max);
|
||||
}
|
||||
|
||||
static struct xtables_match length2_mt_reg = {
|
||||
.version = XTABLES_VERSION,
|
||||
.name = "length2",
|
||||
.revision = 2,
|
||||
.family = PF_UNSPEC,
|
||||
.size = XT_ALIGN(sizeof(struct xt_length_mtinfo2)),
|
||||
.userspacesize = XT_ALIGN(sizeof(struct xt_length_mtinfo2)),
|
||||
.init = length_mt_init,
|
||||
.help = length_mt_help,
|
||||
.parse = length_mt_parse,
|
||||
.final_check = length_mt_check,
|
||||
.print = length_mt_print,
|
||||
.save = length_mt_save,
|
||||
.extra_opts = length_mt_opts,
|
||||
};
|
||||
|
||||
static void _init(void)
|
||||
{
|
||||
xtables_register_match(&length2_mt_reg);
|
||||
}
|
@@ -1,12 +1,14 @@
|
||||
/*
|
||||
* portscan target for Xtables
|
||||
* Copyright © CC Computer Consultants GmbH, 2006 - 2008
|
||||
* "portscan" match extension for iptables
|
||||
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2006 - 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License; either version
|
||||
* 2 or 3 as published by the Free Software Foundation.
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
* version 2 of the License, or any later version, as published by the
|
||||
* Free Software Foundation.
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@@ -21,7 +23,7 @@ static const struct option portscan_mt_opts[] = {
|
||||
{.name = "synscan", .has_arg = false, .val = 's'},
|
||||
{.name = "cnscan", .has_arg = false, .val = 'c'},
|
||||
{.name = "grscan", .has_arg = false, .val = 'g'},
|
||||
{},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static void portscan_mt_help(void)
|
||||
@@ -114,8 +116,7 @@ static struct xtables_match portscan_mt_reg = {
|
||||
.extra_opts = portscan_mt_opts,
|
||||
};
|
||||
|
||||
void _init(void);
|
||||
void _init(void)
|
||||
static __attribute__((constructor)) void portscan_mt_ldr(void)
|
||||
{
|
||||
xtables_register_match(&portscan_mt_reg);
|
||||
}
|
||||
|
@@ -20,7 +20,11 @@ connection was torn down after completion of the 3-way handshake.
|
||||
\fB--grscan\fR
|
||||
Match if data in the connection only flew in the direction of the remote side,
|
||||
e.g. if the connection was terminated after a locally running daemon sent its
|
||||
identification. (e.g. openssh)
|
||||
identification. (E.g. openssh, smtp, ftpd.) This may falsely trigger on
|
||||
warranted single-direction data flows, usually bulk data transfers such as
|
||||
FTP DATA connections or IRC DCC. Grab Scan Detection should only be used on
|
||||
ports where a protocol runs that is guaranteed to do a bidirectional exchange
|
||||
of bytes.
|
||||
.PP
|
||||
NOTE: Some clients (Windows XP for example) may do what looks like a SYN scan,
|
||||
so be advised to carefully use xt_portscan in conjunction with blocking rules,
|
||||
|
139
extensions/libxt_quota2.c
Normal file
139
extensions/libxt_quota2.c
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* "quota2" match extension for iptables
|
||||
* Sam Johnston <samj [at] samj net>
|
||||
* Jan Engelhardt <jengelh [at] medozas de>, 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
* version 2 of the License, or any later version, as published by the
|
||||
* Free Software Foundation.
|
||||
*/
|
||||
#include <getopt.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <xtables.h>
|
||||
#include "xt_quota2.h"
|
||||
|
||||
enum {
|
||||
FL_QUOTA = 1 << 0,
|
||||
FL_NAME = 1 << 1,
|
||||
FL_GROW = 1 << 2,
|
||||
FL_PACKET = 1 << 3,
|
||||
};
|
||||
|
||||
static const struct option quota_mt2_opts[] = {
|
||||
{.name = "grow", .has_arg = false, .val = 'g'},
|
||||
{.name = "name", .has_arg = true, .val = 'n'},
|
||||
{.name = "quota", .has_arg = true, .val = 'q'},
|
||||
{.name = "packets", .has_arg = false, .val = 'p'},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static void quota_mt2_help(void)
|
||||
{
|
||||
printf(
|
||||
"quota match options:\n"
|
||||
" --grow provide an increasing counter\n"
|
||||
" --name name name for the file in sysfs\n"
|
||||
"[!] --quota quota initial quota (bytes or packets)\n"
|
||||
" --packets count packets instead of bytes\n"
|
||||
);
|
||||
}
|
||||
|
||||
static int
|
||||
quota_mt2_parse(int c, char **argv, int invert, unsigned int *flags,
|
||||
const void *entry, struct xt_entry_match **match)
|
||||
{
|
||||
struct xt_quota_mtinfo2 *info = (void *)(*match)->data;
|
||||
char *end;
|
||||
|
||||
switch (c) {
|
||||
case 'g':
|
||||
param_act(P_ONLY_ONCE, "quota", "--grow", *flags & FL_GROW);
|
||||
param_act(P_NO_INVERT, "quota", "--grow", invert);
|
||||
info->flags |= XT_QUOTA_GROW;
|
||||
*flags |= FL_GROW;
|
||||
return true;
|
||||
case 'n':
|
||||
/* zero termination done on behalf of the kernel module */
|
||||
param_act(P_ONLY_ONCE, "quota", "--name", *flags & FL_NAME);
|
||||
param_act(P_NO_INVERT, "quota", "--name", invert);
|
||||
strncpy(info->name, optarg, sizeof(info->name));
|
||||
*flags |= FL_NAME;
|
||||
return true;
|
||||
case 'p':
|
||||
param_act(P_ONLY_ONCE, "quota", "--packets", *flags & FL_PACKET);
|
||||
param_act(P_NO_INVERT, "quota", "--packets", invert);
|
||||
info->flags |= XT_QUOTA_PACKET;
|
||||
*flags |= FL_PACKET;
|
||||
return true;
|
||||
case 'q':
|
||||
param_act(P_ONLY_ONCE, "quota", "--quota", *flags & FL_QUOTA);
|
||||
if (invert)
|
||||
info->flags |= XT_QUOTA_INVERT;
|
||||
info->quota = strtoull(optarg, &end, 0);
|
||||
if (*end != '\0')
|
||||
exit_error(PARAMETER_PROBLEM, "quota match: "
|
||||
"invalid value for --quota");
|
||||
*flags |= FL_QUOTA;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
quota_mt2_save(const void *ip, const struct xt_entry_match *match)
|
||||
{
|
||||
const struct xt_quota_mtinfo2 *q = (void *)match->data;
|
||||
|
||||
if (q->flags & XT_QUOTA_INVERT)
|
||||
printf("! ");
|
||||
if (q->flags & XT_QUOTA_GROW)
|
||||
printf("--grow ");
|
||||
if (q->flags & XT_QUOTA_PACKET)
|
||||
printf("--packets ");
|
||||
if (*q->name != '\0')
|
||||
printf("--name %s ", q->name);
|
||||
printf("--quota %llu ", (unsigned long long)q->quota);
|
||||
}
|
||||
|
||||
static void quota_mt2_print(const void *ip, const struct xt_entry_match *match,
|
||||
int numeric)
|
||||
{
|
||||
const struct xt_quota_mtinfo2 *q = (const void *)match->data;
|
||||
|
||||
if (q->flags & XT_QUOTA_INVERT)
|
||||
printf("! ");
|
||||
if (q->flags & XT_QUOTA_GROW)
|
||||
printf("counter");
|
||||
else
|
||||
printf("quota");
|
||||
if (*q->name != '\0')
|
||||
printf(" %s:", q->name);
|
||||
printf(" %llu ", (unsigned long long)q->quota);
|
||||
if (q->flags & XT_QUOTA_PACKET)
|
||||
printf("packets ");
|
||||
else
|
||||
printf("bytes ");
|
||||
}
|
||||
|
||||
static struct xtables_match quota_mt2_reg = {
|
||||
.family = AF_UNSPEC,
|
||||
.revision = 2,
|
||||
.name = "quota2",
|
||||
.version = XTABLES_VERSION,
|
||||
.size = XT_ALIGN(sizeof (struct xt_quota_mtinfo2)),
|
||||
.userspacesize = offsetof(struct xt_quota_mtinfo2, quota),
|
||||
.help = quota_mt2_help,
|
||||
.parse = quota_mt2_parse,
|
||||
.print = quota_mt2_print,
|
||||
.save = quota_mt2_save,
|
||||
.extra_opts = quota_mt2_opts,
|
||||
};
|
||||
|
||||
static __attribute__((constructor)) void quota2_mt_ldr(void)
|
||||
{
|
||||
xtables_register_match("a_mt2_reg);
|
||||
}
|
31
extensions/libxt_quota2.man
Normal file
31
extensions/libxt_quota2.man
Normal file
@@ -0,0 +1,31 @@
|
||||
The "quota2" implements a named counter which can be increased or decreased
|
||||
on a per-match basis. Available modes are packet counting or byte counting.
|
||||
The value of the counter can be read and reset through procfs, thereby making
|
||||
this match a minimalist accounting tool.
|
||||
.PP
|
||||
When counting down from the initial quota, the counter will stop at 0 and
|
||||
the match will return false, just like the original "quota" match. In growing
|
||||
(upcounting) mode, it will always return true.
|
||||
.TP
|
||||
\fB--grow\fP
|
||||
Count upwards instead of downwards.
|
||||
.TP
|
||||
\fB--name\fP \fIname\fP
|
||||
Assign the counter a specific name. This option must be present, as an empty
|
||||
name is not allowed. Names starting with a dot or names containing a slash are
|
||||
prohibited.
|
||||
.TP
|
||||
[\fB!\fP] \fB--quota\fP \fIiq\fP
|
||||
Specify the initial quota for this counter. If the counter already exists,
|
||||
it is not reset. An "!" may be used to invert the result of the match. The
|
||||
negation has no effect when \fB--grow\fP is used.
|
||||
.TP
|
||||
\fB--packets\fP
|
||||
Count packets instead of bytes that passed the quota2 match.
|
||||
.PP
|
||||
Because counters in quota2 can be shared, you can combine them for various
|
||||
purposes, for example, a bytebucket filter that only lets as much traffic go
|
||||
out as has come in:
|
||||
.PP
|
||||
-A INPUT -p tcp --dport 6881 -m quota --name bt --grow
|
||||
-A OUTPUT -p tcp --sport 6881 -m quota --name bt
|
29
extensions/mac.c
Normal file
29
extensions/mac.c
Normal file
@@ -0,0 +1,29 @@
|
||||
static bool mac_parse(const char *addr, unsigned char *dest, uint8_t *mask)
|
||||
{
|
||||
unsigned int i = 0, value;
|
||||
char *end;
|
||||
|
||||
for (i = 0; i < ETH_ALEN; ++i) {
|
||||
value = strtoul(addr, &end, 16);
|
||||
if (addr == end || value > 0xFF)
|
||||
return false;
|
||||
if (i == ETH_ALEN - 1) {
|
||||
if (*end != '\0' && *end != '/')
|
||||
return false;
|
||||
} else if (*end != ':') {
|
||||
return false;
|
||||
}
|
||||
dest[i] = value;
|
||||
addr = end + 1;
|
||||
}
|
||||
|
||||
*mask = 48;
|
||||
if (*end == '/') {
|
||||
if (!strtonum(end + 1, &end, &value, 0, 48))
|
||||
return false;
|
||||
if (*end != '\0')
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* CHAOS target for netfilter
|
||||
* Copyright © CC Computer Consultants GmbH, 2006 - 2007
|
||||
* Contact: Jan Engelhardt <jengelh@computergmbh.de>
|
||||
* "CHAOS" target extension for Xtables
|
||||
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2006 - 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License; either version
|
||||
* 2 or 3 as published by the Free Software Foundation.
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
* version 2 of the License, or any later version, as published by the
|
||||
* Free Software Foundation.
|
||||
*/
|
||||
#include <linux/icmp.h>
|
||||
#include <linux/in.h>
|
||||
@@ -44,13 +44,13 @@ static const struct xt_tcp tcp_params = {
|
||||
};
|
||||
|
||||
/* CHAOS functions */
|
||||
static void xt_chaos_total(const struct xt_chaos_tginfo *info,
|
||||
struct sk_buff *skb, const struct net_device *in,
|
||||
const struct net_device *out, unsigned int hooknum)
|
||||
static void
|
||||
xt_chaos_total(struct sk_buff *skb, const struct xt_target_param *par)
|
||||
{
|
||||
const struct xt_chaos_tginfo *info = par->targinfo;
|
||||
const struct iphdr *iph = ip_hdr(skb);
|
||||
const int protoff = 4 * iph->ihl;
|
||||
const int offset = ntohs(iph->frag_off) & IP_OFFSET;
|
||||
const int thoff = 4 * iph->ihl;
|
||||
const int fragoff = ntohs(iph->frag_off) & IP_OFFSET;
|
||||
typeof(xt_tarpit) destiny;
|
||||
bool ret;
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 22)
|
||||
@@ -59,25 +59,44 @@ static void xt_chaos_total(const struct xt_chaos_tginfo *info,
|
||||
bool hotdrop = false;
|
||||
#endif
|
||||
|
||||
ret = xm_tcp->match(skb, in, out, xm_tcp, &tcp_params,
|
||||
offset, protoff, &hotdrop);
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
ret = xm_tcp->match(skb, par->in, par->out, xm_tcp, &tcp_params,
|
||||
fragoff, thoff, &hotdrop);
|
||||
#else
|
||||
{
|
||||
struct xt_match_param local_par = {
|
||||
.in = par->in,
|
||||
.out = par->out,
|
||||
.match = xm_tcp,
|
||||
.matchinfo = &tcp_params,
|
||||
.fragoff = fragoff,
|
||||
.thoff = thoff,
|
||||
.hotdrop = &hotdrop,
|
||||
};
|
||||
ret = xm_tcp->match(skb, &local_par);
|
||||
}
|
||||
#endif
|
||||
if (!ret || hotdrop || (unsigned int)net_random() > delude_percentage)
|
||||
return;
|
||||
|
||||
destiny = (info->variant == XTCHAOS_TARPIT) ? xt_tarpit : xt_delude;
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
|
||||
destiny->target(&skb, in, out, hooknum, destiny, NULL, NULL);
|
||||
destiny->target(&skb, par->in, par->out, par->hooknum, destiny, NULL, NULL);
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
destiny->target(&skb, in, out, hooknum, destiny, NULL);
|
||||
destiny->target(&skb, par->in, par->out, par->hooknum, destiny, NULL);
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
destiny->target(skb, par->in, par->out, par->hooknum, destiny, NULL);
|
||||
#else
|
||||
destiny->target(skb, in, out, hooknum, destiny, NULL);
|
||||
{
|
||||
struct xt_target_param local_par = *par;
|
||||
local_par.target = destiny;
|
||||
destiny->target(skb, &local_par);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
static unsigned int chaos_tg(struct sk_buff *skb, const struct net_device *in,
|
||||
const struct net_device *out, unsigned int hooknum,
|
||||
const struct xt_target *target, const void *targinfo)
|
||||
static unsigned int
|
||||
chaos_tg(struct sk_buff **pskb, const struct xt_target_param *par)
|
||||
{
|
||||
/*
|
||||
* Equivalent to:
|
||||
@@ -87,33 +106,44 @@ static unsigned int chaos_tg(struct sk_buff *skb, const struct net_device *in,
|
||||
* $delude_percentage -j DELUDE;
|
||||
* -A chaos -j DROP;
|
||||
*/
|
||||
const struct xt_chaos_tginfo *info = targinfo;
|
||||
const struct xt_chaos_tginfo *info = par->targinfo;
|
||||
struct sk_buff *skb = *pskb;
|
||||
const struct iphdr *iph = ip_hdr(skb);
|
||||
|
||||
if ((unsigned int)net_random() <= reject_percentage)
|
||||
if ((unsigned int)net_random() <= reject_percentage) {
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
|
||||
return xt_reject->target(&skb, in, out, hooknum,
|
||||
target->__compat_target, &reject_params, NULL);
|
||||
return xt_reject->target(pskb, par->in, par->out, par->hooknum,
|
||||
xt_reject, &reject_params, NULL);
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 23)
|
||||
return xt_reject->target(&skb, in, out, hooknum,
|
||||
target->__compat_target, &reject_params);
|
||||
return xt_reject->target(pskb, par->in, par->out, par->hooknum,
|
||||
xt_reject, &reject_params);
|
||||
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
return xt_reject->target(skb, par->in, par->out, par->hooknum,
|
||||
xt_reject, &reject_params);
|
||||
#else
|
||||
return xt_reject->target(skb, in, out, hooknum, target,
|
||||
&reject_params);
|
||||
struct xt_target_param local_par = {
|
||||
.in = par->in,
|
||||
.out = par->out,
|
||||
.hooknum = par->hooknum,
|
||||
.target = xt_reject,
|
||||
.targinfo = &reject_params,
|
||||
};
|
||||
return xt_reject->target(skb, &local_par);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* TARPIT/DELUDE may not be called from the OUTPUT chain */
|
||||
if (iph->protocol == IPPROTO_TCP &&
|
||||
info->variant != XTCHAOS_NORMAL && hooknum != NF_INET_LOCAL_OUT)
|
||||
xt_chaos_total(info, skb, in, out, hooknum);
|
||||
info->variant != XTCHAOS_NORMAL &&
|
||||
par->hooknum != NF_INET_LOCAL_OUT)
|
||||
xt_chaos_total(skb, par);
|
||||
|
||||
return NF_DROP;
|
||||
}
|
||||
|
||||
static bool chaos_tg_check(const char *tablename, const void *entry,
|
||||
const struct xt_target *target, void *targinfo, unsigned int hook_mask)
|
||||
static bool chaos_tg_check(const struct xt_tgchk_param *par)
|
||||
{
|
||||
const struct xt_chaos_tginfo *info = targinfo;
|
||||
const struct xt_chaos_tginfo *info = par->targinfo;
|
||||
|
||||
if (info->variant == XTCHAOS_DELUDE && !have_delude) {
|
||||
printk(KERN_WARNING PFX "Error: Cannot use --delude when "
|
||||
@@ -131,7 +161,8 @@ static bool chaos_tg_check(const char *tablename, const void *entry,
|
||||
|
||||
static struct xt_target chaos_tg_reg = {
|
||||
.name = "CHAOS",
|
||||
.family = AF_INET,
|
||||
.revision = 0,
|
||||
.family = NFPROTO_IPV4,
|
||||
.table = "filter",
|
||||
.hooks = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD) |
|
||||
(1 << NF_INET_LOCAL_OUT),
|
||||
@@ -145,27 +176,27 @@ static int __init chaos_tg_init(void)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
|
||||
xm_tcp = xt_request_find_match(AF_INET, "tcp", 0);
|
||||
xm_tcp = xt_request_find_match(NFPROTO_IPV4, "tcp", 0);
|
||||
if (xm_tcp == NULL) {
|
||||
printk(KERN_WARNING PFX "Error: Could not find or load "
|
||||
"\"tcp\" match\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
xt_reject = xt_request_find_target(AF_INET, "REJECT", 0);
|
||||
xt_reject = xt_request_find_target(NFPROTO_IPV4, "REJECT", 0);
|
||||
if (xt_reject == NULL) {
|
||||
printk(KERN_WARNING PFX "Error: Could not find or load "
|
||||
"\"REJECT\" target\n");
|
||||
goto out2;
|
||||
}
|
||||
|
||||
xt_tarpit = xt_request_find_target(AF_INET, "TARPIT", 0);
|
||||
xt_tarpit = xt_request_find_target(NFPROTO_IPV4, "TARPIT", 0);
|
||||
have_tarpit = xt_tarpit != NULL;
|
||||
if (!have_tarpit)
|
||||
printk(KERN_WARNING PFX "Warning: Could not find or load "
|
||||
"\"TARPIT\" target\n");
|
||||
|
||||
xt_delude = xt_request_find_target(AF_INET, "DELUDE", 0);
|
||||
xt_delude = xt_request_find_target(NFPROTO_IPV4, "DELUDE", 0);
|
||||
have_delude = xt_delude != NULL;
|
||||
if (!have_delude)
|
||||
printk(KERN_WARNING PFX "Warning: Could not find or load "
|
||||
@@ -199,7 +230,6 @@ static void __exit chaos_tg_exit(void)
|
||||
module_put(xt_delude->me);
|
||||
if (have_tarpit)
|
||||
module_put(xt_tarpit->me);
|
||||
return;
|
||||
}
|
||||
|
||||
module_init(chaos_tg_init);
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* DELUDE target
|
||||
* Copyright © CC Computer Consultants GmbH, 2007 - 2008
|
||||
* "DELUDE" target extension for Xtables
|
||||
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2007 - 2008
|
||||
*
|
||||
* Based upon linux-2.6.18.5/net/ipv4/netfilter/ipt_REJECT.c:
|
||||
* (C) 1999-2001 Paul `Rusty' Russell
|
||||
@@ -122,8 +122,10 @@ static void delude_send_reset(struct sk_buff *oldskb, unsigned int hook)
|
||||
dst_hold(oldskb->dst);
|
||||
nskb->dst = oldskb->dst;
|
||||
|
||||
if (ip_route_me_harder(nskb, addr_type))
|
||||
if (ip_route_me_harder(&nskb, addr_type))
|
||||
goto free_nskb;
|
||||
else
|
||||
niph = ip_hdr(nskb);
|
||||
|
||||
niph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT);
|
||||
nskb->ip_summed = CHECKSUM_NONE;
|
||||
@@ -141,21 +143,20 @@ static void delude_send_reset(struct sk_buff *oldskb, unsigned int hook)
|
||||
kfree_skb(nskb);
|
||||
}
|
||||
|
||||
static unsigned int delude_tg(struct sk_buff *skb, const struct net_device *in,
|
||||
const struct net_device *out, unsigned int hooknum,
|
||||
const struct xt_target *target, const void *targinfo)
|
||||
static unsigned int
|
||||
delude_tg(struct sk_buff **pskb, const struct xt_target_param *par)
|
||||
{
|
||||
/* WARNING: This code causes reentry within iptables.
|
||||
This means that the iptables jump stack is now crap. We
|
||||
must return an absolute verdict. --RR */
|
||||
delude_send_reset(skb, hooknum);
|
||||
delude_send_reset(*pskb, par->hooknum);
|
||||
return NF_DROP;
|
||||
}
|
||||
|
||||
static struct xt_target delude_tg_reg __read_mostly = {
|
||||
.name = "DELUDE",
|
||||
.revision = 0,
|
||||
.family = AF_INET,
|
||||
.family = NFPROTO_IPV4,
|
||||
.table = "filter",
|
||||
.hooks = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD),
|
||||
.proto = IPPROTO_TCP,
|
||||
|
173
extensions/xt_DHCPADDR.c
Normal file
173
extensions/xt_DHCPADDR.c
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* "DHCPADDR" extensions for Xtables
|
||||
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
* version 2 of the License, or any later version, as published by the
|
||||
* Free Software Foundation.
|
||||
*/
|
||||
#include <linux/ip.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/udp.h>
|
||||
#include <net/ip.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include "xt_DHCPADDR.h"
|
||||
#include "compat_xtables.h"
|
||||
|
||||
struct dhcp_message {
|
||||
uint8_t op, htype, hlen, hops;
|
||||
__be32 xid;
|
||||
__be16 secs, flags;
|
||||
__be32 ciaddr, yiaddr, siaddr, giaddr;
|
||||
char chaddr[16];
|
||||
/* Omitting all unneeded fields saves runtime memory */
|
||||
/* char sname[64], file[128]; */
|
||||
};
|
||||
|
||||
static void ether_set(unsigned char *addr, const unsigned char *op,
|
||||
uint8_t mask)
|
||||
{
|
||||
uint8_t lo_mask;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ETH_ALEN && mask > 0; ++i) {
|
||||
lo_mask = mask % 8;
|
||||
/* FF << 4 >> 4 = 0F */
|
||||
lo_mask = ~(uint8_t)0U << lo_mask >> lo_mask;
|
||||
addr[i] &= lo_mask;
|
||||
addr[i] |= op[i] & ~lo_mask;
|
||||
if (mask >= 8)
|
||||
mask -= 8;
|
||||
else
|
||||
mask = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ether_cmp(const unsigned char *lh, const unsigned char *rh,
|
||||
uint8_t mask)
|
||||
{
|
||||
uint8_t lo_mask;
|
||||
unsigned int i;
|
||||
#define ZMAC_FMT "%02X:%02X:%02X:%02X:%02X:%02X"
|
||||
#define ZMACHEX(s) s[0], s[1], s[2], s[3], s[4], s[5]
|
||||
|
||||
for (i = 0; i < ETH_ALEN && mask > 0; ++i) {
|
||||
lo_mask = mask % 8;
|
||||
/* ~(0xFF << 4 >> 4) = ~0x0F = 0xF0 */
|
||||
lo_mask = ~(~(uint8_t)0U << lo_mask >> lo_mask);
|
||||
if ((lh[i] ^ rh[i]) & lo_mask)
|
||||
return false;
|
||||
if (mask >= 8)
|
||||
mask -= 8;
|
||||
else
|
||||
mask = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
dhcpaddr_mt(const struct sk_buff *skb, const struct xt_match_param *par)
|
||||
{
|
||||
const struct dhcpaddr_info *info = par->matchinfo;
|
||||
const struct dhcp_message *dh;
|
||||
struct dhcp_message dhcpbuf;
|
||||
|
||||
dh = skb_header_pointer(skb, par->thoff + sizeof(struct udphdr),
|
||||
sizeof(dhcpbuf), &dhcpbuf);
|
||||
if (dh == NULL)
|
||||
/*
|
||||
* No hotdrop. This packet does not look like DHCP, but other
|
||||
* matches may still have a valid reason to get their chance
|
||||
* to match on this.
|
||||
*/
|
||||
return false;
|
||||
|
||||
return ether_cmp((const void *)dh->chaddr, info->addr, info->mask);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
dhcpaddr_tg(struct sk_buff **pskb, const struct xt_target_param *par)
|
||||
{
|
||||
const struct dhcpaddr_info *info = par->targinfo;
|
||||
struct dhcp_message dhcpbuf, *dh;
|
||||
struct udphdr udpbuf, *udph;
|
||||
struct sk_buff *skb = *pskb;
|
||||
unsigned int i;
|
||||
|
||||
if (!skb_make_writable(pskb, 0))
|
||||
return NF_DROP;
|
||||
|
||||
udph = skb_header_pointer(skb, ip_hdrlen(skb),
|
||||
sizeof(udpbuf), &udpbuf);
|
||||
if (udph == NULL)
|
||||
return NF_DROP;
|
||||
|
||||
dh = skb_header_pointer(skb, ip_hdrlen(skb) + sizeof(udpbuf),
|
||||
sizeof(dhcpbuf), &dhcpbuf);
|
||||
if (dh == NULL)
|
||||
return NF_DROP;
|
||||
|
||||
for (i = 0; i < sizeof(dh->chaddr); i += 2)
|
||||
csum_replace2(&udph->check, *(const __be16 *)dh->chaddr, 0);
|
||||
|
||||
memset(dh->chaddr, 0, sizeof(dh->chaddr));
|
||||
ether_set(dh->chaddr, info->addr, info->mask);
|
||||
|
||||
for (i = 0; i < sizeof(dh->chaddr); i += 2)
|
||||
csum_replace2(&udph->check, 0, *(const __be16 *)dh->chaddr);
|
||||
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
|
||||
static struct xt_target dhcpaddr_tg_reg __read_mostly = {
|
||||
.name = "DHCPADDR",
|
||||
.revision = 0,
|
||||
.family = NFPROTO_IPV4,
|
||||
.proto = IPPROTO_UDP,
|
||||
.table = "mangle",
|
||||
.target = dhcpaddr_tg,
|
||||
.targetsize = XT_ALIGN(sizeof(struct dhcpaddr_info)),
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static struct xt_match dhcpaddr_mt_reg __read_mostly = {
|
||||
.name = "dhcpaddr",
|
||||
.revision = 0,
|
||||
.family = NFPROTO_IPV4,
|
||||
.proto = IPPROTO_UDP,
|
||||
.match = dhcpaddr_mt,
|
||||
.matchsize = XT_ALIGN(sizeof(struct dhcpaddr_info)),
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init dhcpaddr_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = xt_register_target(&dhcpaddr_tg_reg);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
ret = xt_register_match(&dhcpaddr_mt_reg);
|
||||
if (ret != 0) {
|
||||
xt_unregister_target(&dhcpaddr_tg_reg);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit dhcpaddr_exit(void)
|
||||
{
|
||||
xt_unregister_target(&dhcpaddr_tg_reg);
|
||||
xt_unregister_match(&dhcpaddr_mt_reg);
|
||||
}
|
||||
|
||||
module_init(dhcpaddr_init);
|
||||
module_exit(dhcpaddr_exit);
|
||||
MODULE_DESCRIPTION("Xtables: Clamp DHCP MAC to packet MAC addresses");
|
||||
MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("ipt_DHCPADDR");
|
||||
MODULE_ALIAS("ipt_dhcpaddr");
|
12
extensions/xt_DHCPADDR.h
Normal file
12
extensions/xt_DHCPADDR.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef _LINUX_NETFILTER_XT_DHCPADDR_H
|
||||
#define _LINUX_NETFILTER_XT_DHCPADDR_H 1
|
||||
|
||||
#define DH_MAC_FMT "%02X:%02X:%02X:%02X:%02X:%02X"
|
||||
#define DH_MAC_HEX(z) z[0], z[1], z[2], z[3], z[4], z[5]
|
||||
|
||||
struct dhcpaddr_info {
|
||||
unsigned char addr[ETH_ALEN];
|
||||
uint8_t mask, invert;
|
||||
};
|
||||
|
||||
#endif /* _LINUX_NETFILTER_XT_DHCPADDR_H */
|
@@ -1,11 +1,14 @@
|
||||
/*
|
||||
* ECHO target (RFC 862)
|
||||
* Copyright © CC Computer Consultants GmbH, 2008
|
||||
* "ECHO" (RFC 862) target extension for Xtables
|
||||
* Sample module for "Writing your own Netfilter Modules"
|
||||
* Copyright © Jan Engelhardt <jengelh [at] medozas de>, 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 or 3 as published by the Free Software Foundation.
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
* version 2 of the License, or any later version, as published by the
|
||||
* Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/ip.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/skbuff.h>
|
||||
@@ -17,10 +20,10 @@
|
||||
#include <net/ip.h>
|
||||
#include "compat_xtables.h"
|
||||
|
||||
static unsigned int echo_tg4(struct sk_buff *oldskb,
|
||||
const struct net_device *in, const struct net_device *out,
|
||||
unsigned int hooknum, const struct xt_target *target, const void *targinfo)
|
||||
static unsigned int
|
||||
echo_tg4(struct sk_buff **poldskb, const struct xt_target_param *par)
|
||||
{
|
||||
const struct sk_buff *oldskb = *poldskb;
|
||||
const struct udphdr *oldudp;
|
||||
const struct iphdr *oldip;
|
||||
struct udphdr *newudp, oldudp_buf;
|
||||
@@ -29,8 +32,10 @@ static unsigned int echo_tg4(struct sk_buff *oldskb,
|
||||
unsigned int addr_type, data_len;
|
||||
void *payload;
|
||||
|
||||
printk(KERN_INFO "dst_out=%p\n", (*poldskb)->dst->output);
|
||||
|
||||
/* This allows us to do the copy operation in fewer lines of code. */
|
||||
if (skb_linearize(oldskb) < 0)
|
||||
if (skb_linearize(*poldskb) < 0)
|
||||
return NF_DROP;
|
||||
|
||||
oldip = ip_hdr(oldskb);
|
||||
@@ -72,10 +77,10 @@ static unsigned int echo_tg4(struct sk_buff *oldskb,
|
||||
|
||||
addr_type = RTN_UNSPEC;
|
||||
#ifdef CONFIG_BRIDGE_NETFILTER
|
||||
if (hooknum != NF_INET_FORWARD || (newskb->nf_bridge != NULL &&
|
||||
if (par->hooknum != NF_INET_FORWARD || (newskb->nf_bridge != NULL &&
|
||||
newskb->nf_bridge->mask & BRNF_BRIDGED))
|
||||
#else
|
||||
if (hooknum != NF_INET_FORWARD)
|
||||
if (par->hooknum != NF_INET_FORWARD)
|
||||
#endif
|
||||
addr_type = RTN_LOCAL;
|
||||
|
||||
@@ -83,7 +88,7 @@ static unsigned int echo_tg4(struct sk_buff *oldskb,
|
||||
dst_hold(oldskb->dst);
|
||||
newskb->dst = oldskb->dst;
|
||||
|
||||
if (ip_route_me_harder(newskb, addr_type) < 0)
|
||||
if (ip_route_me_harder(&newskb, addr_type) < 0)
|
||||
goto free_nskb;
|
||||
|
||||
newip->ttl = dst_metric(newskb->dst, RTAX_HOPLIMIT);
|
||||
@@ -93,7 +98,7 @@ static unsigned int echo_tg4(struct sk_buff *oldskb,
|
||||
if (newskb->len > dst_mtu(newskb->dst))
|
||||
goto free_nskb;
|
||||
|
||||
nf_ct_attach(newskb, oldskb);
|
||||
nf_ct_attach(newskb, *poldskb);
|
||||
ip_local_out(newskb);
|
||||
return NF_DROP;
|
||||
|
||||
@@ -105,7 +110,7 @@ static unsigned int echo_tg4(struct sk_buff *oldskb,
|
||||
static struct xt_target echo_tg_reg __read_mostly = {
|
||||
.name = "ECHO",
|
||||
.revision = 0,
|
||||
.family = AF_INET,
|
||||
.family = NFPROTO_IPV4,
|
||||
.proto = IPPROTO_UDP,
|
||||
.table = "filter",
|
||||
.target = echo_tg4,
|
||||
@@ -125,7 +130,7 @@ static void __exit echo_tg_exit(void)
|
||||
|
||||
module_init(echo_tg_init);
|
||||
module_exit(echo_tg_exit);
|
||||
MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>");
|
||||
MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
|
||||
MODULE_DESCRIPTION("Xtables: ECHO diagnosis target");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("ipt_ECHO");
|
||||
|
@@ -1,3 +1,13 @@
|
||||
/*
|
||||
* "IPMARK" target extension for Xtables
|
||||
* Copyright © Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>, 2003
|
||||
* Jan Engelhardt <jengelh [at] medozas de>, 2008
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License; either
|
||||
* version 2 of the License, or any later version, as published by the
|
||||
* Free Software Foundation.
|
||||
*/
|
||||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/module.h>
|
||||
@@ -15,11 +25,10 @@ MODULE_ALIAS("ipt_IPMARK");
|
||||
MODULE_ALIAS("ip6t_IPMARK");
|
||||
|
||||
static unsigned int
|
||||
ipmark_tg4(struct sk_buff *skb, const struct net_device *in,
|
||||
const struct net_device *out, unsigned int hooknum,
|
||||
const struct xt_target *target, const void *targinfo)
|
||||
ipmark_tg4(struct sk_buff **pskb, const struct xt_target_param *par)
|
||||
{
|
||||
const struct xt_ipmark_tginfo *ipmarkinfo = targinfo;
|
||||
const struct xt_ipmark_tginfo *ipmarkinfo = par->targinfo;
|
||||
const struct sk_buff *skb = *pskb;
|
||||
const struct iphdr *iph = ip_hdr(skb);
|
||||
__u32 mark;
|
||||
|
||||
@@ -52,11 +61,10 @@ static __u32 ipmark_from_ip6(const struct in6_addr *a, unsigned int s)
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
ipmark_tg6(struct sk_buff *skb, const struct net_device *in,
|
||||
const struct net_device *out, unsigned int hooknum,
|
||||
const struct xt_target *target, const void *targinfo)
|
||||
ipmark_tg6(struct sk_buff **pskb, const struct xt_target_param *par)
|
||||
{
|
||||
const struct xt_ipmark_tginfo *info = targinfo;
|
||||
const struct xt_ipmark_tginfo *info = par->targinfo;
|
||||
const struct sk_buff *skb = *pskb;
|
||||
const struct ipv6hdr *iph = ipv6_hdr(skb);
|
||||
__u32 mark;
|
||||
|
||||
@@ -75,7 +83,7 @@ static struct xt_target ipmark_tg_reg[] __read_mostly = {
|
||||
{
|
||||
.name = "IPMARK",
|
||||
.revision = 0,
|
||||
.family = PF_INET,
|
||||
.family = NFPROTO_IPV4,
|
||||
.table = "mangle",
|
||||
.target = ipmark_tg4,
|
||||
.targetsize = XT_ALIGN(sizeof(struct xt_ipmark_tginfo)),
|
||||
@@ -84,7 +92,7 @@ static struct xt_target ipmark_tg_reg[] __read_mostly = {
|
||||
{
|
||||
.name = "IPMARK",
|
||||
.revision = 0,
|
||||
.family = PF_INET6,
|
||||
.family = NFPROTO_IPV6,
|
||||
.table = "mangle",
|
||||
.target = ipmark_tg6,
|
||||
.targetsize = XT_ALIGN(sizeof(struct xt_ipmark_tginfo)),
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user