mirror of
https://github.com/Waujito/youtubeUnblock.git
synced 2025-12-06 03:26:45 +03:00
Specify dependencies libs explicitly.
Such setup is better for cross compilation. Also changed Makefile to properly make the project with these libraries.
This commit is contained in:
61
Makefile
61
Makefile
@@ -1,12 +1,10 @@
|
|||||||
|
BUILD_DIR := $(CURDIR)/build
|
||||||
|
DEPSDIR := $(BUILD_DIR)/deps
|
||||||
|
|
||||||
CC := gcc
|
CC := gcc
|
||||||
CC_FLAGS:=-Wall -Wpedantic -Wno-unused-variable
|
LD := gcc
|
||||||
|
CFLAGS:=-Wall -Wpedantic -Wno-unused-variable -I$(DEPSDIR)/include -Os
|
||||||
LD_FLAGS:=-lmnl -lnetfilter_queue
|
LDFLAGS:=-L$(DEPSDIR)/lib -static
|
||||||
BUILD_DIR:=build
|
|
||||||
APP:=$(BUILD_DIR)/youtubeUnblock
|
|
||||||
|
|
||||||
SRCS := youtubeUnblock.c
|
|
||||||
OBJS := $(SRCS:%.c=$(BUILD_DIR)/%.o)
|
|
||||||
|
|
||||||
# PREFIX is environment variable, if not set default to /usr/local
|
# PREFIX is environment variable, if not set default to /usr/local
|
||||||
ifeq ($(PREFIX),)
|
ifeq ($(PREFIX),)
|
||||||
@@ -15,46 +13,73 @@ else
|
|||||||
PREFIX := $(DESTDIR)
|
PREFIX := $(DESTDIR)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
export CC LD CFLAGS LDFLAGS
|
||||||
|
|
||||||
|
APP:=$(BUILD_DIR)/youtubeUnblock
|
||||||
|
|
||||||
|
SRCS := youtubeUnblock.c
|
||||||
|
OBJS := $(SRCS:%.c=$(BUILD_DIR)/%.o)
|
||||||
|
|
||||||
|
LIBNFNETLINK := $(DEPSDIR)/lib/libnfnetlink.a
|
||||||
|
LIBMNL := $(DEPSDIR)/lib/libmnl.a
|
||||||
|
LIBNETFILTER_QUEUE := $(DEPSDIR)/lib/libnetfilter_queue.a
|
||||||
|
|
||||||
|
|
||||||
.PHONY: default all dev dev_attrs prepare_dirs
|
.PHONY: default all dev dev_attrs prepare_dirs
|
||||||
default: all
|
default: all
|
||||||
|
|
||||||
|
|
||||||
run_dev: dev
|
run_dev: dev
|
||||||
bash -c "sudo ./$(APP) 537"
|
bash -c "sudo ./$(APP) 537"
|
||||||
|
|
||||||
|
|
||||||
dev: dev_attrs all
|
dev: dev_attrs all
|
||||||
|
|
||||||
dev_attrs:
|
dev_attrs:
|
||||||
$(eval CC_FLAGS := $(CC_FLAGS) -DDEBUG -ggdb -g3)
|
$(eval CFLAGS := $(CFLAGS) -DDEBUG -ggdb -g3)
|
||||||
|
|
||||||
all: prepare_dirs $(APP)
|
all: prepare_dirs $(APP)
|
||||||
|
|
||||||
|
|
||||||
prepare_dirs:
|
prepare_dirs:
|
||||||
mkdir -p $(BUILD_DIR)
|
mkdir -p $(BUILD_DIR)
|
||||||
|
mkdir -p $(DEPSDIR)
|
||||||
|
|
||||||
$(APP): $(OBJS)
|
$(LIBNFNETLINK):
|
||||||
|
cd deps/libnfnetlink && ./autogen.sh && ./configure --prefix=$(DEPSDIR)
|
||||||
|
$(MAKE) -C deps/libnfnetlink
|
||||||
|
$(MAKE) install -C deps/libnfnetlink
|
||||||
|
|
||||||
|
$(LIBMNL):
|
||||||
|
cd deps/libmnl && ./autogen.sh && ./configure --prefix=$(DEPSDIR)
|
||||||
|
$(MAKE) -C deps/libmnl
|
||||||
|
$(MAKE) install -C deps/libmnl
|
||||||
|
|
||||||
|
$(LIBNETFILTER_QUEUE): $(LIBNFNETLINK) $(LIBMNL)
|
||||||
|
cd deps/libnetfilter_queue && ./autogen.sh && ./configure --prefix=$(DEPSDIR)
|
||||||
|
$(MAKE) -C deps/libnetfilter_queue
|
||||||
|
$(MAKE) install -C deps/libnetfilter_queue
|
||||||
|
|
||||||
|
$(APP): $(OBJS) $(LIBNETFILTER_QUEUE) $(LIBMNL)
|
||||||
@echo 'LD $(APP)'
|
@echo 'LD $(APP)'
|
||||||
@$(CC) $(OBJS) -o $(APP) $(LD_FLAGS)
|
@$(LD) $(OBJS) -o $(APP) -L$(DEPSDIR)/lib -lmnl -lnetfilter_queue
|
||||||
|
|
||||||
$(BUILD_DIR)/%.o: %.c
|
$(BUILD_DIR)/%.o: %.c $(LIBNETFILTER_QUEUE) $(LIBMNL)
|
||||||
@echo 'CC $@'
|
@echo 'CC $@'
|
||||||
@$(CC) -c $(CC_FLAGS) $^ -o $@
|
@$(CC) -c $(CFLAGS) $^ -o $@
|
||||||
|
|
||||||
install: all
|
install: all
|
||||||
install -d $(PREFIX)/bin/
|
install -d $(PREFIX)/bin/
|
||||||
install -m 755 $(APP) $(PREFIX)/bin/
|
install -m 755 $(APP) $(PREFIX)/bin/
|
||||||
install -d $(PREFIX)/lib/systemd/system/
|
install -d $(PREFIX)/lib/systemd/system/
|
||||||
|
|
||||||
@cp youtubeUnblock.service $(BUILD_DIR)
|
@cp youtubeUnblock.service $(BUILD_DIR)
|
||||||
@sed -i 's/$$(PREFIX)/$(subst /,\/,$(PREFIX))/g' $(BUILD_DIR)/youtubeUnblock.service
|
@sed -i 's/$$(PREFIX)/$(subst /,\/,$(PREFIX))/g' $(BUILD_DIR)/youtubeUnblock.service
|
||||||
install -m 644 $(BUILD_DIR)/youtubeUnblock.service $(PREFIX)/lib/systemd/system/
|
install -m 644 $(BUILD_DIR)/youtubeUnblock.service $(PREFIX)/lib/systemd/system/
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
rm $(PREFIX)/bin/youtubeUnblock
|
rm $(PREFIX)/bin/youtubeUnblock
|
||||||
systemctl disable youtubeUnblock.service
|
|
||||||
rm $(PREFIX)/lib/systemd/system/youtubeUnblock.service
|
rm $(PREFIX)/lib/systemd/system/youtubeUnblock.service
|
||||||
|
systemctl disable youtubeUnblock.service
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(BUILD_DIR)
|
rm -rf $(BUILD_DIR)
|
||||||
|
$(MAKE) distclean -C deps/libnetfilter_queue || true
|
||||||
|
$(MAKE) distclean -C deps/libmnl || true
|
||||||
|
$(MAKE) distclean -C deps/libnfnetlink || true
|
||||||
|
|||||||
20
deps/libmnl/.gitignore
vendored
Normal file
20
deps/libmnl/.gitignore
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
*~
|
||||||
|
*.la
|
||||||
|
*.lo
|
||||||
|
*.o
|
||||||
|
.deps/
|
||||||
|
.libs/
|
||||||
|
Makefile
|
||||||
|
Makefile.in
|
||||||
|
|
||||||
|
/aclocal.m4
|
||||||
|
/autom4te.cache/
|
||||||
|
/build-aux/
|
||||||
|
/config.*
|
||||||
|
/configure
|
||||||
|
/libtool
|
||||||
|
/stamp-h1
|
||||||
|
|
||||||
|
/libmnl.pc
|
||||||
|
|
||||||
|
/libmnl-*.tar.bz2
|
||||||
502
deps/libmnl/COPYING
vendored
Normal file
502
deps/libmnl/COPYING
vendored
Normal file
@@ -0,0 +1,502 @@
|
|||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 2.1, February 1999
|
||||||
|
|
||||||
|
Copyright (C) 1991, 1999 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.
|
||||||
|
|
||||||
|
[This is the first released version of the Lesser GPL. It also counts
|
||||||
|
as the successor of the GNU Library Public License, version 2, hence
|
||||||
|
the version number 2.1.]
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
Licenses are intended to guarantee your freedom to share and change
|
||||||
|
free software--to make sure the software is free for all its users.
|
||||||
|
|
||||||
|
This license, the Lesser General Public License, applies to some
|
||||||
|
specially designated software packages--typically libraries--of the
|
||||||
|
Free Software Foundation and other authors who decide to use it. You
|
||||||
|
can use it too, but we suggest you first think carefully about whether
|
||||||
|
this license or the ordinary General Public License is the better
|
||||||
|
strategy to use in any particular case, based on the explanations below.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom of use,
|
||||||
|
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 and use pieces of
|
||||||
|
it in new free programs; and that you are informed that you can do
|
||||||
|
these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
distributors to deny you these rights or to ask you to surrender these
|
||||||
|
rights. These restrictions translate to certain responsibilities for
|
||||||
|
you if you distribute copies of the library or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of the library, whether gratis
|
||||||
|
or for a fee, you must give the recipients all the rights that we gave
|
||||||
|
you. You must make sure that they, too, receive or can get the source
|
||||||
|
code. If you link other code with the library, you must provide
|
||||||
|
complete object files to the recipients, so that they can relink them
|
||||||
|
with the library after making changes to the library and recompiling
|
||||||
|
it. And you must show them these terms so they know their rights.
|
||||||
|
|
||||||
|
We protect your rights with a two-step method: (1) we copyright the
|
||||||
|
library, and (2) we offer you this license, which gives you legal
|
||||||
|
permission to copy, distribute and/or modify the library.
|
||||||
|
|
||||||
|
To protect each distributor, we want to make it very clear that
|
||||||
|
there is no warranty for the free library. Also, if the library is
|
||||||
|
modified by someone else and passed on, the recipients should know
|
||||||
|
that what they have is not the original version, so that the original
|
||||||
|
author's reputation will not be affected by problems that might be
|
||||||
|
introduced by others.
|
||||||
|
|
||||||
|
Finally, software patents pose a constant threat to the existence of
|
||||||
|
any free program. We wish to make sure that a company cannot
|
||||||
|
effectively restrict the users of a free program by obtaining a
|
||||||
|
restrictive license from a patent holder. Therefore, we insist that
|
||||||
|
any patent license obtained for a version of the library must be
|
||||||
|
consistent with the full freedom of use specified in this license.
|
||||||
|
|
||||||
|
Most GNU software, including some libraries, is covered by the
|
||||||
|
ordinary GNU General Public License. This license, the GNU Lesser
|
||||||
|
General Public License, applies to certain designated libraries, and
|
||||||
|
is quite different from the ordinary General Public License. We use
|
||||||
|
this license for certain libraries in order to permit linking those
|
||||||
|
libraries into non-free programs.
|
||||||
|
|
||||||
|
When a program is linked with a library, whether statically or using
|
||||||
|
a shared library, the combination of the two is legally speaking a
|
||||||
|
combined work, a derivative of the original library. The ordinary
|
||||||
|
General Public License therefore permits such linking only if the
|
||||||
|
entire combination fits its criteria of freedom. The Lesser General
|
||||||
|
Public License permits more lax criteria for linking other code with
|
||||||
|
the library.
|
||||||
|
|
||||||
|
We call this license the "Lesser" General Public License because it
|
||||||
|
does Less to protect the user's freedom than the ordinary General
|
||||||
|
Public License. It also provides other free software developers Less
|
||||||
|
of an advantage over competing non-free programs. These disadvantages
|
||||||
|
are the reason we use the ordinary General Public License for many
|
||||||
|
libraries. However, the Lesser license provides advantages in certain
|
||||||
|
special circumstances.
|
||||||
|
|
||||||
|
For example, on rare occasions, there may be a special need to
|
||||||
|
encourage the widest possible use of a certain library, so that it becomes
|
||||||
|
a de-facto standard. To achieve this, non-free programs must be
|
||||||
|
allowed to use the library. A more frequent case is that a free
|
||||||
|
library does the same job as widely used non-free libraries. In this
|
||||||
|
case, there is little to gain by limiting the free library to free
|
||||||
|
software only, so we use the Lesser General Public License.
|
||||||
|
|
||||||
|
In other cases, permission to use a particular library in non-free
|
||||||
|
programs enables a greater number of people to use a large body of
|
||||||
|
free software. For example, permission to use the GNU C Library in
|
||||||
|
non-free programs enables many more people to use the whole GNU
|
||||||
|
operating system, as well as its variant, the GNU/Linux operating
|
||||||
|
system.
|
||||||
|
|
||||||
|
Although the Lesser General Public License is Less protective of the
|
||||||
|
users' freedom, it does ensure that the user of a program that is
|
||||||
|
linked with the Library has the freedom and the wherewithal to run
|
||||||
|
that program using a modified version of the Library.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow. Pay close attention to the difference between a
|
||||||
|
"work based on the library" and a "work that uses the library". The
|
||||||
|
former contains code derived from the library, whereas the latter must
|
||||||
|
be combined with the library in order to run.
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License Agreement applies to any software library or other
|
||||||
|
program which contains a notice placed by the copyright holder or
|
||||||
|
other authorized party saying it may be distributed under the terms of
|
||||||
|
this Lesser General Public License (also called "this License").
|
||||||
|
Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
A "library" means a collection of software functions and/or data
|
||||||
|
prepared so as to be conveniently linked with application programs
|
||||||
|
(which use some of those functions and data) to form executables.
|
||||||
|
|
||||||
|
The "Library", below, refers to any such software library or work
|
||||||
|
which has been distributed under these terms. A "work based on the
|
||||||
|
Library" means either the Library or any derivative work under
|
||||||
|
copyright law: that is to say, a work containing the Library or a
|
||||||
|
portion of it, either verbatim or with modifications and/or translated
|
||||||
|
straightforwardly into another language. (Hereinafter, translation is
|
||||||
|
included without limitation in the term "modification".)
|
||||||
|
|
||||||
|
"Source code" for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For a library, 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 library.
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running a program using the Library is not restricted, and output from
|
||||||
|
such a program is covered only if its contents constitute a work based
|
||||||
|
on the Library (independent of the use of the Library in a tool for
|
||||||
|
writing it). Whether that is true depends on what the Library does
|
||||||
|
and what the program that uses the Library does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Library's
|
||||||
|
complete 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 distribute a copy of this License along with the
|
||||||
|
Library.
|
||||||
|
|
||||||
|
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 Library or any portion
|
||||||
|
of it, thus forming a work based on the Library, 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) The modified work must itself be a software library.
|
||||||
|
|
||||||
|
b) You must cause the files modified to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
c) You must cause the whole of the work to be licensed at no
|
||||||
|
charge to all third parties under the terms of this License.
|
||||||
|
|
||||||
|
d) If a facility in the modified Library refers to a function or a
|
||||||
|
table of data to be supplied by an application program that uses
|
||||||
|
the facility, other than as an argument passed when the facility
|
||||||
|
is invoked, then you must make a good faith effort to ensure that,
|
||||||
|
in the event an application does not supply such function or
|
||||||
|
table, the facility still operates, and performs whatever part of
|
||||||
|
its purpose remains meaningful.
|
||||||
|
|
||||||
|
(For example, a function in a library to compute square roots has
|
||||||
|
a purpose that is entirely well-defined independent of the
|
||||||
|
application. Therefore, Subsection 2d requires that any
|
||||||
|
application-supplied function or table used by this function must
|
||||||
|
be optional: if the application does not supply it, the square
|
||||||
|
root function must still compute square roots.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Library,
|
||||||
|
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 Library, 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 Library.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Library
|
||||||
|
with the Library (or with a work based on the Library) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||||
|
License instead of this License to a given copy of the Library. To do
|
||||||
|
this, you must alter all the notices that refer to this License, so
|
||||||
|
that they refer to the ordinary GNU General Public License, version 2,
|
||||||
|
instead of to this License. (If a newer version than version 2 of the
|
||||||
|
ordinary GNU General Public License has appeared, then you can specify
|
||||||
|
that version instead if you wish.) Do not make any other change in
|
||||||
|
these notices.
|
||||||
|
|
||||||
|
Once this change is made in a given copy, it is irreversible for
|
||||||
|
that copy, so the ordinary GNU General Public License applies to all
|
||||||
|
subsequent copies and derivative works made from that copy.
|
||||||
|
|
||||||
|
This option is useful when you wish to copy part of the code of
|
||||||
|
the Library into a program that is not a library.
|
||||||
|
|
||||||
|
4. You may copy and distribute the Library (or a portion or
|
||||||
|
derivative of it, under Section 2) in object code or executable form
|
||||||
|
under the terms of Sections 1 and 2 above provided that you 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.
|
||||||
|
|
||||||
|
If distribution of 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 satisfies the requirement to
|
||||||
|
distribute the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
5. A program that contains no derivative of any portion of the
|
||||||
|
Library, but is designed to work with the Library by being compiled or
|
||||||
|
linked with it, is called a "work that uses the Library". Such a
|
||||||
|
work, in isolation, is not a derivative work of the Library, and
|
||||||
|
therefore falls outside the scope of this License.
|
||||||
|
|
||||||
|
However, linking a "work that uses the Library" with the Library
|
||||||
|
creates an executable that is a derivative of the Library (because it
|
||||||
|
contains portions of the Library), rather than a "work that uses the
|
||||||
|
library". The executable is therefore covered by this License.
|
||||||
|
Section 6 states terms for distribution of such executables.
|
||||||
|
|
||||||
|
When a "work that uses the Library" uses material from a header file
|
||||||
|
that is part of the Library, the object code for the work may be a
|
||||||
|
derivative work of the Library even though the source code is not.
|
||||||
|
Whether this is true is especially significant if the work can be
|
||||||
|
linked without the Library, or if the work is itself a library. The
|
||||||
|
threshold for this to be true is not precisely defined by law.
|
||||||
|
|
||||||
|
If such an object file uses only numerical parameters, data
|
||||||
|
structure layouts and accessors, and small macros and small inline
|
||||||
|
functions (ten lines or less in length), then the use of the object
|
||||||
|
file is unrestricted, regardless of whether it is legally a derivative
|
||||||
|
work. (Executables containing this object code plus portions of the
|
||||||
|
Library will still fall under Section 6.)
|
||||||
|
|
||||||
|
Otherwise, if the work is a derivative of the Library, you may
|
||||||
|
distribute the object code for the work under the terms of Section 6.
|
||||||
|
Any executables containing that work also fall under Section 6,
|
||||||
|
whether or not they are linked directly with the Library itself.
|
||||||
|
|
||||||
|
6. As an exception to the Sections above, you may also combine or
|
||||||
|
link a "work that uses the Library" with the Library to produce a
|
||||||
|
work containing portions of the Library, and distribute that work
|
||||||
|
under terms of your choice, provided that the terms permit
|
||||||
|
modification of the work for the customer's own use and reverse
|
||||||
|
engineering for debugging such modifications.
|
||||||
|
|
||||||
|
You must give prominent notice with each copy of the work that the
|
||||||
|
Library is used in it and that the Library and its use are covered by
|
||||||
|
this License. You must supply a copy of this License. If the work
|
||||||
|
during execution displays copyright notices, you must include the
|
||||||
|
copyright notice for the Library among them, as well as a reference
|
||||||
|
directing the user to the copy of this License. Also, you must do one
|
||||||
|
of these things:
|
||||||
|
|
||||||
|
a) Accompany the work with the complete corresponding
|
||||||
|
machine-readable source code for the Library including whatever
|
||||||
|
changes were used in the work (which must be distributed under
|
||||||
|
Sections 1 and 2 above); and, if the work is an executable linked
|
||||||
|
with the Library, with the complete machine-readable "work that
|
||||||
|
uses the Library", as object code and/or source code, so that the
|
||||||
|
user can modify the Library and then relink to produce a modified
|
||||||
|
executable containing the modified Library. (It is understood
|
||||||
|
that the user who changes the contents of definitions files in the
|
||||||
|
Library will not necessarily be able to recompile the application
|
||||||
|
to use the modified definitions.)
|
||||||
|
|
||||||
|
b) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (1) uses at run time a
|
||||||
|
copy of the library already present on the user's computer system,
|
||||||
|
rather than copying library functions into the executable, and (2)
|
||||||
|
will operate properly with a modified version of the library, if
|
||||||
|
the user installs one, as long as the modified version is
|
||||||
|
interface-compatible with the version that the work was made with.
|
||||||
|
|
||||||
|
c) Accompany the work with a written offer, valid for at
|
||||||
|
least three years, to give the same user the materials
|
||||||
|
specified in Subsection 6a, above, for a charge no more
|
||||||
|
than the cost of performing this distribution.
|
||||||
|
|
||||||
|
d) If distribution of the work is made by offering access to copy
|
||||||
|
from a designated place, offer equivalent access to copy the above
|
||||||
|
specified materials from the same place.
|
||||||
|
|
||||||
|
e) Verify that the user has already received a copy of these
|
||||||
|
materials or that you have already sent this user a copy.
|
||||||
|
|
||||||
|
For an executable, the required form of the "work that uses the
|
||||||
|
Library" must include any data and utility programs needed for
|
||||||
|
reproducing the executable from it. However, as a special exception,
|
||||||
|
the materials to be 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.
|
||||||
|
|
||||||
|
It may happen that this requirement contradicts the license
|
||||||
|
restrictions of other proprietary libraries that do not normally
|
||||||
|
accompany the operating system. Such a contradiction means you cannot
|
||||||
|
use both them and the Library together in an executable that you
|
||||||
|
distribute.
|
||||||
|
|
||||||
|
7. You may place library facilities that are a work based on the
|
||||||
|
Library side-by-side in a single library together with other library
|
||||||
|
facilities not covered by this License, and distribute such a combined
|
||||||
|
library, provided that the separate distribution of the work based on
|
||||||
|
the Library and of the other library facilities is otherwise
|
||||||
|
permitted, and provided that you do these two things:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work
|
||||||
|
based on the Library, uncombined with any other library
|
||||||
|
facilities. This must be distributed under the terms of the
|
||||||
|
Sections above.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library of the fact
|
||||||
|
that part of it is a work based on the Library, and explaining
|
||||||
|
where to find the accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
8. You may not copy, modify, sublicense, link with, or distribute
|
||||||
|
the Library except as expressly provided under this License. Any
|
||||||
|
attempt otherwise to copy, modify, sublicense, link with, or
|
||||||
|
distribute the Library 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.
|
||||||
|
|
||||||
|
9. 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 Library or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Library (or any work based on the
|
||||||
|
Library), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Library or works based on it.
|
||||||
|
|
||||||
|
10. Each time you redistribute the Library (or any work based on the
|
||||||
|
Library), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute, link with or modify the Library
|
||||||
|
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 with
|
||||||
|
this License.
|
||||||
|
|
||||||
|
11. 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 Library at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Library 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 Library.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
12. If the distribution and/or use of the Library is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Library 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.
|
||||||
|
|
||||||
|
13. The Free Software Foundation may publish revised and/or new
|
||||||
|
versions of the Lesser 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 Library
|
||||||
|
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 Library does not specify a
|
||||||
|
license version number, you may choose any version ever published by
|
||||||
|
the Free Software Foundation.
|
||||||
|
|
||||||
|
14. If you wish to incorporate parts of the Library into other free
|
||||||
|
programs whose distribution conditions are incompatible with these,
|
||||||
|
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
|
||||||
|
|
||||||
|
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||||
|
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||||
|
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||||
|
OTHER PARTIES PROVIDE THE LIBRARY "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
|
||||||
|
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||||
|
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. 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 LIBRARY 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
|
||||||
|
LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries
|
||||||
|
|
||||||
|
If you develop a new library, and you want it to be of the greatest
|
||||||
|
possible use to the public, we recommend making it free software that
|
||||||
|
everyone can redistribute and change. You can do so by permitting
|
||||||
|
redistribution under these terms (or, alternatively, under the terms of the
|
||||||
|
ordinary General Public License).
|
||||||
|
|
||||||
|
To apply these terms, attach the following notices to the library. 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 library's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; 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.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||||
|
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1990
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
That's all there is to it!
|
||||||
24
deps/libmnl/Make_global.am
vendored
Normal file
24
deps/libmnl/Make_global.am
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# This is _NOT_ the library release version, it's an API version.
|
||||||
|
# Extracted from Chapter 6 "Library interface versions" of the libtool docs.
|
||||||
|
#
|
||||||
|
# <snippet>
|
||||||
|
# Here are a set of rules to help you update your library version information:
|
||||||
|
#
|
||||||
|
# 1. Start with version information of `0:0:0' for each libtool library.
|
||||||
|
# 2. Update the version information only immediately before a public release
|
||||||
|
# of your software. More frequent updates are unnecessary, and only guarantee
|
||||||
|
# that the current interface number gets larger faster.
|
||||||
|
# 3. If the library source code has changed at all since the last update,
|
||||||
|
# then increment revision (`c:r:a' becomes `c:r+1:a').
|
||||||
|
# 4. If any interfaces have been added, removed, or changed since the last
|
||||||
|
# update, increment current, and set revision to 0.
|
||||||
|
# 5. If any interfaces have been added since the last public release, then
|
||||||
|
# increment age.
|
||||||
|
# 6. If any interfaces have been removed since the last public release, then
|
||||||
|
# set age to 0.
|
||||||
|
# </snippet>
|
||||||
|
#
|
||||||
|
LIBVERSION=2:0:2
|
||||||
|
|
||||||
|
AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_srcdir}/include
|
||||||
|
AM_CFLAGS = ${regular_CFLAGS} ${GCC_FVISIBILITY_HIDDEN}
|
||||||
11
deps/libmnl/Makefile.am
vendored
Normal file
11
deps/libmnl/Makefile.am
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
include $(top_srcdir)/Make_global.am
|
||||||
|
|
||||||
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
|
|
||||||
|
SUBDIRS = src include examples doxygen
|
||||||
|
DIST_SUBDIRS = src include examples doxygen
|
||||||
|
|
||||||
|
pkgconfigdir = $(libdir)/pkgconfig
|
||||||
|
pkgconfig_DATA = libmnl.pc
|
||||||
|
|
||||||
|
${pkgconfig_DATA}: ${top_builddir}/config.status
|
||||||
28
deps/libmnl/README
vendored
Normal file
28
deps/libmnl/README
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
= What is libmnl? =
|
||||||
|
|
||||||
|
libmnl is a minimalistic user-space library oriented to Netlink developers.
|
||||||
|
There are a lot of common tasks in parsing, validating, constructing of
|
||||||
|
both the Netlink header and TLVs that are repetitive and easy to get wrong.
|
||||||
|
This library aims to provide simple helpers that allows you to re-use code
|
||||||
|
and to avoid re-inventing the wheel. The main features of this library are:
|
||||||
|
|
||||||
|
* Small: the shared library requires around 30KB for an x86-based computer.
|
||||||
|
* Simple: this library avoids complexity and elaborated abstractions that
|
||||||
|
tend to hide Netlink details.
|
||||||
|
* Easy to use: the library simplifies the work for Netlink-wise developers.
|
||||||
|
It provides functions to make socket handling, message building, validating,
|
||||||
|
parsing and sequence tracking, easier.
|
||||||
|
* Easy to re-use: you can use the library to build your own abstraction layer
|
||||||
|
on top of this library.
|
||||||
|
* Decoupling: the interdependency of the main bricks that compose the library
|
||||||
|
is reduced, i.e. the library provides many helpers, but the programmer is not
|
||||||
|
forced to use them.
|
||||||
|
|
||||||
|
= Example files =
|
||||||
|
|
||||||
|
You can find several example files under examples/ that you can compile by
|
||||||
|
invoking `make check'.
|
||||||
|
|
||||||
|
--
|
||||||
|
08/sep/2010
|
||||||
|
Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
4
deps/libmnl/autogen.sh
vendored
Executable file
4
deps/libmnl/autogen.sh
vendored
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
autoreconf -fi
|
||||||
|
rm -Rf autom4te.cache
|
||||||
70
deps/libmnl/configure.ac
vendored
Normal file
70
deps/libmnl/configure.ac
vendored
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
dnl Process this file with autoconf to create configure.
|
||||||
|
|
||||||
|
AC_INIT([libmnl], [1.0.5])
|
||||||
|
AC_CONFIG_AUX_DIR([build-aux])
|
||||||
|
AC_CANONICAL_HOST
|
||||||
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
|
AC_CONFIG_HEADERS([config.h])
|
||||||
|
AM_INIT_AUTOMAKE([foreign tar-pax no-dist-gzip dist-xz 1.6 subdir-objects])
|
||||||
|
|
||||||
|
dnl kernel style compile messages
|
||||||
|
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||||
|
|
||||||
|
AC_PROG_CC
|
||||||
|
AM_PROG_CC_C_O
|
||||||
|
AC_EXEEXT
|
||||||
|
AC_DISABLE_STATIC
|
||||||
|
LT_INIT
|
||||||
|
CHECK_GCC_FVISIBILITY
|
||||||
|
case "$host" in
|
||||||
|
*-*-linux* | *-*-uclinux*) ;;
|
||||||
|
*) AC_MSG_ERROR([Linux only, dude!]);;
|
||||||
|
esac
|
||||||
|
|
||||||
|
regular_CPPFLAGS="-D_FILE_OFFSET_BITS=64 -D_REENTRANT"
|
||||||
|
regular_CFLAGS="-Wall -Waggregate-return -Wmissing-declarations \
|
||||||
|
-Wmissing-prototypes -Wshadow -Wstrict-prototypes \
|
||||||
|
-Wformat=2 -pipe"
|
||||||
|
AC_SUBST([regular_CPPFLAGS])
|
||||||
|
AC_SUBST([regular_CFLAGS])
|
||||||
|
AC_CONFIG_FILES([Makefile
|
||||||
|
src/Makefile
|
||||||
|
include/Makefile
|
||||||
|
include/libmnl/Makefile
|
||||||
|
include/linux/Makefile
|
||||||
|
include/linux/can/Makefile
|
||||||
|
include/linux/netfilter/Makefile
|
||||||
|
examples/Makefile
|
||||||
|
examples/genl/Makefile
|
||||||
|
examples/kobject/Makefile
|
||||||
|
examples/netfilter/Makefile
|
||||||
|
examples/rtnl/Makefile
|
||||||
|
libmnl.pc
|
||||||
|
doxygen/doxygen.cfg
|
||||||
|
doxygen/Makefile])
|
||||||
|
|
||||||
|
AC_ARG_WITH([doxygen], [AS_HELP_STRING([--with-doxygen],
|
||||||
|
[create doxygen documentation])],
|
||||||
|
[with_doxygen="$withval"], [with_doxygen=yes])
|
||||||
|
|
||||||
|
AS_IF([test "x$with_doxygen" != xno], [
|
||||||
|
AC_CHECK_PROGS([DOXYGEN], [doxygen])
|
||||||
|
AC_CHECK_PROGS([DOT], [dot], [""])
|
||||||
|
AS_IF([test "x$DOT" != "x"],
|
||||||
|
[AC_SUBST(HAVE_DOT, YES)],
|
||||||
|
[AC_SUBST(HAVE_DOT, NO)])
|
||||||
|
])
|
||||||
|
|
||||||
|
AM_CONDITIONAL([HAVE_DOXYGEN], [test -n "$DOXYGEN"])
|
||||||
|
AS_IF([test "x$DOXYGEN" = x], [
|
||||||
|
AS_IF([test "x$with_doxygen" != xno], [
|
||||||
|
dnl Only run doxygen Makefile if doxygen installed
|
||||||
|
AC_MSG_WARN([Doxygen not found - continuing without Doxygen support])
|
||||||
|
with_doxygen=no
|
||||||
|
])
|
||||||
|
])
|
||||||
|
AC_OUTPUT
|
||||||
|
|
||||||
|
echo "
|
||||||
|
libmnl configuration:
|
||||||
|
doxygen: ${with_doxygen}"
|
||||||
4
deps/libmnl/doxygen/.gitignore
vendored
Normal file
4
deps/libmnl/doxygen/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
doxyfile.stamp
|
||||||
|
doxygen.cfg
|
||||||
|
html/
|
||||||
|
man/
|
||||||
25
deps/libmnl/doxygen/Makefile.am
vendored
Normal file
25
deps/libmnl/doxygen/Makefile.am
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
if HAVE_DOXYGEN
|
||||||
|
doc_srcs = $(shell find $(top_srcdir)/src -name '*.c')
|
||||||
|
|
||||||
|
doxyfile.stamp: $(doc_srcs) Makefile.am
|
||||||
|
rm -rf html man
|
||||||
|
doxygen doxygen.cfg >/dev/null
|
||||||
|
$(SHELL) $(top_srcdir)/doxygen/finalize_manpages.sh
|
||||||
|
touch doxyfile.stamp
|
||||||
|
|
||||||
|
CLEANFILES = doxyfile.stamp
|
||||||
|
|
||||||
|
all-local: doxyfile.stamp
|
||||||
|
clean-local:
|
||||||
|
rm -rf $(top_srcdir)/doxygen/man $(top_srcdir)/doxygen/html
|
||||||
|
install-data-local:
|
||||||
|
mkdir -p $(DESTDIR)$(mandir)/man3
|
||||||
|
cp --no-dereference --preserve=links,mode,timestamps man/man3/*.3\
|
||||||
|
$(DESTDIR)$(mandir)/man3/
|
||||||
|
|
||||||
|
# make distcheck needs uninstall-local
|
||||||
|
uninstall-local:
|
||||||
|
rm -r $(DESTDIR)$(mandir) man html doxyfile.stamp
|
||||||
|
endif
|
||||||
|
|
||||||
|
EXTRA_DIST = finalize_manpages.sh
|
||||||
23
deps/libmnl/doxygen/doxygen.cfg.in
vendored
Normal file
23
deps/libmnl/doxygen/doxygen.cfg.in
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# Difference with default Doxyfile 1.8.20
|
||||||
|
PROJECT_NAME = @PACKAGE@
|
||||||
|
PROJECT_NUMBER = @VERSION@
|
||||||
|
OUTPUT_DIRECTORY = .
|
||||||
|
ABBREVIATE_BRIEF =
|
||||||
|
FULL_PATH_NAMES = NO
|
||||||
|
TAB_SIZE = 8
|
||||||
|
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||||
|
INPUT = @top_srcdir@
|
||||||
|
FILE_PATTERNS = */src/*.c
|
||||||
|
RECURSIVE = YES
|
||||||
|
EXCLUDE_SYMBOLS = EXPORT_SYMBOL mnl_nlmsg_batch mnl_socket
|
||||||
|
EXAMPLE_PATTERNS =
|
||||||
|
INPUT_FILTER = "sed 's/EXPORT_SYMBOL//g'"
|
||||||
|
SOURCE_BROWSER = YES
|
||||||
|
ALPHABETICAL_INDEX = NO
|
||||||
|
SEARCHENGINE = NO
|
||||||
|
GENERATE_LATEX = NO
|
||||||
|
LATEX_CMD_NAME = latex
|
||||||
|
GENERATE_MAN = YES
|
||||||
|
MAN_LINKS = YES
|
||||||
|
HAVE_DOT = @HAVE_DOT@
|
||||||
|
DOT_TRANSPARENT = YES
|
||||||
40
deps/libmnl/doxygen/finalize_manpages.sh
vendored
Normal file
40
deps/libmnl/doxygen/finalize_manpages.sh
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#
|
||||||
|
# We need to use bash for its associative array facility
|
||||||
|
#
|
||||||
|
[ "$BASH" ] || exec bash $0
|
||||||
|
#
|
||||||
|
# (`bash -p` prevents import of functions from the environment).
|
||||||
|
#
|
||||||
|
set -p
|
||||||
|
|
||||||
|
declare -A renamed_page
|
||||||
|
|
||||||
|
main(){ set -e; cd man/man3; rm -f _*
|
||||||
|
count_real_pages
|
||||||
|
rename_real_pages
|
||||||
|
make_symlinks
|
||||||
|
}
|
||||||
|
|
||||||
|
count_real_pages(){ page_count=0
|
||||||
|
for i in $(ls -S)
|
||||||
|
do head -n1 $i | grep -E -q '^\.so' && break
|
||||||
|
page_count=$(($page_count + 1))
|
||||||
|
done
|
||||||
|
first_link=$(($page_count + 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
rename_real_pages(){ for i in $(ls -S | head -n$page_count)
|
||||||
|
do for j in $(ls -S | tail -n+$first_link)
|
||||||
|
do grep -E -q $i$ $j && break
|
||||||
|
done
|
||||||
|
mv -f $i $j
|
||||||
|
renamed_page[$i]=$j
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
make_symlinks(){ for j in $(ls -S | tail -n+$first_link)
|
||||||
|
do ln -sf ${renamed_page[$(cat $j | cut -f2 -d/)]} $j
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
main
|
||||||
1
deps/libmnl/examples/Makefile.am
vendored
Normal file
1
deps/libmnl/examples/Makefile.am
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
SUBDIRS = genl kobject netfilter rtnl
|
||||||
2
deps/libmnl/examples/genl/.gitignore
vendored
Normal file
2
deps/libmnl/examples/genl/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/genl-family-get
|
||||||
|
/genl-group-events
|
||||||
10
deps/libmnl/examples/genl/Makefile.am
vendored
Normal file
10
deps/libmnl/examples/genl/Makefile.am
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
include $(top_srcdir)/Make_global.am
|
||||||
|
|
||||||
|
check_PROGRAMS = genl-family-get \
|
||||||
|
genl-group-events
|
||||||
|
|
||||||
|
genl_family_get_SOURCES = genl-family-get.c
|
||||||
|
genl_family_get_LDADD = ../../src/libmnl.la
|
||||||
|
|
||||||
|
genl_group_events_SOURCES = genl-group-events.c
|
||||||
|
genl_group_events_LDADD = ../../src/libmnl.la
|
||||||
241
deps/libmnl/examples/genl/genl-family-get.c
vendored
Normal file
241
deps/libmnl/examples/genl/genl-family-get.c
vendored
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
/* This example is placed in the public domain. */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <linux/genetlink.h>
|
||||||
|
|
||||||
|
static int parse_mc_grps_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
/* skip unsupported attribute in user-space */
|
||||||
|
if (mnl_attr_type_valid(attr, CTRL_ATTR_MCAST_GRP_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case CTRL_ATTR_MCAST_GRP_ID:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CTRL_ATTR_MCAST_GRP_NAME:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tb[type] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parse_genl_mc_grps(struct nlattr *nested)
|
||||||
|
{
|
||||||
|
struct nlattr *pos;
|
||||||
|
|
||||||
|
mnl_attr_for_each_nested(pos, nested) {
|
||||||
|
struct nlattr *tb[CTRL_ATTR_MCAST_GRP_MAX+1] = {};
|
||||||
|
|
||||||
|
mnl_attr_parse_nested(pos, parse_mc_grps_cb, tb);
|
||||||
|
if (tb[CTRL_ATTR_MCAST_GRP_ID]) {
|
||||||
|
printf("id-0x%x ",
|
||||||
|
mnl_attr_get_u32(tb[CTRL_ATTR_MCAST_GRP_ID]));
|
||||||
|
}
|
||||||
|
if (tb[CTRL_ATTR_MCAST_GRP_NAME]) {
|
||||||
|
printf("name: %s ",
|
||||||
|
mnl_attr_get_str(tb[CTRL_ATTR_MCAST_GRP_NAME]));
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_family_ops_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
if (mnl_attr_type_valid(attr, CTRL_ATTR_OP_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case CTRL_ATTR_OP_ID:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CTRL_ATTR_OP_MAX:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
tb[type] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parse_genl_family_ops(struct nlattr *nested)
|
||||||
|
{
|
||||||
|
struct nlattr *pos;
|
||||||
|
|
||||||
|
mnl_attr_for_each_nested(pos, nested) {
|
||||||
|
struct nlattr *tb[CTRL_ATTR_OP_MAX+1] = {};
|
||||||
|
|
||||||
|
mnl_attr_parse_nested(pos, parse_family_ops_cb, tb);
|
||||||
|
if (tb[CTRL_ATTR_OP_ID]) {
|
||||||
|
printf("id-0x%x ",
|
||||||
|
mnl_attr_get_u32(tb[CTRL_ATTR_OP_ID]));
|
||||||
|
}
|
||||||
|
if (tb[CTRL_ATTR_OP_MAX]) {
|
||||||
|
printf("flags ");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int data_attr_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
if (mnl_attr_type_valid(attr, CTRL_ATTR_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case CTRL_ATTR_FAMILY_NAME:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CTRL_ATTR_FAMILY_ID:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CTRL_ATTR_VERSION:
|
||||||
|
case CTRL_ATTR_HDRSIZE:
|
||||||
|
case CTRL_ATTR_MAXATTR:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CTRL_ATTR_OPS:
|
||||||
|
case CTRL_ATTR_MCAST_GROUPS:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tb[type] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int data_cb(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
struct nlattr *tb[CTRL_ATTR_MAX+1] = {};
|
||||||
|
struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
|
||||||
|
|
||||||
|
mnl_attr_parse(nlh, sizeof(*genl), data_attr_cb, tb);
|
||||||
|
if (tb[CTRL_ATTR_FAMILY_NAME]) {
|
||||||
|
printf("name=%s\t",
|
||||||
|
mnl_attr_get_str(tb[CTRL_ATTR_FAMILY_NAME]));
|
||||||
|
}
|
||||||
|
if (tb[CTRL_ATTR_FAMILY_ID]) {
|
||||||
|
printf("id=%u\t",
|
||||||
|
mnl_attr_get_u16(tb[CTRL_ATTR_FAMILY_ID]));
|
||||||
|
}
|
||||||
|
if (tb[CTRL_ATTR_VERSION]) {
|
||||||
|
printf("version=%u\t",
|
||||||
|
mnl_attr_get_u32(tb[CTRL_ATTR_VERSION]));
|
||||||
|
}
|
||||||
|
if (tb[CTRL_ATTR_HDRSIZE]) {
|
||||||
|
printf("hdrsize=%u\t",
|
||||||
|
mnl_attr_get_u32(tb[CTRL_ATTR_HDRSIZE]));
|
||||||
|
}
|
||||||
|
if (tb[CTRL_ATTR_MAXATTR]) {
|
||||||
|
printf("maxattr=%u\t",
|
||||||
|
mnl_attr_get_u32(tb[CTRL_ATTR_MAXATTR]));
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
if (tb[CTRL_ATTR_OPS]) {
|
||||||
|
printf("ops:\n");
|
||||||
|
parse_genl_family_ops(tb[CTRL_ATTR_OPS]);
|
||||||
|
}
|
||||||
|
if (tb[CTRL_ATTR_MCAST_GROUPS]) {
|
||||||
|
printf("grps:\n");
|
||||||
|
parse_genl_mc_grps(tb[CTRL_ATTR_MCAST_GROUPS]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct mnl_socket *nl;
|
||||||
|
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
struct genlmsghdr *genl;
|
||||||
|
int ret;
|
||||||
|
unsigned int seq, portid;
|
||||||
|
|
||||||
|
if (argc > 2) {
|
||||||
|
printf("%s [family name]\n", argv[0]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
nlh = mnl_nlmsg_put_header(buf);
|
||||||
|
nlh->nlmsg_type = GENL_ID_CTRL;
|
||||||
|
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||||
|
nlh->nlmsg_seq = seq = time(NULL);
|
||||||
|
|
||||||
|
genl = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr));
|
||||||
|
genl->cmd = CTRL_CMD_GETFAMILY;
|
||||||
|
genl->version = 1;
|
||||||
|
|
||||||
|
mnl_attr_put_u32(nlh, CTRL_ATTR_FAMILY_ID, GENL_ID_CTRL);
|
||||||
|
if (argc >= 2)
|
||||||
|
mnl_attr_put_strz(nlh, CTRL_ATTR_FAMILY_NAME, argv[1]);
|
||||||
|
else
|
||||||
|
nlh->nlmsg_flags |= NLM_F_DUMP;
|
||||||
|
|
||||||
|
nl = mnl_socket_open(NETLINK_GENERIC);
|
||||||
|
if (nl == NULL) {
|
||||||
|
perror("mnl_socket_open");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||||
|
perror("mnl_socket_bind");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
portid = mnl_socket_get_portid(nl);
|
||||||
|
|
||||||
|
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||||
|
perror("mnl_socket_sendto");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
while (ret > 0) {
|
||||||
|
ret = mnl_cb_run(buf, ret, seq, portid, data_cb, NULL);
|
||||||
|
if (ret <= 0)
|
||||||
|
break;
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
}
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("error");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
mnl_socket_close(nl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
63
deps/libmnl/examples/genl/genl-group-events.c
vendored
Normal file
63
deps/libmnl/examples/genl/genl-group-events.c
vendored
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
/* This example is placed in the public domain. */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <linux/genetlink.h>
|
||||||
|
|
||||||
|
static int group;
|
||||||
|
|
||||||
|
static int data_cb(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
printf("received event type=%d from genetlink group %d\n",
|
||||||
|
nlh->nlmsg_type, group);
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct mnl_socket *nl;
|
||||||
|
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
printf("%s [group]\n", argv[0]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
group = atoi(argv[1]);
|
||||||
|
|
||||||
|
nl = mnl_socket_open(NETLINK_GENERIC);
|
||||||
|
if (nl == NULL) {
|
||||||
|
perror("mnl_socket_open");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||||
|
perror("mnl_socket_bind");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mnl_socket_setsockopt(nl, NETLINK_ADD_MEMBERSHIP, &group,
|
||||||
|
sizeof(int)) < 0) {
|
||||||
|
perror("mnl_socket_setsockopt");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
while (ret > 0) {
|
||||||
|
ret = mnl_cb_run(buf, ret, 0, 0, data_cb, NULL);
|
||||||
|
if (ret <= 0)
|
||||||
|
break;
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
}
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("error");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
mnl_socket_close(nl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
1
deps/libmnl/examples/kobject/.gitignore
vendored
Normal file
1
deps/libmnl/examples/kobject/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/kobject-event
|
||||||
6
deps/libmnl/examples/kobject/Makefile.am
vendored
Normal file
6
deps/libmnl/examples/kobject/Makefile.am
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
include $(top_srcdir)/Make_global.am
|
||||||
|
|
||||||
|
check_PROGRAMS = kobject-event
|
||||||
|
|
||||||
|
kobject_event_SOURCES = kobject-event.c
|
||||||
|
kobject_event_LDADD = ../../src/libmnl.la
|
||||||
49
deps/libmnl/examples/kobject/kobject-event.c
vendored
Normal file
49
deps/libmnl/examples/kobject/kobject-event.c
vendored
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/* This example is placed in the public domain. */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <linux/netlink.h>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct mnl_socket *nl;
|
||||||
|
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
nl = mnl_socket_open(NETLINK_KOBJECT_UEVENT);
|
||||||
|
if (nl == NULL) {
|
||||||
|
perror("mnl_socket_open");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* There is one single group in kobject over netlink */
|
||||||
|
if (mnl_socket_bind(nl, (1<<0), MNL_SOCKET_AUTOPID) < 0) {
|
||||||
|
perror("mnl_socket_bind");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
while (ret > 0) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* kobject uses a string based protocol, with no initial
|
||||||
|
* netlink header.
|
||||||
|
*/
|
||||||
|
for (i=0; i<ret; i++)
|
||||||
|
printf("%c", buf[i]);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
}
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("error");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
mnl_socket_close(nl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
6
deps/libmnl/examples/netfilter/.gitignore
vendored
Normal file
6
deps/libmnl/examples/netfilter/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
/nf-log
|
||||||
|
/nf-queue
|
||||||
|
/nfct-create-batch
|
||||||
|
/nfct-daemon
|
||||||
|
/nfct-dump
|
||||||
|
/nfct-event
|
||||||
26
deps/libmnl/examples/netfilter/Makefile.am
vendored
Normal file
26
deps/libmnl/examples/netfilter/Makefile.am
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
include $(top_srcdir)/Make_global.am
|
||||||
|
|
||||||
|
check_PROGRAMS = nf-queue \
|
||||||
|
nf-log \
|
||||||
|
nfct-dump \
|
||||||
|
nfct-event \
|
||||||
|
nfct-create-batch \
|
||||||
|
nfct-daemon
|
||||||
|
|
||||||
|
nf_queue_SOURCES = nf-queue.c
|
||||||
|
nf_queue_LDADD = ../../src/libmnl.la
|
||||||
|
|
||||||
|
nf_log_SOURCES = nf-log.c
|
||||||
|
nf_log_LDADD = ../../src/libmnl.la
|
||||||
|
|
||||||
|
nfct_dump_SOURCES = nfct-dump.c
|
||||||
|
nfct_dump_LDADD = ../../src/libmnl.la
|
||||||
|
|
||||||
|
nfct_daemon_SOURCES = nfct-daemon.c
|
||||||
|
nfct_daemon_LDADD = ../../src/libmnl.la
|
||||||
|
|
||||||
|
nfct_event_SOURCES = nfct-event.c
|
||||||
|
nfct_event_LDADD = ../../src/libmnl.la
|
||||||
|
|
||||||
|
nfct_create_batch_SOURCES = nfct-create-batch.c
|
||||||
|
nfct_create_batch_LDADD = ../../src/libmnl.la
|
||||||
219
deps/libmnl/examples/netfilter/nf-log.c
vendored
Normal file
219
deps/libmnl/examples/netfilter/nf-log.c
vendored
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
/* This example is placed in the public domain. */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <linux/netfilter.h>
|
||||||
|
#include <linux/netfilter/nfnetlink.h>
|
||||||
|
#include <linux/netfilter/nfnetlink_log.h>
|
||||||
|
|
||||||
|
static int parse_attr_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
/* skip unsupported attribute in user-space */
|
||||||
|
if (mnl_attr_type_valid(attr, NFULA_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case NFULA_MARK:
|
||||||
|
case NFULA_IFINDEX_INDEV:
|
||||||
|
case NFULA_IFINDEX_OUTDEV:
|
||||||
|
case NFULA_IFINDEX_PHYSINDEV:
|
||||||
|
case NFULA_IFINDEX_PHYSOUTDEV:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NFULA_TIMESTAMP:
|
||||||
|
if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC,
|
||||||
|
sizeof(struct nfulnl_msg_packet_timestamp)) < 0) {
|
||||||
|
perror("mnl_attr_validate2");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NFULA_HWADDR:
|
||||||
|
if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC,
|
||||||
|
sizeof(struct nfulnl_msg_packet_hw)) < 0) {
|
||||||
|
perror("mnl_attr_validate2");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NFULA_PREFIX:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_NUL_STRING) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NFULA_PAYLOAD:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tb[type] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int log_cb(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
struct nlattr *tb[NFULA_MAX+1] = {};
|
||||||
|
struct nfulnl_msg_packet_hdr *ph = NULL;
|
||||||
|
const char *prefix = NULL;
|
||||||
|
uint32_t mark = 0;
|
||||||
|
|
||||||
|
mnl_attr_parse(nlh, sizeof(struct nfgenmsg), parse_attr_cb, tb);
|
||||||
|
if (tb[NFULA_PACKET_HDR])
|
||||||
|
ph = mnl_attr_get_payload(tb[NFULA_PACKET_HDR]);
|
||||||
|
if (tb[NFULA_PREFIX])
|
||||||
|
prefix = mnl_attr_get_str(tb[NFULA_PREFIX]);
|
||||||
|
if (tb[NFULA_MARK])
|
||||||
|
mark = ntohl(mnl_attr_get_u32(tb[NFULA_MARK]));
|
||||||
|
|
||||||
|
printf("log received (prefix=\"%s\" hw=0x%04x hook=%u mark=%u)\n",
|
||||||
|
prefix ? prefix : "", ntohs(ph->hw_protocol), ph->hook,
|
||||||
|
mark);
|
||||||
|
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct nlmsghdr *
|
||||||
|
nflog_build_cfg_pf_request(char *buf, uint8_t command)
|
||||||
|
{
|
||||||
|
struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
|
||||||
|
nlh->nlmsg_type = (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_CONFIG;
|
||||||
|
nlh->nlmsg_flags = NLM_F_REQUEST;
|
||||||
|
|
||||||
|
struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
|
||||||
|
nfg->nfgen_family = AF_INET;
|
||||||
|
nfg->version = NFNETLINK_V0;
|
||||||
|
|
||||||
|
struct nfulnl_msg_config_cmd cmd = {
|
||||||
|
.command = command,
|
||||||
|
};
|
||||||
|
mnl_attr_put(nlh, NFULA_CFG_CMD, sizeof(cmd), &cmd);
|
||||||
|
|
||||||
|
return nlh;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct nlmsghdr *
|
||||||
|
nflog_build_cfg_request(char *buf, uint8_t command, int qnum)
|
||||||
|
{
|
||||||
|
struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
|
||||||
|
nlh->nlmsg_type = (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_CONFIG;
|
||||||
|
nlh->nlmsg_flags = NLM_F_REQUEST;
|
||||||
|
|
||||||
|
struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
|
||||||
|
nfg->nfgen_family = AF_INET;
|
||||||
|
nfg->version = NFNETLINK_V0;
|
||||||
|
nfg->res_id = htons(qnum);
|
||||||
|
|
||||||
|
struct nfulnl_msg_config_cmd cmd = {
|
||||||
|
.command = command,
|
||||||
|
};
|
||||||
|
mnl_attr_put(nlh, NFULA_CFG_CMD, sizeof(cmd), &cmd);
|
||||||
|
|
||||||
|
return nlh;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct nlmsghdr *
|
||||||
|
nflog_build_cfg_params(char *buf, uint8_t mode, int range, int qnum)
|
||||||
|
{
|
||||||
|
struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
|
||||||
|
nlh->nlmsg_type = (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_CONFIG;
|
||||||
|
nlh->nlmsg_flags = NLM_F_REQUEST;
|
||||||
|
|
||||||
|
struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
|
||||||
|
nfg->nfgen_family = AF_UNSPEC;
|
||||||
|
nfg->version = NFNETLINK_V0;
|
||||||
|
nfg->res_id = htons(qnum);
|
||||||
|
|
||||||
|
struct nfulnl_msg_config_mode params = {
|
||||||
|
.copy_range = htonl(range),
|
||||||
|
.copy_mode = mode,
|
||||||
|
};
|
||||||
|
mnl_attr_put(nlh, NFULA_CFG_MODE, sizeof(params), ¶ms);
|
||||||
|
|
||||||
|
return nlh;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct mnl_socket *nl;
|
||||||
|
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
int ret;
|
||||||
|
unsigned int portid, qnum;
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
printf("Usage: %s [queue_num]\n", argv[0]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
qnum = atoi(argv[1]);
|
||||||
|
|
||||||
|
nl = mnl_socket_open(NETLINK_NETFILTER);
|
||||||
|
if (nl == NULL) {
|
||||||
|
perror("mnl_socket_open");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||||
|
perror("mnl_socket_bind");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
portid = mnl_socket_get_portid(nl);
|
||||||
|
|
||||||
|
nlh = nflog_build_cfg_pf_request(buf, NFULNL_CFG_CMD_PF_UNBIND);
|
||||||
|
|
||||||
|
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||||
|
perror("mnl_socket_sendto");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
nlh = nflog_build_cfg_pf_request(buf, NFULNL_CFG_CMD_PF_BIND);
|
||||||
|
|
||||||
|
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||||
|
perror("mnl_socket_sendto");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
nlh = nflog_build_cfg_request(buf, NFULNL_CFG_CMD_BIND, qnum);
|
||||||
|
|
||||||
|
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||||
|
perror("mnl_socket_sendto");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
nlh = nflog_build_cfg_params(buf, NFULNL_COPY_PACKET, 0xFFFF, qnum);
|
||||||
|
|
||||||
|
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||||
|
perror("mnl_socket_sendto");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("mnl_socket_recvfrom");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
while (ret > 0) {
|
||||||
|
ret = mnl_cb_run(buf, ret, 0, portid, log_cb, NULL);
|
||||||
|
if (ret < 0){
|
||||||
|
perror("mnl_cb_run");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("mnl_socket_recvfrom");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mnl_socket_close(nl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
243
deps/libmnl/examples/netfilter/nf-queue.c
vendored
Normal file
243
deps/libmnl/examples/netfilter/nf-queue.c
vendored
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
/* This example is placed in the public domain. */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <linux/netfilter.h>
|
||||||
|
#include <linux/netfilter/nfnetlink.h>
|
||||||
|
#include <linux/netfilter/nfnetlink_queue.h>
|
||||||
|
|
||||||
|
static int parse_attr_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
/* skip unsupported attribute in user-space */
|
||||||
|
if (mnl_attr_type_valid(attr, NFQA_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case NFQA_MARK:
|
||||||
|
case NFQA_IFINDEX_INDEV:
|
||||||
|
case NFQA_IFINDEX_OUTDEV:
|
||||||
|
case NFQA_IFINDEX_PHYSINDEV:
|
||||||
|
case NFQA_IFINDEX_PHYSOUTDEV:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NFQA_TIMESTAMP:
|
||||||
|
if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC,
|
||||||
|
sizeof(struct nfqnl_msg_packet_timestamp)) < 0) {
|
||||||
|
perror("mnl_attr_validate2");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NFQA_HWADDR:
|
||||||
|
if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC,
|
||||||
|
sizeof(struct nfqnl_msg_packet_hw)) < 0) {
|
||||||
|
perror("mnl_attr_validate2");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NFQA_PAYLOAD:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tb[type] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int queue_cb(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
struct nlattr *tb[NFQA_MAX+1] = {};
|
||||||
|
struct nfqnl_msg_packet_hdr *ph = NULL;
|
||||||
|
uint32_t id = 0;
|
||||||
|
|
||||||
|
mnl_attr_parse(nlh, sizeof(struct nfgenmsg), parse_attr_cb, tb);
|
||||||
|
if (tb[NFQA_PACKET_HDR]) {
|
||||||
|
ph = mnl_attr_get_payload(tb[NFQA_PACKET_HDR]);
|
||||||
|
id = ntohl(ph->packet_id);
|
||||||
|
|
||||||
|
printf("packet received (id=%u hw=0x%04x hook=%u)\n",
|
||||||
|
id, ntohs(ph->hw_protocol), ph->hook);
|
||||||
|
}
|
||||||
|
|
||||||
|
return MNL_CB_OK + id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct nlmsghdr *
|
||||||
|
nfq_build_cfg_pf_request(char *buf, uint8_t command)
|
||||||
|
{
|
||||||
|
struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
|
||||||
|
nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_CONFIG;
|
||||||
|
nlh->nlmsg_flags = NLM_F_REQUEST;
|
||||||
|
|
||||||
|
struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
|
||||||
|
nfg->nfgen_family = AF_UNSPEC;
|
||||||
|
nfg->version = NFNETLINK_V0;
|
||||||
|
|
||||||
|
struct nfqnl_msg_config_cmd cmd = {
|
||||||
|
.command = command,
|
||||||
|
.pf = htons(AF_INET),
|
||||||
|
};
|
||||||
|
mnl_attr_put(nlh, NFQA_CFG_CMD, sizeof(cmd), &cmd);
|
||||||
|
|
||||||
|
return nlh;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct nlmsghdr *
|
||||||
|
nfq_build_cfg_request(char *buf, uint8_t command, int queue_num)
|
||||||
|
{
|
||||||
|
struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
|
||||||
|
nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_CONFIG;
|
||||||
|
nlh->nlmsg_flags = NLM_F_REQUEST;
|
||||||
|
|
||||||
|
struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
|
||||||
|
nfg->nfgen_family = AF_UNSPEC;
|
||||||
|
nfg->version = NFNETLINK_V0;
|
||||||
|
nfg->res_id = htons(queue_num);
|
||||||
|
|
||||||
|
struct nfqnl_msg_config_cmd cmd = {
|
||||||
|
.command = command,
|
||||||
|
.pf = htons(AF_INET),
|
||||||
|
};
|
||||||
|
mnl_attr_put(nlh, NFQA_CFG_CMD, sizeof(cmd), &cmd);
|
||||||
|
|
||||||
|
return nlh;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct nlmsghdr *
|
||||||
|
nfq_build_cfg_params(char *buf, uint8_t mode, int range, int queue_num)
|
||||||
|
{
|
||||||
|
struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
|
||||||
|
nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_CONFIG;
|
||||||
|
nlh->nlmsg_flags = NLM_F_REQUEST;
|
||||||
|
|
||||||
|
struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
|
||||||
|
nfg->nfgen_family = AF_UNSPEC;
|
||||||
|
nfg->version = NFNETLINK_V0;
|
||||||
|
nfg->res_id = htons(queue_num);
|
||||||
|
|
||||||
|
struct nfqnl_msg_config_params params = {
|
||||||
|
.copy_range = htonl(range),
|
||||||
|
.copy_mode = mode,
|
||||||
|
};
|
||||||
|
mnl_attr_put(nlh, NFQA_CFG_PARAMS, sizeof(params), ¶ms);
|
||||||
|
|
||||||
|
return nlh;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct nlmsghdr *
|
||||||
|
nfq_build_verdict(char *buf, int id, int queue_num, int verd)
|
||||||
|
{
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
struct nfgenmsg *nfg;
|
||||||
|
|
||||||
|
nlh = mnl_nlmsg_put_header(buf);
|
||||||
|
nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_VERDICT;
|
||||||
|
nlh->nlmsg_flags = NLM_F_REQUEST;
|
||||||
|
nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
|
||||||
|
nfg->nfgen_family = AF_UNSPEC;
|
||||||
|
nfg->version = NFNETLINK_V0;
|
||||||
|
nfg->res_id = htons(queue_num);
|
||||||
|
|
||||||
|
struct nfqnl_msg_verdict_hdr vh = {
|
||||||
|
.verdict = htonl(verd),
|
||||||
|
.id = htonl(id),
|
||||||
|
};
|
||||||
|
mnl_attr_put(nlh, NFQA_VERDICT_HDR, sizeof(vh), &vh);
|
||||||
|
|
||||||
|
return nlh;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct mnl_socket *nl;
|
||||||
|
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
int ret;
|
||||||
|
unsigned int portid, queue_num;
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
printf("Usage: %s [queue_num]\n", argv[0]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
queue_num = atoi(argv[1]);
|
||||||
|
|
||||||
|
nl = mnl_socket_open(NETLINK_NETFILTER);
|
||||||
|
if (nl == NULL) {
|
||||||
|
perror("mnl_socket_open");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||||
|
perror("mnl_socket_bind");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
portid = mnl_socket_get_portid(nl);
|
||||||
|
|
||||||
|
nlh = nfq_build_cfg_pf_request(buf, NFQNL_CFG_CMD_PF_UNBIND);
|
||||||
|
|
||||||
|
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||||
|
perror("mnl_socket_sendto");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
nlh = nfq_build_cfg_pf_request(buf, NFQNL_CFG_CMD_PF_BIND);
|
||||||
|
|
||||||
|
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||||
|
perror("mnl_socket_sendto");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
nlh = nfq_build_cfg_request(buf, NFQNL_CFG_CMD_BIND, queue_num);
|
||||||
|
|
||||||
|
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||||
|
perror("mnl_socket_sendto");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
nlh = nfq_build_cfg_params(buf, NFQNL_COPY_PACKET, 0xFFFF, queue_num);
|
||||||
|
|
||||||
|
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||||
|
perror("mnl_socket_sendto");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("mnl_socket_recvfrom");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
while (ret > 0) {
|
||||||
|
uint32_t id;
|
||||||
|
|
||||||
|
ret = mnl_cb_run(buf, ret, 0, portid, queue_cb, NULL);
|
||||||
|
if (ret < 0){
|
||||||
|
perror("mnl_cb_run");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
id = ret - MNL_CB_OK;
|
||||||
|
nlh = nfq_build_verdict(buf, id, queue_num, NF_ACCEPT);
|
||||||
|
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||||
|
perror("mnl_socket_sendto");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("mnl_socket_recvfrom");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mnl_socket_close(nl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
187
deps/libmnl/examples/netfilter/nfct-create-batch.c
vendored
Normal file
187
deps/libmnl/examples/netfilter/nfct-create-batch.c
vendored
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
/* This example is placed in the public domain. */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <linux/netfilter/nfnetlink.h>
|
||||||
|
#include <linux/netfilter/nfnetlink_conntrack.h>
|
||||||
|
#include <linux/netfilter/nf_conntrack_common.h>
|
||||||
|
#include <linux/netfilter/nf_conntrack_tcp.h>
|
||||||
|
|
||||||
|
static void put_msg(char *buf, uint16_t i, int seq)
|
||||||
|
{
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
struct nfgenmsg *nfh;
|
||||||
|
struct nlattr *nest1, *nest2;
|
||||||
|
|
||||||
|
nlh = mnl_nlmsg_put_header(buf);
|
||||||
|
nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_NEW;
|
||||||
|
nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
|
||||||
|
nlh->nlmsg_seq = seq;
|
||||||
|
|
||||||
|
nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg));
|
||||||
|
nfh->nfgen_family = AF_INET;
|
||||||
|
nfh->version = NFNETLINK_V0;
|
||||||
|
nfh->res_id = 0;
|
||||||
|
|
||||||
|
nest1 = mnl_attr_nest_start(nlh, CTA_TUPLE_ORIG);
|
||||||
|
nest2 = mnl_attr_nest_start(nlh, CTA_TUPLE_IP);
|
||||||
|
mnl_attr_put_u32(nlh, CTA_IP_V4_SRC, inet_addr("1.1.1.1"));
|
||||||
|
mnl_attr_put_u32(nlh, CTA_IP_V4_DST, inet_addr("2.2.2.2"));
|
||||||
|
mnl_attr_nest_end(nlh, nest2);
|
||||||
|
|
||||||
|
nest2 = mnl_attr_nest_start(nlh, CTA_TUPLE_PROTO);
|
||||||
|
mnl_attr_put_u8(nlh, CTA_PROTO_NUM, IPPROTO_TCP);
|
||||||
|
mnl_attr_put_u16(nlh, CTA_PROTO_SRC_PORT, htons(i));
|
||||||
|
mnl_attr_put_u16(nlh, CTA_PROTO_DST_PORT, htons(1025));
|
||||||
|
mnl_attr_nest_end(nlh, nest2);
|
||||||
|
mnl_attr_nest_end(nlh, nest1);
|
||||||
|
|
||||||
|
nest1 = mnl_attr_nest_start(nlh, CTA_TUPLE_REPLY);
|
||||||
|
nest2 = mnl_attr_nest_start(nlh, CTA_TUPLE_IP);
|
||||||
|
mnl_attr_put_u32(nlh, CTA_IP_V4_SRC, inet_addr("2.2.2.2"));
|
||||||
|
mnl_attr_put_u32(nlh, CTA_IP_V4_DST, inet_addr("1.1.1.1"));
|
||||||
|
mnl_attr_nest_end(nlh, nest2);
|
||||||
|
|
||||||
|
nest2 = mnl_attr_nest_start(nlh, CTA_TUPLE_PROTO);
|
||||||
|
mnl_attr_put_u8(nlh, CTA_PROTO_NUM, IPPROTO_TCP);
|
||||||
|
mnl_attr_put_u16(nlh, CTA_PROTO_SRC_PORT, htons(1025));
|
||||||
|
mnl_attr_put_u16(nlh, CTA_PROTO_DST_PORT, htons(i));
|
||||||
|
mnl_attr_nest_end(nlh, nest2);
|
||||||
|
mnl_attr_nest_end(nlh, nest1);
|
||||||
|
|
||||||
|
nest1 = mnl_attr_nest_start(nlh, CTA_PROTOINFO);
|
||||||
|
nest2 = mnl_attr_nest_start(nlh, CTA_PROTOINFO_TCP);
|
||||||
|
mnl_attr_put_u8(nlh, CTA_PROTOINFO_TCP_STATE, TCP_CONNTRACK_SYN_SENT);
|
||||||
|
mnl_attr_nest_end(nlh, nest2);
|
||||||
|
mnl_attr_nest_end(nlh, nest1);
|
||||||
|
|
||||||
|
mnl_attr_put_u32(nlh, CTA_STATUS, htonl(IPS_CONFIRMED));
|
||||||
|
mnl_attr_put_u32(nlh, CTA_TIMEOUT, htonl(1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cb_err(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh);
|
||||||
|
if (err->error != 0)
|
||||||
|
printf("message with seq %u has failed: %s\n",
|
||||||
|
nlh->nlmsg_seq, strerror(-err->error));
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mnl_cb_t cb_ctl_array[NLMSG_MIN_TYPE] = {
|
||||||
|
[NLMSG_ERROR] = cb_err,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
send_batch(struct mnl_socket *nl, struct mnl_nlmsg_batch *b, int portid)
|
||||||
|
{
|
||||||
|
int ret, fd = mnl_socket_get_fd(nl);
|
||||||
|
size_t len = mnl_nlmsg_batch_size(b);
|
||||||
|
char rcv_buf[MNL_SOCKET_BUFFER_SIZE];
|
||||||
|
|
||||||
|
ret = mnl_socket_sendto(nl, mnl_nlmsg_batch_head(b), len);
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("mnl_socket_sendto");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* receive and digest all the acknowledgments from the kernel. */
|
||||||
|
struct timeval tv = {
|
||||||
|
.tv_sec = 0,
|
||||||
|
.tv_usec = 0
|
||||||
|
};
|
||||||
|
fd_set readfds;
|
||||||
|
FD_ZERO(&readfds);
|
||||||
|
FD_SET(fd, &readfds);
|
||||||
|
|
||||||
|
ret = select(fd+1, &readfds, NULL, NULL, &tv);
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("select");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
while (ret > 0 && FD_ISSET(fd, &readfds)) {
|
||||||
|
ret = mnl_socket_recvfrom(nl, rcv_buf, sizeof(rcv_buf));
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("mnl_socket_recvfrom");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_cb_run2(rcv_buf, ret, 0, portid,
|
||||||
|
NULL, NULL, cb_ctl_array,
|
||||||
|
MNL_ARRAY_SIZE(cb_ctl_array));
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("mnl_cb_run2");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = select(fd+1, &readfds, NULL, NULL, &tv);
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("select");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
FD_ZERO(&readfds);
|
||||||
|
FD_SET(fd, &readfds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
struct mnl_socket *nl;
|
||||||
|
char snd_buf[MNL_SOCKET_BUFFER_SIZE*2];
|
||||||
|
struct mnl_nlmsg_batch *b;
|
||||||
|
int j;
|
||||||
|
unsigned int seq, portid;
|
||||||
|
uint16_t i;
|
||||||
|
|
||||||
|
nl = mnl_socket_open(NETLINK_NETFILTER);
|
||||||
|
if (nl == NULL) {
|
||||||
|
perror("mnl_socket_open");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||||
|
perror("mnl_socket_bind");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
portid = mnl_socket_get_portid(nl);
|
||||||
|
|
||||||
|
/* The buffer that we use to batch messages is MNL_SOCKET_BUFFER_SIZE
|
||||||
|
* multiplied by 2 bytes long, but we limit the batch to half of it
|
||||||
|
* since the last message that does not fit the batch goes over the
|
||||||
|
* upper boundary, if you break this rule, expect memory corruptions. */
|
||||||
|
b = mnl_nlmsg_batch_start(snd_buf, MNL_SOCKET_BUFFER_SIZE);
|
||||||
|
if (b == NULL) {
|
||||||
|
perror("mnl_nlmsg_batch_start");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
seq = time(NULL);
|
||||||
|
for (i=1024, j=0; i<65535; i++, j++) {
|
||||||
|
put_msg(mnl_nlmsg_batch_current(b), i, seq+j);
|
||||||
|
|
||||||
|
/* is there room for more messages in this batch?
|
||||||
|
* if so, continue. */
|
||||||
|
if (mnl_nlmsg_batch_next(b))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
send_batch(nl, b, portid);
|
||||||
|
|
||||||
|
/* this moves the last message that did not fit into the
|
||||||
|
* batch to the head of it. */
|
||||||
|
mnl_nlmsg_batch_reset(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if there is any message in the batch not sent yet. */
|
||||||
|
if (!mnl_nlmsg_batch_is_empty(b))
|
||||||
|
send_batch(nl, b, portid);
|
||||||
|
|
||||||
|
mnl_nlmsg_batch_stop(b);
|
||||||
|
mnl_socket_close(nl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
365
deps/libmnl/examples/netfilter/nfct-daemon.c
vendored
Normal file
365
deps/libmnl/examples/netfilter/nfct-daemon.c
vendored
Normal file
@@ -0,0 +1,365 @@
|
|||||||
|
/* A very simple skeleton code that implements a daemon that collects
|
||||||
|
* conntrack statistics from ctnetlink.
|
||||||
|
*
|
||||||
|
* This example is placed in the public domain.
|
||||||
|
*/
|
||||||
|
#include <endian.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <linux/netlink.h>
|
||||||
|
#include <linux/netfilter/nfnetlink.h>
|
||||||
|
#include <linux/netfilter/nfnetlink_conntrack.h>
|
||||||
|
|
||||||
|
#include <sys/queue.h>
|
||||||
|
|
||||||
|
struct nstats {
|
||||||
|
LIST_ENTRY(nstats) list;
|
||||||
|
|
||||||
|
uint8_t family;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct in_addr ip;
|
||||||
|
struct in6_addr ip6;
|
||||||
|
};
|
||||||
|
uint64_t pkts, bytes;
|
||||||
|
};
|
||||||
|
|
||||||
|
static LIST_HEAD(nstats_head, nstats) nstats_head;
|
||||||
|
|
||||||
|
static int parse_counters_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
if (mnl_attr_type_valid(attr, CTA_COUNTERS_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case CTA_COUNTERS_PACKETS:
|
||||||
|
case CTA_COUNTERS_BYTES:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tb[type] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parse_counters(const struct nlattr *nest, struct nstats *ns)
|
||||||
|
{
|
||||||
|
struct nlattr *tb[CTA_COUNTERS_MAX+1] = {};
|
||||||
|
|
||||||
|
mnl_attr_parse_nested(nest, parse_counters_cb, tb);
|
||||||
|
if (tb[CTA_COUNTERS_PACKETS])
|
||||||
|
ns->pkts += be64toh(mnl_attr_get_u64(tb[CTA_COUNTERS_PACKETS]));
|
||||||
|
|
||||||
|
if (tb[CTA_COUNTERS_BYTES])
|
||||||
|
ns->bytes += be64toh(mnl_attr_get_u64(tb[CTA_COUNTERS_BYTES]));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_ip_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
if (mnl_attr_type_valid(attr, CTA_IP_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case CTA_IP_V4_SRC:
|
||||||
|
case CTA_IP_V4_DST:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CTA_IP_V6_SRC:
|
||||||
|
case CTA_IP_V6_DST:
|
||||||
|
if (mnl_attr_validate2(attr, MNL_TYPE_BINARY,
|
||||||
|
sizeof(struct in6_addr)) < 0) {
|
||||||
|
perror("mnl_attr_validate2");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tb[type] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parse_ip(const struct nlattr *nest, struct nstats *ns)
|
||||||
|
{
|
||||||
|
struct nlattr *tb[CTA_IP_MAX+1] = {};
|
||||||
|
|
||||||
|
mnl_attr_parse_nested(nest, parse_ip_cb, tb);
|
||||||
|
if (tb[CTA_IP_V4_SRC]) {
|
||||||
|
struct in_addr *in = mnl_attr_get_payload(tb[CTA_IP_V4_SRC]);
|
||||||
|
ns->ip = *in;
|
||||||
|
ns->family = AF_INET;
|
||||||
|
}
|
||||||
|
if (tb[CTA_IP_V6_SRC]) {
|
||||||
|
struct in6_addr *in = mnl_attr_get_payload(tb[CTA_IP_V6_SRC]);
|
||||||
|
ns->ip6 = *in;
|
||||||
|
ns->family = AF_INET6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_tuple_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
if (mnl_attr_type_valid(attr, CTA_TUPLE_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case CTA_TUPLE_IP:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tb[type] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parse_tuple(const struct nlattr *nest, struct nstats *ns)
|
||||||
|
{
|
||||||
|
struct nlattr *tb[CTA_TUPLE_MAX+1] = {};
|
||||||
|
|
||||||
|
mnl_attr_parse_nested(nest, parse_tuple_cb, tb);
|
||||||
|
if (tb[CTA_TUPLE_IP])
|
||||||
|
parse_ip(tb[CTA_TUPLE_IP], ns);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int data_attr_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
if (mnl_attr_type_valid(attr, CTA_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case CTA_TUPLE_ORIG:
|
||||||
|
case CTA_COUNTERS_ORIG:
|
||||||
|
case CTA_COUNTERS_REPLY:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tb[type] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int data_cb(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
struct nlattr *tb[CTA_MAX+1] = {};
|
||||||
|
struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
|
||||||
|
struct nstats ns = {}, *cur, *new;
|
||||||
|
|
||||||
|
mnl_attr_parse(nlh, sizeof(*nfg), data_attr_cb, tb);
|
||||||
|
if (tb[CTA_TUPLE_ORIG])
|
||||||
|
parse_tuple(tb[CTA_TUPLE_ORIG], &ns);
|
||||||
|
|
||||||
|
if (tb[CTA_COUNTERS_ORIG])
|
||||||
|
parse_counters(tb[CTA_COUNTERS_ORIG], &ns);
|
||||||
|
|
||||||
|
if (tb[CTA_COUNTERS_REPLY])
|
||||||
|
parse_counters(tb[CTA_COUNTERS_REPLY], &ns);
|
||||||
|
|
||||||
|
/* Look up for existing statistics object ... */
|
||||||
|
LIST_FOREACH(cur, &nstats_head, list) {
|
||||||
|
if (memcmp(&ns.ip6, &cur->ip6, sizeof(struct in6_addr)) == 0) {
|
||||||
|
/* ... and sum counters */
|
||||||
|
cur->pkts += ns.pkts;
|
||||||
|
cur->bytes += ns.bytes;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ... if it does not exist, add new stats object */
|
||||||
|
new = calloc(1, sizeof(struct nstats));
|
||||||
|
if (!new)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
new->family = ns.family;
|
||||||
|
new->ip6 = ns.ip6;
|
||||||
|
new->pkts = ns.pkts;
|
||||||
|
new->bytes = ns.bytes;
|
||||||
|
|
||||||
|
LIST_INSERT_HEAD(&nstats_head, new, list);
|
||||||
|
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int handle(struct mnl_socket *nl)
|
||||||
|
{
|
||||||
|
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
if (ret == -1) {
|
||||||
|
/* It only happens if NETLINK_NO_ENOBUFS is not set, it means
|
||||||
|
* we are leaking statistics.
|
||||||
|
*/
|
||||||
|
if (errno == ENOBUFS) {
|
||||||
|
fprintf(stderr, "The daemon has hit ENOBUFS, you can "
|
||||||
|
"increase the size of your receiver "
|
||||||
|
"buffer to mitigate this or enable "
|
||||||
|
"reliable delivery.\n");
|
||||||
|
} else {
|
||||||
|
perror("mnl_socket_recvfrom");
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_cb_run(buf, ret, 0, 0, data_cb, NULL);
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("mnl_cb_run");
|
||||||
|
return -1;
|
||||||
|
} else if (ret <= MNL_CB_STOP)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct mnl_socket *nl;
|
||||||
|
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
struct nfgenmsg *nfh;
|
||||||
|
struct nstats *cur;
|
||||||
|
struct timeval tv = {};
|
||||||
|
int ret, secs, on = 1, buffersize = (1 << 22);
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
printf("Usage: %s <poll-secs>\n", argv[0]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
secs = atoi(argv[1]);
|
||||||
|
|
||||||
|
LIST_INIT(&nstats_head);
|
||||||
|
|
||||||
|
printf("Polling every %d seconds from kernel...\n", secs);
|
||||||
|
|
||||||
|
/* Set high priority for this process, less chances to overrun
|
||||||
|
* the netlink receiver buffer since the scheduler gives this process
|
||||||
|
* more chances to run.
|
||||||
|
*/
|
||||||
|
nice(-20);
|
||||||
|
|
||||||
|
/* Open netlink socket to operate with netfilter */
|
||||||
|
nl = mnl_socket_open(NETLINK_NETFILTER);
|
||||||
|
if (nl == NULL) {
|
||||||
|
perror("mnl_socket_open");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Subscribe to destroy events to avoid leaking counters. The same
|
||||||
|
* socket is used to periodically atomically dump and reset counters.
|
||||||
|
*/
|
||||||
|
if (mnl_socket_bind(nl, NF_NETLINK_CONNTRACK_DESTROY,
|
||||||
|
MNL_SOCKET_AUTOPID) < 0) {
|
||||||
|
perror("mnl_socket_bind");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set netlink receiver buffer to 16 MBytes, to avoid packet drops */
|
||||||
|
setsockopt(mnl_socket_get_fd(nl), SOL_SOCKET, SO_RCVBUFFORCE,
|
||||||
|
&buffersize, sizeof(socklen_t));
|
||||||
|
|
||||||
|
/* The two tweaks below enable reliable event delivery, packets may
|
||||||
|
* be dropped if the netlink receiver buffer overruns. This happens ...
|
||||||
|
*
|
||||||
|
* a) if the kernel spams this user-space process until the receiver
|
||||||
|
* is filled.
|
||||||
|
*
|
||||||
|
* or:
|
||||||
|
*
|
||||||
|
* b) if the user-space process does not pull messages from the
|
||||||
|
* receiver buffer so often.
|
||||||
|
*/
|
||||||
|
mnl_socket_setsockopt(nl, NETLINK_BROADCAST_ERROR, &on, sizeof(int));
|
||||||
|
mnl_socket_setsockopt(nl, NETLINK_NO_ENOBUFS, &on, sizeof(int));
|
||||||
|
|
||||||
|
nlh = mnl_nlmsg_put_header(buf);
|
||||||
|
/* Counters are atomically zeroed in each dump */
|
||||||
|
nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) |
|
||||||
|
IPCTNL_MSG_CT_GET_CTRZERO;
|
||||||
|
nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP;
|
||||||
|
|
||||||
|
nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg));
|
||||||
|
nfh->nfgen_family = AF_INET;
|
||||||
|
nfh->version = NFNETLINK_V0;
|
||||||
|
nfh->res_id = 0;
|
||||||
|
|
||||||
|
/* Filter by mark: We only want to dump entries whose mark is zero */
|
||||||
|
mnl_attr_put_u32(nlh, CTA_MARK, htonl(0));
|
||||||
|
mnl_attr_put_u32(nlh, CTA_MARK_MASK, htonl(0xffffffff));
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
int fd_max = mnl_socket_get_fd(nl);
|
||||||
|
fd_set readfds;
|
||||||
|
|
||||||
|
/* Every N seconds ... */
|
||||||
|
if (tv.tv_sec == 0 && tv.tv_usec == 0) {
|
||||||
|
/* ... request a fresh dump of the table from kernel */
|
||||||
|
ret = mnl_socket_sendto(nl, nlh, nlh->nlmsg_len);
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("mnl_socket_sendto");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
tv.tv_sec = secs;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
|
/* print the content of the list */
|
||||||
|
LIST_FOREACH(cur, &nstats_head, list) {
|
||||||
|
char out[INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
|
if (inet_ntop(cur->family, &cur->ip, out, sizeof(out)))
|
||||||
|
printf("src=%s ", out);
|
||||||
|
|
||||||
|
printf("counters %"PRIu64" %"PRIu64"\n",
|
||||||
|
cur->pkts, cur->bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FD_ZERO(&readfds);
|
||||||
|
FD_SET(mnl_socket_get_fd(nl), &readfds);
|
||||||
|
|
||||||
|
ret = select(fd_max+1, &readfds, NULL, NULL, &tv);
|
||||||
|
if (ret < 0) {
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
perror("select");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handled event and periodic atomic-dump-and-reset messages */
|
||||||
|
if (FD_ISSET(mnl_socket_get_fd(nl), &readfds)) {
|
||||||
|
if (handle(nl) < 0)
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mnl_socket_close(nl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
319
deps/libmnl/examples/netfilter/nfct-dump.c
vendored
Normal file
319
deps/libmnl/examples/netfilter/nfct-dump.c
vendored
Normal file
@@ -0,0 +1,319 @@
|
|||||||
|
/* This example is placed in the public domain. */
|
||||||
|
#include <endian.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <linux/netfilter/nfnetlink.h>
|
||||||
|
#include <linux/netfilter/nfnetlink_conntrack.h>
|
||||||
|
|
||||||
|
static int parse_counters_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
if (mnl_attr_type_valid(attr, CTA_COUNTERS_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case CTA_COUNTERS_PACKETS:
|
||||||
|
case CTA_COUNTERS_BYTES:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tb[type] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_counters(const struct nlattr *nest)
|
||||||
|
{
|
||||||
|
struct nlattr *tb[CTA_COUNTERS_MAX+1] = {};
|
||||||
|
|
||||||
|
mnl_attr_parse_nested(nest, parse_counters_cb, tb);
|
||||||
|
if (tb[CTA_COUNTERS_PACKETS]) {
|
||||||
|
printf("packets=%"PRIu64" ",
|
||||||
|
be64toh(mnl_attr_get_u64(tb[CTA_COUNTERS_PACKETS])));
|
||||||
|
}
|
||||||
|
if (tb[CTA_COUNTERS_BYTES]) {
|
||||||
|
printf("bytes=%"PRIu64" ",
|
||||||
|
be64toh(mnl_attr_get_u64(tb[CTA_COUNTERS_BYTES])));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_ip_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
if (mnl_attr_type_valid(attr, CTA_IP_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case CTA_IP_V4_SRC:
|
||||||
|
case CTA_IP_V4_DST:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CTA_IP_V6_SRC:
|
||||||
|
case CTA_IP_V6_DST:
|
||||||
|
if (mnl_attr_validate2(attr, MNL_TYPE_BINARY,
|
||||||
|
sizeof(struct in6_addr)) < 0) {
|
||||||
|
perror("mnl_attr_validate2");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tb[type] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_ip(const struct nlattr *nest)
|
||||||
|
{
|
||||||
|
struct nlattr *tb[CTA_IP_MAX+1] = {};
|
||||||
|
|
||||||
|
mnl_attr_parse_nested(nest, parse_ip_cb, tb);
|
||||||
|
if (tb[CTA_IP_V4_SRC]) {
|
||||||
|
struct in_addr *in = mnl_attr_get_payload(tb[CTA_IP_V4_SRC]);
|
||||||
|
printf("src=%s ", inet_ntoa(*in));
|
||||||
|
}
|
||||||
|
if (tb[CTA_IP_V4_DST]) {
|
||||||
|
struct in_addr *in = mnl_attr_get_payload(tb[CTA_IP_V4_DST]);
|
||||||
|
printf("dst=%s ", inet_ntoa(*in));
|
||||||
|
}
|
||||||
|
if (tb[CTA_IP_V6_SRC]) {
|
||||||
|
struct in6_addr *in = mnl_attr_get_payload(tb[CTA_IP_V6_SRC]);
|
||||||
|
char out[INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
|
if (!inet_ntop(AF_INET6, in, out, sizeof(out)))
|
||||||
|
printf("src=%s ", out);
|
||||||
|
}
|
||||||
|
if (tb[CTA_IP_V6_DST]) {
|
||||||
|
struct in6_addr *in = mnl_attr_get_payload(tb[CTA_IP_V6_DST]);
|
||||||
|
char out[INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
|
if (!inet_ntop(AF_INET6, in, out, sizeof(out)))
|
||||||
|
printf("dst=%s ", out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_proto_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
if (mnl_attr_type_valid(attr, CTA_PROTO_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case CTA_PROTO_NUM:
|
||||||
|
case CTA_PROTO_ICMP_TYPE:
|
||||||
|
case CTA_PROTO_ICMP_CODE:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CTA_PROTO_SRC_PORT:
|
||||||
|
case CTA_PROTO_DST_PORT:
|
||||||
|
case CTA_PROTO_ICMP_ID:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tb[type] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_proto(const struct nlattr *nest)
|
||||||
|
{
|
||||||
|
struct nlattr *tb[CTA_PROTO_MAX+1] = {};
|
||||||
|
|
||||||
|
mnl_attr_parse_nested(nest, parse_proto_cb, tb);
|
||||||
|
if (tb[CTA_PROTO_NUM]) {
|
||||||
|
printf("proto=%u ", mnl_attr_get_u8(tb[CTA_PROTO_NUM]));
|
||||||
|
}
|
||||||
|
if (tb[CTA_PROTO_SRC_PORT]) {
|
||||||
|
printf("sport=%u ",
|
||||||
|
ntohs(mnl_attr_get_u16(tb[CTA_PROTO_SRC_PORT])));
|
||||||
|
}
|
||||||
|
if (tb[CTA_PROTO_DST_PORT]) {
|
||||||
|
printf("dport=%u ",
|
||||||
|
ntohs(mnl_attr_get_u16(tb[CTA_PROTO_DST_PORT])));
|
||||||
|
}
|
||||||
|
if (tb[CTA_PROTO_ICMP_ID]) {
|
||||||
|
printf("id=%u ",
|
||||||
|
ntohs(mnl_attr_get_u16(tb[CTA_PROTO_ICMP_ID])));
|
||||||
|
}
|
||||||
|
if (tb[CTA_PROTO_ICMP_TYPE]) {
|
||||||
|
printf("type=%u ", mnl_attr_get_u8(tb[CTA_PROTO_ICMP_TYPE]));
|
||||||
|
}
|
||||||
|
if (tb[CTA_PROTO_ICMP_CODE]) {
|
||||||
|
printf("code=%u ", mnl_attr_get_u8(tb[CTA_PROTO_ICMP_CODE]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_tuple_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
if (mnl_attr_type_valid(attr, CTA_TUPLE_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case CTA_TUPLE_IP:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CTA_TUPLE_PROTO:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tb[type] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_tuple(const struct nlattr *nest)
|
||||||
|
{
|
||||||
|
struct nlattr *tb[CTA_TUPLE_MAX+1] = {};
|
||||||
|
|
||||||
|
mnl_attr_parse_nested(nest, parse_tuple_cb, tb);
|
||||||
|
if (tb[CTA_TUPLE_IP]) {
|
||||||
|
print_ip(tb[CTA_TUPLE_IP]);
|
||||||
|
}
|
||||||
|
if (tb[CTA_TUPLE_PROTO]) {
|
||||||
|
print_proto(tb[CTA_TUPLE_PROTO]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int data_attr_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
if (mnl_attr_type_valid(attr, CTA_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case CTA_TUPLE_ORIG:
|
||||||
|
case CTA_COUNTERS_ORIG:
|
||||||
|
case CTA_COUNTERS_REPLY:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CTA_TIMEOUT:
|
||||||
|
case CTA_MARK:
|
||||||
|
case CTA_SECMARK:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tb[type] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int data_cb(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
struct nlattr *tb[CTA_MAX+1] = {};
|
||||||
|
struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
|
||||||
|
|
||||||
|
mnl_attr_parse(nlh, sizeof(*nfg), data_attr_cb, tb);
|
||||||
|
if (tb[CTA_TUPLE_ORIG])
|
||||||
|
print_tuple(tb[CTA_TUPLE_ORIG]);
|
||||||
|
|
||||||
|
if (tb[CTA_MARK])
|
||||||
|
printf("mark=%u ", ntohl(mnl_attr_get_u32(tb[CTA_MARK])));
|
||||||
|
|
||||||
|
if (tb[CTA_SECMARK])
|
||||||
|
printf("secmark=%u ", ntohl(mnl_attr_get_u32(tb[CTA_SECMARK])));
|
||||||
|
|
||||||
|
if (tb[CTA_COUNTERS_ORIG]) {
|
||||||
|
printf("original ");
|
||||||
|
print_counters(tb[CTA_COUNTERS_ORIG]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tb[CTA_COUNTERS_REPLY]) {
|
||||||
|
printf("reply ");
|
||||||
|
print_counters(tb[CTA_COUNTERS_REPLY]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
char buf[MNL_SOCKET_DUMP_SIZE];
|
||||||
|
struct mnl_socket *nl;
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
struct nfgenmsg *nfh;
|
||||||
|
uint32_t seq, portid;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
nl = mnl_socket_open(NETLINK_NETFILTER);
|
||||||
|
if (nl == NULL) {
|
||||||
|
perror("mnl_socket_open");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||||
|
perror("mnl_socket_bind");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
nlh = mnl_nlmsg_put_header(buf);
|
||||||
|
nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_GET;
|
||||||
|
nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP;
|
||||||
|
nlh->nlmsg_seq = seq = time(NULL);
|
||||||
|
|
||||||
|
nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg));
|
||||||
|
nfh->nfgen_family = AF_INET;
|
||||||
|
nfh->version = NFNETLINK_V0;
|
||||||
|
nfh->res_id = 0;
|
||||||
|
|
||||||
|
ret = mnl_socket_sendto(nl, nlh, nlh->nlmsg_len);
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("mnl_socket_sendto");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
portid = mnl_socket_get_portid(nl);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("mnl_socket_recvfrom");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_cb_run(buf, ret, seq, portid, data_cb, NULL);
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("mnl_cb_run");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
} else if (ret <= MNL_CB_STOP)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mnl_socket_close(nl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
240
deps/libmnl/examples/netfilter/nfct-event.c
vendored
Normal file
240
deps/libmnl/examples/netfilter/nfct-event.c
vendored
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
/* This example is placed in the public domain. */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <linux/netfilter/nfnetlink.h>
|
||||||
|
#include <linux/netfilter/nfnetlink_conntrack.h>
|
||||||
|
|
||||||
|
static int parse_ip_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
if (mnl_attr_type_valid(attr, CTA_IP_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case CTA_IP_V4_SRC:
|
||||||
|
case CTA_IP_V4_DST:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tb[type] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_ip(const struct nlattr *nest)
|
||||||
|
{
|
||||||
|
struct nlattr *tb[CTA_IP_MAX+1] = {};
|
||||||
|
|
||||||
|
mnl_attr_parse_nested(nest, parse_ip_cb, tb);
|
||||||
|
if (tb[CTA_IP_V4_SRC]) {
|
||||||
|
struct in_addr *in = mnl_attr_get_payload(tb[CTA_IP_V4_SRC]);
|
||||||
|
printf("src=%s ", inet_ntoa(*in));
|
||||||
|
}
|
||||||
|
if (tb[CTA_IP_V4_DST]) {
|
||||||
|
struct in_addr *in = mnl_attr_get_payload(tb[CTA_IP_V4_DST]);
|
||||||
|
printf("dst=%s ", inet_ntoa(*in));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_proto_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
if (mnl_attr_type_valid(attr, CTA_PROTO_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case CTA_PROTO_NUM:
|
||||||
|
case CTA_PROTO_ICMP_TYPE:
|
||||||
|
case CTA_PROTO_ICMP_CODE:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CTA_PROTO_SRC_PORT:
|
||||||
|
case CTA_PROTO_DST_PORT:
|
||||||
|
case CTA_PROTO_ICMP_ID:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tb[type] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_proto(const struct nlattr *nest)
|
||||||
|
{
|
||||||
|
struct nlattr *tb[CTA_PROTO_MAX+1] = {};
|
||||||
|
|
||||||
|
mnl_attr_parse_nested(nest, parse_proto_cb, tb);
|
||||||
|
if (tb[CTA_PROTO_NUM]) {
|
||||||
|
printf("proto=%u ", mnl_attr_get_u8(tb[CTA_PROTO_NUM]));
|
||||||
|
}
|
||||||
|
if (tb[CTA_PROTO_SRC_PORT]) {
|
||||||
|
printf("sport=%u ",
|
||||||
|
ntohs(mnl_attr_get_u16(tb[CTA_PROTO_SRC_PORT])));
|
||||||
|
}
|
||||||
|
if (tb[CTA_PROTO_DST_PORT]) {
|
||||||
|
printf("dport=%u ",
|
||||||
|
ntohs(mnl_attr_get_u16(tb[CTA_PROTO_DST_PORT])));
|
||||||
|
}
|
||||||
|
if (tb[CTA_PROTO_ICMP_ID]) {
|
||||||
|
printf("id=%u ",
|
||||||
|
ntohs(mnl_attr_get_u16(tb[CTA_PROTO_ICMP_ID])));
|
||||||
|
}
|
||||||
|
if (tb[CTA_PROTO_ICMP_TYPE]) {
|
||||||
|
printf("type=%u ", mnl_attr_get_u8(tb[CTA_PROTO_ICMP_TYPE]));
|
||||||
|
}
|
||||||
|
if (tb[CTA_PROTO_ICMP_CODE]) {
|
||||||
|
printf("code=%u ", mnl_attr_get_u8(tb[CTA_PROTO_ICMP_CODE]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_tuple_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
if (mnl_attr_type_valid(attr, CTA_TUPLE_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case CTA_TUPLE_IP:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CTA_TUPLE_PROTO:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tb[type] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_tuple(const struct nlattr *nest)
|
||||||
|
{
|
||||||
|
struct nlattr *tb[CTA_TUPLE_MAX+1] = {};
|
||||||
|
|
||||||
|
mnl_attr_parse_nested(nest, parse_tuple_cb, tb);
|
||||||
|
if (tb[CTA_TUPLE_IP]) {
|
||||||
|
print_ip(tb[CTA_TUPLE_IP]);
|
||||||
|
}
|
||||||
|
if (tb[CTA_TUPLE_PROTO]) {
|
||||||
|
print_proto(tb[CTA_TUPLE_PROTO]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int data_attr_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
if (mnl_attr_type_valid(attr, CTA_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case CTA_TUPLE_ORIG:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CTA_TIMEOUT:
|
||||||
|
case CTA_MARK:
|
||||||
|
case CTA_SECMARK:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tb[type] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int data_cb(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
struct nlattr *tb[CTA_MAX+1] = {};
|
||||||
|
struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
|
||||||
|
|
||||||
|
switch(nlh->nlmsg_type & 0xFF) {
|
||||||
|
case IPCTNL_MSG_CT_NEW:
|
||||||
|
if (nlh->nlmsg_flags & (NLM_F_CREATE|NLM_F_EXCL))
|
||||||
|
printf("%9s ", "[NEW] ");
|
||||||
|
else
|
||||||
|
printf("%9s ", "[UPDATE] ");
|
||||||
|
break;
|
||||||
|
case IPCTNL_MSG_CT_DELETE:
|
||||||
|
printf("%9s ", "[DESTROY] ");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mnl_attr_parse(nlh, sizeof(*nfg), data_attr_cb, tb);
|
||||||
|
if (tb[CTA_TUPLE_ORIG]) {
|
||||||
|
print_tuple(tb[CTA_TUPLE_ORIG]);
|
||||||
|
}
|
||||||
|
if (tb[CTA_MARK]) {
|
||||||
|
printf("mark=%u ", ntohl(mnl_attr_get_u32(tb[CTA_MARK])));
|
||||||
|
}
|
||||||
|
if (tb[CTA_SECMARK]) {
|
||||||
|
printf("secmark=%u ", ntohl(mnl_attr_get_u32(tb[CTA_SECMARK])));
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
struct mnl_socket *nl;
|
||||||
|
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
nl = mnl_socket_open(NETLINK_NETFILTER);
|
||||||
|
if (nl == NULL) {
|
||||||
|
perror("mnl_socket_open");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mnl_socket_bind(nl, NF_NETLINK_CONNTRACK_NEW |
|
||||||
|
NF_NETLINK_CONNTRACK_UPDATE |
|
||||||
|
NF_NETLINK_CONNTRACK_DESTROY,
|
||||||
|
MNL_SOCKET_AUTOPID) < 0) {
|
||||||
|
perror("mnl_socket_bind");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("mnl_socket_recvfrom");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_cb_run(buf, ret, 0, 0, data_cb, NULL);
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("mnl_cb_run");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mnl_socket_close(nl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
12
deps/libmnl/examples/rtnl/.gitignore
vendored
Normal file
12
deps/libmnl/examples/rtnl/.gitignore
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/rtnl-addr-add
|
||||||
|
/rtnl-addr-dump
|
||||||
|
/rtnl-link-can
|
||||||
|
/rtnl-link-dump
|
||||||
|
/rtnl-link-dump2
|
||||||
|
/rtnl-link-dump3
|
||||||
|
/rtnl-link-event
|
||||||
|
/rtnl-link-set
|
||||||
|
/rtnl-neigh-dump
|
||||||
|
/rtnl-route-event
|
||||||
|
/rtnl-route-add
|
||||||
|
/rtnl-route-dump
|
||||||
48
deps/libmnl/examples/rtnl/Makefile.am
vendored
Normal file
48
deps/libmnl/examples/rtnl/Makefile.am
vendored
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
include $(top_srcdir)/Make_global.am
|
||||||
|
|
||||||
|
check_PROGRAMS = rtnl-addr-add \
|
||||||
|
rtnl-addr-dump \
|
||||||
|
rtnl-link-can \
|
||||||
|
rtnl-link-dump rtnl-link-dump2 rtnl-link-dump3 \
|
||||||
|
rtnl-link-event \
|
||||||
|
rtnl-link-set \
|
||||||
|
rtnl-route-add \
|
||||||
|
rtnl-route-dump \
|
||||||
|
rtnl-route-event \
|
||||||
|
rtnl-neigh-dump
|
||||||
|
|
||||||
|
rtnl_addr_add_SOURCES = rtnl-addr-add.c
|
||||||
|
rtnl_addr_add_LDADD = ../../src/libmnl.la
|
||||||
|
|
||||||
|
rtnl_link_can_SOURCES = rtnl-link-can.c
|
||||||
|
rtnl_link_can_LDADD = ../../src/libmnl.la
|
||||||
|
|
||||||
|
rtnl_addr_dump_SOURCES = rtnl-addr-dump.c
|
||||||
|
rtnl_addr_dump_LDADD = ../../src/libmnl.la
|
||||||
|
|
||||||
|
rtnl_link_dump_SOURCES = rtnl-link-dump.c
|
||||||
|
rtnl_link_dump_LDADD = ../../src/libmnl.la
|
||||||
|
|
||||||
|
rtnl_link_dump2_SOURCES = rtnl-link-dump2.c
|
||||||
|
rtnl_link_dump2_LDADD = ../../src/libmnl.la
|
||||||
|
|
||||||
|
rtnl_link_dump3_SOURCES = rtnl-link-dump3.c
|
||||||
|
rtnl_link_dump3_LDADD = ../../src/libmnl.la
|
||||||
|
|
||||||
|
rtnl_route_add_SOURCES = rtnl-route-add.c
|
||||||
|
rtnl_route_add_LDADD = ../../src/libmnl.la
|
||||||
|
|
||||||
|
rtnl_link_event_SOURCES = rtnl-link-event.c
|
||||||
|
rtnl_link_event_LDADD = ../../src/libmnl.la
|
||||||
|
|
||||||
|
rtnl_link_set_SOURCES = rtnl-link-set.c
|
||||||
|
rtnl_link_set_LDADD = ../../src/libmnl.la
|
||||||
|
|
||||||
|
rtnl_route_dump_SOURCES = rtnl-route-dump.c
|
||||||
|
rtnl_route_dump_LDADD = ../../src/libmnl.la
|
||||||
|
|
||||||
|
rtnl_route_event_SOURCES = rtnl-route-event.c
|
||||||
|
rtnl_route_event_LDADD = ../../src/libmnl.la
|
||||||
|
|
||||||
|
rtnl_neigh_dump_SOURCES = rtnl-neigh-dump.c
|
||||||
|
rtnl_neigh_dump_LDADD = ../../src/libmnl.la
|
||||||
119
deps/libmnl/examples/rtnl/rtnl-addr-add.c
vendored
Normal file
119
deps/libmnl/examples/rtnl/rtnl-addr-add.c
vendored
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
/* This example is placed in the public domain. */
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <linux/if_link.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct mnl_socket *nl;
|
||||||
|
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
struct ifaddrmsg *ifm;
|
||||||
|
uint32_t seq, portid;
|
||||||
|
union {
|
||||||
|
in_addr_t ip;
|
||||||
|
struct in6_addr ip6;
|
||||||
|
} addr;
|
||||||
|
int ret, family = AF_INET;
|
||||||
|
|
||||||
|
uint32_t prefix;
|
||||||
|
int iface;
|
||||||
|
|
||||||
|
|
||||||
|
if (argc <= 3) {
|
||||||
|
printf("Usage: %s iface destination cidr\n", argv[0]);
|
||||||
|
printf("Example: %s eth0 10.0.1.12 32\n", argv[0]);
|
||||||
|
printf(" %s eth0 ffff::10.0.1.12 128\n", argv[0]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
iface = if_nametoindex(argv[1]);
|
||||||
|
if (iface == 0) {
|
||||||
|
perror("if_nametoindex");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!inet_pton(AF_INET, argv[2], &addr)) {
|
||||||
|
if (!inet_pton(AF_INET6, argv[2], &addr)) {
|
||||||
|
perror("inet_pton");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
family = AF_INET6;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sscanf(argv[3], "%u", &prefix) == 0) {
|
||||||
|
perror("sscanf");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
nlh = mnl_nlmsg_put_header(buf);
|
||||||
|
nlh->nlmsg_type = RTM_NEWADDR;
|
||||||
|
|
||||||
|
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE | NLM_F_ACK;
|
||||||
|
nlh->nlmsg_seq = seq = time(NULL);
|
||||||
|
|
||||||
|
ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(struct ifaddrmsg));
|
||||||
|
|
||||||
|
ifm->ifa_family = family;
|
||||||
|
ifm->ifa_prefixlen = prefix;
|
||||||
|
ifm->ifa_flags = IFA_F_PERMANENT;
|
||||||
|
|
||||||
|
ifm->ifa_scope = RT_SCOPE_UNIVERSE;
|
||||||
|
ifm->ifa_index = iface;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The exact meaning of IFA_LOCAL and IFA_ADDRESS depend
|
||||||
|
* on the address family being used and the device type.
|
||||||
|
* For broadcast devices (like the interfaces we use),
|
||||||
|
* for IPv4 we specify both and they are used interchangeably.
|
||||||
|
* For IPv6, only IFA_ADDRESS needs to be set.
|
||||||
|
*/
|
||||||
|
if (family == AF_INET) {
|
||||||
|
mnl_attr_put_u32(nlh, IFA_LOCAL, addr.ip);
|
||||||
|
mnl_attr_put_u32(nlh, IFA_ADDRESS, addr.ip);
|
||||||
|
} else {
|
||||||
|
mnl_attr_put(nlh, IFA_ADDRESS, sizeof(struct in6_addr), &addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
nl = mnl_socket_open(NETLINK_ROUTE);
|
||||||
|
if (nl == NULL) {
|
||||||
|
perror("mnl_socket_open");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||||
|
perror("mnl_socket_bind");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
portid = mnl_socket_get_portid(nl);
|
||||||
|
|
||||||
|
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||||
|
perror("mnl_socket_sendto");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
if (ret < 0) {
|
||||||
|
perror("mnl_socket_recvfrom");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
|
||||||
|
if (ret < 0) {
|
||||||
|
perror("mnl_cb_run");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
mnl_socket_close(nl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
133
deps/libmnl/examples/rtnl/rtnl-addr-dump.c
vendored
Normal file
133
deps/libmnl/examples/rtnl/rtnl-addr-dump.c
vendored
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
/* This example is placed in the public domain. */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <linux/if.h>
|
||||||
|
#include <linux/if_link.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
|
||||||
|
static int data_attr_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
/* skip unsupported attribute in user-space */
|
||||||
|
if (mnl_attr_type_valid(attr, IFA_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case IFA_ADDRESS:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tb[type] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int data_cb(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
struct nlattr *tb[IFA_MAX + 1] = {};
|
||||||
|
struct ifaddrmsg *ifa = mnl_nlmsg_get_payload(nlh);
|
||||||
|
|
||||||
|
printf("index=%d family=%d ", ifa->ifa_index, ifa->ifa_family);
|
||||||
|
|
||||||
|
mnl_attr_parse(nlh, sizeof(*ifa), data_attr_cb, tb);
|
||||||
|
printf("addr=");
|
||||||
|
if (tb[IFA_ADDRESS]) {
|
||||||
|
void *addr = mnl_attr_get_payload(tb[IFA_ADDRESS]);
|
||||||
|
char out[INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
|
if (inet_ntop(ifa->ifa_family, addr, out, sizeof(out)))
|
||||||
|
printf("%s ", out);
|
||||||
|
}
|
||||||
|
printf("scope=");
|
||||||
|
switch(ifa->ifa_scope) {
|
||||||
|
case 0:
|
||||||
|
printf("global ");
|
||||||
|
break;
|
||||||
|
case 200:
|
||||||
|
printf("site ");
|
||||||
|
break;
|
||||||
|
case 253:
|
||||||
|
printf("link ");
|
||||||
|
break;
|
||||||
|
case 254:
|
||||||
|
printf("host ");
|
||||||
|
break;
|
||||||
|
case 255:
|
||||||
|
printf("nowhere ");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("%d ", ifa->ifa_scope);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char buf[MNL_SOCKET_DUMP_SIZE];
|
||||||
|
unsigned int seq, portid;
|
||||||
|
struct mnl_socket *nl;
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
struct rtgenmsg *rt;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
fprintf(stderr, "Usage: %s <inet|inet6>\n", argv[0]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
nlh = mnl_nlmsg_put_header(buf);
|
||||||
|
nlh->nlmsg_type = RTM_GETADDR;
|
||||||
|
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
|
||||||
|
nlh->nlmsg_seq = seq = time(NULL);
|
||||||
|
rt = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtgenmsg));
|
||||||
|
if (strcmp(argv[1], "inet") == 0)
|
||||||
|
rt->rtgen_family = AF_INET;
|
||||||
|
else if (strcmp(argv[1], "inet6") == 0)
|
||||||
|
rt->rtgen_family = AF_INET6;
|
||||||
|
|
||||||
|
nl = mnl_socket_open(NETLINK_ROUTE);
|
||||||
|
if (nl == NULL) {
|
||||||
|
perror("mnl_socket_open");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||||
|
perror("mnl_socket_bind");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
portid = mnl_socket_get_portid(nl);
|
||||||
|
|
||||||
|
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||||
|
perror("mnl_socket_sendto");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
while (ret > 0) {
|
||||||
|
ret = mnl_cb_run(buf, ret, seq, portid, data_cb, NULL);
|
||||||
|
if (ret <= MNL_CB_STOP)
|
||||||
|
break;
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
}
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("error");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
mnl_socket_close(nl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
452
deps/libmnl/examples/rtnl/rtnl-link-can.c
vendored
Normal file
452
deps/libmnl/examples/rtnl/rtnl-link-can.c
vendored
Normal file
@@ -0,0 +1,452 @@
|
|||||||
|
/* This example is placed in the public domain. */
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <linux/can/netlink.h>
|
||||||
|
#include <linux/if.h>
|
||||||
|
#include <linux/if_link.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
|
||||||
|
static void incomplete_command(void) __attribute__((noreturn));
|
||||||
|
|
||||||
|
#define NEXT_ARG() \
|
||||||
|
do { \
|
||||||
|
if (argc <= 0) incomplete_command(); \
|
||||||
|
argv++; \
|
||||||
|
argc--; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
static void duparg2(const char *key, const char *arg)
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"Error: either \"%s\" is duplicate, or \"%s\" is a garbage.\n",
|
||||||
|
key, arg);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void incomplete_command(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Command line is not complete. Try option \"help\"\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns false if 'prefix' is a not empty prefix of 'string'.
|
||||||
|
*/
|
||||||
|
static bool matches(const char *prefix, const char *string)
|
||||||
|
{
|
||||||
|
if (!*prefix)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
while (*string && *prefix == *string) {
|
||||||
|
prefix++;
|
||||||
|
string++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !!*prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_u16(__u16 *val, const char *arg, int base)
|
||||||
|
{
|
||||||
|
unsigned long res;
|
||||||
|
char *ptr;
|
||||||
|
|
||||||
|
if (!arg || !*arg)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
res = strtoul(arg, &ptr, base);
|
||||||
|
|
||||||
|
/* empty string or trailing non-digits */
|
||||||
|
if (!ptr || ptr == arg || *ptr)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* overflow */
|
||||||
|
if (res == ULONG_MAX && errno == ERANGE)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (res > 0xFFFFUL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*val = res;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_u32(__u32 *val, const char *arg, int base)
|
||||||
|
{
|
||||||
|
unsigned long res;
|
||||||
|
char *ptr;
|
||||||
|
|
||||||
|
if (!arg || !*arg)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
res = strtoul(arg, &ptr, base);
|
||||||
|
|
||||||
|
/* empty string or trailing non-digits */
|
||||||
|
if (!ptr || ptr == arg || *ptr)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* overflow */
|
||||||
|
if (res == ULONG_MAX && errno == ERANGE)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* in case UL > 32 bits */
|
||||||
|
if (res > 0xFFFFFFFFUL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*val = res;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_float(float *val, const char *arg)
|
||||||
|
{
|
||||||
|
float res;
|
||||||
|
char *ptr;
|
||||||
|
|
||||||
|
if (!arg || !*arg)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
res = strtof(arg, &ptr);
|
||||||
|
if (!ptr || ptr == arg || *ptr)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*val = res;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_ctrlmode(char *name, char *arg,
|
||||||
|
struct can_ctrlmode *cm, __u32 flags)
|
||||||
|
{
|
||||||
|
if (strcmp(arg, "on") == 0) {
|
||||||
|
cm->flags |= flags;
|
||||||
|
} else if (strcmp(arg, "off") != 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Error: argument of \"%s\" must be \"on\" or \"off\", not \"%s\"\n",
|
||||||
|
name, arg);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
cm->mask |= flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void invarg(const char *msg, const char *arg)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error: argument \"%s\" is wrong: %s\n", arg, msg);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_usage(FILE *f)
|
||||||
|
{
|
||||||
|
fprintf(f,
|
||||||
|
"Usage: ip link set DEVICE type can\n"
|
||||||
|
"\t[ bitrate BITRATE [ sample-point SAMPLE-POINT] ] |\n"
|
||||||
|
"\t[ tq TQ prop-seg PROP_SEG phase-seg1 PHASE-SEG1\n \t phase-seg2 PHASE-SEG2 [ sjw SJW ] ]\n"
|
||||||
|
"\n"
|
||||||
|
"\t[ dbitrate BITRATE [ dsample-point SAMPLE-POINT] ] |\n"
|
||||||
|
"\t[ dtq TQ dprop-seg PROP_SEG dphase-seg1 PHASE-SEG1\n \t dphase-seg2 PHASE-SEG2 [ dsjw SJW ] ]\n"
|
||||||
|
"\n"
|
||||||
|
"\t[ loopback { on | off } ]\n"
|
||||||
|
"\t[ listen-only { on | off } ]\n"
|
||||||
|
"\t[ triple-sampling { on | off } ]\n"
|
||||||
|
"\t[ one-shot { on | off } ]\n"
|
||||||
|
"\t[ berr-reporting { on | off } ]\n"
|
||||||
|
"\t[ fd { on | off } ]\n"
|
||||||
|
"\t[ fd-non-iso { on | off } ]\n"
|
||||||
|
"\t[ presume-ack { on | off } ]\n"
|
||||||
|
"\t[ cc-len8-dlc { on | off } ]\n"
|
||||||
|
"\n"
|
||||||
|
"\t[ restart-ms TIME-MS ]\n"
|
||||||
|
"\t[ restart ]\n"
|
||||||
|
"\n"
|
||||||
|
"\t[ termination { 0..65535 } ]\n"
|
||||||
|
"\n"
|
||||||
|
"\tWhere: BITRATE := { 1..1000000 }\n"
|
||||||
|
"\t SAMPLE-POINT := { 0.000..0.999 }\n"
|
||||||
|
"\t TQ := { NUMBER }\n"
|
||||||
|
"\t PROP-SEG := { 1..8 }\n"
|
||||||
|
"\t PHASE-SEG1 := { 1..8 }\n"
|
||||||
|
"\t PHASE-SEG2 := { 1..8 }\n"
|
||||||
|
"\t SJW := { 1..4 }\n"
|
||||||
|
"\t RESTART-MS := { 0 | NUMBER }\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usage(void)
|
||||||
|
{
|
||||||
|
print_usage(stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int iplink_set_can_parse(int argc, char **argv, struct nlmsghdr *nlh)
|
||||||
|
{
|
||||||
|
struct can_bittiming bt = {}, dbt = {};
|
||||||
|
struct can_ctrlmode cm = {};
|
||||||
|
|
||||||
|
while (argc > 0) {
|
||||||
|
if (matches(*argv, "bitrate") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
if (get_u32(&bt.bitrate, *argv, 0))
|
||||||
|
invarg("invalid \"bitrate\" value\n", *argv);
|
||||||
|
} else if (matches(*argv, "sample-point") == 0) {
|
||||||
|
float sp;
|
||||||
|
|
||||||
|
NEXT_ARG();
|
||||||
|
if (get_float(&sp, *argv))
|
||||||
|
invarg("invalid \"sample-point\" value\n",
|
||||||
|
*argv);
|
||||||
|
|
||||||
|
bt.sample_point = (__u32)(sp * 1000);
|
||||||
|
} else if (matches(*argv, "tq") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
if (get_u32(&bt.tq, *argv, 0))
|
||||||
|
invarg("invalid \"tq\" value\n", *argv);
|
||||||
|
} else if (matches(*argv, "prop-seg") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
if (get_u32(&bt.prop_seg, *argv, 0))
|
||||||
|
invarg("invalid \"prop-seg\" value\n", *argv);
|
||||||
|
} else if (matches(*argv, "phase-seg1") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
if (get_u32(&bt.phase_seg1, *argv, 0))
|
||||||
|
invarg("invalid \"phase-seg1\" value\n", *argv);
|
||||||
|
} else if (matches(*argv, "phase-seg2") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
if (get_u32(&bt.phase_seg2, *argv, 0))
|
||||||
|
invarg("invalid \"phase-seg2\" value\n", *argv);
|
||||||
|
} else if (matches(*argv, "sjw") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
if (get_u32(&bt.sjw, *argv, 0))
|
||||||
|
invarg("invalid \"sjw\" value\n", *argv);
|
||||||
|
} else if (matches(*argv, "dbitrate") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
if (get_u32(&dbt.bitrate, *argv, 0))
|
||||||
|
invarg("invalid \"dbitrate\" value\n", *argv);
|
||||||
|
} else if (matches(*argv, "dsample-point") == 0) {
|
||||||
|
float sp;
|
||||||
|
|
||||||
|
NEXT_ARG();
|
||||||
|
if (get_float(&sp, *argv))
|
||||||
|
invarg("invalid \"dsample-point\" value\n", *argv);
|
||||||
|
dbt.sample_point = (__u32)(sp * 1000);
|
||||||
|
} else if (matches(*argv, "dtq") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
if (get_u32(&dbt.tq, *argv, 0))
|
||||||
|
invarg("invalid \"dtq\" value\n", *argv);
|
||||||
|
} else if (matches(*argv, "dprop-seg") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
if (get_u32(&dbt.prop_seg, *argv, 0))
|
||||||
|
invarg("invalid \"dprop-seg\" value\n", *argv);
|
||||||
|
} else if (matches(*argv, "dphase-seg1") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
if (get_u32(&dbt.phase_seg1, *argv, 0))
|
||||||
|
invarg("invalid \"dphase-seg1\" value\n", *argv);
|
||||||
|
} else if (matches(*argv, "dphase-seg2") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
if (get_u32(&dbt.phase_seg2, *argv, 0))
|
||||||
|
invarg("invalid \"dphase-seg2\" value\n", *argv);
|
||||||
|
} else if (matches(*argv, "dsjw") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
if (get_u32(&dbt.sjw, *argv, 0))
|
||||||
|
invarg("invalid \"dsjw\" value\n", *argv);
|
||||||
|
} else if (matches(*argv, "loopback") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
set_ctrlmode("loopback", *argv, &cm,
|
||||||
|
CAN_CTRLMODE_LOOPBACK);
|
||||||
|
} else if (matches(*argv, "listen-only") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
set_ctrlmode("listen-only", *argv, &cm,
|
||||||
|
CAN_CTRLMODE_LISTENONLY);
|
||||||
|
} else if (matches(*argv, "triple-sampling") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
set_ctrlmode("triple-sampling", *argv, &cm,
|
||||||
|
CAN_CTRLMODE_3_SAMPLES);
|
||||||
|
} else if (matches(*argv, "one-shot") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
set_ctrlmode("one-shot", *argv, &cm,
|
||||||
|
CAN_CTRLMODE_ONE_SHOT);
|
||||||
|
} else if (matches(*argv, "berr-reporting") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
set_ctrlmode("berr-reporting", *argv, &cm,
|
||||||
|
CAN_CTRLMODE_BERR_REPORTING);
|
||||||
|
} else if (matches(*argv, "fd") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
set_ctrlmode("fd", *argv, &cm,
|
||||||
|
CAN_CTRLMODE_FD);
|
||||||
|
} else if (matches(*argv, "fd-non-iso") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
set_ctrlmode("fd-non-iso", *argv, &cm,
|
||||||
|
CAN_CTRLMODE_FD_NON_ISO);
|
||||||
|
} else if (matches(*argv, "presume-ack") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
set_ctrlmode("presume-ack", *argv, &cm,
|
||||||
|
CAN_CTRLMODE_PRESUME_ACK);
|
||||||
|
#if defined(CAN_CTRLMODE_CC_LEN8_DLC)
|
||||||
|
} else if (matches(*argv, "cc-len8-dlc") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
set_ctrlmode("cc-len8-dlc", *argv, &cm,
|
||||||
|
CAN_CTRLMODE_CC_LEN8_DLC);
|
||||||
|
#endif
|
||||||
|
} else if (matches(*argv, "restart") == 0) {
|
||||||
|
__u32 val = 1;
|
||||||
|
|
||||||
|
mnl_attr_put(nlh, IFLA_CAN_RESTART, sizeof(val), &val);
|
||||||
|
} else if (matches(*argv, "restart-ms") == 0) {
|
||||||
|
__u32 val;
|
||||||
|
|
||||||
|
NEXT_ARG();
|
||||||
|
if (get_u32(&val, *argv, 0))
|
||||||
|
invarg("invalid \"restart-ms\" value\n", *argv);
|
||||||
|
|
||||||
|
mnl_attr_put(nlh, IFLA_CAN_RESTART_MS, sizeof(val), &val);
|
||||||
|
} else if (matches(*argv, "termination") == 0) {
|
||||||
|
__u16 val;
|
||||||
|
|
||||||
|
NEXT_ARG();
|
||||||
|
if (get_u16(&val, *argv, 0))
|
||||||
|
invarg("invalid \"termination\" value\n",
|
||||||
|
*argv);
|
||||||
|
|
||||||
|
mnl_attr_put(nlh, IFLA_CAN_TERMINATION, sizeof(val), &val);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "unknown option \"%s\"\n", *argv);
|
||||||
|
usage();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
NEXT_ARG();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bt.bitrate || bt.tq)
|
||||||
|
mnl_attr_put(nlh, IFLA_CAN_BITTIMING, sizeof(bt), &bt);
|
||||||
|
|
||||||
|
if (cm.mask)
|
||||||
|
mnl_attr_put(nlh, IFLA_CAN_CTRLMODE, sizeof(cm), &cm);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||||
|
struct mnl_socket *nl;
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
struct ifinfomsg *ifm;
|
||||||
|
int ret;
|
||||||
|
unsigned int seq, portid;
|
||||||
|
struct nlattr *linkinfo, *data;
|
||||||
|
const char *signatures[] = {
|
||||||
|
"ip", "link", "set", ""
|
||||||
|
};
|
||||||
|
char *type = NULL;
|
||||||
|
char *dev = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
NEXT_ARG();
|
||||||
|
for (i = 0; argc > 0 && signatures[i][0];) {
|
||||||
|
if (matches(*argv, signatures[i]))
|
||||||
|
incomplete_command();
|
||||||
|
|
||||||
|
NEXT_ARG();
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc == 0)
|
||||||
|
incomplete_command();
|
||||||
|
|
||||||
|
nlh = mnl_nlmsg_put_header(buf);
|
||||||
|
nlh->nlmsg_type = RTM_NEWLINK;
|
||||||
|
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||||
|
nlh->nlmsg_seq = seq = time(NULL);
|
||||||
|
ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm));
|
||||||
|
ifm->ifi_family = AF_UNSPEC;
|
||||||
|
ifm->ifi_change = 0;
|
||||||
|
ifm->ifi_flags = 0;
|
||||||
|
|
||||||
|
while (argc > 0) {
|
||||||
|
if (matches(*argv, "up") == 0) {
|
||||||
|
ifm->ifi_change |= IFF_UP;
|
||||||
|
ifm->ifi_flags |= IFF_UP;
|
||||||
|
} else if (matches(*argv, "down") == 0) {
|
||||||
|
ifm->ifi_change |= IFF_UP;
|
||||||
|
ifm->ifi_flags &= ~IFF_UP;
|
||||||
|
} else if (matches(*argv, "type") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
type = *argv;
|
||||||
|
NEXT_ARG();
|
||||||
|
break;
|
||||||
|
} else if (matches(*argv, "help") == 0) {
|
||||||
|
usage();
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
} else {
|
||||||
|
if (matches(*argv, "dev") == 0)
|
||||||
|
NEXT_ARG();
|
||||||
|
|
||||||
|
if (dev)
|
||||||
|
duparg2("dev", *argv);
|
||||||
|
|
||||||
|
dev = *argv;
|
||||||
|
}
|
||||||
|
|
||||||
|
NEXT_ARG();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dev)
|
||||||
|
mnl_attr_put_str(nlh, IFLA_IFNAME, dev);
|
||||||
|
|
||||||
|
if (type) {
|
||||||
|
if (matches(type, "can")) {
|
||||||
|
fprintf(stderr, "unknown type \"%s\"\n", type);
|
||||||
|
usage();
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
linkinfo = mnl_attr_nest_start(nlh, IFLA_LINKINFO);
|
||||||
|
mnl_attr_put_str(nlh, IFLA_INFO_KIND, "can");
|
||||||
|
data = mnl_attr_nest_start(nlh, IFLA_INFO_DATA);
|
||||||
|
|
||||||
|
if (iplink_set_can_parse(argc, argv, nlh))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
mnl_attr_nest_end(nlh, data);
|
||||||
|
mnl_attr_nest_end(nlh, linkinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
nl = mnl_socket_open(NETLINK_ROUTE);
|
||||||
|
if (nl == NULL) {
|
||||||
|
perror("mnl_socket_open");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||||
|
perror("mnl_socket_bind");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
portid = mnl_socket_get_portid(nl);
|
||||||
|
|
||||||
|
mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len,
|
||||||
|
sizeof(struct ifinfomsg));
|
||||||
|
|
||||||
|
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||||
|
perror("mnl_socket_sendto");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("mnl_socket_recvfrom");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("mnl_cb_run");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
mnl_socket_close(nl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
130
deps/libmnl/examples/rtnl/rtnl-link-dump.c
vendored
Normal file
130
deps/libmnl/examples/rtnl/rtnl-link-dump.c
vendored
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
/* This example is placed in the public domain. */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <linux/if.h>
|
||||||
|
#include <linux/if_link.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
|
||||||
|
static int data_attr_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
/* skip unsupported attribute in user-space */
|
||||||
|
if (mnl_attr_type_valid(attr, IFLA_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case IFLA_ADDRESS:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IFLA_MTU:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IFLA_IFNAME:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tb[type] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int data_cb(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
struct nlattr *tb[IFLA_MAX+1] = {};
|
||||||
|
struct ifinfomsg *ifm = mnl_nlmsg_get_payload(nlh);
|
||||||
|
|
||||||
|
printf("index=%d type=%d flags=%d family=%d ",
|
||||||
|
ifm->ifi_index, ifm->ifi_type,
|
||||||
|
ifm->ifi_flags, ifm->ifi_family);
|
||||||
|
|
||||||
|
if (ifm->ifi_flags & IFF_RUNNING)
|
||||||
|
printf("[RUNNING] ");
|
||||||
|
else
|
||||||
|
printf("[NOT RUNNING] ");
|
||||||
|
|
||||||
|
mnl_attr_parse(nlh, sizeof(*ifm), data_attr_cb, tb);
|
||||||
|
if (tb[IFLA_MTU]) {
|
||||||
|
printf("mtu=%d ", mnl_attr_get_u32(tb[IFLA_MTU]));
|
||||||
|
}
|
||||||
|
if (tb[IFLA_IFNAME]) {
|
||||||
|
printf("name=%s ", mnl_attr_get_str(tb[IFLA_IFNAME]));
|
||||||
|
}
|
||||||
|
if (tb[IFLA_ADDRESS]) {
|
||||||
|
uint8_t *hwaddr = mnl_attr_get_payload(tb[IFLA_ADDRESS]);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
printf("hwaddr=");
|
||||||
|
for (i=0; i<mnl_attr_get_payload_len(tb[IFLA_ADDRESS]); i++) {
|
||||||
|
printf("%.2x", hwaddr[i] & 0xff);
|
||||||
|
if (i+1 != mnl_attr_get_payload_len(tb[IFLA_ADDRESS]))
|
||||||
|
printf(":");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
char buf[MNL_SOCKET_DUMP_SIZE];
|
||||||
|
unsigned int seq, portid;
|
||||||
|
struct mnl_socket *nl;
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
struct rtgenmsg *rt;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
nlh = mnl_nlmsg_put_header(buf);
|
||||||
|
nlh->nlmsg_type = RTM_GETLINK;
|
||||||
|
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
|
||||||
|
nlh->nlmsg_seq = seq = time(NULL);
|
||||||
|
rt = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtgenmsg));
|
||||||
|
rt->rtgen_family = AF_PACKET;
|
||||||
|
|
||||||
|
nl = mnl_socket_open(NETLINK_ROUTE);
|
||||||
|
if (nl == NULL) {
|
||||||
|
perror("mnl_socket_open");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||||
|
perror("mnl_socket_bind");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
portid = mnl_socket_get_portid(nl);
|
||||||
|
|
||||||
|
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||||
|
perror("mnl_socket_sendto");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
while (ret > 0) {
|
||||||
|
ret = mnl_cb_run(buf, ret, seq, portid, data_cb, NULL);
|
||||||
|
if (ret <= MNL_CB_STOP)
|
||||||
|
break;
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
}
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("error");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
mnl_socket_close(nl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
103
deps/libmnl/examples/rtnl/rtnl-link-dump2.c
vendored
Normal file
103
deps/libmnl/examples/rtnl/rtnl-link-dump2.c
vendored
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
/* This example is placed in the public domain. */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <linux/if.h>
|
||||||
|
#include <linux/if_link.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
|
||||||
|
static int data_attr_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
/* skip unsupported attribute in user-space */
|
||||||
|
if (mnl_attr_type_valid(attr, IFLA_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(mnl_attr_get_type(attr)) {
|
||||||
|
case IFLA_MTU:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
printf("mtu=%d ", mnl_attr_get_u32(attr));
|
||||||
|
break;
|
||||||
|
case IFLA_IFNAME:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
printf("name=%s ", mnl_attr_get_str(attr));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int data_cb(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
struct ifinfomsg *ifm = mnl_nlmsg_get_payload(nlh);
|
||||||
|
|
||||||
|
printf("index=%d type=%d flags=%d family=%d ",
|
||||||
|
ifm->ifi_index, ifm->ifi_type,
|
||||||
|
ifm->ifi_flags, ifm->ifi_family);
|
||||||
|
|
||||||
|
if (ifm->ifi_flags & IFF_RUNNING)
|
||||||
|
printf("[RUNNING] ");
|
||||||
|
else
|
||||||
|
printf("[NOT RUNNING] ");
|
||||||
|
|
||||||
|
mnl_attr_parse(nlh, sizeof(*ifm), data_attr_cb, NULL);
|
||||||
|
printf("\n");
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
char buf[MNL_SOCKET_DUMP_SIZE];
|
||||||
|
unsigned int seq, portid;
|
||||||
|
struct mnl_socket *nl;
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
struct rtgenmsg *rt;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
nlh = mnl_nlmsg_put_header(buf);
|
||||||
|
nlh->nlmsg_type = RTM_GETLINK;
|
||||||
|
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
|
||||||
|
nlh->nlmsg_seq = seq = time(NULL);
|
||||||
|
rt = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtgenmsg));
|
||||||
|
rt->rtgen_family = AF_PACKET;
|
||||||
|
|
||||||
|
nl = mnl_socket_open(NETLINK_ROUTE);
|
||||||
|
if (nl == NULL) {
|
||||||
|
perror("mnl_socket_open");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||||
|
perror("mnl_socket_bind");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
portid = mnl_socket_get_portid(nl);
|
||||||
|
|
||||||
|
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||||
|
perror("mnl_socket_sendto");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
while (ret > 0) {
|
||||||
|
ret = mnl_cb_run(buf, ret, seq, portid, data_cb, NULL);
|
||||||
|
if (ret <= MNL_CB_STOP)
|
||||||
|
break;
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
}
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("error");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
mnl_socket_close(nl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
103
deps/libmnl/examples/rtnl/rtnl-link-dump3.c
vendored
Normal file
103
deps/libmnl/examples/rtnl/rtnl-link-dump3.c
vendored
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
/* This example is placed in the public domain. */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <linux/if.h>
|
||||||
|
#include <linux/if_link.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
|
||||||
|
static int data_cb(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
struct ifinfomsg *ifm = mnl_nlmsg_get_payload(nlh);
|
||||||
|
struct nlattr *attr;
|
||||||
|
|
||||||
|
printf("index=%d type=%d flags=%d family=%d ",
|
||||||
|
ifm->ifi_index, ifm->ifi_type,
|
||||||
|
ifm->ifi_flags, ifm->ifi_family);
|
||||||
|
|
||||||
|
if (ifm->ifi_flags & IFF_RUNNING)
|
||||||
|
printf("[RUNNING] ");
|
||||||
|
else
|
||||||
|
printf("[NOT RUNNING] ");
|
||||||
|
|
||||||
|
mnl_attr_for_each(attr, nlh, sizeof(*ifm)) {
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
/* skip unsupported attribute in user-space */
|
||||||
|
if (mnl_attr_type_valid(attr, IFLA_MAX) < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case IFLA_MTU:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
printf("mtu=%d ", mnl_attr_get_u32(attr));
|
||||||
|
break;
|
||||||
|
case IFLA_IFNAME:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
printf("name=%s ", mnl_attr_get_str(attr));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
char buf[MNL_SOCKET_DUMP_SIZE];
|
||||||
|
unsigned int seq, portid;
|
||||||
|
struct mnl_socket *nl;
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
struct rtgenmsg *rt;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
nlh = mnl_nlmsg_put_header(buf);
|
||||||
|
nlh->nlmsg_type = RTM_GETLINK;
|
||||||
|
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
|
||||||
|
nlh->nlmsg_seq = seq = time(NULL);
|
||||||
|
rt = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtgenmsg));
|
||||||
|
rt->rtgen_family = AF_PACKET;
|
||||||
|
|
||||||
|
nl = mnl_socket_open(NETLINK_ROUTE);
|
||||||
|
if (nl == NULL) {
|
||||||
|
perror("mnl_socket_open");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||||
|
perror("mnl_socket_bind");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
portid = mnl_socket_get_portid(nl);
|
||||||
|
|
||||||
|
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||||
|
perror("mnl_socket_sendto");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
while (ret > 0) {
|
||||||
|
ret = mnl_cb_run(buf, ret, seq, portid, data_cb, NULL);
|
||||||
|
if (ret <= MNL_CB_STOP)
|
||||||
|
break;
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
}
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("error");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
mnl_socket_close(nl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
95
deps/libmnl/examples/rtnl/rtnl-link-event.c
vendored
Normal file
95
deps/libmnl/examples/rtnl/rtnl-link-event.c
vendored
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
/* This example is placed in the public domain. */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <linux/if.h>
|
||||||
|
#include <linux/if_link.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
|
||||||
|
static int data_attr_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
/* skip unsupported attribute in user-space */
|
||||||
|
if (mnl_attr_type_valid(attr, IFLA_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case IFLA_MTU:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IFLA_IFNAME:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tb[type] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int data_cb(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
struct nlattr *tb[IFLA_MAX+1] = {};
|
||||||
|
struct ifinfomsg *ifm = mnl_nlmsg_get_payload(nlh);
|
||||||
|
|
||||||
|
printf("index=%d type=%d flags=%d family=%d ",
|
||||||
|
ifm->ifi_index, ifm->ifi_type,
|
||||||
|
ifm->ifi_flags, ifm->ifi_family);
|
||||||
|
|
||||||
|
if (ifm->ifi_flags & IFF_RUNNING)
|
||||||
|
printf("[RUNNING] ");
|
||||||
|
else
|
||||||
|
printf("[NOT RUNNING] ");
|
||||||
|
|
||||||
|
mnl_attr_parse(nlh, sizeof(*ifm), data_attr_cb, tb);
|
||||||
|
if (tb[IFLA_MTU]) {
|
||||||
|
printf("mtu=%d ", mnl_attr_get_u32(tb[IFLA_MTU]));
|
||||||
|
}
|
||||||
|
if (tb[IFLA_IFNAME]) {
|
||||||
|
printf("name=%s", mnl_attr_get_str(tb[IFLA_IFNAME]));
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
struct mnl_socket *nl;
|
||||||
|
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
nl = mnl_socket_open(NETLINK_ROUTE);
|
||||||
|
if (nl == NULL) {
|
||||||
|
perror("mnl_socket_open");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mnl_socket_bind(nl, RTMGRP_LINK, MNL_SOCKET_AUTOPID) < 0) {
|
||||||
|
perror("mnl_socket_bind");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
while (ret > 0) {
|
||||||
|
ret = mnl_cb_run(buf, ret, 0, 0, data_cb, NULL);
|
||||||
|
if (ret <= 0)
|
||||||
|
break;
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
}
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("error");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
mnl_socket_close(nl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
84
deps/libmnl/examples/rtnl/rtnl-link-set.c
vendored
Normal file
84
deps/libmnl/examples/rtnl/rtnl-link-set.c
vendored
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
/* This example is placed in the public domain. */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <linux/if.h>
|
||||||
|
#include <linux/if_link.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct mnl_socket *nl;
|
||||||
|
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
struct ifinfomsg *ifm;
|
||||||
|
int ret;
|
||||||
|
unsigned int seq, portid, change = 0, flags = 0;
|
||||||
|
|
||||||
|
if (argc != 3) {
|
||||||
|
printf("Usage: %s [ifname] [up|down]\n", argv[0]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strncasecmp(argv[2], "up", strlen("up")) == 0) {
|
||||||
|
change |= IFF_UP;
|
||||||
|
flags |= IFF_UP;
|
||||||
|
} else if (strncasecmp(argv[2], "down", strlen("down")) == 0) {
|
||||||
|
change |= IFF_UP;
|
||||||
|
flags &= ~IFF_UP;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "%s is not `up' nor `down'\n", argv[2]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
nlh = mnl_nlmsg_put_header(buf);
|
||||||
|
nlh->nlmsg_type = RTM_NEWLINK;
|
||||||
|
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||||
|
nlh->nlmsg_seq = seq = time(NULL);
|
||||||
|
ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm));
|
||||||
|
ifm->ifi_family = AF_UNSPEC;
|
||||||
|
ifm->ifi_change = change;
|
||||||
|
ifm->ifi_flags = flags;
|
||||||
|
|
||||||
|
mnl_attr_put_str(nlh, IFLA_IFNAME, argv[1]);
|
||||||
|
|
||||||
|
nl = mnl_socket_open(NETLINK_ROUTE);
|
||||||
|
if (nl == NULL) {
|
||||||
|
perror("mnl_socket_open");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||||
|
perror("mnl_socket_bind");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
portid = mnl_socket_get_portid(nl);
|
||||||
|
|
||||||
|
mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len,
|
||||||
|
sizeof(struct ifinfomsg));
|
||||||
|
|
||||||
|
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||||
|
perror("mnl_socket_sendto");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("mnl_socket_recvfrom");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
|
||||||
|
if (ret == -1){
|
||||||
|
perror("mnl_cb_run");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
mnl_socket_close(nl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
158
deps/libmnl/examples/rtnl/rtnl-neigh-dump.c
vendored
Normal file
158
deps/libmnl/examples/rtnl/rtnl-neigh-dump.c
vendored
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
/* This example is placed in the public domain. */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <linux/if.h>
|
||||||
|
#include <linux/if_link.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
|
||||||
|
static int data_attr_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
/* skip unsupported attribute in user-space */
|
||||||
|
if (mnl_attr_type_valid(attr, NDA_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case NDA_DST:
|
||||||
|
case NDA_LLADDR:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tb[type] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int data_cb(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
struct nlattr *tb[NDA_MAX + 1] = {};
|
||||||
|
struct ndmsg *ndm = mnl_nlmsg_get_payload(nlh);
|
||||||
|
|
||||||
|
printf("index=%d family=%d ", ndm->ndm_ifindex, ndm->ndm_family);
|
||||||
|
|
||||||
|
mnl_attr_parse(nlh, sizeof(*ndm), data_attr_cb, tb);
|
||||||
|
printf("dst=");
|
||||||
|
if (tb[NDA_DST]) {
|
||||||
|
void *addr = mnl_attr_get_payload(tb[NDA_DST]);
|
||||||
|
char out[INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
|
if (inet_ntop(ndm->ndm_family, addr, out, sizeof(out)))
|
||||||
|
printf("%s ", out);
|
||||||
|
}
|
||||||
|
|
||||||
|
mnl_attr_parse(nlh, sizeof(*ndm), data_attr_cb, tb);
|
||||||
|
printf("lladdr=");
|
||||||
|
if (tb[NDA_LLADDR]) {
|
||||||
|
void *addr = mnl_attr_get_payload(tb[NDA_LLADDR]);
|
||||||
|
unsigned char lladdr[6] = {0};
|
||||||
|
|
||||||
|
if (memcpy(&lladdr, addr, 6))
|
||||||
|
printf("%02x:%02x:%02x:%02x:%02x:%02x ",
|
||||||
|
lladdr[0], lladdr[1], lladdr[2],
|
||||||
|
lladdr[3], lladdr[4], lladdr[5]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("state=");
|
||||||
|
switch(ndm->ndm_state) {
|
||||||
|
case NUD_INCOMPLETE:
|
||||||
|
printf("incomplete ");
|
||||||
|
break;
|
||||||
|
case NUD_REACHABLE:
|
||||||
|
printf("reachable ");
|
||||||
|
break;
|
||||||
|
case NUD_STALE:
|
||||||
|
printf("stale ");
|
||||||
|
break;
|
||||||
|
case NUD_DELAY:
|
||||||
|
printf("delay ");
|
||||||
|
break;
|
||||||
|
case NUD_PROBE:
|
||||||
|
printf("probe ");
|
||||||
|
break;
|
||||||
|
case NUD_FAILED:
|
||||||
|
printf("failed ");
|
||||||
|
break;
|
||||||
|
case NUD_NOARP:
|
||||||
|
printf("noarp ");
|
||||||
|
break;
|
||||||
|
case NUD_PERMANENT:
|
||||||
|
printf("permanent ");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("%d ", ndm->ndm_state);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char buf[MNL_SOCKET_DUMP_SIZE];
|
||||||
|
unsigned int seq, portid;
|
||||||
|
struct mnl_socket *nl;
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
struct ndmsg *nd;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
fprintf(stderr, "Usage: %s <inet|inet6>\n", argv[0]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
nlh = mnl_nlmsg_put_header(buf);
|
||||||
|
nlh->nlmsg_type = RTM_GETNEIGH;
|
||||||
|
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
|
||||||
|
nlh->nlmsg_seq = seq = time(NULL);
|
||||||
|
|
||||||
|
nd = mnl_nlmsg_put_extra_header(nlh, sizeof(struct ndmsg));
|
||||||
|
if (strcmp(argv[1], "inet") == 0)
|
||||||
|
nd->ndm_family = AF_INET;
|
||||||
|
else if (strcmp(argv[1], "inet6") == 0)
|
||||||
|
nd->ndm_family = AF_INET6;
|
||||||
|
|
||||||
|
nl = mnl_socket_open(NETLINK_ROUTE);
|
||||||
|
if (nl == NULL) {
|
||||||
|
perror("mnl_socket_open");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||||
|
perror("mnl_socket_bind");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
portid = mnl_socket_get_portid(nl);
|
||||||
|
|
||||||
|
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||||
|
perror("mnl_socket_sendto");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
while (ret > 0) {
|
||||||
|
ret = mnl_cb_run(buf, ret, seq, portid, data_cb, NULL);
|
||||||
|
if (ret <= MNL_CB_STOP)
|
||||||
|
break;
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("error");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
mnl_socket_close(nl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
127
deps/libmnl/examples/rtnl/rtnl-route-add.c
vendored
Normal file
127
deps/libmnl/examples/rtnl/rtnl-route-add.c
vendored
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
/* This example is placed in the public domain. */
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <linux/if_link.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct mnl_socket *nl;
|
||||||
|
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
struct rtmsg *rtm;
|
||||||
|
uint32_t prefix, seq, portid;
|
||||||
|
union {
|
||||||
|
in_addr_t ip;
|
||||||
|
struct in6_addr ip6;
|
||||||
|
} dst;
|
||||||
|
union {
|
||||||
|
in_addr_t ip;
|
||||||
|
struct in6_addr ip6;
|
||||||
|
} gw;
|
||||||
|
int iface, ret, family = AF_INET;
|
||||||
|
|
||||||
|
if (argc <= 3) {
|
||||||
|
printf("Usage: %s iface destination cidr [gateway]\n", argv[0]);
|
||||||
|
printf("Example: %s eth0 10.0.1.12 32 10.0.1.11\n", argv[0]);
|
||||||
|
printf(" %s eth0 ffff::10.0.1.12 128 fdff::1\n", argv[0]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
iface = if_nametoindex(argv[1]);
|
||||||
|
if (iface == 0) {
|
||||||
|
perror("if_nametoindex");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!inet_pton(AF_INET, argv[2], &dst)) {
|
||||||
|
if (!inet_pton(AF_INET6, argv[2], &dst)) {
|
||||||
|
perror("inet_pton");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
family = AF_INET6;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sscanf(argv[3], "%u", &prefix) == 0) {
|
||||||
|
perror("sscanf");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc == 5 && !inet_pton(family, argv[4], &gw)) {
|
||||||
|
perror("inet_pton");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
nlh = mnl_nlmsg_put_header(buf);
|
||||||
|
nlh->nlmsg_type = RTM_NEWROUTE;
|
||||||
|
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK;
|
||||||
|
nlh->nlmsg_seq = seq = time(NULL);
|
||||||
|
|
||||||
|
rtm = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtmsg));
|
||||||
|
rtm->rtm_family = family;
|
||||||
|
rtm->rtm_dst_len = prefix;
|
||||||
|
rtm->rtm_src_len = 0;
|
||||||
|
rtm->rtm_tos = 0;
|
||||||
|
rtm->rtm_protocol = RTPROT_STATIC;
|
||||||
|
rtm->rtm_table = RT_TABLE_MAIN;
|
||||||
|
rtm->rtm_type = RTN_UNICAST;
|
||||||
|
/* is there any gateway? */
|
||||||
|
rtm->rtm_scope = (argc == 4) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE;
|
||||||
|
rtm->rtm_flags = 0;
|
||||||
|
|
||||||
|
if (family == AF_INET)
|
||||||
|
mnl_attr_put_u32(nlh, RTA_DST, dst.ip);
|
||||||
|
else
|
||||||
|
mnl_attr_put(nlh, RTA_DST, sizeof(struct in6_addr), &dst);
|
||||||
|
|
||||||
|
mnl_attr_put_u32(nlh, RTA_OIF, iface);
|
||||||
|
if (argc == 5) {
|
||||||
|
if (family == AF_INET)
|
||||||
|
mnl_attr_put_u32(nlh, RTA_GATEWAY, gw.ip);
|
||||||
|
else {
|
||||||
|
mnl_attr_put(nlh, RTA_GATEWAY, sizeof(struct in6_addr),
|
||||||
|
&gw.ip6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nl = mnl_socket_open(NETLINK_ROUTE);
|
||||||
|
if (nl == NULL) {
|
||||||
|
perror("mnl_socket_open");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||||
|
perror("mnl_socket_bind");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
portid = mnl_socket_get_portid(nl);
|
||||||
|
|
||||||
|
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||||
|
perror("mnl_socket_sendto");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
if (ret < 0) {
|
||||||
|
perror("mnl_socket_recvfrom");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
|
||||||
|
if (ret < 0) {
|
||||||
|
perror("mnl_cb_run");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
mnl_socket_close(nl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
356
deps/libmnl/examples/rtnl/rtnl-route-dump.c
vendored
Normal file
356
deps/libmnl/examples/rtnl/rtnl-route-dump.c
vendored
Normal file
@@ -0,0 +1,356 @@
|
|||||||
|
/* This example is placed in the public domain. */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <linux/if.h>
|
||||||
|
#include <linux/if_link.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
|
||||||
|
static int data_attr_cb2(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
|
||||||
|
/* skip unsupported attribute in user-space */
|
||||||
|
if (mnl_attr_type_valid(attr, RTAX_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
tb[mnl_attr_get_type(attr)] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void attributes_show_ipv4(struct nlattr *tb[])
|
||||||
|
{
|
||||||
|
if (tb[RTA_TABLE]) {
|
||||||
|
printf("table=%u ", mnl_attr_get_u32(tb[RTA_TABLE]));
|
||||||
|
}
|
||||||
|
if (tb[RTA_DST]) {
|
||||||
|
struct in_addr *addr = mnl_attr_get_payload(tb[RTA_DST]);
|
||||||
|
printf("dst=%s ", inet_ntoa(*addr));
|
||||||
|
}
|
||||||
|
if (tb[RTA_SRC]) {
|
||||||
|
struct in_addr *addr = mnl_attr_get_payload(tb[RTA_SRC]);
|
||||||
|
printf("src=%s ", inet_ntoa(*addr));
|
||||||
|
}
|
||||||
|
if (tb[RTA_OIF]) {
|
||||||
|
printf("oif=%u ", mnl_attr_get_u32(tb[RTA_OIF]));
|
||||||
|
}
|
||||||
|
if (tb[RTA_FLOW]) {
|
||||||
|
printf("flow=%u ", mnl_attr_get_u32(tb[RTA_FLOW]));
|
||||||
|
}
|
||||||
|
if (tb[RTA_PREFSRC]) {
|
||||||
|
struct in_addr *addr = mnl_attr_get_payload(tb[RTA_PREFSRC]);
|
||||||
|
printf("prefsrc=%s ", inet_ntoa(*addr));
|
||||||
|
}
|
||||||
|
if (tb[RTA_GATEWAY]) {
|
||||||
|
struct in_addr *addr = mnl_attr_get_payload(tb[RTA_GATEWAY]);
|
||||||
|
printf("gw=%s ", inet_ntoa(*addr));
|
||||||
|
}
|
||||||
|
if (tb[RTA_PRIORITY]) {
|
||||||
|
printf("prio=%u ", mnl_attr_get_u32(tb[RTA_PRIORITY]));
|
||||||
|
}
|
||||||
|
if (tb[RTA_METRICS]) {
|
||||||
|
int i;
|
||||||
|
struct nlattr *tbx[RTAX_MAX+1] = {};
|
||||||
|
|
||||||
|
mnl_attr_parse_nested(tb[RTA_METRICS], data_attr_cb2, tbx);
|
||||||
|
|
||||||
|
for (i=0; i<RTAX_MAX; i++) {
|
||||||
|
if (tbx[i]) {
|
||||||
|
printf("metrics[%d]=%u ",
|
||||||
|
i, mnl_attr_get_u32(tbx[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* like inet_ntoa(), not reentrant */
|
||||||
|
static const char *inet6_ntoa(struct in6_addr in6)
|
||||||
|
{
|
||||||
|
static char buf[INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
|
return inet_ntop(AF_INET6, &in6.s6_addr, buf, sizeof(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void attributes_show_ipv6(struct nlattr *tb[])
|
||||||
|
{
|
||||||
|
if (tb[RTA_TABLE]) {
|
||||||
|
printf("table=%u ", mnl_attr_get_u32(tb[RTA_TABLE]));
|
||||||
|
}
|
||||||
|
if (tb[RTA_DST]) {
|
||||||
|
struct in6_addr *addr = mnl_attr_get_payload(tb[RTA_DST]);
|
||||||
|
printf("dst=%s ", inet6_ntoa(*addr));
|
||||||
|
}
|
||||||
|
if (tb[RTA_SRC]) {
|
||||||
|
struct in6_addr *addr = mnl_attr_get_payload(tb[RTA_SRC]);
|
||||||
|
printf("src=%s ", inet6_ntoa(*addr));
|
||||||
|
}
|
||||||
|
if (tb[RTA_OIF]) {
|
||||||
|
printf("oif=%u ", mnl_attr_get_u32(tb[RTA_OIF]));
|
||||||
|
}
|
||||||
|
if (tb[RTA_FLOW]) {
|
||||||
|
printf("flow=%u ", mnl_attr_get_u32(tb[RTA_FLOW]));
|
||||||
|
}
|
||||||
|
if (tb[RTA_PREFSRC]) {
|
||||||
|
struct in6_addr *addr = mnl_attr_get_payload(tb[RTA_PREFSRC]);
|
||||||
|
printf("prefsrc=%s ", inet6_ntoa(*addr));
|
||||||
|
}
|
||||||
|
if (tb[RTA_GATEWAY]) {
|
||||||
|
struct in6_addr *addr = mnl_attr_get_payload(tb[RTA_GATEWAY]);
|
||||||
|
printf("gw=%s ", inet6_ntoa(*addr));
|
||||||
|
}
|
||||||
|
if (tb[RTA_PRIORITY]) {
|
||||||
|
printf("prio=%u ", mnl_attr_get_u32(tb[RTA_PRIORITY]));
|
||||||
|
}
|
||||||
|
if (tb[RTA_METRICS]) {
|
||||||
|
int i;
|
||||||
|
struct nlattr *tbx[RTAX_MAX+1] = {};
|
||||||
|
|
||||||
|
mnl_attr_parse_nested(tb[RTA_METRICS], data_attr_cb2, tbx);
|
||||||
|
|
||||||
|
for (i=0; i<RTAX_MAX; i++) {
|
||||||
|
if (tbx[i]) {
|
||||||
|
printf("metrics[%d]=%u ",
|
||||||
|
i, mnl_attr_get_u32(tbx[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int data_ipv4_attr_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
/* skip unsupported attribute in user-space */
|
||||||
|
if (mnl_attr_type_valid(attr, RTA_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case RTA_TABLE:
|
||||||
|
case RTA_DST:
|
||||||
|
case RTA_SRC:
|
||||||
|
case RTA_OIF:
|
||||||
|
case RTA_FLOW:
|
||||||
|
case RTA_PREFSRC:
|
||||||
|
case RTA_GATEWAY:
|
||||||
|
case RTA_PRIORITY:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RTA_METRICS:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tb[type] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int data_ipv6_attr_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
/* skip unsupported attribute in user-space */
|
||||||
|
if (mnl_attr_type_valid(attr, RTA_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case RTA_TABLE:
|
||||||
|
case RTA_OIF:
|
||||||
|
case RTA_FLOW:
|
||||||
|
case RTA_PRIORITY:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RTA_DST:
|
||||||
|
case RTA_SRC:
|
||||||
|
case RTA_PREFSRC:
|
||||||
|
case RTA_GATEWAY:
|
||||||
|
if (mnl_attr_validate2(attr, MNL_TYPE_BINARY,
|
||||||
|
sizeof(struct in6_addr)) < 0) {
|
||||||
|
perror("mnl_attr_validate2");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RTA_METRICS:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tb[type] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int data_cb(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
struct nlattr *tb[RTA_MAX+1] = {};
|
||||||
|
struct rtmsg *rm = mnl_nlmsg_get_payload(nlh);
|
||||||
|
|
||||||
|
/* protocol family = AF_INET | AF_INET6 */
|
||||||
|
printf("family=%u ", rm->rtm_family);
|
||||||
|
|
||||||
|
/* destination CIDR, eg. 24 or 32 for IPv4 */
|
||||||
|
printf("dst_len=%u ", rm->rtm_dst_len);
|
||||||
|
|
||||||
|
/* source CIDR */
|
||||||
|
printf("src_len=%u ", rm->rtm_src_len);
|
||||||
|
|
||||||
|
/* type of service (TOS), eg. 0 */
|
||||||
|
printf("tos=%u ", rm->rtm_tos);
|
||||||
|
|
||||||
|
/* table id:
|
||||||
|
* RT_TABLE_UNSPEC = 0
|
||||||
|
*
|
||||||
|
* ... user defined values ...
|
||||||
|
*
|
||||||
|
* RT_TABLE_COMPAT = 252
|
||||||
|
* RT_TABLE_DEFAULT = 253
|
||||||
|
* RT_TABLE_MAIN = 254
|
||||||
|
* RT_TABLE_LOCAL = 255
|
||||||
|
* RT_TABLE_MAX = 0xFFFFFFFF
|
||||||
|
*
|
||||||
|
* Synonimous attribute: RTA_TABLE.
|
||||||
|
*/
|
||||||
|
printf("table=%u ", rm->rtm_table);
|
||||||
|
|
||||||
|
/* type:
|
||||||
|
* RTN_UNSPEC = 0
|
||||||
|
* RTN_UNICAST = 1
|
||||||
|
* RTN_LOCAL = 2
|
||||||
|
* RTN_BROADCAST = 3
|
||||||
|
* RTN_ANYCAST = 4
|
||||||
|
* RTN_MULTICAST = 5
|
||||||
|
* RTN_BLACKHOLE = 6
|
||||||
|
* RTN_UNREACHABLE = 7
|
||||||
|
* RTN_PROHIBIT = 8
|
||||||
|
* RTN_THROW = 9
|
||||||
|
* RTN_NAT = 10
|
||||||
|
* RTN_XRESOLVE = 11
|
||||||
|
* __RTN_MAX = 12
|
||||||
|
*/
|
||||||
|
printf("type=%u ", rm->rtm_type);
|
||||||
|
|
||||||
|
/* scope:
|
||||||
|
* RT_SCOPE_UNIVERSE = 0 : everywhere in the universe
|
||||||
|
*
|
||||||
|
* ... user defined values ...
|
||||||
|
*
|
||||||
|
* RT_SCOPE_SITE = 200
|
||||||
|
* RT_SCOPE_LINK = 253 : destination attached to link
|
||||||
|
* RT_SCOPE_HOST = 254 : local address
|
||||||
|
* RT_SCOPE_NOWHERE = 255 : not existing destination
|
||||||
|
*/
|
||||||
|
printf("scope=%u ", rm->rtm_scope);
|
||||||
|
|
||||||
|
/* protocol:
|
||||||
|
* RTPROT_UNSPEC = 0
|
||||||
|
* RTPROT_REDIRECT = 1
|
||||||
|
* RTPROT_KERNEL = 2 : route installed by kernel
|
||||||
|
* RTPROT_BOOT = 3 : route installed during boot
|
||||||
|
* RTPROT_STATIC = 4 : route installed by administrator
|
||||||
|
*
|
||||||
|
* Values >= RTPROT_STATIC are not interpreted by kernel, they are
|
||||||
|
* just user-defined.
|
||||||
|
*/
|
||||||
|
printf("proto=%u ", rm->rtm_protocol);
|
||||||
|
|
||||||
|
/* flags:
|
||||||
|
* RTM_F_NOTIFY = 0x100: notify user of route change
|
||||||
|
* RTM_F_CLONED = 0x200: this route is cloned
|
||||||
|
* RTM_F_EQUALIZE = 0x400: Multipath equalizer: NI
|
||||||
|
* RTM_F_PREFIX = 0x800: Prefix addresses
|
||||||
|
*/
|
||||||
|
printf("flags=%x ", rm->rtm_flags);
|
||||||
|
|
||||||
|
switch(rm->rtm_family) {
|
||||||
|
case AF_INET:
|
||||||
|
mnl_attr_parse(nlh, sizeof(*rm), data_ipv4_attr_cb, tb);
|
||||||
|
attributes_show_ipv4(tb);
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
mnl_attr_parse(nlh, sizeof(*rm), data_ipv6_attr_cb, tb);
|
||||||
|
attributes_show_ipv6(tb);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char buf[MNL_SOCKET_DUMP_SIZE];
|
||||||
|
unsigned int seq, portid;
|
||||||
|
struct mnl_socket *nl;
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
struct rtmsg *rtm;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
fprintf(stderr, "Usage: %s <inet|inet6>\n", argv[0]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
nlh = mnl_nlmsg_put_header(buf);
|
||||||
|
nlh->nlmsg_type = RTM_GETROUTE;
|
||||||
|
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
|
||||||
|
nlh->nlmsg_seq = seq = time(NULL);
|
||||||
|
rtm = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtmsg));
|
||||||
|
|
||||||
|
if (strcmp(argv[1], "inet") == 0)
|
||||||
|
rtm->rtm_family = AF_INET;
|
||||||
|
else if (strcmp(argv[1], "inet6") == 0)
|
||||||
|
rtm->rtm_family = AF_INET6;
|
||||||
|
|
||||||
|
nl = mnl_socket_open(NETLINK_ROUTE);
|
||||||
|
if (nl == NULL) {
|
||||||
|
perror("mnl_socket_open");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||||
|
perror("mnl_socket_bind");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
portid = mnl_socket_get_portid(nl);
|
||||||
|
|
||||||
|
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||||
|
perror("mnl_socket_sendto");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
while (ret > 0) {
|
||||||
|
ret = mnl_cb_run(buf, ret, seq, portid, data_cb, NULL);
|
||||||
|
if (ret <= MNL_CB_STOP)
|
||||||
|
break;
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
}
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("error");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
mnl_socket_close(nl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
341
deps/libmnl/examples/rtnl/rtnl-route-event.c
vendored
Normal file
341
deps/libmnl/examples/rtnl/rtnl-route-event.c
vendored
Normal file
@@ -0,0 +1,341 @@
|
|||||||
|
/* This example is placed in the public domain. */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <linux/if.h>
|
||||||
|
#include <linux/if_link.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
|
||||||
|
static int data_attr_cb2(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
|
||||||
|
/* skip unsupported attribute in user-space */
|
||||||
|
if (mnl_attr_type_valid(attr, RTAX_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
tb[mnl_attr_get_type(attr)] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void attributes_show_ipv4(struct nlattr *tb[])
|
||||||
|
{
|
||||||
|
if (tb[RTA_TABLE]) {
|
||||||
|
printf("table=%u ", mnl_attr_get_u32(tb[RTA_TABLE]));
|
||||||
|
}
|
||||||
|
if (tb[RTA_DST]) {
|
||||||
|
struct in_addr *addr = mnl_attr_get_payload(tb[RTA_DST]);
|
||||||
|
printf("dst=%s ", inet_ntoa(*addr));
|
||||||
|
}
|
||||||
|
if (tb[RTA_SRC]) {
|
||||||
|
struct in_addr *addr = mnl_attr_get_payload(tb[RTA_SRC]);
|
||||||
|
printf("src=%s ", inet_ntoa(*addr));
|
||||||
|
}
|
||||||
|
if (tb[RTA_OIF]) {
|
||||||
|
printf("oif=%u ", mnl_attr_get_u32(tb[RTA_OIF]));
|
||||||
|
}
|
||||||
|
if (tb[RTA_FLOW]) {
|
||||||
|
printf("flow=%u ", mnl_attr_get_u32(tb[RTA_FLOW]));
|
||||||
|
}
|
||||||
|
if (tb[RTA_PREFSRC]) {
|
||||||
|
struct in_addr *addr = mnl_attr_get_payload(tb[RTA_PREFSRC]);
|
||||||
|
printf("prefsrc=%s ", inet_ntoa(*addr));
|
||||||
|
}
|
||||||
|
if (tb[RTA_GATEWAY]) {
|
||||||
|
struct in_addr *addr = mnl_attr_get_payload(tb[RTA_GATEWAY]);
|
||||||
|
printf("gw=%s ", inet_ntoa(*addr));
|
||||||
|
}
|
||||||
|
if (tb[RTA_PRIORITY]) {
|
||||||
|
printf("prio=%u ", mnl_attr_get_u32(tb[RTA_PRIORITY]));
|
||||||
|
}
|
||||||
|
if (tb[RTA_METRICS]) {
|
||||||
|
int i;
|
||||||
|
struct nlattr *tbx[RTAX_MAX+1] = {};
|
||||||
|
|
||||||
|
mnl_attr_parse_nested(tb[RTA_METRICS], data_attr_cb2, tbx);
|
||||||
|
|
||||||
|
for (i=0; i<RTAX_MAX; i++) {
|
||||||
|
if (tbx[i]) {
|
||||||
|
printf("metrics[%d]=%u ",
|
||||||
|
i, mnl_attr_get_u32(tbx[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* like inet_ntoa(), not reentrant */
|
||||||
|
static const char *inet6_ntoa(struct in6_addr in6)
|
||||||
|
{
|
||||||
|
static char buf[INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
|
return inet_ntop(AF_INET6, &in6.s6_addr, buf, sizeof(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void attributes_show_ipv6(struct nlattr *tb[])
|
||||||
|
{
|
||||||
|
if (tb[RTA_TABLE]) {
|
||||||
|
printf("table=%u ", mnl_attr_get_u32(tb[RTA_TABLE]));
|
||||||
|
}
|
||||||
|
if (tb[RTA_DST]) {
|
||||||
|
struct in6_addr *addr = mnl_attr_get_payload(tb[RTA_DST]);
|
||||||
|
printf("dst=%s ", inet6_ntoa(*addr));
|
||||||
|
}
|
||||||
|
if (tb[RTA_SRC]) {
|
||||||
|
struct in6_addr *addr = mnl_attr_get_payload(tb[RTA_SRC]);
|
||||||
|
printf("src=%s ", inet6_ntoa(*addr));
|
||||||
|
}
|
||||||
|
if (tb[RTA_OIF]) {
|
||||||
|
printf("oif=%u ", mnl_attr_get_u32(tb[RTA_OIF]));
|
||||||
|
}
|
||||||
|
if (tb[RTA_FLOW]) {
|
||||||
|
printf("flow=%u ", mnl_attr_get_u32(tb[RTA_FLOW]));
|
||||||
|
}
|
||||||
|
if (tb[RTA_PREFSRC]) {
|
||||||
|
struct in6_addr *addr = mnl_attr_get_payload(tb[RTA_PREFSRC]);
|
||||||
|
printf("prefsrc=%s ", inet6_ntoa(*addr));
|
||||||
|
}
|
||||||
|
if (tb[RTA_GATEWAY]) {
|
||||||
|
struct in6_addr *addr = mnl_attr_get_payload(tb[RTA_GATEWAY]);
|
||||||
|
printf("gw=%s ", inet6_ntoa(*addr));
|
||||||
|
}
|
||||||
|
if (tb[RTA_PRIORITY]) {
|
||||||
|
printf("prio=%u ", mnl_attr_get_u32(tb[RTA_PRIORITY]));
|
||||||
|
}
|
||||||
|
if (tb[RTA_METRICS]) {
|
||||||
|
int i;
|
||||||
|
struct nlattr *tbx[RTAX_MAX+1] = {};
|
||||||
|
|
||||||
|
mnl_attr_parse_nested(tb[RTA_METRICS], data_attr_cb2, tbx);
|
||||||
|
|
||||||
|
for (i=0; i<RTAX_MAX; i++) {
|
||||||
|
if (tbx[i]) {
|
||||||
|
printf("metrics[%d]=%u ",
|
||||||
|
i, mnl_attr_get_u32(tbx[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int data_ipv4_attr_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
/* skip unsupported attribute in user-space */
|
||||||
|
if (mnl_attr_type_valid(attr, RTA_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case RTA_TABLE:
|
||||||
|
case RTA_DST:
|
||||||
|
case RTA_SRC:
|
||||||
|
case RTA_OIF:
|
||||||
|
case RTA_FLOW:
|
||||||
|
case RTA_PREFSRC:
|
||||||
|
case RTA_GATEWAY:
|
||||||
|
case RTA_PRIORITY:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RTA_METRICS:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tb[type] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int data_ipv6_attr_cb(const struct nlattr *attr, void *data)
|
||||||
|
{
|
||||||
|
const struct nlattr **tb = data;
|
||||||
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
|
/* skip unsupported attribute in user-space */
|
||||||
|
if (mnl_attr_type_valid(attr, RTA_MAX) < 0)
|
||||||
|
return MNL_CB_OK;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case RTA_TABLE:
|
||||||
|
case RTA_OIF:
|
||||||
|
case RTA_FLOW:
|
||||||
|
case RTA_PRIORITY:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RTA_DST:
|
||||||
|
case RTA_SRC:
|
||||||
|
case RTA_PREFSRC:
|
||||||
|
case RTA_GATEWAY:
|
||||||
|
if (mnl_attr_validate2(attr, MNL_TYPE_BINARY,
|
||||||
|
sizeof(struct in6_addr)) < 0) {
|
||||||
|
perror("mnl_attr_validate2");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RTA_METRICS:
|
||||||
|
if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
|
||||||
|
perror("mnl_attr_validate");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tb[type] = attr;
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int data_cb(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
struct nlattr *tb[RTA_MAX+1] = {};
|
||||||
|
struct rtmsg *rm = mnl_nlmsg_get_payload(nlh);
|
||||||
|
|
||||||
|
switch(nlh->nlmsg_type) {
|
||||||
|
case RTM_NEWROUTE:
|
||||||
|
printf("[NEW] ");
|
||||||
|
break;
|
||||||
|
case RTM_DELROUTE:
|
||||||
|
printf("[DEL] ");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* protocol family = AF_INET | AF_INET6 */
|
||||||
|
printf("family=%u ", rm->rtm_family);
|
||||||
|
|
||||||
|
/* destination CIDR, eg. 24 or 32 for IPv4 */
|
||||||
|
printf("dst_len=%u ", rm->rtm_dst_len);
|
||||||
|
|
||||||
|
/* source CIDR */
|
||||||
|
printf("src_len=%u ", rm->rtm_src_len);
|
||||||
|
|
||||||
|
/* type of service (TOS), eg. 0 */
|
||||||
|
printf("tos=%u ", rm->rtm_tos);
|
||||||
|
|
||||||
|
/* table id:
|
||||||
|
* RT_TABLE_UNSPEC = 0
|
||||||
|
*
|
||||||
|
* ... user defined values ...
|
||||||
|
*
|
||||||
|
* RT_TABLE_COMPAT = 252
|
||||||
|
* RT_TABLE_DEFAULT = 253
|
||||||
|
* RT_TABLE_MAIN = 254
|
||||||
|
* RT_TABLE_LOCAL = 255
|
||||||
|
* RT_TABLE_MAX = 0xFFFFFFFF
|
||||||
|
*
|
||||||
|
* Synonimous attribute: RTA_TABLE.
|
||||||
|
*/
|
||||||
|
printf("table=%u ", rm->rtm_table);
|
||||||
|
|
||||||
|
/* type:
|
||||||
|
* RTN_UNSPEC = 0
|
||||||
|
* RTN_UNICAST = 1
|
||||||
|
* RTN_LOCAL = 2
|
||||||
|
* RTN_BROADCAST = 3
|
||||||
|
* RTN_ANYCAST = 4
|
||||||
|
* RTN_MULTICAST = 5
|
||||||
|
* RTN_BLACKHOLE = 6
|
||||||
|
* RTN_UNREACHABLE = 7
|
||||||
|
* RTN_PROHIBIT = 8
|
||||||
|
* RTN_THROW = 9
|
||||||
|
* RTN_NAT = 10
|
||||||
|
* RTN_XRESOLVE = 11
|
||||||
|
* __RTN_MAX = 12
|
||||||
|
*/
|
||||||
|
printf("type=%u ", rm->rtm_type);
|
||||||
|
|
||||||
|
/* scope:
|
||||||
|
* RT_SCOPE_UNIVERSE = 0 : everywhere in the universe
|
||||||
|
*
|
||||||
|
* ... user defined values ...
|
||||||
|
*
|
||||||
|
* RT_SCOPE_SITE = 200
|
||||||
|
* RT_SCOPE_LINK = 253 : destination attached to link
|
||||||
|
* RT_SCOPE_HOST = 254 : local address
|
||||||
|
* RT_SCOPE_NOWHERE = 255 : not existing destination
|
||||||
|
*/
|
||||||
|
printf("scope=%u ", rm->rtm_scope);
|
||||||
|
|
||||||
|
/* protocol:
|
||||||
|
* RTPROT_UNSPEC = 0
|
||||||
|
* RTPROT_REDIRECT = 1
|
||||||
|
* RTPROT_KERNEL = 2 : route installed by kernel
|
||||||
|
* RTPROT_BOOT = 3 : route installed during boot
|
||||||
|
* RTPROT_STATIC = 4 : route installed by administrator
|
||||||
|
*
|
||||||
|
* Values >= RTPROT_STATIC are not interpreted by kernel, they are
|
||||||
|
* just user-defined.
|
||||||
|
*/
|
||||||
|
printf("proto=%u ", rm->rtm_protocol);
|
||||||
|
|
||||||
|
/* flags:
|
||||||
|
* RTM_F_NOTIFY = 0x100: notify user of route change
|
||||||
|
* RTM_F_CLONED = 0x200: this route is cloned
|
||||||
|
* RTM_F_EQUALIZE = 0x400: Multipath equalizer: NI
|
||||||
|
* RTM_F_PREFIX = 0x800: Prefix addresses
|
||||||
|
*/
|
||||||
|
printf("flags=%x ", rm->rtm_flags);
|
||||||
|
|
||||||
|
switch(rm->rtm_family) {
|
||||||
|
case AF_INET:
|
||||||
|
mnl_attr_parse(nlh, sizeof(*rm), data_ipv4_attr_cb, tb);
|
||||||
|
attributes_show_ipv4(tb);
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
mnl_attr_parse(nlh, sizeof(*rm), data_ipv6_attr_cb, tb);
|
||||||
|
attributes_show_ipv6(tb);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct mnl_socket *nl;
|
||||||
|
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
nl = mnl_socket_open(NETLINK_ROUTE);
|
||||||
|
if (nl == NULL) {
|
||||||
|
perror("mnl_socket_open");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mnl_socket_bind(nl, RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE,
|
||||||
|
MNL_SOCKET_AUTOPID) < 0) {
|
||||||
|
perror("mnl_socket_bind");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
while (ret > 0) {
|
||||||
|
ret = mnl_cb_run(buf, ret, 0, 0, data_cb, NULL);
|
||||||
|
if (ret <= MNL_CB_STOP)
|
||||||
|
break;
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||||
|
}
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("error");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
mnl_socket_close(nl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
1
deps/libmnl/include/Makefile.am
vendored
Normal file
1
deps/libmnl/include/Makefile.am
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
SUBDIRS = libmnl linux
|
||||||
1
deps/libmnl/include/libmnl/Makefile.am
vendored
Normal file
1
deps/libmnl/include/libmnl/Makefile.am
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pkginclude_HEADERS = libmnl.h
|
||||||
202
deps/libmnl/include/libmnl/libmnl.h
vendored
Normal file
202
deps/libmnl/include/libmnl/libmnl.h
vendored
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
#ifndef _LIBMNL_H_
|
||||||
|
#define _LIBMNL_H_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/socket.h> /* for sa_family_t */
|
||||||
|
#include <linux/netlink.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Netlink socket API
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MNL_SOCKET_AUTOPID 0
|
||||||
|
#define MNL_SOCKET_BUFFER_SIZE (sysconf(_SC_PAGESIZE) < 8192L ? sysconf(_SC_PAGESIZE) : 8192L)
|
||||||
|
#define MNL_SOCKET_DUMP_SIZE 32768
|
||||||
|
|
||||||
|
struct mnl_socket;
|
||||||
|
|
||||||
|
extern struct mnl_socket *mnl_socket_open(int bus);
|
||||||
|
extern struct mnl_socket *mnl_socket_open2(int bus, int flags);
|
||||||
|
extern struct mnl_socket *mnl_socket_fdopen(int fd);
|
||||||
|
extern int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups, pid_t pid);
|
||||||
|
extern int mnl_socket_close(struct mnl_socket *nl);
|
||||||
|
extern int mnl_socket_get_fd(const struct mnl_socket *nl);
|
||||||
|
extern unsigned int mnl_socket_get_portid(const struct mnl_socket *nl);
|
||||||
|
extern ssize_t mnl_socket_sendto(const struct mnl_socket *nl, const void *req, size_t siz);
|
||||||
|
extern ssize_t mnl_socket_recvfrom(const struct mnl_socket *nl, void *buf, size_t siz);
|
||||||
|
extern int mnl_socket_setsockopt(const struct mnl_socket *nl, int type, void *buf, socklen_t len);
|
||||||
|
extern int mnl_socket_getsockopt(const struct mnl_socket *nl, int type, void *buf, socklen_t *len);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Netlink message API
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MNL_ALIGNTO 4
|
||||||
|
#define MNL_ALIGN(len) (((len)+MNL_ALIGNTO-1) & ~(MNL_ALIGNTO-1))
|
||||||
|
#define MNL_NLMSG_HDRLEN MNL_ALIGN(sizeof(struct nlmsghdr))
|
||||||
|
|
||||||
|
extern size_t mnl_nlmsg_size(size_t len);
|
||||||
|
extern size_t mnl_nlmsg_get_payload_len(const struct nlmsghdr *nlh);
|
||||||
|
|
||||||
|
/* Netlink message header builder */
|
||||||
|
extern struct nlmsghdr *mnl_nlmsg_put_header(void *buf);
|
||||||
|
extern void *mnl_nlmsg_put_extra_header(struct nlmsghdr *nlh, size_t size);
|
||||||
|
|
||||||
|
/* Netlink message iterators */
|
||||||
|
extern bool mnl_nlmsg_ok(const struct nlmsghdr *nlh, int len);
|
||||||
|
extern struct nlmsghdr *mnl_nlmsg_next(const struct nlmsghdr *nlh, int *len);
|
||||||
|
|
||||||
|
/* Netlink sequence tracking */
|
||||||
|
extern bool mnl_nlmsg_seq_ok(const struct nlmsghdr *nlh, unsigned int seq);
|
||||||
|
|
||||||
|
/* Netlink portID checking */
|
||||||
|
extern bool mnl_nlmsg_portid_ok(const struct nlmsghdr *nlh, unsigned int portid);
|
||||||
|
|
||||||
|
/* Netlink message getters */
|
||||||
|
extern void *mnl_nlmsg_get_payload(const struct nlmsghdr *nlh);
|
||||||
|
extern void *mnl_nlmsg_get_payload_offset(const struct nlmsghdr *nlh, size_t offset);
|
||||||
|
extern void *mnl_nlmsg_get_payload_tail(const struct nlmsghdr *nlh);
|
||||||
|
|
||||||
|
/* Netlink message printer */
|
||||||
|
extern void mnl_nlmsg_fprintf(FILE *fd, const void *data, size_t datalen, size_t extra_header_size);
|
||||||
|
|
||||||
|
/* Message batch helpers */
|
||||||
|
struct mnl_nlmsg_batch;
|
||||||
|
extern struct mnl_nlmsg_batch *mnl_nlmsg_batch_start(void *buf, size_t bufsiz);
|
||||||
|
extern bool mnl_nlmsg_batch_next(struct mnl_nlmsg_batch *b);
|
||||||
|
extern void mnl_nlmsg_batch_stop(struct mnl_nlmsg_batch *b);
|
||||||
|
extern size_t mnl_nlmsg_batch_size(struct mnl_nlmsg_batch *b);
|
||||||
|
extern void mnl_nlmsg_batch_reset(struct mnl_nlmsg_batch *b);
|
||||||
|
extern void *mnl_nlmsg_batch_head(struct mnl_nlmsg_batch *b);
|
||||||
|
extern void *mnl_nlmsg_batch_current(struct mnl_nlmsg_batch *b);
|
||||||
|
extern bool mnl_nlmsg_batch_is_empty(struct mnl_nlmsg_batch *b);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Netlink attributes API
|
||||||
|
*/
|
||||||
|
#define MNL_ATTR_HDRLEN MNL_ALIGN(sizeof(struct nlattr))
|
||||||
|
|
||||||
|
/* TLV attribute getters */
|
||||||
|
extern uint16_t mnl_attr_get_type(const struct nlattr *attr);
|
||||||
|
extern uint16_t mnl_attr_get_len(const struct nlattr *attr);
|
||||||
|
extern uint16_t mnl_attr_get_payload_len(const struct nlattr *attr);
|
||||||
|
extern void *mnl_attr_get_payload(const struct nlattr *attr);
|
||||||
|
extern uint8_t mnl_attr_get_u8(const struct nlattr *attr);
|
||||||
|
extern uint16_t mnl_attr_get_u16(const struct nlattr *attr);
|
||||||
|
extern uint32_t mnl_attr_get_u32(const struct nlattr *attr);
|
||||||
|
extern uint64_t mnl_attr_get_u64(const struct nlattr *attr);
|
||||||
|
extern const char *mnl_attr_get_str(const struct nlattr *attr);
|
||||||
|
|
||||||
|
/* TLV attribute putters */
|
||||||
|
extern void mnl_attr_put(struct nlmsghdr *nlh, uint16_t type, size_t len, const void *data);
|
||||||
|
extern void mnl_attr_put_u8(struct nlmsghdr *nlh, uint16_t type, uint8_t data);
|
||||||
|
extern void mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type, uint16_t data);
|
||||||
|
extern void mnl_attr_put_u32(struct nlmsghdr *nlh, uint16_t type, uint32_t data);
|
||||||
|
extern void mnl_attr_put_u64(struct nlmsghdr *nlh, uint16_t type, uint64_t data);
|
||||||
|
extern void mnl_attr_put_str(struct nlmsghdr *nlh, uint16_t type, const char *data);
|
||||||
|
extern void mnl_attr_put_strz(struct nlmsghdr *nlh, uint16_t type, const char *data);
|
||||||
|
|
||||||
|
/* TLV attribute putters with buffer boundary checkings */
|
||||||
|
extern bool mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, size_t len, const void *data);
|
||||||
|
extern bool mnl_attr_put_u8_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint8_t data);
|
||||||
|
extern bool mnl_attr_put_u16_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint16_t data);
|
||||||
|
extern bool mnl_attr_put_u32_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint32_t data);
|
||||||
|
extern bool mnl_attr_put_u64_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint64_t data);
|
||||||
|
extern bool mnl_attr_put_str_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, const char *data);
|
||||||
|
extern bool mnl_attr_put_strz_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, const char *data);
|
||||||
|
|
||||||
|
/* TLV attribute nesting */
|
||||||
|
extern struct nlattr *mnl_attr_nest_start(struct nlmsghdr *nlh, uint16_t type);
|
||||||
|
extern struct nlattr *mnl_attr_nest_start_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type);
|
||||||
|
extern void mnl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *start);
|
||||||
|
extern void mnl_attr_nest_cancel(struct nlmsghdr *nlh, struct nlattr *start);
|
||||||
|
|
||||||
|
/* TLV validation */
|
||||||
|
extern int mnl_attr_type_valid(const struct nlattr *attr, uint16_t maxtype);
|
||||||
|
|
||||||
|
enum mnl_attr_data_type {
|
||||||
|
MNL_TYPE_UNSPEC,
|
||||||
|
MNL_TYPE_U8,
|
||||||
|
MNL_TYPE_U16,
|
||||||
|
MNL_TYPE_U32,
|
||||||
|
MNL_TYPE_U64,
|
||||||
|
MNL_TYPE_STRING,
|
||||||
|
MNL_TYPE_FLAG,
|
||||||
|
MNL_TYPE_MSECS,
|
||||||
|
MNL_TYPE_NESTED,
|
||||||
|
MNL_TYPE_NESTED_COMPAT,
|
||||||
|
MNL_TYPE_NUL_STRING,
|
||||||
|
MNL_TYPE_BINARY,
|
||||||
|
MNL_TYPE_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type);
|
||||||
|
extern int mnl_attr_validate2(const struct nlattr *attr, enum mnl_attr_data_type type, size_t len);
|
||||||
|
|
||||||
|
/* TLV iterators */
|
||||||
|
extern bool mnl_attr_ok(const struct nlattr *attr, int len);
|
||||||
|
extern struct nlattr *mnl_attr_next(const struct nlattr *attr);
|
||||||
|
|
||||||
|
#define mnl_attr_for_each(attr, nlh, offset) \
|
||||||
|
for ((attr) = mnl_nlmsg_get_payload_offset((nlh), (offset)); \
|
||||||
|
mnl_attr_ok((attr), (char *)mnl_nlmsg_get_payload_tail(nlh) - (char *)(attr)); \
|
||||||
|
(attr) = mnl_attr_next(attr))
|
||||||
|
|
||||||
|
#define mnl_attr_for_each_nested(attr, nest) \
|
||||||
|
for ((attr) = mnl_attr_get_payload(nest); \
|
||||||
|
mnl_attr_ok((attr), (char *)mnl_attr_get_payload(nest) + mnl_attr_get_payload_len(nest) - (char *)(attr)); \
|
||||||
|
(attr) = mnl_attr_next(attr))
|
||||||
|
|
||||||
|
#define mnl_attr_for_each_payload(payload, payload_size) \
|
||||||
|
for ((attr) = (payload); \
|
||||||
|
mnl_attr_ok((attr), (char *)(payload) + payload_size - (char *)(attr)); \
|
||||||
|
(attr) = mnl_attr_next(attr))
|
||||||
|
|
||||||
|
/* TLV callback-based attribute parsers */
|
||||||
|
typedef int (*mnl_attr_cb_t)(const struct nlattr *attr, void *data);
|
||||||
|
|
||||||
|
extern int mnl_attr_parse(const struct nlmsghdr *nlh, unsigned int offset, mnl_attr_cb_t cb, void *data);
|
||||||
|
extern int mnl_attr_parse_nested(const struct nlattr *attr, mnl_attr_cb_t cb, void *data);
|
||||||
|
extern int mnl_attr_parse_payload(const void *payload, size_t payload_len, mnl_attr_cb_t cb, void *data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* callback API
|
||||||
|
*/
|
||||||
|
#define MNL_CB_ERROR -1
|
||||||
|
#define MNL_CB_STOP 0
|
||||||
|
#define MNL_CB_OK 1
|
||||||
|
|
||||||
|
typedef int (*mnl_cb_t)(const struct nlmsghdr *nlh, void *data);
|
||||||
|
|
||||||
|
extern int mnl_cb_run(const void *buf, size_t numbytes, unsigned int seq,
|
||||||
|
unsigned int portid, mnl_cb_t cb_data, void *data);
|
||||||
|
|
||||||
|
extern int mnl_cb_run2(const void *buf, size_t numbytes, unsigned int seq,
|
||||||
|
unsigned int portid, mnl_cb_t cb_data, void *data,
|
||||||
|
const mnl_cb_t *cb_ctl_array,
|
||||||
|
unsigned int cb_ctl_array_len);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* other declarations
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SOL_NETLINK
|
||||||
|
#define SOL_NETLINK 270
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MNL_ARRAY_SIZE
|
||||||
|
#define MNL_ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
2
deps/libmnl/include/linux/Makefile.am
vendored
Normal file
2
deps/libmnl/include/linux/Makefile.am
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
SUBDIRS = can netfilter
|
||||||
|
noinst_HEADERS = can.h netlink.h socket.h
|
||||||
298
deps/libmnl/include/linux/can.h
vendored
Normal file
298
deps/libmnl/include/linux/can.h
vendored
Normal file
@@ -0,0 +1,298 @@
|
|||||||
|
/* SPDX-License-Identifier: ((GPL-2.0-only WITH Linux-syscall-note) OR BSD-3-Clause) */
|
||||||
|
/*
|
||||||
|
* linux/can.h
|
||||||
|
*
|
||||||
|
* Definitions for CAN network layer (socket addr / CAN frame / CAN filter)
|
||||||
|
*
|
||||||
|
* Authors: Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
|
||||||
|
* Urs Thuermann <urs.thuermann@volkswagen.de>
|
||||||
|
* Copyright (c) 2002-2007 Volkswagen Group Electronic Research
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of Volkswagen nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* Alternatively, provided that this notice is retained in full, this
|
||||||
|
* software may be distributed under the terms of the GNU General
|
||||||
|
* Public License ("GPL") version 2, in which case the provisions of the
|
||||||
|
* GPL apply INSTEAD OF those given above.
|
||||||
|
*
|
||||||
|
* The provided data structures and external interfaces from this code
|
||||||
|
* are not restricted to be used by modules with a GPL compatible license.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
* DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _UAPI_CAN_H
|
||||||
|
#define _UAPI_CAN_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/socket.h>
|
||||||
|
#include <linux/stddef.h> /* for offsetof */
|
||||||
|
|
||||||
|
/* controller area network (CAN) kernel definitions */
|
||||||
|
|
||||||
|
/* special address description flags for the CAN_ID */
|
||||||
|
#define CAN_EFF_FLAG 0x80000000U /* EFF/SFF is set in the MSB */
|
||||||
|
#define CAN_RTR_FLAG 0x40000000U /* remote transmission request */
|
||||||
|
#define CAN_ERR_FLAG 0x20000000U /* error message frame */
|
||||||
|
|
||||||
|
/* valid bits in CAN ID for frame formats */
|
||||||
|
#define CAN_SFF_MASK 0x000007FFU /* standard frame format (SFF) */
|
||||||
|
#define CAN_EFF_MASK 0x1FFFFFFFU /* extended frame format (EFF) */
|
||||||
|
#define CAN_ERR_MASK 0x1FFFFFFFU /* omit EFF, RTR, ERR flags */
|
||||||
|
#define CANXL_PRIO_MASK CAN_SFF_MASK /* 11 bit priority mask */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Controller Area Network Identifier structure
|
||||||
|
*
|
||||||
|
* bit 0-28 : CAN identifier (11/29 bit)
|
||||||
|
* bit 29 : error message frame flag (0 = data frame, 1 = error message)
|
||||||
|
* bit 30 : remote transmission request flag (1 = rtr frame)
|
||||||
|
* bit 31 : frame format flag (0 = standard 11 bit, 1 = extended 29 bit)
|
||||||
|
*/
|
||||||
|
typedef __u32 canid_t;
|
||||||
|
|
||||||
|
#define CAN_SFF_ID_BITS 11
|
||||||
|
#define CAN_EFF_ID_BITS 29
|
||||||
|
#define CANXL_PRIO_BITS CAN_SFF_ID_BITS
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Controller Area Network Error Message Frame Mask structure
|
||||||
|
*
|
||||||
|
* bit 0-28 : error class mask (see include/uapi/linux/can/error.h)
|
||||||
|
* bit 29-31 : set to zero
|
||||||
|
*/
|
||||||
|
typedef __u32 can_err_mask_t;
|
||||||
|
|
||||||
|
/* CAN payload length and DLC definitions according to ISO 11898-1 */
|
||||||
|
#define CAN_MAX_DLC 8
|
||||||
|
#define CAN_MAX_RAW_DLC 15
|
||||||
|
#define CAN_MAX_DLEN 8
|
||||||
|
|
||||||
|
/* CAN FD payload length and DLC definitions according to ISO 11898-7 */
|
||||||
|
#define CANFD_MAX_DLC 15
|
||||||
|
#define CANFD_MAX_DLEN 64
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CAN XL payload length and DLC definitions according to ISO 11898-1
|
||||||
|
* CAN XL DLC ranges from 0 .. 2047 => data length from 1 .. 2048 byte
|
||||||
|
*/
|
||||||
|
#define CANXL_MIN_DLC 0
|
||||||
|
#define CANXL_MAX_DLC 2047
|
||||||
|
#define CANXL_MAX_DLC_MASK 0x07FF
|
||||||
|
#define CANXL_MIN_DLEN 1
|
||||||
|
#define CANXL_MAX_DLEN 2048
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct can_frame - Classical CAN frame structure (aka CAN 2.0B)
|
||||||
|
* @can_id: CAN ID of the frame and CAN_*_FLAG flags, see canid_t definition
|
||||||
|
* @len: CAN frame payload length in byte (0 .. 8)
|
||||||
|
* @can_dlc: deprecated name for CAN frame payload length in byte (0 .. 8)
|
||||||
|
* @__pad: padding
|
||||||
|
* @__res0: reserved / padding
|
||||||
|
* @len8_dlc: optional DLC value (9 .. 15) at 8 byte payload length
|
||||||
|
* len8_dlc contains values from 9 .. 15 when the payload length is
|
||||||
|
* 8 bytes but the DLC value (see ISO 11898-1) is greater then 8.
|
||||||
|
* CAN_CTRLMODE_CC_LEN8_DLC flag has to be enabled in CAN driver.
|
||||||
|
* @data: CAN frame payload (up to 8 byte)
|
||||||
|
*/
|
||||||
|
struct can_frame {
|
||||||
|
canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
|
||||||
|
union {
|
||||||
|
/* CAN frame payload length in byte (0 .. CAN_MAX_DLEN)
|
||||||
|
* was previously named can_dlc so we need to carry that
|
||||||
|
* name for legacy support
|
||||||
|
*/
|
||||||
|
__u8 len;
|
||||||
|
__u8 can_dlc; /* deprecated */
|
||||||
|
} __attribute__((packed)); /* disable padding added in some ABIs */
|
||||||
|
__u8 __pad; /* padding */
|
||||||
|
__u8 __res0; /* reserved / padding */
|
||||||
|
__u8 len8_dlc; /* optional DLC for 8 byte payload length (9 .. 15) */
|
||||||
|
__u8 data[CAN_MAX_DLEN] __attribute__((aligned(8)));
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* defined bits for canfd_frame.flags
|
||||||
|
*
|
||||||
|
* The use of struct canfd_frame implies the FD Frame (FDF) bit to
|
||||||
|
* be set in the CAN frame bitstream on the wire. The FDF bit switch turns
|
||||||
|
* the CAN controllers bitstream processor into the CAN FD mode which creates
|
||||||
|
* two new options within the CAN FD frame specification:
|
||||||
|
*
|
||||||
|
* Bit Rate Switch - to indicate a second bitrate is/was used for the payload
|
||||||
|
* Error State Indicator - represents the error state of the transmitting node
|
||||||
|
*
|
||||||
|
* As the CANFD_ESI bit is internally generated by the transmitting CAN
|
||||||
|
* controller only the CANFD_BRS bit is relevant for real CAN controllers when
|
||||||
|
* building a CAN FD frame for transmission. Setting the CANFD_ESI bit can make
|
||||||
|
* sense for virtual CAN interfaces to test applications with echoed frames.
|
||||||
|
*
|
||||||
|
* The struct can_frame and struct canfd_frame intentionally share the same
|
||||||
|
* layout to be able to write CAN frame content into a CAN FD frame structure.
|
||||||
|
* When this is done the former differentiation via CAN_MTU / CANFD_MTU gets
|
||||||
|
* lost. CANFD_FDF allows programmers to mark CAN FD frames in the case of
|
||||||
|
* using struct canfd_frame for mixed CAN / CAN FD content (dual use).
|
||||||
|
* Since the introduction of CAN XL the CANFD_FDF flag is set in all CAN FD
|
||||||
|
* frame structures provided by the CAN subsystem of the Linux kernel.
|
||||||
|
*/
|
||||||
|
#define CANFD_BRS 0x01 /* bit rate switch (second bitrate for payload data) */
|
||||||
|
#define CANFD_ESI 0x02 /* error state indicator of the transmitting node */
|
||||||
|
#define CANFD_FDF 0x04 /* mark CAN FD for dual use of struct canfd_frame */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct canfd_frame - CAN flexible data rate frame structure
|
||||||
|
* @can_id: CAN ID of the frame and CAN_*_FLAG flags, see canid_t definition
|
||||||
|
* @len: frame payload length in byte (0 .. CANFD_MAX_DLEN)
|
||||||
|
* @flags: additional flags for CAN FD
|
||||||
|
* @__res0: reserved / padding
|
||||||
|
* @__res1: reserved / padding
|
||||||
|
* @data: CAN FD frame payload (up to CANFD_MAX_DLEN byte)
|
||||||
|
*/
|
||||||
|
struct canfd_frame {
|
||||||
|
canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
|
||||||
|
__u8 len; /* frame payload length in byte */
|
||||||
|
__u8 flags; /* additional flags for CAN FD */
|
||||||
|
__u8 __res0; /* reserved / padding */
|
||||||
|
__u8 __res1; /* reserved / padding */
|
||||||
|
__u8 data[CANFD_MAX_DLEN] __attribute__((aligned(8)));
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* defined bits for canxl_frame.flags
|
||||||
|
*
|
||||||
|
* The canxl_frame.flags element contains two bits CANXL_XLF and CANXL_SEC
|
||||||
|
* and shares the relative position of the struct can[fd]_frame.len element.
|
||||||
|
* The CANXL_XLF bit ALWAYS needs to be set to indicate a valid CAN XL frame.
|
||||||
|
* As a side effect setting this bit intentionally breaks the length checks
|
||||||
|
* for Classical CAN and CAN FD frames.
|
||||||
|
*
|
||||||
|
* Undefined bits in canxl_frame.flags are reserved and shall be set to zero.
|
||||||
|
*/
|
||||||
|
#define CANXL_XLF 0x80 /* mandatory CAN XL frame flag (must always be set!) */
|
||||||
|
#define CANXL_SEC 0x01 /* Simple Extended Content (security/segmentation) */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct canxl_frame - CAN with e'X'tended frame 'L'ength frame structure
|
||||||
|
* @prio: 11 bit arbitration priority with zero'ed CAN_*_FLAG flags
|
||||||
|
* @flags: additional flags for CAN XL
|
||||||
|
* @sdt: SDU (service data unit) type
|
||||||
|
* @len: frame payload length in byte (CANXL_MIN_DLEN .. CANXL_MAX_DLEN)
|
||||||
|
* @af: acceptance field
|
||||||
|
* @data: CAN XL frame payload (CANXL_MIN_DLEN .. CANXL_MAX_DLEN byte)
|
||||||
|
*
|
||||||
|
* @prio shares the same position as @can_id from struct can[fd]_frame.
|
||||||
|
*/
|
||||||
|
struct canxl_frame {
|
||||||
|
canid_t prio; /* 11 bit priority for arbitration (canid_t) */
|
||||||
|
__u8 flags; /* additional flags for CAN XL */
|
||||||
|
__u8 sdt; /* SDU (service data unit) type */
|
||||||
|
__u16 len; /* frame payload length in byte */
|
||||||
|
__u32 af; /* acceptance field */
|
||||||
|
__u8 data[CANXL_MAX_DLEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CAN_MTU (sizeof(struct can_frame))
|
||||||
|
#define CANFD_MTU (sizeof(struct canfd_frame))
|
||||||
|
#define CANXL_MTU (sizeof(struct canxl_frame))
|
||||||
|
#define CANXL_HDR_SIZE (offsetof(struct canxl_frame, data))
|
||||||
|
#define CANXL_MIN_MTU (CANXL_HDR_SIZE + 64)
|
||||||
|
#define CANXL_MAX_MTU CANXL_MTU
|
||||||
|
|
||||||
|
/* particular protocols of the protocol family PF_CAN */
|
||||||
|
#define CAN_RAW 1 /* RAW sockets */
|
||||||
|
#define CAN_BCM 2 /* Broadcast Manager */
|
||||||
|
#define CAN_TP16 3 /* VAG Transport Protocol v1.6 */
|
||||||
|
#define CAN_TP20 4 /* VAG Transport Protocol v2.0 */
|
||||||
|
#define CAN_MCNET 5 /* Bosch MCNet */
|
||||||
|
#define CAN_ISOTP 6 /* ISO 15765-2 Transport Protocol */
|
||||||
|
#define CAN_J1939 7 /* SAE J1939 */
|
||||||
|
#define CAN_NPROTO 8
|
||||||
|
|
||||||
|
#define SOL_CAN_BASE 100
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This typedef was introduced in Linux v3.1-rc2
|
||||||
|
* (commit 6602a4b net: Make userland include of netlink.h more sane)
|
||||||
|
* in <linux/socket.h>. It must be duplicated here to make the CAN
|
||||||
|
* headers self-contained.
|
||||||
|
*/
|
||||||
|
typedef unsigned short __kernel_sa_family_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct sockaddr_can - the sockaddr structure for CAN sockets
|
||||||
|
* @can_family: address family number AF_CAN.
|
||||||
|
* @can_ifindex: CAN network interface index.
|
||||||
|
* @can_addr: protocol specific address information
|
||||||
|
*/
|
||||||
|
struct sockaddr_can {
|
||||||
|
__kernel_sa_family_t can_family;
|
||||||
|
int can_ifindex;
|
||||||
|
union {
|
||||||
|
/* transport protocol class address information (e.g. ISOTP) */
|
||||||
|
struct { canid_t rx_id, tx_id; } tp;
|
||||||
|
|
||||||
|
/* J1939 address information */
|
||||||
|
struct {
|
||||||
|
/* 8 byte name when using dynamic addressing */
|
||||||
|
__u64 name;
|
||||||
|
|
||||||
|
/* pgn:
|
||||||
|
* 8 bit: PS in PDU2 case, else 0
|
||||||
|
* 8 bit: PF
|
||||||
|
* 1 bit: DP
|
||||||
|
* 1 bit: reserved
|
||||||
|
*/
|
||||||
|
__u32 pgn;
|
||||||
|
|
||||||
|
/* 1 byte address */
|
||||||
|
__u8 addr;
|
||||||
|
} j1939;
|
||||||
|
|
||||||
|
/* reserved for future CAN protocols address information */
|
||||||
|
} can_addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct can_filter - CAN ID based filter in can_register().
|
||||||
|
* @can_id: relevant bits of CAN ID which are not masked out.
|
||||||
|
* @can_mask: CAN mask (see description)
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* A filter matches, when
|
||||||
|
*
|
||||||
|
* <received_can_id> & mask == can_id & mask
|
||||||
|
*
|
||||||
|
* The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can
|
||||||
|
* filter for error message frames (CAN_ERR_FLAG bit set in mask).
|
||||||
|
*/
|
||||||
|
struct can_filter {
|
||||||
|
canid_t can_id;
|
||||||
|
canid_t can_mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CAN_INV_FILTER 0x20000000U /* to be set in can_filter.can_id */
|
||||||
|
#define CAN_RAW_FILTER_MAX 512 /* maximum number of can_filter set via setsockopt() */
|
||||||
|
|
||||||
|
#endif /* !_UAPI_CAN_H */
|
||||||
1
deps/libmnl/include/linux/can/Makefile.am
vendored
Normal file
1
deps/libmnl/include/linux/can/Makefile.am
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
noinst_HEADERS = netlink.h
|
||||||
185
deps/libmnl/include/linux/can/netlink.h
vendored
Normal file
185
deps/libmnl/include/linux/can/netlink.h
vendored
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
|
||||||
|
/*
|
||||||
|
* linux/can/netlink.h
|
||||||
|
*
|
||||||
|
* Definitions for the CAN netlink interface
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Wolfgang Grandegger <wg@grandegger.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the version 2 of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _UAPI_CAN_NETLINK_H
|
||||||
|
#define _UAPI_CAN_NETLINK_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CAN bit-timing parameters
|
||||||
|
*
|
||||||
|
* For further information, please read chapter "8 BIT TIMING
|
||||||
|
* REQUIREMENTS" of the "Bosch CAN Specification version 2.0"
|
||||||
|
* at http://www.semiconductors.bosch.de/pdf/can2spec.pdf.
|
||||||
|
*/
|
||||||
|
struct can_bittiming {
|
||||||
|
__u32 bitrate; /* Bit-rate in bits/second */
|
||||||
|
__u32 sample_point; /* Sample point in one-tenth of a percent */
|
||||||
|
__u32 tq; /* Time quanta (TQ) in nanoseconds */
|
||||||
|
__u32 prop_seg; /* Propagation segment in TQs */
|
||||||
|
__u32 phase_seg1; /* Phase buffer segment 1 in TQs */
|
||||||
|
__u32 phase_seg2; /* Phase buffer segment 2 in TQs */
|
||||||
|
__u32 sjw; /* Synchronisation jump width in TQs */
|
||||||
|
__u32 brp; /* Bit-rate prescaler */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CAN hardware-dependent bit-timing constant
|
||||||
|
*
|
||||||
|
* Used for calculating and checking bit-timing parameters
|
||||||
|
*/
|
||||||
|
struct can_bittiming_const {
|
||||||
|
char name[16]; /* Name of the CAN controller hardware */
|
||||||
|
__u32 tseg1_min; /* Time segment 1 = prop_seg + phase_seg1 */
|
||||||
|
__u32 tseg1_max;
|
||||||
|
__u32 tseg2_min; /* Time segment 2 = phase_seg2 */
|
||||||
|
__u32 tseg2_max;
|
||||||
|
__u32 sjw_max; /* Synchronisation jump width */
|
||||||
|
__u32 brp_min; /* Bit-rate prescaler */
|
||||||
|
__u32 brp_max;
|
||||||
|
__u32 brp_inc;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CAN clock parameters
|
||||||
|
*/
|
||||||
|
struct can_clock {
|
||||||
|
__u32 freq; /* CAN system clock frequency in Hz */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CAN operational and error states
|
||||||
|
*/
|
||||||
|
enum can_state {
|
||||||
|
CAN_STATE_ERROR_ACTIVE = 0, /* RX/TX error count < 96 */
|
||||||
|
CAN_STATE_ERROR_WARNING, /* RX/TX error count < 128 */
|
||||||
|
CAN_STATE_ERROR_PASSIVE, /* RX/TX error count < 256 */
|
||||||
|
CAN_STATE_BUS_OFF, /* RX/TX error count >= 256 */
|
||||||
|
CAN_STATE_STOPPED, /* Device is stopped */
|
||||||
|
CAN_STATE_SLEEPING, /* Device is sleeping */
|
||||||
|
CAN_STATE_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CAN bus error counters
|
||||||
|
*/
|
||||||
|
struct can_berr_counter {
|
||||||
|
__u16 txerr;
|
||||||
|
__u16 rxerr;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CAN controller mode
|
||||||
|
*/
|
||||||
|
struct can_ctrlmode {
|
||||||
|
__u32 mask;
|
||||||
|
__u32 flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CAN_CTRLMODE_LOOPBACK 0x01 /* Loopback mode */
|
||||||
|
#define CAN_CTRLMODE_LISTENONLY 0x02 /* Listen-only mode */
|
||||||
|
#define CAN_CTRLMODE_3_SAMPLES 0x04 /* Triple sampling mode */
|
||||||
|
#define CAN_CTRLMODE_ONE_SHOT 0x08 /* One-Shot mode */
|
||||||
|
#define CAN_CTRLMODE_BERR_REPORTING 0x10 /* Bus-error reporting */
|
||||||
|
#define CAN_CTRLMODE_FD 0x20 /* CAN FD mode */
|
||||||
|
#define CAN_CTRLMODE_PRESUME_ACK 0x40 /* Ignore missing CAN ACKs */
|
||||||
|
#define CAN_CTRLMODE_FD_NON_ISO 0x80 /* CAN FD in non-ISO mode */
|
||||||
|
#define CAN_CTRLMODE_CC_LEN8_DLC 0x100 /* Classic CAN DLC option */
|
||||||
|
#define CAN_CTRLMODE_TDC_AUTO 0x200 /* CAN transiver automatically calculates TDCV */
|
||||||
|
#define CAN_CTRLMODE_TDC_MANUAL 0x400 /* TDCV is manually set up by user */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CAN device statistics
|
||||||
|
*/
|
||||||
|
struct can_device_stats {
|
||||||
|
__u32 bus_error; /* Bus errors */
|
||||||
|
__u32 error_warning; /* Changes to error warning state */
|
||||||
|
__u32 error_passive; /* Changes to error passive state */
|
||||||
|
__u32 bus_off; /* Changes to bus off state */
|
||||||
|
__u32 arbitration_lost; /* Arbitration lost errors */
|
||||||
|
__u32 restarts; /* CAN controller re-starts */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CAN netlink interface
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
IFLA_CAN_UNSPEC,
|
||||||
|
IFLA_CAN_BITTIMING,
|
||||||
|
IFLA_CAN_BITTIMING_CONST,
|
||||||
|
IFLA_CAN_CLOCK,
|
||||||
|
IFLA_CAN_STATE,
|
||||||
|
IFLA_CAN_CTRLMODE,
|
||||||
|
IFLA_CAN_RESTART_MS,
|
||||||
|
IFLA_CAN_RESTART,
|
||||||
|
IFLA_CAN_BERR_COUNTER,
|
||||||
|
IFLA_CAN_DATA_BITTIMING,
|
||||||
|
IFLA_CAN_DATA_BITTIMING_CONST,
|
||||||
|
IFLA_CAN_TERMINATION,
|
||||||
|
IFLA_CAN_TERMINATION_CONST,
|
||||||
|
IFLA_CAN_BITRATE_CONST,
|
||||||
|
IFLA_CAN_DATA_BITRATE_CONST,
|
||||||
|
IFLA_CAN_BITRATE_MAX,
|
||||||
|
IFLA_CAN_TDC,
|
||||||
|
IFLA_CAN_CTRLMODE_EXT,
|
||||||
|
|
||||||
|
/* add new constants above here */
|
||||||
|
__IFLA_CAN_MAX,
|
||||||
|
IFLA_CAN_MAX = __IFLA_CAN_MAX - 1
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CAN FD Transmitter Delay Compensation (TDC)
|
||||||
|
*
|
||||||
|
* Please refer to struct can_tdc_const and can_tdc in
|
||||||
|
* include/linux/can/bittiming.h for further details.
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
IFLA_CAN_TDC_UNSPEC,
|
||||||
|
IFLA_CAN_TDC_TDCV_MIN, /* u32 */
|
||||||
|
IFLA_CAN_TDC_TDCV_MAX, /* u32 */
|
||||||
|
IFLA_CAN_TDC_TDCO_MIN, /* u32 */
|
||||||
|
IFLA_CAN_TDC_TDCO_MAX, /* u32 */
|
||||||
|
IFLA_CAN_TDC_TDCF_MIN, /* u32 */
|
||||||
|
IFLA_CAN_TDC_TDCF_MAX, /* u32 */
|
||||||
|
IFLA_CAN_TDC_TDCV, /* u32 */
|
||||||
|
IFLA_CAN_TDC_TDCO, /* u32 */
|
||||||
|
IFLA_CAN_TDC_TDCF, /* u32 */
|
||||||
|
|
||||||
|
/* add new constants above here */
|
||||||
|
__IFLA_CAN_TDC,
|
||||||
|
IFLA_CAN_TDC_MAX = __IFLA_CAN_TDC - 1
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IFLA_CAN_CTRLMODE_EXT nest: controller mode extended parameters
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
IFLA_CAN_CTRLMODE_UNSPEC,
|
||||||
|
IFLA_CAN_CTRLMODE_SUPPORTED, /* u32 */
|
||||||
|
|
||||||
|
/* add new constants above here */
|
||||||
|
__IFLA_CAN_CTRLMODE,
|
||||||
|
IFLA_CAN_CTRLMODE_MAX = __IFLA_CAN_CTRLMODE - 1
|
||||||
|
};
|
||||||
|
|
||||||
|
/* u16 termination range: 1..65535 Ohms */
|
||||||
|
#define CAN_TERMINATION_DISABLED 0
|
||||||
|
|
||||||
|
#endif /* !_UAPI_CAN_NETLINK_H */
|
||||||
1
deps/libmnl/include/linux/netfilter/Makefile.am
vendored
Normal file
1
deps/libmnl/include/linux/netfilter/Makefile.am
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
noinst_HEADERS = nfnetlink_conntrack.h
|
||||||
252
deps/libmnl/include/linux/netfilter/nfnetlink_conntrack.h
vendored
Normal file
252
deps/libmnl/include/linux/netfilter/nfnetlink_conntrack.h
vendored
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
#ifndef _IPCONNTRACK_NETLINK_H
|
||||||
|
#define _IPCONNTRACK_NETLINK_H
|
||||||
|
#include <linux/netfilter/nfnetlink.h>
|
||||||
|
|
||||||
|
enum cntl_msg_types {
|
||||||
|
IPCTNL_MSG_CT_NEW,
|
||||||
|
IPCTNL_MSG_CT_GET,
|
||||||
|
IPCTNL_MSG_CT_DELETE,
|
||||||
|
IPCTNL_MSG_CT_GET_CTRZERO,
|
||||||
|
IPCTNL_MSG_CT_GET_STATS_CPU,
|
||||||
|
IPCTNL_MSG_CT_GET_STATS,
|
||||||
|
IPCTNL_MSG_CT_GET_DYING,
|
||||||
|
IPCTNL_MSG_CT_GET_UNCONFIRMED,
|
||||||
|
|
||||||
|
IPCTNL_MSG_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ctnl_exp_msg_types {
|
||||||
|
IPCTNL_MSG_EXP_NEW,
|
||||||
|
IPCTNL_MSG_EXP_GET,
|
||||||
|
IPCTNL_MSG_EXP_DELETE,
|
||||||
|
IPCTNL_MSG_EXP_GET_STATS_CPU,
|
||||||
|
|
||||||
|
IPCTNL_MSG_EXP_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum ctattr_type {
|
||||||
|
CTA_UNSPEC,
|
||||||
|
CTA_TUPLE_ORIG,
|
||||||
|
CTA_TUPLE_REPLY,
|
||||||
|
CTA_STATUS,
|
||||||
|
CTA_PROTOINFO,
|
||||||
|
CTA_HELP,
|
||||||
|
CTA_NAT_SRC,
|
||||||
|
#define CTA_NAT CTA_NAT_SRC /* backwards compatibility */
|
||||||
|
CTA_TIMEOUT,
|
||||||
|
CTA_MARK,
|
||||||
|
CTA_COUNTERS_ORIG,
|
||||||
|
CTA_COUNTERS_REPLY,
|
||||||
|
CTA_USE,
|
||||||
|
CTA_ID,
|
||||||
|
CTA_NAT_DST,
|
||||||
|
CTA_TUPLE_MASTER,
|
||||||
|
CTA_NAT_SEQ_ADJ_ORIG,
|
||||||
|
CTA_NAT_SEQ_ADJ_REPLY,
|
||||||
|
CTA_SECMARK, /* obsolete */
|
||||||
|
CTA_ZONE,
|
||||||
|
CTA_SECCTX,
|
||||||
|
CTA_TIMESTAMP,
|
||||||
|
CTA_MARK_MASK,
|
||||||
|
CTA_LABELS,
|
||||||
|
CTA_LABELS_MASK,
|
||||||
|
__CTA_MAX
|
||||||
|
};
|
||||||
|
#define CTA_MAX (__CTA_MAX - 1)
|
||||||
|
|
||||||
|
enum ctattr_tuple {
|
||||||
|
CTA_TUPLE_UNSPEC,
|
||||||
|
CTA_TUPLE_IP,
|
||||||
|
CTA_TUPLE_PROTO,
|
||||||
|
__CTA_TUPLE_MAX
|
||||||
|
};
|
||||||
|
#define CTA_TUPLE_MAX (__CTA_TUPLE_MAX - 1)
|
||||||
|
|
||||||
|
enum ctattr_ip {
|
||||||
|
CTA_IP_UNSPEC,
|
||||||
|
CTA_IP_V4_SRC,
|
||||||
|
CTA_IP_V4_DST,
|
||||||
|
CTA_IP_V6_SRC,
|
||||||
|
CTA_IP_V6_DST,
|
||||||
|
__CTA_IP_MAX
|
||||||
|
};
|
||||||
|
#define CTA_IP_MAX (__CTA_IP_MAX - 1)
|
||||||
|
|
||||||
|
enum ctattr_l4proto {
|
||||||
|
CTA_PROTO_UNSPEC,
|
||||||
|
CTA_PROTO_NUM,
|
||||||
|
CTA_PROTO_SRC_PORT,
|
||||||
|
CTA_PROTO_DST_PORT,
|
||||||
|
CTA_PROTO_ICMP_ID,
|
||||||
|
CTA_PROTO_ICMP_TYPE,
|
||||||
|
CTA_PROTO_ICMP_CODE,
|
||||||
|
CTA_PROTO_ICMPV6_ID,
|
||||||
|
CTA_PROTO_ICMPV6_TYPE,
|
||||||
|
CTA_PROTO_ICMPV6_CODE,
|
||||||
|
__CTA_PROTO_MAX
|
||||||
|
};
|
||||||
|
#define CTA_PROTO_MAX (__CTA_PROTO_MAX - 1)
|
||||||
|
|
||||||
|
enum ctattr_protoinfo {
|
||||||
|
CTA_PROTOINFO_UNSPEC,
|
||||||
|
CTA_PROTOINFO_TCP,
|
||||||
|
CTA_PROTOINFO_DCCP,
|
||||||
|
CTA_PROTOINFO_SCTP,
|
||||||
|
__CTA_PROTOINFO_MAX
|
||||||
|
};
|
||||||
|
#define CTA_PROTOINFO_MAX (__CTA_PROTOINFO_MAX - 1)
|
||||||
|
|
||||||
|
enum ctattr_protoinfo_tcp {
|
||||||
|
CTA_PROTOINFO_TCP_UNSPEC,
|
||||||
|
CTA_PROTOINFO_TCP_STATE,
|
||||||
|
CTA_PROTOINFO_TCP_WSCALE_ORIGINAL,
|
||||||
|
CTA_PROTOINFO_TCP_WSCALE_REPLY,
|
||||||
|
CTA_PROTOINFO_TCP_FLAGS_ORIGINAL,
|
||||||
|
CTA_PROTOINFO_TCP_FLAGS_REPLY,
|
||||||
|
__CTA_PROTOINFO_TCP_MAX
|
||||||
|
};
|
||||||
|
#define CTA_PROTOINFO_TCP_MAX (__CTA_PROTOINFO_TCP_MAX - 1)
|
||||||
|
|
||||||
|
enum ctattr_protoinfo_dccp {
|
||||||
|
CTA_PROTOINFO_DCCP_UNSPEC,
|
||||||
|
CTA_PROTOINFO_DCCP_STATE,
|
||||||
|
CTA_PROTOINFO_DCCP_ROLE,
|
||||||
|
CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ,
|
||||||
|
__CTA_PROTOINFO_DCCP_MAX,
|
||||||
|
};
|
||||||
|
#define CTA_PROTOINFO_DCCP_MAX (__CTA_PROTOINFO_DCCP_MAX - 1)
|
||||||
|
|
||||||
|
enum ctattr_protoinfo_sctp {
|
||||||
|
CTA_PROTOINFO_SCTP_UNSPEC,
|
||||||
|
CTA_PROTOINFO_SCTP_STATE,
|
||||||
|
CTA_PROTOINFO_SCTP_VTAG_ORIGINAL,
|
||||||
|
CTA_PROTOINFO_SCTP_VTAG_REPLY,
|
||||||
|
__CTA_PROTOINFO_SCTP_MAX
|
||||||
|
};
|
||||||
|
#define CTA_PROTOINFO_SCTP_MAX (__CTA_PROTOINFO_SCTP_MAX - 1)
|
||||||
|
|
||||||
|
enum ctattr_counters {
|
||||||
|
CTA_COUNTERS_UNSPEC,
|
||||||
|
CTA_COUNTERS_PACKETS, /* 64bit counters */
|
||||||
|
CTA_COUNTERS_BYTES, /* 64bit counters */
|
||||||
|
CTA_COUNTERS32_PACKETS, /* old 32bit counters, unused */
|
||||||
|
CTA_COUNTERS32_BYTES, /* old 32bit counters, unused */
|
||||||
|
__CTA_COUNTERS_MAX
|
||||||
|
};
|
||||||
|
#define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1)
|
||||||
|
|
||||||
|
enum ctattr_tstamp {
|
||||||
|
CTA_TIMESTAMP_UNSPEC,
|
||||||
|
CTA_TIMESTAMP_START,
|
||||||
|
CTA_TIMESTAMP_STOP,
|
||||||
|
__CTA_TIMESTAMP_MAX
|
||||||
|
};
|
||||||
|
#define CTA_TIMESTAMP_MAX (__CTA_TIMESTAMP_MAX - 1)
|
||||||
|
|
||||||
|
enum ctattr_nat {
|
||||||
|
CTA_NAT_UNSPEC,
|
||||||
|
CTA_NAT_V4_MINIP,
|
||||||
|
#define CTA_NAT_MINIP CTA_NAT_V4_MINIP
|
||||||
|
CTA_NAT_V4_MAXIP,
|
||||||
|
#define CTA_NAT_MAXIP CTA_NAT_V4_MAXIP
|
||||||
|
CTA_NAT_PROTO,
|
||||||
|
CTA_NAT_V6_MINIP,
|
||||||
|
CTA_NAT_V6_MAXIP,
|
||||||
|
__CTA_NAT_MAX
|
||||||
|
};
|
||||||
|
#define CTA_NAT_MAX (__CTA_NAT_MAX - 1)
|
||||||
|
|
||||||
|
enum ctattr_protonat {
|
||||||
|
CTA_PROTONAT_UNSPEC,
|
||||||
|
CTA_PROTONAT_PORT_MIN,
|
||||||
|
CTA_PROTONAT_PORT_MAX,
|
||||||
|
__CTA_PROTONAT_MAX
|
||||||
|
};
|
||||||
|
#define CTA_PROTONAT_MAX (__CTA_PROTONAT_MAX - 1)
|
||||||
|
|
||||||
|
enum ctattr_natseq {
|
||||||
|
CTA_NAT_SEQ_UNSPEC,
|
||||||
|
CTA_NAT_SEQ_CORRECTION_POS,
|
||||||
|
CTA_NAT_SEQ_OFFSET_BEFORE,
|
||||||
|
CTA_NAT_SEQ_OFFSET_AFTER,
|
||||||
|
__CTA_NAT_SEQ_MAX
|
||||||
|
};
|
||||||
|
#define CTA_NAT_SEQ_MAX (__CTA_NAT_SEQ_MAX - 1)
|
||||||
|
|
||||||
|
enum ctattr_expect {
|
||||||
|
CTA_EXPECT_UNSPEC,
|
||||||
|
CTA_EXPECT_MASTER,
|
||||||
|
CTA_EXPECT_TUPLE,
|
||||||
|
CTA_EXPECT_MASK,
|
||||||
|
CTA_EXPECT_TIMEOUT,
|
||||||
|
CTA_EXPECT_ID,
|
||||||
|
CTA_EXPECT_HELP_NAME,
|
||||||
|
CTA_EXPECT_ZONE,
|
||||||
|
CTA_EXPECT_FLAGS,
|
||||||
|
CTA_EXPECT_CLASS,
|
||||||
|
CTA_EXPECT_NAT,
|
||||||
|
CTA_EXPECT_FN,
|
||||||
|
__CTA_EXPECT_MAX
|
||||||
|
};
|
||||||
|
#define CTA_EXPECT_MAX (__CTA_EXPECT_MAX - 1)
|
||||||
|
|
||||||
|
enum ctattr_expect_nat {
|
||||||
|
CTA_EXPECT_NAT_UNSPEC,
|
||||||
|
CTA_EXPECT_NAT_DIR,
|
||||||
|
CTA_EXPECT_NAT_TUPLE,
|
||||||
|
__CTA_EXPECT_NAT_MAX
|
||||||
|
};
|
||||||
|
#define CTA_EXPECT_NAT_MAX (__CTA_EXPECT_NAT_MAX - 1)
|
||||||
|
|
||||||
|
enum ctattr_help {
|
||||||
|
CTA_HELP_UNSPEC,
|
||||||
|
CTA_HELP_NAME,
|
||||||
|
CTA_HELP_INFO,
|
||||||
|
__CTA_HELP_MAX
|
||||||
|
};
|
||||||
|
#define CTA_HELP_MAX (__CTA_HELP_MAX - 1)
|
||||||
|
|
||||||
|
enum ctattr_secctx {
|
||||||
|
CTA_SECCTX_UNSPEC,
|
||||||
|
CTA_SECCTX_NAME,
|
||||||
|
__CTA_SECCTX_MAX
|
||||||
|
};
|
||||||
|
#define CTA_SECCTX_MAX (__CTA_SECCTX_MAX - 1)
|
||||||
|
|
||||||
|
enum ctattr_stats_cpu {
|
||||||
|
CTA_STATS_UNSPEC,
|
||||||
|
CTA_STATS_SEARCHED,
|
||||||
|
CTA_STATS_FOUND,
|
||||||
|
CTA_STATS_NEW,
|
||||||
|
CTA_STATS_INVALID,
|
||||||
|
CTA_STATS_IGNORE,
|
||||||
|
CTA_STATS_DELETE,
|
||||||
|
CTA_STATS_DELETE_LIST,
|
||||||
|
CTA_STATS_INSERT,
|
||||||
|
CTA_STATS_INSERT_FAILED,
|
||||||
|
CTA_STATS_DROP,
|
||||||
|
CTA_STATS_EARLY_DROP,
|
||||||
|
CTA_STATS_ERROR,
|
||||||
|
CTA_STATS_SEARCH_RESTART,
|
||||||
|
__CTA_STATS_MAX,
|
||||||
|
};
|
||||||
|
#define CTA_STATS_MAX (__CTA_STATS_MAX - 1)
|
||||||
|
|
||||||
|
enum ctattr_stats_global {
|
||||||
|
CTA_STATS_GLOBAL_UNSPEC,
|
||||||
|
CTA_STATS_GLOBAL_ENTRIES,
|
||||||
|
__CTA_STATS_GLOBAL_MAX,
|
||||||
|
};
|
||||||
|
#define CTA_STATS_GLOBAL_MAX (__CTA_STATS_GLOBAL_MAX - 1)
|
||||||
|
|
||||||
|
enum ctattr_expect_stats {
|
||||||
|
CTA_STATS_EXP_UNSPEC,
|
||||||
|
CTA_STATS_EXP_NEW,
|
||||||
|
CTA_STATS_EXP_CREATE,
|
||||||
|
CTA_STATS_EXP_DELETE,
|
||||||
|
__CTA_STATS_EXP_MAX,
|
||||||
|
};
|
||||||
|
#define CTA_STATS_EXP_MAX (__CTA_STATS_EXP_MAX - 1)
|
||||||
|
|
||||||
|
#endif /* _IPCONNTRACK_NETLINK_H */
|
||||||
153
deps/libmnl/include/linux/netlink.h
vendored
Normal file
153
deps/libmnl/include/linux/netlink.h
vendored
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
#ifndef __LINUX_NETLINK_H
|
||||||
|
#define __LINUX_NETLINK_H
|
||||||
|
|
||||||
|
#include <linux/socket.h> /* for __kernel_sa_family_t */
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#define NETLINK_ROUTE 0 /* Routing/device hook */
|
||||||
|
#define NETLINK_UNUSED 1 /* Unused number */
|
||||||
|
#define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */
|
||||||
|
#define NETLINK_FIREWALL 3 /* Unused number, formerly ip_queue */
|
||||||
|
#define NETLINK_SOCK_DIAG 4 /* socket monitoring */
|
||||||
|
#define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */
|
||||||
|
#define NETLINK_XFRM 6 /* ipsec */
|
||||||
|
#define NETLINK_SELINUX 7 /* SELinux event notifications */
|
||||||
|
#define NETLINK_ISCSI 8 /* Open-iSCSI */
|
||||||
|
#define NETLINK_AUDIT 9 /* auditing */
|
||||||
|
#define NETLINK_FIB_LOOKUP 10
|
||||||
|
#define NETLINK_CONNECTOR 11
|
||||||
|
#define NETLINK_NETFILTER 12 /* netfilter subsystem */
|
||||||
|
#define NETLINK_IP6_FW 13
|
||||||
|
#define NETLINK_DNRTMSG 14 /* DECnet routing messages */
|
||||||
|
#define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */
|
||||||
|
#define NETLINK_GENERIC 16
|
||||||
|
/* leave room for NETLINK_DM (DM Events) */
|
||||||
|
#define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */
|
||||||
|
#define NETLINK_ECRYPTFS 19
|
||||||
|
#define NETLINK_RDMA 20
|
||||||
|
#define NETLINK_CRYPTO 21 /* Crypto layer */
|
||||||
|
|
||||||
|
#define NETLINK_INET_DIAG NETLINK_SOCK_DIAG
|
||||||
|
|
||||||
|
#define MAX_LINKS 32
|
||||||
|
|
||||||
|
struct sockaddr_nl {
|
||||||
|
__kernel_sa_family_t nl_family; /* AF_NETLINK */
|
||||||
|
unsigned short nl_pad; /* zero */
|
||||||
|
__u32 nl_pid; /* port ID */
|
||||||
|
__u32 nl_groups; /* multicast groups mask */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nlmsghdr {
|
||||||
|
__u32 nlmsg_len; /* Length of message including header */
|
||||||
|
__u16 nlmsg_type; /* Message content */
|
||||||
|
__u16 nlmsg_flags; /* Additional flags */
|
||||||
|
__u32 nlmsg_seq; /* Sequence number */
|
||||||
|
__u32 nlmsg_pid; /* Sending process port ID */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Flags values */
|
||||||
|
|
||||||
|
#define NLM_F_REQUEST 1 /* It is request message. */
|
||||||
|
#define NLM_F_MULTI 2 /* Multipart message, terminated by NLMSG_DONE */
|
||||||
|
#define NLM_F_ACK 4 /* Reply with ack, with zero or error code */
|
||||||
|
#define NLM_F_ECHO 8 /* Echo this request */
|
||||||
|
#define NLM_F_DUMP_INTR 16 /* Dump was inconsistent due to sequence change */
|
||||||
|
|
||||||
|
/* Modifiers to GET request */
|
||||||
|
#define NLM_F_ROOT 0x100 /* specify tree root */
|
||||||
|
#define NLM_F_MATCH 0x200 /* return all matching */
|
||||||
|
#define NLM_F_ATOMIC 0x400 /* atomic GET */
|
||||||
|
#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH)
|
||||||
|
|
||||||
|
/* Modifiers to NEW request */
|
||||||
|
#define NLM_F_REPLACE 0x100 /* Override existing */
|
||||||
|
#define NLM_F_EXCL 0x200 /* Do not touch, if it exists */
|
||||||
|
#define NLM_F_CREATE 0x400 /* Create, if it does not exist */
|
||||||
|
#define NLM_F_APPEND 0x800 /* Add to end of list */
|
||||||
|
|
||||||
|
/*
|
||||||
|
4.4BSD ADD NLM_F_CREATE|NLM_F_EXCL
|
||||||
|
4.4BSD CHANGE NLM_F_REPLACE
|
||||||
|
|
||||||
|
True CHANGE NLM_F_CREATE|NLM_F_REPLACE
|
||||||
|
Append NLM_F_CREATE
|
||||||
|
Check NLM_F_EXCL
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NLMSG_ALIGNTO 4U
|
||||||
|
#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) )
|
||||||
|
#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
|
||||||
|
#define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(NLMSG_HDRLEN))
|
||||||
|
#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
|
||||||
|
#define NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))
|
||||||
|
#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
|
||||||
|
(struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
|
||||||
|
#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \
|
||||||
|
(nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \
|
||||||
|
(nlh)->nlmsg_len <= (len))
|
||||||
|
#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len)))
|
||||||
|
|
||||||
|
#define NLMSG_NOOP 0x1 /* Nothing. */
|
||||||
|
#define NLMSG_ERROR 0x2 /* Error */
|
||||||
|
#define NLMSG_DONE 0x3 /* End of a dump */
|
||||||
|
#define NLMSG_OVERRUN 0x4 /* Data lost */
|
||||||
|
|
||||||
|
#define NLMSG_MIN_TYPE 0x10 /* < 0x10: reserved control messages */
|
||||||
|
|
||||||
|
struct nlmsgerr {
|
||||||
|
int error;
|
||||||
|
struct nlmsghdr msg;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NETLINK_ADD_MEMBERSHIP 1
|
||||||
|
#define NETLINK_DROP_MEMBERSHIP 2
|
||||||
|
#define NETLINK_PKTINFO 3
|
||||||
|
#define NETLINK_BROADCAST_ERROR 4
|
||||||
|
#define NETLINK_NO_ENOBUFS 5
|
||||||
|
|
||||||
|
struct nl_pktinfo {
|
||||||
|
__u32 group;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NET_MAJOR 36 /* Major 36 is reserved for networking */
|
||||||
|
|
||||||
|
enum {
|
||||||
|
NETLINK_UNCONNECTED = 0,
|
||||||
|
NETLINK_CONNECTED,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)-->
|
||||||
|
* +---------------------+- - -+- - - - - - - - - -+- - -+
|
||||||
|
* | Header | Pad | Payload | Pad |
|
||||||
|
* | (struct nlattr) | ing | | ing |
|
||||||
|
* +---------------------+- - -+- - - - - - - - - -+- - -+
|
||||||
|
* <-------------- nlattr->nla_len -------------->
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct nlattr {
|
||||||
|
__u16 nla_len;
|
||||||
|
__u16 nla_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* nla_type (16 bits)
|
||||||
|
* +---+---+-------------------------------+
|
||||||
|
* | N | O | Attribute Type |
|
||||||
|
* +---+---+-------------------------------+
|
||||||
|
* N := Carries nested attributes
|
||||||
|
* O := Payload stored in network byte order
|
||||||
|
*
|
||||||
|
* Note: The N and O flag are mutually exclusive.
|
||||||
|
*/
|
||||||
|
#define NLA_F_NESTED (1 << 15)
|
||||||
|
#define NLA_F_NET_BYTEORDER (1 << 14)
|
||||||
|
#define NLA_TYPE_MASK ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER)
|
||||||
|
|
||||||
|
#define NLA_ALIGNTO 4
|
||||||
|
#define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1))
|
||||||
|
#define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr)))
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __LINUX_NETLINK_H */
|
||||||
21
deps/libmnl/include/linux/socket.h
vendored
Normal file
21
deps/libmnl/include/linux/socket.h
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#ifndef _LINUX_SOCKET_H
|
||||||
|
#define _LINUX_SOCKET_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Desired design of maximum size and alignment (see RFC2553)
|
||||||
|
*/
|
||||||
|
#define _K_SS_MAXSIZE 128 /* Implementation specific max size */
|
||||||
|
#define _K_SS_ALIGNSIZE (__alignof__ (struct sockaddr *))
|
||||||
|
/* Implementation specific desired alignment */
|
||||||
|
|
||||||
|
typedef unsigned short __kernel_sa_family_t;
|
||||||
|
|
||||||
|
struct __kernel_sockaddr_storage {
|
||||||
|
__kernel_sa_family_t ss_family; /* address family */
|
||||||
|
/* Following field(s) are implementation specific */
|
||||||
|
char __data[_K_SS_MAXSIZE - sizeof(unsigned short)];
|
||||||
|
/* space to achieve desired size, */
|
||||||
|
/* _SS_MAXSIZE value minus size of ss_family */
|
||||||
|
} __attribute__ ((aligned(_K_SS_ALIGNSIZE))); /* force desired alignment */
|
||||||
|
|
||||||
|
#endif /* _LINUX_SOCKET_H */
|
||||||
15
deps/libmnl/libmnl.pc.in
vendored
Normal file
15
deps/libmnl/libmnl.pc.in
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# libmnl pkg-config file
|
||||||
|
|
||||||
|
prefix=@prefix@
|
||||||
|
exec_prefix=@exec_prefix@
|
||||||
|
libdir=@libdir@
|
||||||
|
includedir=@includedir@
|
||||||
|
|
||||||
|
Name: libmnl
|
||||||
|
Description: Minimalistic Netlink communication library
|
||||||
|
URL: http://netfilter.org/projects/libmnl/
|
||||||
|
Version: @VERSION@
|
||||||
|
Requires:
|
||||||
|
Conflicts:
|
||||||
|
Libs: -L${libdir} -lmnl
|
||||||
|
Cflags: -I${includedir}
|
||||||
2
deps/libmnl/m4/.gitignore
vendored
Normal file
2
deps/libmnl/m4/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/libtool.m4
|
||||||
|
/lt*.m4
|
||||||
21
deps/libmnl/m4/gcc4_visibility.m4
vendored
Normal file
21
deps/libmnl/m4/gcc4_visibility.m4
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
# GCC 4.x -fvisibility=hidden
|
||||||
|
|
||||||
|
AC_DEFUN([CHECK_GCC_FVISIBILITY], [
|
||||||
|
AC_LANG_PUSH([C])
|
||||||
|
saved_CFLAGS="$CFLAGS"
|
||||||
|
CFLAGS="$saved_CFLAGS -fvisibility=hidden"
|
||||||
|
AC_CACHE_CHECK([whether compiler accepts -fvisibility=hidden],
|
||||||
|
[ac_cv_fvisibility_hidden], AC_COMPILE_IFELSE(
|
||||||
|
[AC_LANG_SOURCE()],
|
||||||
|
[ac_cv_fvisibility_hidden=yes],
|
||||||
|
[ac_cv_fvisibility_hidden=no]
|
||||||
|
))
|
||||||
|
if test "$ac_cv_fvisibility_hidden" = "yes"; then
|
||||||
|
AC_DEFINE([HAVE_VISIBILITY_HIDDEN], [1],
|
||||||
|
[True if compiler supports -fvisibility=hidden])
|
||||||
|
AC_SUBST([GCC_FVISIBILITY_HIDDEN], [-fvisibility=hidden])
|
||||||
|
fi
|
||||||
|
CFLAGS="$saved_CFLAGS"
|
||||||
|
AC_LANG_POP([C])
|
||||||
|
])
|
||||||
5
deps/libmnl/src/Makefile.am
vendored
Normal file
5
deps/libmnl/src/Makefile.am
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
include $(top_srcdir)/Make_global.am
|
||||||
|
lib_LTLIBRARIES = libmnl.la
|
||||||
|
|
||||||
|
libmnl_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libmnl.map -version-info $(LIBVERSION)
|
||||||
|
libmnl_la_SOURCES = socket.c callback.c nlmsg.c attr.c internal.h libmnl.map
|
||||||
742
deps/libmnl/src/attr.c
vendored
Normal file
742
deps/libmnl/src/attr.c
vendored
Normal file
@@ -0,0 +1,742 @@
|
|||||||
|
/*
|
||||||
|
* (C) 2008-2012 by Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published
|
||||||
|
* by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*/
|
||||||
|
#include <limits.h> /* for INT_MAX */
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup attr Netlink attribute helpers
|
||||||
|
*
|
||||||
|
* Netlink Type-Length-Value (TLV) attribute:
|
||||||
|
* \verbatim
|
||||||
|
|<-- 2 bytes -->|<-- 2 bytes -->|<-- variable -->|
|
||||||
|
-------------------------------------------------
|
||||||
|
| length | type | value |
|
||||||
|
-------------------------------------------------
|
||||||
|
|<--------- header ------------>|<-- payload --->|
|
||||||
|
\endverbatim
|
||||||
|
* The payload of the Netlink message contains sequences of attributes that are
|
||||||
|
* expressed in TLV format.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_get_type - get type of netlink attribute
|
||||||
|
* \param attr pointer to netlink attribute
|
||||||
|
*
|
||||||
|
* \return the attribute type
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL uint16_t mnl_attr_get_type(const struct nlattr *attr)
|
||||||
|
{
|
||||||
|
return attr->nla_type & NLA_TYPE_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_get_len - get length of netlink attribute
|
||||||
|
* \param attr pointer to netlink attribute
|
||||||
|
*
|
||||||
|
* \return the attribute length
|
||||||
|
*
|
||||||
|
* The attribute length is the length of the attribute header plus the
|
||||||
|
* attribute payload.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL uint16_t mnl_attr_get_len(const struct nlattr *attr)
|
||||||
|
{
|
||||||
|
return attr->nla_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_get_payload_len - get the attribute payload-value length
|
||||||
|
* \param attr pointer to netlink attribute
|
||||||
|
*
|
||||||
|
* \return the attribute payload-value length
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL uint16_t mnl_attr_get_payload_len(const struct nlattr *attr)
|
||||||
|
{
|
||||||
|
return attr->nla_len - MNL_ATTR_HDRLEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_get_payload - get pointer to the attribute payload
|
||||||
|
* \param attr pointer to netlink attribute
|
||||||
|
*
|
||||||
|
* \return pointer to the attribute payload
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL void *mnl_attr_get_payload(const struct nlattr *attr)
|
||||||
|
{
|
||||||
|
return (void *)attr + MNL_ATTR_HDRLEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_ok - check if there is room for an attribute in a buffer
|
||||||
|
* \param attr attribute that we want to check if there is room for
|
||||||
|
* \param len remaining bytes in a buffer that contains the attribute
|
||||||
|
*
|
||||||
|
* This function is used to check that a buffer, which is supposed to contain
|
||||||
|
* an attribute, has enough room for the attribute that it stores, i.e. this
|
||||||
|
* function can be used to verify that an attribute is neither malformed nor
|
||||||
|
* truncated.
|
||||||
|
*
|
||||||
|
* This function does not set errno in case of error since it is intended
|
||||||
|
* for iterations.
|
||||||
|
*
|
||||||
|
* The len parameter may be negative in the case of malformed messages during
|
||||||
|
* attribute iteration, that is why we use a signed integer.
|
||||||
|
*
|
||||||
|
* \return true if there is room for the attribute, false otherwise
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL bool mnl_attr_ok(const struct nlattr *attr, int len)
|
||||||
|
{
|
||||||
|
return len >= (int)sizeof(struct nlattr) &&
|
||||||
|
attr->nla_len >= sizeof(struct nlattr) &&
|
||||||
|
(int)attr->nla_len <= len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_next - get the next attribute in the payload of a netlink message
|
||||||
|
* \param attr pointer to the current attribute
|
||||||
|
*
|
||||||
|
* \return a pointer to the next attribute after the one passed in
|
||||||
|
*
|
||||||
|
* You have to use mnl_attr_ok() on the returned attribute to ensure that the
|
||||||
|
* next attribute is valid.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL struct nlattr *mnl_attr_next(const struct nlattr *attr)
|
||||||
|
{
|
||||||
|
return (struct nlattr *)((void *)attr + MNL_ALIGN(attr->nla_len));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_type_valid - check if the attribute type is valid
|
||||||
|
* \param attr pointer to attribute to be checked
|
||||||
|
* \param max maximum attribute type
|
||||||
|
*
|
||||||
|
* This function allows one to check if the attribute type is higher than the
|
||||||
|
* maximum supported type.
|
||||||
|
*
|
||||||
|
* Strict attribute checking in user-space is not a good idea since you may
|
||||||
|
* run an old application with a newer kernel that supports new attributes.
|
||||||
|
* This leads to backward compatibility breakages in user-space. Better check
|
||||||
|
* if you support an attribute, if not, skip it.
|
||||||
|
*
|
||||||
|
* On an error, errno is explicitly set.
|
||||||
|
*
|
||||||
|
* \return 1 if the attribute is valid, -1 otherwise
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL int mnl_attr_type_valid(const struct nlattr *attr, uint16_t max)
|
||||||
|
{
|
||||||
|
if (mnl_attr_get_type(attr) > max) {
|
||||||
|
errno = EOPNOTSUPP;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __mnl_attr_validate(const struct nlattr *attr,
|
||||||
|
enum mnl_attr_data_type type, size_t exp_len)
|
||||||
|
{
|
||||||
|
uint16_t attr_len = mnl_attr_get_payload_len(attr);
|
||||||
|
const char *attr_data = mnl_attr_get_payload(attr);
|
||||||
|
|
||||||
|
if (attr_len < exp_len) {
|
||||||
|
errno = ERANGE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
switch(type) {
|
||||||
|
case MNL_TYPE_FLAG:
|
||||||
|
if (attr_len > 0) {
|
||||||
|
errno = ERANGE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MNL_TYPE_NUL_STRING:
|
||||||
|
if (attr_len == 0) {
|
||||||
|
errno = ERANGE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (attr_data[attr_len-1] != '\0') {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MNL_TYPE_STRING:
|
||||||
|
if (attr_len == 0) {
|
||||||
|
errno = ERANGE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MNL_TYPE_NESTED:
|
||||||
|
/* empty nested attributes are OK. */
|
||||||
|
if (attr_len == 0)
|
||||||
|
break;
|
||||||
|
/* if not empty, they must contain one header, eg. flag */
|
||||||
|
if (attr_len < MNL_ATTR_HDRLEN) {
|
||||||
|
errno = ERANGE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* make gcc happy. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (exp_len && attr_len > exp_len) {
|
||||||
|
errno = ERANGE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const size_t mnl_attr_data_type_len[MNL_TYPE_MAX] = {
|
||||||
|
[MNL_TYPE_U8] = sizeof(uint8_t),
|
||||||
|
[MNL_TYPE_U16] = sizeof(uint16_t),
|
||||||
|
[MNL_TYPE_U32] = sizeof(uint32_t),
|
||||||
|
[MNL_TYPE_U64] = sizeof(uint64_t),
|
||||||
|
[MNL_TYPE_MSECS] = sizeof(uint64_t),
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_validate - validate netlink attribute (simplified version)
|
||||||
|
* \param attr pointer to netlink attribute that we want to validate
|
||||||
|
* \param type data type (see enum mnl_attr_data_type)
|
||||||
|
*
|
||||||
|
* The validation is based on the data type. Specifically, it checks that
|
||||||
|
* integers (u8, u16, u32 and u64) have enough room for them.
|
||||||
|
*
|
||||||
|
* On an error, errno is explicitly set.
|
||||||
|
*
|
||||||
|
* \return 0 on success, -1 on error
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type)
|
||||||
|
{
|
||||||
|
int exp_len;
|
||||||
|
|
||||||
|
if (type >= MNL_TYPE_MAX) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
exp_len = mnl_attr_data_type_len[type];
|
||||||
|
return __mnl_attr_validate(attr, type, exp_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_validate2 - validate netlink attribute (extended version)
|
||||||
|
* \param attr pointer to netlink attribute that we want to validate
|
||||||
|
* \param type attribute type (see enum mnl_attr_data_type)
|
||||||
|
* \param exp_len expected attribute data size
|
||||||
|
*
|
||||||
|
* This function allows one to perform a more accurate validation for attributes
|
||||||
|
* whose size is variable.
|
||||||
|
*
|
||||||
|
* On an error, errno is explicitly set.
|
||||||
|
*
|
||||||
|
* \return 0 if the attribute is valid and fits within the expected length, -1
|
||||||
|
* otherwise
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL int mnl_attr_validate2(const struct nlattr *attr,
|
||||||
|
enum mnl_attr_data_type type,
|
||||||
|
size_t exp_len)
|
||||||
|
{
|
||||||
|
if (type >= MNL_TYPE_MAX) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return __mnl_attr_validate(attr, type, exp_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_parse - parse attributes
|
||||||
|
* \param nlh pointer to netlink message
|
||||||
|
* \param offset offset to start parsing from (if payload is after any header)
|
||||||
|
* \param cb callback function that is called for each attribute
|
||||||
|
* \param data pointer to data that is passed to the callback function
|
||||||
|
*
|
||||||
|
* This function allows you to iterate over the sequence of attributes that
|
||||||
|
* compose the Netlink message. You can then put the attribute in an array as it
|
||||||
|
* usually happens at this stage or you can use any other data structure (such
|
||||||
|
* as lists or trees).
|
||||||
|
*
|
||||||
|
* \return propagated value from callback, one of MNL_CB_ERROR, MNL_CB_STOP
|
||||||
|
* or MNL_CB_OK
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL int mnl_attr_parse(const struct nlmsghdr *nlh,
|
||||||
|
unsigned int offset, mnl_attr_cb_t cb,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
int ret = MNL_CB_OK;
|
||||||
|
const struct nlattr *attr;
|
||||||
|
|
||||||
|
mnl_attr_for_each(attr, nlh, offset)
|
||||||
|
if ((ret = cb(attr, data)) <= MNL_CB_STOP)
|
||||||
|
return ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_parse_nested - parse attributes inside a nest
|
||||||
|
* \param nested pointer to netlink attribute that contains a nest
|
||||||
|
* \param cb callback function that is called for each attribute in the nest
|
||||||
|
* \param data pointer to data passed to the callback function
|
||||||
|
*
|
||||||
|
* This function allows you to iterate over the sequence of attributes that
|
||||||
|
* compose the Netlink message. You can then put the attribute in an array as it
|
||||||
|
* usually happens at this stage or you can use any other data structure (such
|
||||||
|
* as lists or trees).
|
||||||
|
*
|
||||||
|
* \return propagated value from callback, one of MNL_CB_ERROR, MNL_CB_STOP
|
||||||
|
* or MNL_CB_OK
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL int mnl_attr_parse_nested(const struct nlattr *nested,
|
||||||
|
mnl_attr_cb_t cb, void *data)
|
||||||
|
{
|
||||||
|
int ret = MNL_CB_OK;
|
||||||
|
const struct nlattr *attr;
|
||||||
|
|
||||||
|
mnl_attr_for_each_nested(attr, nested)
|
||||||
|
if ((ret = cb(attr, data)) <= MNL_CB_STOP)
|
||||||
|
return ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_parse_payload - parse attributes in payload of Netlink message
|
||||||
|
* \param payload pointer to payload of the Netlink message
|
||||||
|
* \param payload_len payload length that contains the attributes
|
||||||
|
* \param cb callback function that is called for each attribute
|
||||||
|
* \param data pointer to data that is passed to the callback function
|
||||||
|
*
|
||||||
|
* This function takes a pointer to the area that contains the attributes,
|
||||||
|
* commonly known as the payload of the Netlink message. Thus, you have to
|
||||||
|
* pass a pointer to the Netlink message payload, instead of the entire
|
||||||
|
* message.
|
||||||
|
*
|
||||||
|
* This function allows you to iterate over the sequence of attributes that are
|
||||||
|
* located at some payload offset. You can then put the attributes in one array
|
||||||
|
* as usual, or you can use any other data structure (such as lists or trees).
|
||||||
|
*
|
||||||
|
* \return propagated value from callback, one of MNL_CB_ERROR, MNL_CB_STOP
|
||||||
|
* or MNL_CB_OK
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL int mnl_attr_parse_payload(const void *payload,
|
||||||
|
size_t payload_len,
|
||||||
|
mnl_attr_cb_t cb, void *data)
|
||||||
|
{
|
||||||
|
int ret = MNL_CB_OK;
|
||||||
|
const struct nlattr *attr;
|
||||||
|
|
||||||
|
mnl_attr_for_each_payload(payload, payload_len)
|
||||||
|
if ((ret = cb(attr, data)) <= MNL_CB_STOP)
|
||||||
|
return ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_get_u8 - get 8-bit unsigned integer attribute payload
|
||||||
|
* \param attr pointer to netlink attribute
|
||||||
|
*
|
||||||
|
* \return 8-bit value of the attribute payload
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL uint8_t mnl_attr_get_u8(const struct nlattr *attr)
|
||||||
|
{
|
||||||
|
return *((uint8_t *)mnl_attr_get_payload(attr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_get_u16 - get 16-bit unsigned integer attribute payload
|
||||||
|
* \param attr pointer to netlink attribute
|
||||||
|
*
|
||||||
|
* \return 16-bit value of the attribute payload
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL uint16_t mnl_attr_get_u16(const struct nlattr *attr)
|
||||||
|
{
|
||||||
|
return *((uint16_t *)mnl_attr_get_payload(attr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_get_u32 - get 32-bit unsigned integer attribute payload
|
||||||
|
* \param attr pointer to netlink attribute
|
||||||
|
*
|
||||||
|
* \return 32-bit value of the attribute payload
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL uint32_t mnl_attr_get_u32(const struct nlattr *attr)
|
||||||
|
{
|
||||||
|
return *((uint32_t *)mnl_attr_get_payload(attr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_get_u64 - get 64-bit unsigned integer attribute
|
||||||
|
* \param attr pointer to netlink attribute
|
||||||
|
*
|
||||||
|
* This function reads the 64-bit nlattr payload in an alignment safe manner.
|
||||||
|
*
|
||||||
|
* \return 64-bit value of the attribute payload
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL uint64_t mnl_attr_get_u64(const struct nlattr *attr)
|
||||||
|
{
|
||||||
|
uint64_t tmp;
|
||||||
|
memcpy(&tmp, mnl_attr_get_payload(attr), sizeof(tmp));
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_get_str - get pointer to string attribute
|
||||||
|
* \param attr pointer to netlink attribute
|
||||||
|
*
|
||||||
|
* \return string pointer of the attribute payload
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL const char *mnl_attr_get_str(const struct nlattr *attr)
|
||||||
|
{
|
||||||
|
return mnl_attr_get_payload(attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_put - add an attribute to netlink message
|
||||||
|
* \param nlh pointer to the netlink message
|
||||||
|
* \param type netlink attribute type that you want to add
|
||||||
|
* \param len netlink attribute payload length
|
||||||
|
* \param data pointer to the data that will be stored by the new attribute
|
||||||
|
*
|
||||||
|
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||||
|
* by adding the size (header + payload) of the new attribute.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL void mnl_attr_put(struct nlmsghdr *nlh, uint16_t type,
|
||||||
|
size_t len, const void *data)
|
||||||
|
{
|
||||||
|
struct nlattr *attr = mnl_nlmsg_get_payload_tail(nlh);
|
||||||
|
uint16_t payload_len = MNL_ALIGN(sizeof(struct nlattr)) + len;
|
||||||
|
int pad;
|
||||||
|
|
||||||
|
attr->nla_type = type;
|
||||||
|
attr->nla_len = payload_len;
|
||||||
|
memcpy(mnl_attr_get_payload(attr), data, len);
|
||||||
|
pad = MNL_ALIGN(len) - len;
|
||||||
|
if (pad > 0)
|
||||||
|
memset(mnl_attr_get_payload(attr) + len, 0, pad);
|
||||||
|
|
||||||
|
nlh->nlmsg_len += MNL_ALIGN(payload_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_put_u8 - add 8-bit unsigned integer attribute to netlink message
|
||||||
|
* \param nlh pointer to the netlink message
|
||||||
|
* \param type netlink attribute type
|
||||||
|
* \param data 8-bit unsigned integer data that is stored by the new attribute
|
||||||
|
*
|
||||||
|
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||||
|
* by adding the size (header + payload) of the new attribute.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL void mnl_attr_put_u8(struct nlmsghdr *nlh, uint16_t type,
|
||||||
|
uint8_t data)
|
||||||
|
{
|
||||||
|
mnl_attr_put(nlh, type, sizeof(uint8_t), &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_put_u16 - add 16-bit unsigned integer attribute to netlink message
|
||||||
|
* \param nlh pointer to the netlink message
|
||||||
|
* \param type netlink attribute type
|
||||||
|
* \param data 16-bit unsigned integer data that is stored by the new attribute
|
||||||
|
*
|
||||||
|
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||||
|
* by adding the size (header + payload) of the new attribute.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL void mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type,
|
||||||
|
uint16_t data)
|
||||||
|
{
|
||||||
|
mnl_attr_put(nlh, type, sizeof(uint16_t), &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_put_u32 - add 32-bit unsigned integer attribute to netlink message
|
||||||
|
* \param nlh pointer to the netlink message
|
||||||
|
* \param type netlink attribute type
|
||||||
|
* \param data 32-bit unsigned integer data that is stored by the new attribute
|
||||||
|
*
|
||||||
|
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||||
|
* by adding the size (header + payload) of the new attribute.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL void mnl_attr_put_u32(struct nlmsghdr *nlh, uint16_t type,
|
||||||
|
uint32_t data)
|
||||||
|
{
|
||||||
|
mnl_attr_put(nlh, type, sizeof(uint32_t), &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_put_u64 - add 64-bit unsigned integer attribute to netlink message
|
||||||
|
* \param nlh pointer to the netlink message
|
||||||
|
* \param type netlink attribute type
|
||||||
|
* \param data 64-bit unsigned integer data that is stored by the new attribute
|
||||||
|
*
|
||||||
|
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||||
|
* by adding the size (header + payload) of the new attribute.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL void mnl_attr_put_u64(struct nlmsghdr *nlh, uint16_t type,
|
||||||
|
uint64_t data)
|
||||||
|
{
|
||||||
|
mnl_attr_put(nlh, type, sizeof(uint64_t), &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_put_str - add string attribute to netlink message
|
||||||
|
* \param nlh pointer to the netlink message
|
||||||
|
* \param type netlink attribute type
|
||||||
|
* \param data pointer to string data that is stored by the new attribute
|
||||||
|
*
|
||||||
|
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||||
|
* by adding the size (header + payload) of the new attribute.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL void mnl_attr_put_str(struct nlmsghdr *nlh, uint16_t type,
|
||||||
|
const char *data)
|
||||||
|
{
|
||||||
|
mnl_attr_put(nlh, type, strlen(data), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_put_strz - add string attribute to netlink message
|
||||||
|
* \param nlh pointer to the netlink message
|
||||||
|
* \param type netlink attribute type
|
||||||
|
* \param data pointer to string data that is stored by the new attribute
|
||||||
|
*
|
||||||
|
* This function is similar to mnl_attr_put_str, but it includes the
|
||||||
|
* NUL/zero ('\0') terminator at the end of the string.
|
||||||
|
*
|
||||||
|
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||||
|
* by adding the size (header + payload) of the new attribute.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL void mnl_attr_put_strz(struct nlmsghdr *nlh, uint16_t type,
|
||||||
|
const char *data)
|
||||||
|
{
|
||||||
|
mnl_attr_put(nlh, type, strlen(data)+1, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_nest_start - start an attribute nest
|
||||||
|
* \param nlh pointer to the netlink message
|
||||||
|
* \param type netlink attribute type
|
||||||
|
*
|
||||||
|
* This function adds the attribute header that identifies the beginning of
|
||||||
|
* an attribute nest.
|
||||||
|
*
|
||||||
|
* \return valid pointer to the beginning of the nest
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL struct nlattr *mnl_attr_nest_start(struct nlmsghdr *nlh,
|
||||||
|
uint16_t type)
|
||||||
|
{
|
||||||
|
struct nlattr *start = mnl_nlmsg_get_payload_tail(nlh);
|
||||||
|
|
||||||
|
/* set start->nla_len in mnl_attr_nest_end() */
|
||||||
|
start->nla_type = NLA_F_NESTED | type;
|
||||||
|
nlh->nlmsg_len += MNL_ALIGN(sizeof(struct nlattr));
|
||||||
|
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_put_check - add an attribute to netlink message
|
||||||
|
* \param nlh pointer to the netlink message
|
||||||
|
* \param buflen size of buffer which stores the message
|
||||||
|
* \param type netlink attribute type that you want to add
|
||||||
|
* \param len netlink attribute payload length
|
||||||
|
* \param data pointer to the data that will be stored by the new attribute
|
||||||
|
*
|
||||||
|
* This function first checks that the data can be added to the message
|
||||||
|
* (fits into the buffer) and then updates the length field of the Netlink
|
||||||
|
* message (nlmsg_len) by adding the size (header + payload) of the new
|
||||||
|
* attribute.
|
||||||
|
*
|
||||||
|
* \return true if the attribute could be added, false otherwise
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL bool mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen,
|
||||||
|
uint16_t type, size_t len,
|
||||||
|
const void *data)
|
||||||
|
{
|
||||||
|
if (nlh->nlmsg_len + MNL_ATTR_HDRLEN + MNL_ALIGN(len) > buflen)
|
||||||
|
return false;
|
||||||
|
mnl_attr_put(nlh, type, len, data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_put_u8_check - add 8-bit unsigned int attribute to netlink message
|
||||||
|
* \param nlh pointer to the netlink message
|
||||||
|
* \param buflen size of buffer which stores the message
|
||||||
|
* \param type netlink attribute type
|
||||||
|
* \param data 8-bit unsigned integer data that is stored by the new attribute
|
||||||
|
*
|
||||||
|
* This function first checks that the data can be added to the message
|
||||||
|
* (fits into the buffer) and then updates the length field of the Netlink
|
||||||
|
* message (nlmsg_len) by adding the size (header + payload) of the new
|
||||||
|
* attribute.
|
||||||
|
*
|
||||||
|
* \return true if the attribute could be added, false otherwise
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL bool mnl_attr_put_u8_check(struct nlmsghdr *nlh, size_t buflen,
|
||||||
|
uint16_t type, uint8_t data)
|
||||||
|
{
|
||||||
|
return mnl_attr_put_check(nlh, buflen, type, sizeof(uint8_t), &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_put_u16_check - add 16-bit unsigned int attribute to netlink message
|
||||||
|
* \param nlh pointer to the netlink message
|
||||||
|
* \param buflen size of buffer which stores the message
|
||||||
|
* \param type netlink attribute type
|
||||||
|
* \param data 16-bit unsigned integer data that is stored by the new attribute
|
||||||
|
*
|
||||||
|
* This function first checks that the data can be added to the message
|
||||||
|
* (fits into the buffer) and then updates the length field of the Netlink
|
||||||
|
* message (nlmsg_len) by adding the size (header + payload) of the new
|
||||||
|
* attribute.
|
||||||
|
*
|
||||||
|
* \return true if the attribute could be added, false otherwise
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL bool mnl_attr_put_u16_check(struct nlmsghdr *nlh, size_t buflen,
|
||||||
|
uint16_t type, uint16_t data)
|
||||||
|
{
|
||||||
|
return mnl_attr_put_check(nlh, buflen, type, sizeof(uint16_t), &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_put_u32_check - add 32-bit unsigned int attribute to netlink message
|
||||||
|
* \param nlh pointer to the netlink message
|
||||||
|
* \param buflen size of buffer which stores the message
|
||||||
|
* \param type netlink attribute type
|
||||||
|
* \param data 32-bit unsigned integer data that is stored by the new attribute
|
||||||
|
*
|
||||||
|
* This function first checks that the data can be added to the message
|
||||||
|
* (fits into the buffer) and then updates the length field of the Netlink
|
||||||
|
* message (nlmsg_len) by adding the size (header + payload) of the new
|
||||||
|
* attribute.
|
||||||
|
*
|
||||||
|
* \return true if the attribute could be added, false otherwise
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL bool mnl_attr_put_u32_check(struct nlmsghdr *nlh, size_t buflen,
|
||||||
|
uint16_t type, uint32_t data)
|
||||||
|
{
|
||||||
|
return mnl_attr_put_check(nlh, buflen, type, sizeof(uint32_t), &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_put_u64_check - add 64-bit unsigned int attribute to netlink message
|
||||||
|
* \param nlh pointer to the netlink message
|
||||||
|
* \param buflen size of buffer which stores the message
|
||||||
|
* \param type netlink attribute type
|
||||||
|
* \param data 64-bit unsigned integer data that is stored by the new attribute
|
||||||
|
*
|
||||||
|
* This function first checks that the data can be added to the message
|
||||||
|
* (fits into the buffer) and then updates the length field of the Netlink
|
||||||
|
* message (nlmsg_len) by adding the size (header + payload) of the new
|
||||||
|
* attribute.
|
||||||
|
*
|
||||||
|
* \return true if the attribute could be added, false otherwise
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL bool mnl_attr_put_u64_check(struct nlmsghdr *nlh, size_t buflen,
|
||||||
|
uint16_t type, uint64_t data)
|
||||||
|
{
|
||||||
|
return mnl_attr_put_check(nlh, buflen, type, sizeof(uint64_t), &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_put_str_check - add string attribute to netlink message
|
||||||
|
* \param nlh pointer to the netlink message
|
||||||
|
* \param buflen size of buffer which stores the message
|
||||||
|
* \param type netlink attribute type
|
||||||
|
* \param data pointer to string data that is stored by the new attribute
|
||||||
|
*
|
||||||
|
* This function first checks that the data can be added to the message
|
||||||
|
* (fits into the buffer) and then updates the length field of the Netlink
|
||||||
|
* message (nlmsg_len) by adding the size (header + payload) of the new
|
||||||
|
* attribute.
|
||||||
|
*
|
||||||
|
* \return true if the attribute could be added, false otherwise
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL bool mnl_attr_put_str_check(struct nlmsghdr *nlh, size_t buflen,
|
||||||
|
uint16_t type, const char *data)
|
||||||
|
{
|
||||||
|
return mnl_attr_put_check(nlh, buflen, type, strlen(data), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_put_strz_check - add string attribute to netlink message
|
||||||
|
* \param nlh pointer to the netlink message
|
||||||
|
* \param buflen size of buffer which stores the message
|
||||||
|
* \param type netlink attribute type
|
||||||
|
* \param data pointer to string data that is stored by the new attribute
|
||||||
|
*
|
||||||
|
* This function is similar to mnl_attr_put_str, but it includes the
|
||||||
|
* NUL/zero ('\0') terminator at the end of the string.
|
||||||
|
*
|
||||||
|
* This function first checks that the data can be added to the message
|
||||||
|
* (fits into the buffer) and then updates the length field of the Netlink
|
||||||
|
* message (nlmsg_len) by adding the size (header + payload) of the new
|
||||||
|
* attribute.
|
||||||
|
*
|
||||||
|
* \return true if the attribute could be added, false otherwise
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL bool mnl_attr_put_strz_check(struct nlmsghdr *nlh, size_t buflen,
|
||||||
|
uint16_t type, const char *data)
|
||||||
|
{
|
||||||
|
return mnl_attr_put_check(nlh, buflen, type, strlen(data)+1, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_nest_start_check - start an attribute nest
|
||||||
|
* \param buflen size of buffer which stores the message
|
||||||
|
* \param nlh pointer to the netlink message
|
||||||
|
* \param type netlink attribute type
|
||||||
|
*
|
||||||
|
* This function adds the attribute header that identifies the beginning of
|
||||||
|
* an attribute nest.
|
||||||
|
*
|
||||||
|
* \return NULL if the attribute cannot be added, otherwise a pointer to the
|
||||||
|
* beginning of the nest
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL struct nlattr *mnl_attr_nest_start_check(struct nlmsghdr *nlh,
|
||||||
|
size_t buflen,
|
||||||
|
uint16_t type)
|
||||||
|
{
|
||||||
|
if (nlh->nlmsg_len + MNL_ATTR_HDRLEN > buflen)
|
||||||
|
return NULL;
|
||||||
|
return mnl_attr_nest_start(nlh, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_nest_end - end an attribute nest
|
||||||
|
* \param nlh pointer to the netlink message
|
||||||
|
* \param start pointer to the attribute nest returned by mnl_attr_nest_start()
|
||||||
|
*
|
||||||
|
* This function updates the attribute header that identifies the nest.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL void mnl_attr_nest_end(struct nlmsghdr *nlh,
|
||||||
|
struct nlattr *start)
|
||||||
|
{
|
||||||
|
start->nla_len = mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_attr_nest_cancel - cancel an attribute nest
|
||||||
|
* \param nlh pointer to the netlink message
|
||||||
|
* \param start pointer to the attribute nest returned by mnl_attr_nest_start()
|
||||||
|
*
|
||||||
|
* This function updates the attribute header that identifies the nest.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL void mnl_attr_nest_cancel(struct nlmsghdr *nlh,
|
||||||
|
struct nlattr *start)
|
||||||
|
{
|
||||||
|
nlh->nlmsg_len -= mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
167
deps/libmnl/src/callback.c
vendored
Normal file
167
deps/libmnl/src/callback.c
vendored
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
/*
|
||||||
|
* (C) 2008-2010 by Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published
|
||||||
|
* by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
static int mnl_cb_noop(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mnl_cb_error(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh);
|
||||||
|
|
||||||
|
if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr))) {
|
||||||
|
errno = EBADMSG;
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
/* Netlink subsystems returns the errno value with different signess */
|
||||||
|
if (err->error < 0)
|
||||||
|
errno = -err->error;
|
||||||
|
else
|
||||||
|
errno = err->error;
|
||||||
|
|
||||||
|
return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mnl_cb_stop(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
return MNL_CB_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const mnl_cb_t default_cb_array[NLMSG_MIN_TYPE] = {
|
||||||
|
[NLMSG_NOOP] = mnl_cb_noop,
|
||||||
|
[NLMSG_ERROR] = mnl_cb_error,
|
||||||
|
[NLMSG_DONE] = mnl_cb_stop,
|
||||||
|
[NLMSG_OVERRUN] = mnl_cb_noop,
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline int __mnl_cb_run(const void *buf, size_t numbytes,
|
||||||
|
unsigned int seq, unsigned int portid,
|
||||||
|
mnl_cb_t cb_data, void *data,
|
||||||
|
const mnl_cb_t *cb_ctl_array,
|
||||||
|
unsigned int cb_ctl_array_len)
|
||||||
|
{
|
||||||
|
int ret = MNL_CB_OK, len = numbytes;
|
||||||
|
const struct nlmsghdr *nlh = buf;
|
||||||
|
|
||||||
|
while (mnl_nlmsg_ok(nlh, len)) {
|
||||||
|
/* check message source */
|
||||||
|
if (!mnl_nlmsg_portid_ok(nlh, portid)) {
|
||||||
|
errno = ESRCH;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* perform sequence tracking */
|
||||||
|
if (!mnl_nlmsg_seq_ok(nlh, seq)) {
|
||||||
|
errno = EPROTO;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dump was interrupted */
|
||||||
|
if (nlh->nlmsg_flags & NLM_F_DUMP_INTR) {
|
||||||
|
errno = EINTR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* netlink data message handling */
|
||||||
|
if (nlh->nlmsg_type >= NLMSG_MIN_TYPE) {
|
||||||
|
if (cb_data){
|
||||||
|
ret = cb_data(nlh, data);
|
||||||
|
if (ret <= MNL_CB_STOP)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
} else if (nlh->nlmsg_type < cb_ctl_array_len) {
|
||||||
|
if (cb_ctl_array && cb_ctl_array[nlh->nlmsg_type]) {
|
||||||
|
ret = cb_ctl_array[nlh->nlmsg_type](nlh, data);
|
||||||
|
if (ret <= MNL_CB_STOP)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
} else if (default_cb_array[nlh->nlmsg_type]) {
|
||||||
|
ret = default_cb_array[nlh->nlmsg_type](nlh, data);
|
||||||
|
if (ret <= MNL_CB_STOP)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
nlh = mnl_nlmsg_next(nlh, &len);
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup callback Callback helpers
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_cb_run2 - callback runqueue for netlink messages
|
||||||
|
* \param buf buffer that contains the netlink messages
|
||||||
|
* \param numbytes number of bytes stored in the buffer
|
||||||
|
* \param seq sequence number that we expect to receive
|
||||||
|
* \param portid Netlink PortID that we expect to receive
|
||||||
|
* \param cb_data callback handler for data messages
|
||||||
|
* \param data pointer to data that will be passed to the data callback handler
|
||||||
|
* \param cb_ctl_array array of custom callback handlers from control messages
|
||||||
|
* \param cb_ctl_array_len array length of custom control callback handlers
|
||||||
|
*
|
||||||
|
* You can set the cb_ctl_array to NULL if you want to use the default control
|
||||||
|
* callback handlers, in that case, the parameter cb_ctl_array_len is not
|
||||||
|
* checked.
|
||||||
|
*
|
||||||
|
* Your callback may return three possible values:
|
||||||
|
* - MNL_CB_ERROR (<=-1): an error has occurred. Stop callback runqueue.
|
||||||
|
* - MNL_CB_STOP (=0): stop callback runqueue.
|
||||||
|
* - MNL_CB_OK (>=1): no problem has occurred.
|
||||||
|
*
|
||||||
|
* This function propagates the callback return value. On error, it returns
|
||||||
|
* -1 and errno is explicitly set. If the portID is not the expected, errno
|
||||||
|
* is set to ESRCH. If the sequence number is not the expected, errno is set
|
||||||
|
* to EPROTO. If the dump was interrupted, errno is set to EINTR and you should
|
||||||
|
* request a new fresh dump again.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL int mnl_cb_run2(const void *buf, size_t numbytes,
|
||||||
|
unsigned int seq, unsigned int portid,
|
||||||
|
mnl_cb_t cb_data, void *data,
|
||||||
|
const mnl_cb_t *cb_ctl_array,
|
||||||
|
unsigned int cb_ctl_array_len)
|
||||||
|
{
|
||||||
|
return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data,
|
||||||
|
cb_ctl_array, cb_ctl_array_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_cb_run - callback runqueue for netlink messages (simplified version)
|
||||||
|
* \param buf buffer that contains the netlink messages
|
||||||
|
* \param numbytes number of bytes stored in the buffer
|
||||||
|
* \param seq sequence number that we expect to receive
|
||||||
|
* \param portid Netlink PortID that we expect to receive
|
||||||
|
* \param cb_data callback handler for data messages
|
||||||
|
* \param data pointer to data that will be passed to the data callback handler
|
||||||
|
*
|
||||||
|
* This function is like mnl_cb_run2() but it does not allow you to set
|
||||||
|
* the control callback handlers.
|
||||||
|
*
|
||||||
|
* Your callback may return three possible values:
|
||||||
|
* - MNL_CB_ERROR (<=-1): an error has occurred. Stop callback runqueue.
|
||||||
|
* - MNL_CB_STOP (=0): stop callback runqueue.
|
||||||
|
* - MNL_CB_OK (>=1): no problems has occurred.
|
||||||
|
*
|
||||||
|
* This function propagates the callback return value.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL int mnl_cb_run(const void *buf, size_t numbytes, unsigned int seq,
|
||||||
|
unsigned int portid, mnl_cb_t cb_data, void *data)
|
||||||
|
{
|
||||||
|
return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
11
deps/libmnl/src/internal.h
vendored
Normal file
11
deps/libmnl/src/internal.h
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#ifndef INTERNAL_H
|
||||||
|
#define INTERNAL_H 1
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#ifdef HAVE_VISIBILITY_HIDDEN
|
||||||
|
# define EXPORT_SYMBOL __attribute__((visibility("default")))
|
||||||
|
#else
|
||||||
|
# define EXPORT_SYMBOL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
79
deps/libmnl/src/libmnl.map
vendored
Normal file
79
deps/libmnl/src/libmnl.map
vendored
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
LIBMNL_1.0 {
|
||||||
|
global:
|
||||||
|
mnl_attr_get_len;
|
||||||
|
mnl_attr_get_payload;
|
||||||
|
mnl_attr_get_payload_len;
|
||||||
|
mnl_attr_get_str;
|
||||||
|
mnl_attr_get_type;
|
||||||
|
mnl_attr_get_u16;
|
||||||
|
mnl_attr_get_u32;
|
||||||
|
mnl_attr_get_u64;
|
||||||
|
mnl_attr_get_u8;
|
||||||
|
mnl_attr_nest_end;
|
||||||
|
mnl_attr_nest_start;
|
||||||
|
mnl_attr_nest_start_check;
|
||||||
|
mnl_attr_nest_cancel;
|
||||||
|
mnl_attr_next;
|
||||||
|
mnl_attr_ok;
|
||||||
|
mnl_attr_parse;
|
||||||
|
mnl_attr_parse_nested;
|
||||||
|
mnl_attr_put;
|
||||||
|
mnl_attr_put_str;
|
||||||
|
mnl_attr_put_strz;
|
||||||
|
mnl_attr_put_u16;
|
||||||
|
mnl_attr_put_u32;
|
||||||
|
mnl_attr_put_u64;
|
||||||
|
mnl_attr_put_u8;
|
||||||
|
mnl_attr_put_check;
|
||||||
|
mnl_attr_put_str_check;
|
||||||
|
mnl_attr_put_strz_check;
|
||||||
|
mnl_attr_put_u16_check;
|
||||||
|
mnl_attr_put_u32_check;
|
||||||
|
mnl_attr_put_u64_check;
|
||||||
|
mnl_attr_put_u8_check;
|
||||||
|
mnl_attr_type_valid;
|
||||||
|
mnl_attr_validate;
|
||||||
|
mnl_attr_validate2;
|
||||||
|
mnl_cb_run;
|
||||||
|
mnl_cb_run2;
|
||||||
|
mnl_nlmsg_fprintf;
|
||||||
|
mnl_nlmsg_get_payload;
|
||||||
|
mnl_nlmsg_get_payload_len;
|
||||||
|
mnl_nlmsg_get_payload_offset;
|
||||||
|
mnl_nlmsg_get_payload_tail;
|
||||||
|
mnl_nlmsg_next;
|
||||||
|
mnl_nlmsg_ok;
|
||||||
|
mnl_nlmsg_portid_ok;
|
||||||
|
mnl_nlmsg_put_extra_header;
|
||||||
|
mnl_nlmsg_put_header;
|
||||||
|
mnl_nlmsg_seq_ok;
|
||||||
|
mnl_nlmsg_size;
|
||||||
|
mnl_nlmsg_batch_start;
|
||||||
|
mnl_nlmsg_batch_stop;
|
||||||
|
mnl_nlmsg_batch_next;
|
||||||
|
mnl_nlmsg_batch_size;
|
||||||
|
mnl_nlmsg_batch_reset;
|
||||||
|
mnl_nlmsg_batch_current;
|
||||||
|
mnl_nlmsg_batch_head;
|
||||||
|
mnl_nlmsg_batch_is_empty;
|
||||||
|
mnl_socket_bind;
|
||||||
|
mnl_socket_close;
|
||||||
|
mnl_socket_get_fd;
|
||||||
|
mnl_socket_get_portid;
|
||||||
|
mnl_socket_getsockopt;
|
||||||
|
mnl_socket_open;
|
||||||
|
mnl_socket_recvfrom;
|
||||||
|
mnl_socket_sendto;
|
||||||
|
mnl_socket_setsockopt;
|
||||||
|
|
||||||
|
local: *;
|
||||||
|
};
|
||||||
|
|
||||||
|
LIBMNL_1.1 {
|
||||||
|
mnl_attr_parse_payload;
|
||||||
|
} LIBMNL_1.0;
|
||||||
|
|
||||||
|
LIBMNL_1.2 {
|
||||||
|
mnl_socket_open2;
|
||||||
|
mnl_socket_fdopen;
|
||||||
|
} LIBMNL_1.1;
|
||||||
592
deps/libmnl/src/nlmsg.c
vendored
Normal file
592
deps/libmnl/src/nlmsg.c
vendored
Normal file
@@ -0,0 +1,592 @@
|
|||||||
|
/*
|
||||||
|
* (C) 2008-2010 by Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published
|
||||||
|
* by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*/
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup nlmsg Netlink message helpers
|
||||||
|
*
|
||||||
|
* Netlink message:
|
||||||
|
* \verbatim
|
||||||
|
|<----------------- 4 bytes ------------------->|
|
||||||
|
|<----- 2 bytes ------>|<------- 2 bytes ------>|
|
||||||
|
|-----------------------------------------------|
|
||||||
|
| Message length (including header) |
|
||||||
|
|-----------------------------------------------|
|
||||||
|
| Message type | Message flags |
|
||||||
|
|-----------------------------------------------|
|
||||||
|
| Message sequence number |
|
||||||
|
|-----------------------------------------------|
|
||||||
|
| Netlink PortID |
|
||||||
|
|-----------------------------------------------|
|
||||||
|
| |
|
||||||
|
. Payload .
|
||||||
|
|_______________________________________________|
|
||||||
|
\endverbatim
|
||||||
|
*
|
||||||
|
* There is usually an extra header after the the Netlink header (at the
|
||||||
|
* beginning of the payload). This extra header is specific of the Netlink
|
||||||
|
* subsystem. After this extra header, it comes the sequence of attributes
|
||||||
|
* that are expressed in Type-Length-Value (TLV) format.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_nlmsg_size - calculate the size of Netlink message (without alignment)
|
||||||
|
* \param len length of the Netlink payload
|
||||||
|
*
|
||||||
|
* This function returns the size of a netlink message (header plus payload)
|
||||||
|
* without alignment.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL size_t mnl_nlmsg_size(size_t len)
|
||||||
|
{
|
||||||
|
return len + MNL_NLMSG_HDRLEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_nlmsg_get_payload_len - get the length of the Netlink payload
|
||||||
|
* \param nlh pointer to the header of the Netlink message
|
||||||
|
*
|
||||||
|
* This function returns the Length of the netlink payload, ie. the length
|
||||||
|
* of the full message minus the size of the Netlink header.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL size_t mnl_nlmsg_get_payload_len(const struct nlmsghdr *nlh)
|
||||||
|
{
|
||||||
|
return nlh->nlmsg_len - MNL_NLMSG_HDRLEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_nlmsg_put_header - reserve and prepare room for Netlink header
|
||||||
|
* \param buf memory already allocated to store the Netlink header
|
||||||
|
*
|
||||||
|
* This function sets to zero the room that is required to put the Netlink
|
||||||
|
* header in the memory buffer passed as parameter. This function also
|
||||||
|
* initializes the nlmsg_len field to the size of the Netlink header. This
|
||||||
|
* function returns a pointer to the Netlink header structure.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL struct nlmsghdr *mnl_nlmsg_put_header(void *buf)
|
||||||
|
{
|
||||||
|
int len = MNL_ALIGN(sizeof(struct nlmsghdr));
|
||||||
|
struct nlmsghdr *nlh = buf;
|
||||||
|
|
||||||
|
memset(buf, 0, len);
|
||||||
|
nlh->nlmsg_len = len;
|
||||||
|
return nlh;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_nlmsg_put_extra_header - reserve and prepare room for an extra header
|
||||||
|
* \param nlh pointer to Netlink header
|
||||||
|
* \param size size of the extra header that we want to put
|
||||||
|
*
|
||||||
|
* This function sets to zero the room that is required to put the extra
|
||||||
|
* header after the initial Netlink header. This function also increases
|
||||||
|
* the nlmsg_len field. You have to invoke mnl_nlmsg_put_header() before
|
||||||
|
* you call this function. This function returns a pointer to the extra
|
||||||
|
* header.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL void *mnl_nlmsg_put_extra_header(struct nlmsghdr *nlh,
|
||||||
|
size_t size)
|
||||||
|
{
|
||||||
|
char *ptr = (char *)nlh + nlh->nlmsg_len;
|
||||||
|
size_t len = MNL_ALIGN(size);
|
||||||
|
nlh->nlmsg_len += len;
|
||||||
|
memset(ptr, 0, len);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_nlmsg_get_payload - get a pointer to the payload of the netlink message
|
||||||
|
* \param nlh pointer to a netlink header
|
||||||
|
*
|
||||||
|
* This function returns a pointer to the payload of the netlink message.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL void *mnl_nlmsg_get_payload(const struct nlmsghdr *nlh)
|
||||||
|
{
|
||||||
|
return (void *)nlh + MNL_NLMSG_HDRLEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_nlmsg_get_payload_offset - get a pointer to the payload of the message
|
||||||
|
* \param nlh pointer to a netlink header
|
||||||
|
* \param offset offset to the payload of the attributes TLV set
|
||||||
|
*
|
||||||
|
* This function returns a pointer to the payload of the netlink message plus
|
||||||
|
* a given offset.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL void *mnl_nlmsg_get_payload_offset(const struct nlmsghdr *nlh,
|
||||||
|
size_t offset)
|
||||||
|
{
|
||||||
|
return (void *)nlh + MNL_NLMSG_HDRLEN + MNL_ALIGN(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_nlmsg_ok - check a there is room for netlink message
|
||||||
|
* \param nlh netlink message that we want to check
|
||||||
|
* \param len remaining bytes in a buffer that contains the netlink message
|
||||||
|
*
|
||||||
|
* This function is used to check that a buffer that contains a netlink
|
||||||
|
* message has enough room for the netlink message that it stores, ie. this
|
||||||
|
* function can be used to verify that a netlink message is not malformed nor
|
||||||
|
* truncated.
|
||||||
|
*
|
||||||
|
* This function does not set errno in case of error since it is intended
|
||||||
|
* for iterations. Thus, it returns true on success and false on error.
|
||||||
|
*
|
||||||
|
* The len parameter may become negative in malformed messages during message
|
||||||
|
* iteration, that is why we use a signed integer.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL bool mnl_nlmsg_ok(const struct nlmsghdr *nlh, int len)
|
||||||
|
{
|
||||||
|
size_t ulen = len;
|
||||||
|
|
||||||
|
if (len < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return ulen >= sizeof(struct nlmsghdr) &&
|
||||||
|
nlh->nlmsg_len >= sizeof(struct nlmsghdr) &&
|
||||||
|
nlh->nlmsg_len <= ulen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_nlmsg_next - get the next netlink message in a multipart message
|
||||||
|
* \param nlh current netlink message that we are handling
|
||||||
|
* \param len length of the remaining bytes in the buffer (passed by reference).
|
||||||
|
*
|
||||||
|
* This function returns a pointer to the next netlink message that is part
|
||||||
|
* of a multi-part netlink message. Netlink can batch several messages into
|
||||||
|
* one buffer so that the receiver has to iterate over the whole set of
|
||||||
|
* Netlink messages.
|
||||||
|
*
|
||||||
|
* You have to use mnl_nlmsg_ok() to check if the next Netlink message is
|
||||||
|
* valid.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL struct nlmsghdr *mnl_nlmsg_next(const struct nlmsghdr *nlh,
|
||||||
|
int *len)
|
||||||
|
{
|
||||||
|
*len -= MNL_ALIGN(nlh->nlmsg_len);
|
||||||
|
return (struct nlmsghdr *)((void *)nlh + MNL_ALIGN(nlh->nlmsg_len));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_nlmsg_get_payload_tail - get the ending of the netlink message
|
||||||
|
* \param nlh pointer to netlink message
|
||||||
|
*
|
||||||
|
* This function returns a pointer to the netlink message tail. This is useful
|
||||||
|
* to build a message since we continue adding attributes at the end of the
|
||||||
|
* message.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL void *mnl_nlmsg_get_payload_tail(const struct nlmsghdr *nlh)
|
||||||
|
{
|
||||||
|
return (void *)nlh + MNL_ALIGN(nlh->nlmsg_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_nlmsg_seq_ok - perform sequence tracking
|
||||||
|
* \param nlh current netlink message that we are handling
|
||||||
|
* \param seq last sequence number used to send a message
|
||||||
|
*
|
||||||
|
* This functions returns true if the sequence tracking is fulfilled, otherwise
|
||||||
|
* false is returned. We skip the tracking for netlink messages whose sequence
|
||||||
|
* number is zero since it is usually reserved for event-based kernel
|
||||||
|
* notifications. On the other hand, if seq is set but the message sequence
|
||||||
|
* number is not set (i.e. this is an event message coming from kernel-space),
|
||||||
|
* then we also skip the tracking. This approach is good if we use the same
|
||||||
|
* socket to send commands to kernel-space (that we want to track) and to
|
||||||
|
* listen to events (that we do not track).
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL bool mnl_nlmsg_seq_ok(const struct nlmsghdr *nlh,
|
||||||
|
unsigned int seq)
|
||||||
|
{
|
||||||
|
return nlh->nlmsg_seq && seq ? nlh->nlmsg_seq == seq : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_nlmsg_portid_ok - perform portID origin check
|
||||||
|
* \param nlh current netlink message that we are handling
|
||||||
|
* \param portid netlink portid that we want to check
|
||||||
|
*
|
||||||
|
* This functions returns true if the origin is fulfilled, otherwise
|
||||||
|
* false is returned. We skip the tracking for netlink message whose portID
|
||||||
|
* is zero since it is reserved for event-based kernel notifications. On the
|
||||||
|
* other hand, if portid is set but the message PortID is not (i.e. this
|
||||||
|
* is an event message coming from kernel-space), then we also skip the
|
||||||
|
* tracking. This approach is good if we use the same socket to send commands
|
||||||
|
* to kernel-space (that we want to track) and to listen to events (that we
|
||||||
|
* do not track).
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL bool mnl_nlmsg_portid_ok(const struct nlmsghdr *nlh,
|
||||||
|
unsigned int portid)
|
||||||
|
{
|
||||||
|
return nlh->nlmsg_pid && portid ? nlh->nlmsg_pid == portid : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mnl_nlmsg_fprintf_header(FILE *fd, const struct nlmsghdr *nlh)
|
||||||
|
{
|
||||||
|
fprintf(fd, "----------------\t------------------\n");
|
||||||
|
fprintf(fd, "| %.010u |\t| message length |\n", nlh->nlmsg_len);
|
||||||
|
fprintf(fd, "| %.05u | %c%c%c%c |\t| type | flags |\n",
|
||||||
|
nlh->nlmsg_type,
|
||||||
|
nlh->nlmsg_flags & NLM_F_REQUEST ? 'R' : '-',
|
||||||
|
nlh->nlmsg_flags & NLM_F_MULTI ? 'M' : '-',
|
||||||
|
nlh->nlmsg_flags & NLM_F_ACK ? 'A' : '-',
|
||||||
|
nlh->nlmsg_flags & NLM_F_ECHO ? 'E' : '-');
|
||||||
|
fprintf(fd, "| %.010u |\t| sequence number|\n", nlh->nlmsg_seq);
|
||||||
|
fprintf(fd, "| %.010u |\t| port ID |\n", nlh->nlmsg_pid);
|
||||||
|
fprintf(fd, "----------------\t------------------\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mnl_fprintf_attr_color(FILE *fd, const struct nlattr *attr)
|
||||||
|
{
|
||||||
|
fprintf(fd, "|%c[%d;%dm"
|
||||||
|
"%.5u"
|
||||||
|
"%c[%dm"
|
||||||
|
"|"
|
||||||
|
"%c[%d;%dm"
|
||||||
|
"%c%c"
|
||||||
|
"%c[%dm"
|
||||||
|
"|"
|
||||||
|
"%c[%d;%dm"
|
||||||
|
"%.5u"
|
||||||
|
"%c[%dm|\t",
|
||||||
|
27, 1, 31,
|
||||||
|
attr->nla_len,
|
||||||
|
27, 0,
|
||||||
|
27, 1, 32,
|
||||||
|
attr->nla_type & NLA_F_NESTED ? 'N' : '-',
|
||||||
|
attr->nla_type & NLA_F_NET_BYTEORDER ? 'B' : '-',
|
||||||
|
27, 0,
|
||||||
|
27, 1, 34,
|
||||||
|
attr->nla_type & NLA_TYPE_MASK,
|
||||||
|
27, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mnl_fprintf_attr_raw(FILE *fd, const struct nlattr *attr)
|
||||||
|
{
|
||||||
|
fprintf(fd, "|"
|
||||||
|
"%.5u"
|
||||||
|
"|"
|
||||||
|
"%c%c"
|
||||||
|
"|"
|
||||||
|
"%.5u"
|
||||||
|
"|\t",
|
||||||
|
attr->nla_len,
|
||||||
|
attr->nla_type & NLA_F_NESTED ? 'N' : '-',
|
||||||
|
attr->nla_type & NLA_F_NET_BYTEORDER ? 'B' : '-',
|
||||||
|
attr->nla_type & NLA_TYPE_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mnl_nlmsg_fprintf_payload(FILE *fd, const struct nlmsghdr *nlh,
|
||||||
|
size_t extra_header_size)
|
||||||
|
{
|
||||||
|
int colorize = 0;
|
||||||
|
unsigned int i;
|
||||||
|
int rem = 0;
|
||||||
|
int fdnum;
|
||||||
|
|
||||||
|
fdnum = fileno(fd);
|
||||||
|
if (fdnum != -1)
|
||||||
|
colorize = isatty(fdnum);
|
||||||
|
|
||||||
|
for (i=sizeof(struct nlmsghdr); i<nlh->nlmsg_len; i+=4) {
|
||||||
|
char *b = (char *) nlh;
|
||||||
|
struct nlattr *attr = (struct nlattr *) (b+i);
|
||||||
|
|
||||||
|
/* netlink control message. */
|
||||||
|
if (nlh->nlmsg_type < NLMSG_MIN_TYPE) {
|
||||||
|
fprintf(fd, "| %.2x %.2x %.2x %.2x |\t",
|
||||||
|
0xff & b[i], 0xff & b[i+1],
|
||||||
|
0xff & b[i+2], 0xff & b[i+3]);
|
||||||
|
fprintf(fd, "| |\n");
|
||||||
|
/* special handling for the extra header. */
|
||||||
|
} else if (extra_header_size > 0) {
|
||||||
|
extra_header_size -= 4;
|
||||||
|
fprintf(fd, "| %.2x %.2x %.2x %.2x |\t",
|
||||||
|
0xff & b[i], 0xff & b[i+1],
|
||||||
|
0xff & b[i+2], 0xff & b[i+3]);
|
||||||
|
fprintf(fd, "| extra header |\n");
|
||||||
|
/* this seems like an attribute header. */
|
||||||
|
} else if (rem == 0 && (attr->nla_type & NLA_TYPE_MASK) != 0) {
|
||||||
|
if (colorize) {
|
||||||
|
mnl_fprintf_attr_color(fd, attr);
|
||||||
|
} else {
|
||||||
|
mnl_fprintf_attr_raw(fd, attr);
|
||||||
|
}
|
||||||
|
fprintf(fd, "|len |flags| type|\n");
|
||||||
|
|
||||||
|
if (!(attr->nla_type & NLA_F_NESTED)) {
|
||||||
|
rem = NLA_ALIGN(attr->nla_len) -
|
||||||
|
sizeof(struct nlattr);
|
||||||
|
}
|
||||||
|
/* this is the attribute payload. */
|
||||||
|
} else if (rem > 0) {
|
||||||
|
rem -= 4;
|
||||||
|
fprintf(fd, "| %.2x %.2x %.2x %.2x |\t",
|
||||||
|
0xff & b[i], 0xff & b[i+1],
|
||||||
|
0xff & b[i+2], 0xff & b[i+3]);
|
||||||
|
fprintf(fd, "| data |");
|
||||||
|
fprintf(fd, "\t %c %c %c %c\n",
|
||||||
|
isprint(b[i]) ? b[i] : ' ',
|
||||||
|
isprint(b[i+1]) ? b[i+1] : ' ',
|
||||||
|
isprint(b[i+2]) ? b[i+2] : ' ',
|
||||||
|
isprint(b[i+3]) ? b[i+3] : ' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(fd, "----------------\t------------------\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_nlmsg_fprintf - print netlink message to file
|
||||||
|
* \param fd pointer to file type
|
||||||
|
* \param data pointer to the buffer that contains messages to be printed
|
||||||
|
* \param datalen length of data stored in the buffer
|
||||||
|
* \param extra_header_size size of the extra header (if any)
|
||||||
|
*
|
||||||
|
* This function prints the netlink header to a file handle.
|
||||||
|
* It may be useful for debugging purposes. One example of the output
|
||||||
|
* is the following:
|
||||||
|
*
|
||||||
|
*\verbatim
|
||||||
|
---------------- ------------------
|
||||||
|
| 0000000040 | | message length |
|
||||||
|
| 00016 | R-A- | | type | flags |
|
||||||
|
| 1289148991 | | sequence number|
|
||||||
|
| 0000000000 | | port ID |
|
||||||
|
---------------- ------------------
|
||||||
|
| 00 00 00 00 | | extra header |
|
||||||
|
| 00 00 00 00 | | extra header |
|
||||||
|
| 01 00 00 00 | | extra header |
|
||||||
|
| 01 00 00 00 | | extra header |
|
||||||
|
|00008|--|00003| |len |flags| type|
|
||||||
|
| 65 74 68 30 | | data | e t h 0
|
||||||
|
---------------- ------------------
|
||||||
|
\endverbatim
|
||||||
|
*
|
||||||
|
* This example above shows the netlink message that is send to kernel-space
|
||||||
|
* to set up the link interface eth0. The netlink and attribute header data
|
||||||
|
* are displayed in base 10 whereas the extra header and the attribute payload
|
||||||
|
* are expressed in base 16. The possible flags in the netlink header are:
|
||||||
|
*
|
||||||
|
* - R, that indicates that NLM_F_REQUEST is set.
|
||||||
|
* - M, that indicates that NLM_F_MULTI is set.
|
||||||
|
* - A, that indicates that NLM_F_ACK is set.
|
||||||
|
* - E, that indicates that NLM_F_ECHO is set.
|
||||||
|
*
|
||||||
|
* The lack of one flag is displayed with '-'. On the other hand, the possible
|
||||||
|
* attribute flags available are:
|
||||||
|
*
|
||||||
|
* - N, that indicates that NLA_F_NESTED is set.
|
||||||
|
* - B, that indicates that NLA_F_NET_BYTEORDER is set.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL void mnl_nlmsg_fprintf(FILE *fd, const void *data, size_t datalen,
|
||||||
|
size_t extra_header_size)
|
||||||
|
{
|
||||||
|
const struct nlmsghdr *nlh = data;
|
||||||
|
int len = datalen;
|
||||||
|
|
||||||
|
while (mnl_nlmsg_ok(nlh, len)) {
|
||||||
|
mnl_nlmsg_fprintf_header(fd, nlh);
|
||||||
|
mnl_nlmsg_fprintf_payload(fd, nlh, extra_header_size);
|
||||||
|
nlh = mnl_nlmsg_next(nlh, &len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup batch Netlink message batch helpers
|
||||||
|
*
|
||||||
|
* This library provides helpers to batch several messages into one single
|
||||||
|
* datagram. These helpers do not perform strict memory boundary checkings.
|
||||||
|
*
|
||||||
|
* The following figure represents a Netlink message batch:
|
||||||
|
*\verbatim
|
||||||
|
|<-------------- MNL_SOCKET_BUFFER_SIZE ------------->|
|
||||||
|
|<-------------------- batch ------------------>| |
|
||||||
|
|-----------|-----------|-----------|-----------|-----------|
|
||||||
|
|<- nlmsg ->|<- nlmsg ->|<- nlmsg ->|<- nlmsg ->|<- nlmsg ->|
|
||||||
|
|-----------|-----------|-----------|-----------|-----------|
|
||||||
|
^ ^
|
||||||
|
| |
|
||||||
|
message N message N+1
|
||||||
|
\endverbatim
|
||||||
|
*
|
||||||
|
* To start the batch, you have to call mnl_nlmsg_batch_start() and you can
|
||||||
|
* use mnl_nlmsg_batch_stop() to release it.
|
||||||
|
*
|
||||||
|
* You have to invoke mnl_nlmsg_batch_next() to get room for a new message
|
||||||
|
* in the batch. If this function returns NULL, it means that the last
|
||||||
|
* message that was added (message N+1 in the figure above) does not fit the
|
||||||
|
* batch. Thus, you have to send the batch (which includes until message N)
|
||||||
|
* and, then, you have to call mnl_nlmsg_batch_reset() to re-initialize
|
||||||
|
* the batch (this moves message N+1 to the head of the buffer). For that
|
||||||
|
* reason, the buffer that you have to use to store the batch must be double
|
||||||
|
* of MNL_SOCKET_BUFFER_SIZE to ensure that the last message (message N+1)
|
||||||
|
* that did not fit into the batch is written inside valid memory boundaries.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct mnl_nlmsg_batch {
|
||||||
|
/* the buffer that is used to store the batch. */
|
||||||
|
void *buf;
|
||||||
|
size_t limit;
|
||||||
|
size_t buflen;
|
||||||
|
/* the current netlink message in the batch. */
|
||||||
|
void *cur;
|
||||||
|
bool overflow;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_nlmsg_batch_start - initialize a batch
|
||||||
|
* \param buf pointer to the buffer that will store this batch
|
||||||
|
* \param limit maximum size of the batch (should be MNL_SOCKET_BUFFER_SIZE).
|
||||||
|
*
|
||||||
|
* The buffer that you pass must be double of MNL_SOCKET_BUFFER_SIZE. The
|
||||||
|
* limit must be half of the buffer size, otherwise expect funny memory
|
||||||
|
* corruptions 8-).
|
||||||
|
*
|
||||||
|
* You can allocate the buffer that you use to store the batch in the stack or
|
||||||
|
* the heap, no restrictions in this regard. This function returns NULL on
|
||||||
|
* error.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL struct mnl_nlmsg_batch *mnl_nlmsg_batch_start(void *buf,
|
||||||
|
size_t limit)
|
||||||
|
{
|
||||||
|
struct mnl_nlmsg_batch *b;
|
||||||
|
|
||||||
|
b = malloc(sizeof(struct mnl_nlmsg_batch));
|
||||||
|
if (b == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
b->buf = buf;
|
||||||
|
b->limit = limit;
|
||||||
|
b->buflen = 0;
|
||||||
|
b->cur = buf;
|
||||||
|
b->overflow = false;
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_nlmsg_batch_stop - release a batch
|
||||||
|
* \param b pointer to batch
|
||||||
|
*
|
||||||
|
* This function releases the batch allocated by mnl_nlmsg_batch_start().
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL void mnl_nlmsg_batch_stop(struct mnl_nlmsg_batch *b)
|
||||||
|
{
|
||||||
|
free(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_nlmsg_batch_next - get room for the next message in the batch
|
||||||
|
* \param b pointer to batch
|
||||||
|
*
|
||||||
|
* This function returns false if the last message did not fit into the
|
||||||
|
* batch. Otherwise, it prepares the batch to provide room for the new
|
||||||
|
* Netlink message in the batch and returns true.
|
||||||
|
*
|
||||||
|
* You have to put at least one message in the batch before calling this
|
||||||
|
* function, otherwise your application is likely to crash.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL bool mnl_nlmsg_batch_next(struct mnl_nlmsg_batch *b)
|
||||||
|
{
|
||||||
|
struct nlmsghdr *nlh = b->cur;
|
||||||
|
|
||||||
|
if (b->buflen + nlh->nlmsg_len > b->limit) {
|
||||||
|
b->overflow = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
b->cur = b->buf + b->buflen + nlh->nlmsg_len;
|
||||||
|
b->buflen += nlh->nlmsg_len;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_nlmsg_batch_reset - reset the batch
|
||||||
|
* \param b pointer to batch
|
||||||
|
*
|
||||||
|
* This function allows you to reset a batch, so you can reuse it to create a
|
||||||
|
* new one. This function moves the last message which does not fit the batch to
|
||||||
|
* the head of the buffer, if any.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL void mnl_nlmsg_batch_reset(struct mnl_nlmsg_batch *b)
|
||||||
|
{
|
||||||
|
if (b->overflow) {
|
||||||
|
struct nlmsghdr *nlh = b->cur;
|
||||||
|
memcpy(b->buf, b->cur, nlh->nlmsg_len);
|
||||||
|
b->buflen = nlh->nlmsg_len;
|
||||||
|
b->cur = b->buf + b->buflen;
|
||||||
|
b->overflow = false;
|
||||||
|
} else {
|
||||||
|
b->buflen = 0;
|
||||||
|
b->cur = b->buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_nlmsg_batch_size - get current size of the batch
|
||||||
|
* \param b pointer to batch
|
||||||
|
*
|
||||||
|
* This function returns the current size of the batch.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL size_t mnl_nlmsg_batch_size(struct mnl_nlmsg_batch *b)
|
||||||
|
{
|
||||||
|
return b->buflen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_nlmsg_batch_head - get head of this batch
|
||||||
|
* \param b pointer to batch
|
||||||
|
*
|
||||||
|
* This function returns a pointer to the head of the batch, which is the
|
||||||
|
* beginning of the buffer that is used.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL void *mnl_nlmsg_batch_head(struct mnl_nlmsg_batch *b)
|
||||||
|
{
|
||||||
|
return b->buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_nlmsg_batch_current - returns current position in the batch
|
||||||
|
* \param b pointer to batch
|
||||||
|
*
|
||||||
|
* This function returns a pointer to the current position in the buffer
|
||||||
|
* that is used to store the batch.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL void *mnl_nlmsg_batch_current(struct mnl_nlmsg_batch *b)
|
||||||
|
{
|
||||||
|
return b->cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_nlmsg_batch_is_empty - check if there is any message in the batch
|
||||||
|
* \param b pointer to batch
|
||||||
|
*
|
||||||
|
* This function returns true if the batch is empty.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL bool mnl_nlmsg_batch_is_empty(struct mnl_nlmsg_batch *b)
|
||||||
|
{
|
||||||
|
return b->buflen == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
351
deps/libmnl/src/socket.c
vendored
Normal file
351
deps/libmnl/src/socket.c
vendored
Normal file
@@ -0,0 +1,351 @@
|
|||||||
|
/*
|
||||||
|
* (C) 2008-2010 by Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published
|
||||||
|
* by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \mainpage
|
||||||
|
*
|
||||||
|
* libmnl is a minimalistic user-space library oriented to Netlink developers.
|
||||||
|
* There are a lot of common tasks in parsing, validating, constructing of
|
||||||
|
* both the Netlink header and TLVs that are repetitive and easy to get wrong.
|
||||||
|
* This library aims to provide simple helpers that allows you to avoid
|
||||||
|
* re-inventing the wheel in common Netlink tasks.
|
||||||
|
*
|
||||||
|
* \verbatim
|
||||||
|
"Simplify, simplify" -- Henry David Thoureau. Walden (1854)
|
||||||
|
\endverbatim
|
||||||
|
*
|
||||||
|
* The acronym libmnl stands for LIBrary Minimalistic NetLink.
|
||||||
|
*
|
||||||
|
* libmnl homepage is:
|
||||||
|
* http://www.netfilter.org/projects/libmnl/
|
||||||
|
*
|
||||||
|
* \section features Main Features
|
||||||
|
* - Small: the shared library requires around 30KB for an x86-based computer.
|
||||||
|
* - Simple: this library avoids complex abstractions that tend to hide Netlink
|
||||||
|
* details. It avoids elaborated object-oriented infrastructure and complex
|
||||||
|
* callback-based workflow.
|
||||||
|
* - Easy to use: the library simplifies the work for Netlink-wise developers.
|
||||||
|
* It provides functions to make socket handling, message building,
|
||||||
|
* validating, parsing and sequence tracking, easier.
|
||||||
|
* - Easy to re-use: you can use this library to build your own abstraction
|
||||||
|
* layer upon this library, if you want to provide another library that
|
||||||
|
* hides Netlink details to your users.
|
||||||
|
* - Decoupling: the interdependency of the main bricks that compose this
|
||||||
|
* library is reduced, i.e. the library provides many helpers, but the
|
||||||
|
* programmer is not forced to use them.
|
||||||
|
*
|
||||||
|
* \section licensing Licensing terms
|
||||||
|
* This library is released under the LGPLv2.1 or any later (at your option).
|
||||||
|
*
|
||||||
|
* \section Dependencies
|
||||||
|
* You have to install the Linux kernel headers that you want to use to develop
|
||||||
|
* your application. Moreover, this library requires that you have some basics
|
||||||
|
* on Netlink.
|
||||||
|
*
|
||||||
|
* \section scm Git Tree
|
||||||
|
* The current development version of libmnl can be accessed at:
|
||||||
|
* https://git.netfilter.org/libmnl/
|
||||||
|
*
|
||||||
|
* \section using Using libmnl
|
||||||
|
* You can access several example files under examples/ in the libmnl source
|
||||||
|
* code tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct mnl_socket {
|
||||||
|
int fd;
|
||||||
|
struct sockaddr_nl addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup socket Netlink socket helpers
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_socket_get_fd - obtain file descriptor from netlink socket
|
||||||
|
* \param nl netlink socket obtained via mnl_socket_open()
|
||||||
|
*
|
||||||
|
* This function returns the file descriptor of a given netlink socket.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL int mnl_socket_get_fd(const struct mnl_socket *nl)
|
||||||
|
{
|
||||||
|
return nl->fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_socket_get_portid - obtain Netlink PortID from netlink socket
|
||||||
|
* \param nl netlink socket obtained via mnl_socket_open()
|
||||||
|
*
|
||||||
|
* This function returns the Netlink PortID of a given netlink socket.
|
||||||
|
* It's a common mistake to assume that this PortID equals the process ID
|
||||||
|
* which is not always true. This is the case if you open more than one
|
||||||
|
* socket that is binded to the same Netlink subsystem from the same process.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL unsigned int mnl_socket_get_portid(const struct mnl_socket *nl)
|
||||||
|
{
|
||||||
|
return nl->addr.nl_pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct mnl_socket *__mnl_socket_open(int bus, int flags)
|
||||||
|
{
|
||||||
|
struct mnl_socket *nl;
|
||||||
|
|
||||||
|
nl = calloc(1, sizeof(struct mnl_socket));
|
||||||
|
if (nl == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
nl->fd = socket(AF_NETLINK, SOCK_RAW | flags, bus);
|
||||||
|
if (nl->fd == -1) {
|
||||||
|
free(nl);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_socket_open - open a netlink socket
|
||||||
|
* \param bus the netlink socket bus ID (see NETLINK_* constants)
|
||||||
|
*
|
||||||
|
* On error, it returns NULL and errno is appropriately set. Otherwise, it
|
||||||
|
* returns a valid pointer to the mnl_socket structure.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL struct mnl_socket *mnl_socket_open(int bus)
|
||||||
|
{
|
||||||
|
return __mnl_socket_open(bus, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_socket_open2 - open a netlink socket with appropriate flags
|
||||||
|
* \param bus the netlink socket bus ID (see NETLINK_* constants)
|
||||||
|
* \param flags the netlink socket flags (see SOCK_* constants in socket(2))
|
||||||
|
*
|
||||||
|
* This is similar to mnl_socket_open(), but allows one to set flags like
|
||||||
|
* SOCK_CLOEXEC at socket creation time (useful for multi-threaded programs
|
||||||
|
* performing exec calls).
|
||||||
|
*
|
||||||
|
* On error, it returns NULL and errno is appropriately set. Otherwise, it
|
||||||
|
* returns a valid pointer to the mnl_socket structure.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL struct mnl_socket *mnl_socket_open2(int bus, int flags)
|
||||||
|
{
|
||||||
|
return __mnl_socket_open(bus, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_socket_fdopen - associates a mnl_socket object with pre-existing socket.
|
||||||
|
* \param fd pre-existing socket descriptor.
|
||||||
|
*
|
||||||
|
* On error, it returns NULL and errno is appropriately set. Otherwise, it
|
||||||
|
* returns a valid pointer to the mnl_socket structure. It also sets the portID
|
||||||
|
* if the socket fd is already bound and it is AF_NETLINK.
|
||||||
|
*
|
||||||
|
* Note that mnl_socket_get_portid() returns 0 if this function is used with
|
||||||
|
* non-netlink socket.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL struct mnl_socket *mnl_socket_fdopen(int fd)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct mnl_socket *nl;
|
||||||
|
struct sockaddr_nl addr;
|
||||||
|
socklen_t addr_len = sizeof(struct sockaddr_nl);
|
||||||
|
|
||||||
|
ret = getsockname(fd, (struct sockaddr *) &addr, &addr_len);
|
||||||
|
if (ret == -1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
nl = calloc(1, sizeof(struct mnl_socket));
|
||||||
|
if (nl == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
nl->fd = fd;
|
||||||
|
if (addr.nl_family == AF_NETLINK)
|
||||||
|
nl->addr = addr;
|
||||||
|
|
||||||
|
return nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_socket_bind - bind netlink socket
|
||||||
|
* \param nl netlink socket obtained via mnl_socket_open()
|
||||||
|
* \param groups the group of message you're interested in
|
||||||
|
* \param pid the port ID you want to use (use zero for automatic selection)
|
||||||
|
*
|
||||||
|
* On error, this function returns -1 and errno is appropriately set. On
|
||||||
|
* success, 0 is returned. You can use MNL_SOCKET_AUTOPID which is 0 for
|
||||||
|
* automatic port ID selection.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups,
|
||||||
|
pid_t pid)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
socklen_t addr_len;
|
||||||
|
|
||||||
|
nl->addr.nl_family = AF_NETLINK;
|
||||||
|
nl->addr.nl_groups = groups;
|
||||||
|
nl->addr.nl_pid = pid;
|
||||||
|
|
||||||
|
ret = bind(nl->fd, (struct sockaddr *) &nl->addr, sizeof (nl->addr));
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
addr_len = sizeof(nl->addr);
|
||||||
|
ret = getsockname(nl->fd, (struct sockaddr *) &nl->addr, &addr_len);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (addr_len != sizeof(nl->addr)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (nl->addr.nl_family != AF_NETLINK) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_socket_sendto - send a netlink message of a certain size
|
||||||
|
* \param nl netlink socket obtained via mnl_socket_open()
|
||||||
|
* \param buf buffer containing the netlink message to be sent
|
||||||
|
* \param len number of bytes in the buffer that you want to send
|
||||||
|
*
|
||||||
|
* On error, it returns -1 and errno is appropriately set. Otherwise, it
|
||||||
|
* returns the number of bytes sent.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL ssize_t mnl_socket_sendto(const struct mnl_socket *nl,
|
||||||
|
const void *buf, size_t len)
|
||||||
|
{
|
||||||
|
static const struct sockaddr_nl snl = {
|
||||||
|
.nl_family = AF_NETLINK
|
||||||
|
};
|
||||||
|
return sendto(nl->fd, buf, len, 0,
|
||||||
|
(struct sockaddr *) &snl, sizeof(snl));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_socket_recvfrom - receive a netlink message
|
||||||
|
* \param nl netlink socket obtained via mnl_socket_open()
|
||||||
|
* \param buf buffer that you want to use to store the netlink message
|
||||||
|
* \param bufsiz size of the buffer passed to store the netlink message
|
||||||
|
*
|
||||||
|
* On error, it returns -1 and errno is appropriately set. If errno is set
|
||||||
|
* to ENOSPC, it means that the buffer that you have passed to store the
|
||||||
|
* netlink message is too small, so you have received a truncated message.
|
||||||
|
* To avoid this, you have to allocate a buffer of MNL_SOCKET_BUFFER_SIZE
|
||||||
|
* (which is 8KB, see linux/netlink.h for more information). Using this
|
||||||
|
* buffer size ensures that your buffer is big enough to store the netlink
|
||||||
|
* message without truncating it.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL ssize_t mnl_socket_recvfrom(const struct mnl_socket *nl,
|
||||||
|
void *buf, size_t bufsiz)
|
||||||
|
{
|
||||||
|
ssize_t ret;
|
||||||
|
struct sockaddr_nl addr;
|
||||||
|
struct iovec iov = {
|
||||||
|
.iov_base = buf,
|
||||||
|
.iov_len = bufsiz,
|
||||||
|
};
|
||||||
|
struct msghdr msg = {
|
||||||
|
.msg_name = &addr,
|
||||||
|
.msg_namelen = sizeof(struct sockaddr_nl),
|
||||||
|
.msg_iov = &iov,
|
||||||
|
.msg_iovlen = 1,
|
||||||
|
.msg_control = NULL,
|
||||||
|
.msg_controllen = 0,
|
||||||
|
.msg_flags = 0,
|
||||||
|
};
|
||||||
|
ret = recvmsg(nl->fd, &msg, 0);
|
||||||
|
if (ret == -1)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (msg.msg_flags & MSG_TRUNC) {
|
||||||
|
errno = ENOSPC;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_socket_close - close a given netlink socket
|
||||||
|
* \param nl netlink socket obtained via mnl_socket_open()
|
||||||
|
*
|
||||||
|
* On error, this function returns -1 and errno is appropriately set.
|
||||||
|
* On success, it returns 0.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL int mnl_socket_close(struct mnl_socket *nl)
|
||||||
|
{
|
||||||
|
int ret = close(nl->fd);
|
||||||
|
free(nl);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_socket_setsockopt - set Netlink socket option
|
||||||
|
* \param nl netlink socket obtained via mnl_socket_open()
|
||||||
|
* \param type type of Netlink socket options
|
||||||
|
* \param buf the buffer that contains the data about this option
|
||||||
|
* \param len the size of the buffer passed
|
||||||
|
*
|
||||||
|
* This function allows you to set some Netlink socket option. As of writing
|
||||||
|
* this (see linux/netlink.h), the existing options are:
|
||||||
|
*
|
||||||
|
* - \#define NETLINK_ADD_MEMBERSHIP 1
|
||||||
|
* - \#define NETLINK_DROP_MEMBERSHIP 2
|
||||||
|
* - \#define NETLINK_PKTINFO 3
|
||||||
|
* - \#define NETLINK_BROADCAST_ERROR 4
|
||||||
|
* - \#define NETLINK_NO_ENOBUFS 5
|
||||||
|
*
|
||||||
|
* In the early days, Netlink only supported 32 groups expressed in a
|
||||||
|
* 32-bits mask. However, since 2.6.14, Netlink may have up to 2^32 multicast
|
||||||
|
* groups but you have to use setsockopt() with NETLINK_ADD_MEMBERSHIP to
|
||||||
|
* join a given multicast group. This function internally calls setsockopt()
|
||||||
|
* to join a given netlink multicast group. You can still use mnl_bind()
|
||||||
|
* and the 32-bit mask to join a set of Netlink multicast groups.
|
||||||
|
*
|
||||||
|
* On error, this function returns -1 and errno is appropriately set.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL int mnl_socket_setsockopt(const struct mnl_socket *nl, int type,
|
||||||
|
void *buf, socklen_t len)
|
||||||
|
{
|
||||||
|
return setsockopt(nl->fd, SOL_NETLINK, type, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mnl_socket_getsockopt - get a Netlink socket option
|
||||||
|
* \param nl netlink socket obtained via mnl_socket_open()
|
||||||
|
* \param type type of Netlink socket options
|
||||||
|
* \param buf pointer to the buffer to store the value of this option
|
||||||
|
* \param len size of the information written in the buffer
|
||||||
|
*
|
||||||
|
* On error, this function returns -1 and errno is appropriately set.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL int mnl_socket_getsockopt(const struct mnl_socket *nl, int type,
|
||||||
|
void *buf, socklen_t *len)
|
||||||
|
{
|
||||||
|
return getsockopt(nl->fd, SOL_NETLINK, type, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
24
deps/libnetfilter_queue/.gitignore
vendored
Normal file
24
deps/libnetfilter_queue/.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
.deps/
|
||||||
|
.libs/
|
||||||
|
Makefile
|
||||||
|
Makefile.in
|
||||||
|
.dirstamp
|
||||||
|
*.o
|
||||||
|
*.la
|
||||||
|
*.lo
|
||||||
|
|
||||||
|
/aclocal.m4
|
||||||
|
/autom4te.cache/
|
||||||
|
/build-aux/
|
||||||
|
/config.*
|
||||||
|
/configure
|
||||||
|
/libtool
|
||||||
|
/stamp-h1
|
||||||
|
|
||||||
|
/doxygen/doxygen.cfg
|
||||||
|
/libnetfilter_queue.pc
|
||||||
|
|
||||||
|
/examples/nf-queue
|
||||||
|
/doxygen/doxyfile.stamp
|
||||||
|
/doxygen/html/
|
||||||
|
/doxygen/man/
|
||||||
339
deps/libnetfilter_queue/COPYING
vendored
Normal file
339
deps/libnetfilter_queue/COPYING
vendored
Normal file
@@ -0,0 +1,339 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||||
|
675 Mass Ave, Cambridge, MA 02139, 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 Library 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
|
||||||
|
|
||||||
|
Appendix: 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) 19yy <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., 675 Mass Ave, Cambridge, MA 02139, 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) 19yy 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 Library General
|
||||||
|
Public License instead of this License.
|
||||||
2
deps/libnetfilter_queue/Make_global.am
vendored
Normal file
2
deps/libnetfilter_queue/Make_global.am
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
AM_CPPFLAGS = -I${top_srcdir}/include ${LIBNFNETLINK_CFLAGS} ${LIBMNL_CFLAGS}
|
||||||
|
AM_CFLAGS = -Wall ${GCC_FVISIBILITY_HIDDEN}
|
||||||
12
deps/libnetfilter_queue/Makefile.am
vendored
Normal file
12
deps/libnetfilter_queue/Makefile.am
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
|
|
||||||
|
EXTRA_DIST = $(man_MANS) include/linux
|
||||||
|
|
||||||
|
SUBDIRS = src utils include examples doxygen
|
||||||
|
|
||||||
|
man_MANS = #nfnetlink_queue.3 nfnetlink_queue.7
|
||||||
|
|
||||||
|
pkgconfigdir = $(libdir)/pkgconfig
|
||||||
|
pkgconfig_DATA = libnetfilter_queue.pc
|
||||||
|
|
||||||
|
EXTRA_DIST += Make_global.am
|
||||||
39
deps/libnetfilter_queue/autogen.sh
vendored
Executable file
39
deps/libnetfilter_queue/autogen.sh
vendored
Executable file
@@ -0,0 +1,39 @@
|
|||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
include ()
|
||||||
|
{
|
||||||
|
# If we keep a copy of the kernel header in the SVN tree, we'll have
|
||||||
|
# to worry about synchronization issues forever. Instead, we just copy
|
||||||
|
# the headers that we need from the lastest kernel version at autogen
|
||||||
|
# stage.
|
||||||
|
|
||||||
|
INCLUDEDIR=${KERNEL_DIR:-/lib/modules/`uname -r`/build}/include/linux
|
||||||
|
if [ -f $INCLUDEDIR/netfilter/nfnetlink_queue.h ]
|
||||||
|
then
|
||||||
|
TARGET=include/libnetfilter_queue/linux_nfnetlink_queue.h
|
||||||
|
echo "Copying nfnetlink_queue.h to linux_nfnetlink_queue.h"
|
||||||
|
cp $INCLUDEDIR/netfilter/nfnetlink_queue.h $TARGET
|
||||||
|
TEMP=`tempfile`
|
||||||
|
sed 's/linux\/netfilter\/nfnetlink.h/libnfnetlink\/linux_nfnetlink.h/g' $TARGET > $TEMP
|
||||||
|
# Add aligned_u64 definition after #define _NFNETLINK_QUEUE_H
|
||||||
|
awk '{
|
||||||
|
if ( $0 == "#define _NFNETLINK_QUEUE_H" ) {
|
||||||
|
print $0
|
||||||
|
getline
|
||||||
|
print $0
|
||||||
|
print "#ifndef aligned_u64"
|
||||||
|
print "#define aligned_u64 unsigned long long __attribute__((aligned(8)))"
|
||||||
|
print "#endif"
|
||||||
|
}
|
||||||
|
|
||||||
|
print $0
|
||||||
|
}' $TEMP > $TARGET
|
||||||
|
else
|
||||||
|
echo "can't find nfnetlink_queue.h kernel file in $INCLUDEDIR"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
[ "x$1" = "xdistrib" ] && include
|
||||||
|
autoreconf -fi
|
||||||
|
rm -Rf autom4te.cache
|
||||||
85
deps/libnetfilter_queue/configure.ac
vendored
Normal file
85
deps/libnetfilter_queue/configure.ac
vendored
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
dnl Process this file with autoconf to create configure.
|
||||||
|
|
||||||
|
AC_INIT([libnetfilter_queue], [1.0.5])
|
||||||
|
AC_CONFIG_AUX_DIR([build-aux])
|
||||||
|
AC_CANONICAL_HOST
|
||||||
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
|
AC_CONFIG_HEADERS([config.h])
|
||||||
|
|
||||||
|
AM_INIT_AUTOMAKE([-Wall foreign subdir-objects
|
||||||
|
tar-pax no-dist-gzip dist-xz 1.6])
|
||||||
|
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
|
||||||
|
|
||||||
|
dnl kernel style compile messages
|
||||||
|
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([html-doc],
|
||||||
|
AS_HELP_STRING([--enable-html-doc], [Enable html documentation]),
|
||||||
|
[], [enable_html_doc=no])
|
||||||
|
AM_CONDITIONAL([BUILD_HTML], [test "$enable_html_doc" = yes])
|
||||||
|
AS_IF([test "$enable_html_doc" = yes],
|
||||||
|
[AC_SUBST(GEN_HTML, YES)],
|
||||||
|
[AC_SUBST(GEN_HTML, NO)])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([man-pages],
|
||||||
|
AS_HELP_STRING([--disable-man-pages], [Disable man page documentation]),
|
||||||
|
[], [enable_man_pages=yes])
|
||||||
|
AM_CONDITIONAL([BUILD_MAN], [test "$enable_man_pages" = yes])
|
||||||
|
AS_IF([test "$enable_man_pages" = yes],
|
||||||
|
[AC_SUBST(GEN_MAN, YES)],
|
||||||
|
[AC_SUBST(GEN_MAN, NO)])
|
||||||
|
|
||||||
|
AC_PROG_CC
|
||||||
|
AM_PROG_CC_C_O
|
||||||
|
AC_DISABLE_STATIC
|
||||||
|
AM_PROG_LIBTOOL
|
||||||
|
AC_PROG_INSTALL
|
||||||
|
CHECK_GCC_FVISIBILITY
|
||||||
|
|
||||||
|
case "$host" in
|
||||||
|
*-*-linux* | *-*-uclinux*) ;;
|
||||||
|
*) AC_MSG_ERROR([Linux only, dude!]);;
|
||||||
|
esac
|
||||||
|
|
||||||
|
dnl Dependencies
|
||||||
|
PKG_CHECK_MODULES([LIBNFNETLINK], [libnfnetlink >= 0.0.41])
|
||||||
|
PKG_CHECK_MODULES([LIBMNL], [libmnl >= 1.0.3])
|
||||||
|
|
||||||
|
AS_IF([test "$enable_man_pages" = no -a "$enable_html_doc" = no],
|
||||||
|
[with_doxygen=no], [with_doxygen=yes])
|
||||||
|
|
||||||
|
AS_IF([test "x$with_doxygen" != xno], [
|
||||||
|
AC_CHECK_PROGS([DOXYGEN], [doxygen], [""])
|
||||||
|
AC_CHECK_PROGS([DOT], [dot], [""])
|
||||||
|
AS_IF([test "x$DOT" != "x"],
|
||||||
|
[AC_SUBST(HAVE_DOT, YES)],
|
||||||
|
[AC_SUBST(HAVE_DOT, NO)])
|
||||||
|
])
|
||||||
|
|
||||||
|
AM_CONDITIONAL([HAVE_DOXYGEN], [test -n "$DOXYGEN"])
|
||||||
|
AS_IF([test "x$DOXYGEN" = x], [
|
||||||
|
AS_IF([test "x$with_doxygen" != xno], [
|
||||||
|
dnl Only run doxygen Makefile if doxygen installed
|
||||||
|
AC_MSG_WARN([Doxygen not found - not building documentation])
|
||||||
|
enable_html_doc=no
|
||||||
|
enable_man_pages=no
|
||||||
|
])
|
||||||
|
], [
|
||||||
|
dnl Warn user if html docs will be missing diagrams
|
||||||
|
AS_IF([test "$enable_html_doc" = yes -a -z "$DOT"],
|
||||||
|
AC_MSG_WARN([Dot not found - install graphviz to get interactive diagrams in HTML]))
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl Output the makefiles
|
||||||
|
AC_CONFIG_FILES([Makefile src/Makefile utils/Makefile examples/Makefile
|
||||||
|
libnetfilter_queue.pc
|
||||||
|
include/Makefile include/libnetfilter_queue/Makefile
|
||||||
|
doxygen/Makefile doxygen/doxygen.cfg
|
||||||
|
include/linux/Makefile include/linux/netfilter/Makefile])
|
||||||
|
|
||||||
|
AC_OUTPUT
|
||||||
|
|
||||||
|
echo "
|
||||||
|
libnetfilter_queue configuration:
|
||||||
|
man pages: ${enable_man_pages}
|
||||||
|
html docs: ${enable_html_doc}"
|
||||||
45
deps/libnetfilter_queue/doxygen/Makefile.am
vendored
Normal file
45
deps/libnetfilter_queue/doxygen/Makefile.am
vendored
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
if HAVE_DOXYGEN
|
||||||
|
|
||||||
|
doc_srcs = $(top_srcdir)/src/libnetfilter_queue.c\
|
||||||
|
$(top_srcdir)/src/nlmsg.c\
|
||||||
|
$(top_srcdir)/src/extra/checksum.c\
|
||||||
|
$(top_srcdir)/src/extra/ipv4.c\
|
||||||
|
$(top_srcdir)/src/extra/pktbuff.c\
|
||||||
|
$(top_srcdir)/src/extra/ipv6.c\
|
||||||
|
$(top_srcdir)/src/extra/tcp.c\
|
||||||
|
$(top_srcdir)/src/extra/udp.c\
|
||||||
|
$(top_srcdir)/src/extra/icmp.c
|
||||||
|
|
||||||
|
doxyfile.stamp: $(doc_srcs) Makefile build_man.sh
|
||||||
|
rm -rf html man
|
||||||
|
doxygen doxygen.cfg >/dev/null
|
||||||
|
|
||||||
|
if BUILD_MAN
|
||||||
|
$(abs_top_srcdir)/doxygen/build_man.sh libnetfilter_queue libnetfilter_queue.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
touch doxyfile.stamp
|
||||||
|
|
||||||
|
CLEANFILES = doxyfile.stamp
|
||||||
|
|
||||||
|
all-local: doxyfile.stamp
|
||||||
|
clean-local:
|
||||||
|
rm -rf man html
|
||||||
|
install-data-local:
|
||||||
|
if BUILD_MAN
|
||||||
|
mkdir -p $(DESTDIR)$(mandir)/man3
|
||||||
|
cp --no-dereference --preserve=links,mode,timestamps man/man3/*.3\
|
||||||
|
$(DESTDIR)$(mandir)/man3/
|
||||||
|
endif
|
||||||
|
if BUILD_HTML
|
||||||
|
mkdir -p $(DESTDIR)$(htmldir)
|
||||||
|
cp --no-dereference --preserve=links,mode,timestamps html/*\
|
||||||
|
$(DESTDIR)$(htmldir)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# make distcheck needs uninstall-local
|
||||||
|
uninstall-local:
|
||||||
|
rm -rf $(DESTDIR)$(mandir) man html doxyfile.stamp $(DESTDIR)$(htmldir)
|
||||||
|
endif
|
||||||
|
|
||||||
|
EXTRA_DIST = build_man.sh
|
||||||
323
deps/libnetfilter_queue/doxygen/build_man.sh
vendored
Executable file
323
deps/libnetfilter_queue/doxygen/build_man.sh
vendored
Executable file
@@ -0,0 +1,323 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
[ -n "$BASH" ] || exec bash -p $0 $@
|
||||||
|
|
||||||
|
# Script to process man pages output by doxygen.
|
||||||
|
# We need to use bash for its associative array facility.
|
||||||
|
# (`bash -p` prevents import of functions from the environment).
|
||||||
|
# Args: none or 2 being man7 page name & relative path of source with \mainpage
|
||||||
|
|
||||||
|
declare -A renamed_page
|
||||||
|
|
||||||
|
main(){
|
||||||
|
set -e
|
||||||
|
pushd man/man3 >/dev/null; rm -f _*
|
||||||
|
count_real_pages
|
||||||
|
rename_real_pages
|
||||||
|
make_symlinks
|
||||||
|
post_process $@
|
||||||
|
}
|
||||||
|
|
||||||
|
count_real_pages(){
|
||||||
|
page_count=0
|
||||||
|
#
|
||||||
|
# Count "real" man pages (i.e. not generated by MAN_LINKS)
|
||||||
|
# MAN_LINKS pages are 1-liners starting .so
|
||||||
|
# Method: list files in descending order of size,
|
||||||
|
# looking for the first 1-liner
|
||||||
|
#
|
||||||
|
for i in $(ls -S)
|
||||||
|
do head -n1 $i | grep -E -q '^\.so' && break
|
||||||
|
page_count=$(($page_count + 1))
|
||||||
|
done
|
||||||
|
first_link=$(($page_count + 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
rename_real_pages(){
|
||||||
|
for i in $(ls -S | head -n$page_count)
|
||||||
|
do for j in $(ls -S | tail -n+$first_link)
|
||||||
|
do grep -E -q $i$ $j && break
|
||||||
|
done
|
||||||
|
mv -f $i $j
|
||||||
|
renamed_page[$i]=$j
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
make_symlinks(){
|
||||||
|
for j in $(ls -S | tail -n+$first_link)
|
||||||
|
do ln -sf ${renamed_page[$(cat $j | cut -f2 -d/)]} $j
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
post_process(){
|
||||||
|
make_temp_files
|
||||||
|
#
|
||||||
|
# DIAGNOSTIC / DEVELOPMENT CODE
|
||||||
|
# set -x and restrict processing to keep_me: un-comment to activate
|
||||||
|
# Change keep_me as required
|
||||||
|
#
|
||||||
|
#keep_me=nfq_icmp_get_hdr.3;\
|
||||||
|
#do_diagnostics;\
|
||||||
|
#
|
||||||
|
# Work through the "real" man pages
|
||||||
|
for target in $(ls -S | head -n$page_count)
|
||||||
|
do mygrep "^\\.SH \"Function Documentation" $target
|
||||||
|
# Next file if this isn't a function page
|
||||||
|
[ $linnum -ne 0 ] || continue
|
||||||
|
|
||||||
|
del_modules
|
||||||
|
del_bogus_synopsis
|
||||||
|
fix_name_line
|
||||||
|
move_synopsis
|
||||||
|
del_empty_det_desc
|
||||||
|
del_def_at_lines
|
||||||
|
fix_double_blanks
|
||||||
|
|
||||||
|
# Fix rendering of verbatim "\n" (in code snippets)
|
||||||
|
sed -i 's/\\n/\\\\n/' $target
|
||||||
|
|
||||||
|
done
|
||||||
|
|
||||||
|
[ $# -ne 2 ] || make_man7 $@
|
||||||
|
|
||||||
|
remove_temp_files
|
||||||
|
}
|
||||||
|
|
||||||
|
make_man7(){
|
||||||
|
popd >/dev/null
|
||||||
|
target=$(grep -Ew INPUT doxygen.cfg | rev | cut -f1 -d' ' | rev)/$2
|
||||||
|
mypath=$(dirname $0)
|
||||||
|
|
||||||
|
# Build up temporary source in temp.c
|
||||||
|
# (doxygen only makes man pages from .c files).
|
||||||
|
mygrep \\\\mainpage $target
|
||||||
|
tail -n+$((linnum-1)) $target | head -n1 >temp.c
|
||||||
|
echo " * \\defgroup $1 $1 overview" >>temp.c
|
||||||
|
tail -n+$((linnum+1)) $target >$fileA
|
||||||
|
linnum=$(grep -En '\*/' $fileA | head -n1 | cut -d: -f1)
|
||||||
|
head -n$((linnum - 1)) $fileA >> temp.c
|
||||||
|
|
||||||
|
echo ' */' >> temp.c
|
||||||
|
cat >> temp.c <<////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* $1 - DELETE_ME
|
||||||
|
*/
|
||||||
|
int $1(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
////
|
||||||
|
|
||||||
|
# Create temporary doxygen config in fileC
|
||||||
|
cat /dev/null >$fileC
|
||||||
|
for i in \
|
||||||
|
PROJECT_NAME \
|
||||||
|
PROJECT_NUMBER \
|
||||||
|
ABBREVIATE_BRIEF \
|
||||||
|
FULL_PATH_NAMES \
|
||||||
|
TAB_SIZE \
|
||||||
|
OPTIMIZE_OUTPUT_FOR_C \
|
||||||
|
EXAMPLE_PATTERNS \
|
||||||
|
ALPHABETICAL_INDEX \
|
||||||
|
SEARCHENGINE \
|
||||||
|
GENERATE_LATEX \
|
||||||
|
; do grep -Ew $i doxygen.cfg >>$fileC; done
|
||||||
|
cat >>$fileC <<////
|
||||||
|
INPUT = temp.c
|
||||||
|
GENERATE_HTML = NO
|
||||||
|
GENERATE_MAN = YES
|
||||||
|
MAN_EXTENSION = .7
|
||||||
|
////
|
||||||
|
|
||||||
|
doxygen $fileC >/dev/null
|
||||||
|
|
||||||
|
# Remove SYNOPSIS line if there is one
|
||||||
|
target=man/man7/$1.7
|
||||||
|
mygrep "SH SYNOPSIS" $target
|
||||||
|
[ $linnum -eq 0 ] || delete_lines $linnum $((linnum+1))
|
||||||
|
|
||||||
|
# doxygen 1.8.9.1 and possibly newer run the first para into NAME
|
||||||
|
# (i.e. in this unusual group). There won't be a SYNOPSIS when this happens
|
||||||
|
if grep -Eq "overview$1" $target; then
|
||||||
|
head -n2 temp.c >$fileA
|
||||||
|
cat >>$fileA <<////
|
||||||
|
* \\manonly
|
||||||
|
.PP
|
||||||
|
.SH "Detailed Description"
|
||||||
|
.PP
|
||||||
|
\\endmanonly
|
||||||
|
////
|
||||||
|
tail -n+3 temp.c >>$fileA
|
||||||
|
cat $fileA >temp.c
|
||||||
|
doxygen $fileC >/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Insert top-level "See also" of man7 page in all real man3 pages
|
||||||
|
for target in $(find man/man3 -type f)
|
||||||
|
do mygrep "Detailed Description" $target
|
||||||
|
[ $linnum -ne 0 ] || mygrep "Function Documentation" $target
|
||||||
|
[ $linnum -ne 0 ] || { echo "NO HEADER IN $target" >&2; continue; }
|
||||||
|
head -n$((linnum-1)) $target >$fileA
|
||||||
|
cat >>$fileA <<////
|
||||||
|
.SH "See also"
|
||||||
|
\\fB${1}\\fP(7)
|
||||||
|
////
|
||||||
|
tail -n+$linnum $target >>$fileA
|
||||||
|
cp $fileA $target
|
||||||
|
done
|
||||||
|
|
||||||
|
rm temp.c
|
||||||
|
}
|
||||||
|
|
||||||
|
fix_double_blanks(){
|
||||||
|
linnum=1
|
||||||
|
#
|
||||||
|
# Older versions of man display a blank line on encountering "\fB\fP";
|
||||||
|
# newer versions of man do not.
|
||||||
|
# doxygen emits "\fB\fP" on seeing "\par" on a line by itself.
|
||||||
|
# "\par" gives us double-spacing in the web doc, which we want, but double-
|
||||||
|
# spacing looks odd in a man page so remove "\fB\fP".
|
||||||
|
#
|
||||||
|
while [ $linnum -ne 0 ]
|
||||||
|
do mygrep \\\\fB\\\\fP $target
|
||||||
|
[ $linnum -eq 0 ] || delete_lines $linnum $linnum
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
del_def_at_lines(){
|
||||||
|
linnum=1
|
||||||
|
while [ $linnum -ne 0 ]
|
||||||
|
do mygrep '^Definition at line (\\fB)?[[:digit:]]*(\\fP)? of file' $target
|
||||||
|
[ $linnum -eq 0 ] || delete_lines $(($linnum - 1)) $linnum
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Only invoked if you un-comment the 2 diagnostic / development lines above
|
||||||
|
do_diagnostics(){
|
||||||
|
mv $keep_me xxx
|
||||||
|
rm *.3
|
||||||
|
mv xxx $keep_me
|
||||||
|
page_count=1
|
||||||
|
set -x
|
||||||
|
}
|
||||||
|
|
||||||
|
del_empty_det_desc(){
|
||||||
|
mygrep "^\\.SH \"Function Documentation" $target
|
||||||
|
i=$linnum
|
||||||
|
mygrep "^\\.SH \"Detailed Description" $target
|
||||||
|
[ $linnum -ne 0 ] || return 0
|
||||||
|
[ $(($i - $linnum)) -eq 3 ] || return 0
|
||||||
|
# A 1-line Detailed Description is also 3 lines long,
|
||||||
|
# but the 3rd line is not empty
|
||||||
|
i=$(($i -1))
|
||||||
|
[ $(tail -n+$i $target | head -n1 | wc -c) -le 2 ] || return 0
|
||||||
|
delete_lines $linnum $i
|
||||||
|
}
|
||||||
|
|
||||||
|
move_synopsis(){
|
||||||
|
mygrep "SH SYNOPSIS" $target
|
||||||
|
[ $linnum -ne 0 ] || return 0
|
||||||
|
i=$linnum
|
||||||
|
# If this is a doxygen-created synopsis, leave it.
|
||||||
|
# (We haven't inserted our own one in the source yet)
|
||||||
|
mygrep "^\\.SS \"Functions" $target
|
||||||
|
[ $i -gt $linnum ] || return 0
|
||||||
|
|
||||||
|
mygrep "^\\.SH \"Function Documentation" $target
|
||||||
|
j=$(($linnum - 1))
|
||||||
|
head -n$(($j - 1)) $target | tail -n$(($linnum - $i - 1)) >$fileC
|
||||||
|
delete_lines $i $j
|
||||||
|
mygrep "^\\.SS \"Functions" $target
|
||||||
|
head -n$(($linnum - 1)) $target >$fileA
|
||||||
|
tail -n+$(($linnum + 1)) $target >$fileB
|
||||||
|
cat $fileA $fileC $fileB >$target
|
||||||
|
}
|
||||||
|
|
||||||
|
fix_name_line(){
|
||||||
|
all_funcs=""
|
||||||
|
|
||||||
|
# Search a shortened version of the page in case there are .RI lines later
|
||||||
|
mygrep "^\\.SH \"Function Documentation" $target
|
||||||
|
head -n$linnum $target >$fileC
|
||||||
|
|
||||||
|
while :
|
||||||
|
do mygrep ^\\.RI $fileC
|
||||||
|
[ $linnum -ne 0 ] || break
|
||||||
|
# Discard this entry
|
||||||
|
tail -n+$(($linnum + 1)) $fileC >$fileB
|
||||||
|
cp $fileB $fileC
|
||||||
|
|
||||||
|
func=$(cat $fileG | cut -f2 -d\\ | cut -c3-)
|
||||||
|
[ -z "$all_funcs" ] && all_funcs=$func ||\
|
||||||
|
all_funcs="$all_funcs, $func"
|
||||||
|
done
|
||||||
|
# For now, assume name is at line 5
|
||||||
|
head -n4 $target >$fileA
|
||||||
|
desc=$(head -n5 $target | tail -n1 | cut -f3- -d" ")
|
||||||
|
tail -n+6 $target >$fileB
|
||||||
|
cat $fileA >$target
|
||||||
|
echo "$all_funcs \\- $desc" >>$target
|
||||||
|
cat $fileB >>$target
|
||||||
|
}
|
||||||
|
|
||||||
|
del_modules(){
|
||||||
|
mygrep "^\.SS \"Modules" $target
|
||||||
|
[ $linnum -ne 0 ] || return 0
|
||||||
|
i=$linnum
|
||||||
|
mygrep "^\\.SS \"Functions" $target
|
||||||
|
delete_lines $i $(($linnum - 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
del_bogus_synopsis(){
|
||||||
|
mygrep "SH SYNOPSIS" $target
|
||||||
|
#
|
||||||
|
# doxygen 1.8.20 inserts its own SYNOPSIS line but there is no mention
|
||||||
|
# in the documentation or git log what to do with it.
|
||||||
|
# So get rid of it
|
||||||
|
#
|
||||||
|
[ $linnum -ne 0 ] || return 0
|
||||||
|
i=$linnum
|
||||||
|
# Look for the next one
|
||||||
|
tail -n+$(($i + 1)) $target >$fileC;\
|
||||||
|
mygrep "SH SYNOPSIS" $fileC
|
||||||
|
[ $linnum -ne 0 ] || return 0
|
||||||
|
|
||||||
|
mygrep "^\\.SS \"Functions" $target
|
||||||
|
delete_lines $i $(($linnum - 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
# Delete lines $1 through $2 from $target
|
||||||
|
delete_lines(){
|
||||||
|
head -n$(($1 - 1)) $target >$fileA
|
||||||
|
tail -n+$(($2 +1)) $target >$fileB
|
||||||
|
cat $fileA $fileB >$target
|
||||||
|
}
|
||||||
|
|
||||||
|
mygrep(){
|
||||||
|
set +e
|
||||||
|
grep -En "$1" $2 2>/dev/null >$fileH
|
||||||
|
[ $? -ne 0 ] && linnum=0 ||\
|
||||||
|
{ head -n1 $fileH >$fileG; linnum=$(cat $fileG | cut -f1 -d:); }
|
||||||
|
set -e
|
||||||
|
}
|
||||||
|
|
||||||
|
make_temp_files(){
|
||||||
|
temps="A B C G H"
|
||||||
|
for i in $temps
|
||||||
|
do declare -g file$i=$(mktemp)
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_temp_files(){
|
||||||
|
for i in $temps
|
||||||
|
do j=file$i
|
||||||
|
rm ${!j}
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
main $@
|
||||||
27
deps/libnetfilter_queue/doxygen/doxygen.cfg.in
vendored
Normal file
27
deps/libnetfilter_queue/doxygen/doxygen.cfg.in
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# Difference with default Doxyfile 1.8.20
|
||||||
|
PROJECT_NAME = @PACKAGE@
|
||||||
|
PROJECT_NUMBER = @VERSION@
|
||||||
|
ABBREVIATE_BRIEF =
|
||||||
|
FULL_PATH_NAMES = NO
|
||||||
|
TAB_SIZE = 8
|
||||||
|
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||||
|
INPUT = @abs_top_srcdir@/src
|
||||||
|
FILE_PATTERNS = *.c
|
||||||
|
RECURSIVE = YES
|
||||||
|
EXCLUDE_SYMBOLS = EXPORT_SYMBOL \
|
||||||
|
tcp_word_hdr \
|
||||||
|
nfq_handle \
|
||||||
|
nfq_data \
|
||||||
|
nfq_q_handle \
|
||||||
|
tcp_flag_word
|
||||||
|
EXAMPLE_PATTERNS =
|
||||||
|
INPUT_FILTER = "sed 's/EXPORT_SYMBOL//g'"
|
||||||
|
SOURCE_BROWSER = YES
|
||||||
|
ALPHABETICAL_INDEX = NO
|
||||||
|
SEARCHENGINE = NO
|
||||||
|
GENERATE_LATEX = NO
|
||||||
|
LATEX_CMD_NAME = latex
|
||||||
|
GENERATE_MAN = @GEN_MAN@
|
||||||
|
GENERATE_HTML = @GEN_HTML@
|
||||||
|
MAN_LINKS = YES
|
||||||
|
HAVE_DOT = @HAVE_DOT@
|
||||||
7
deps/libnetfilter_queue/examples/Makefile.am
vendored
Normal file
7
deps/libnetfilter_queue/examples/Makefile.am
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
include ${top_srcdir}/Make_global.am
|
||||||
|
|
||||||
|
check_PROGRAMS = nf-queue
|
||||||
|
|
||||||
|
nf_queue_SOURCES = nf-queue.c
|
||||||
|
nf_queue_LDADD = ../src/libnetfilter_queue.la -lmnl
|
||||||
|
nf_queue_LDFLAGS = -dynamic
|
||||||
233
deps/libnetfilter_queue/examples/nf-queue.c
vendored
Normal file
233
deps/libnetfilter_queue/examples/nf-queue.c
vendored
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <linux/netfilter.h>
|
||||||
|
#include <linux/netfilter/nfnetlink.h>
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/netfilter/nfnetlink_queue.h>
|
||||||
|
|
||||||
|
#include <libnetfilter_queue/libnetfilter_queue.h>
|
||||||
|
|
||||||
|
/* NFQA_CT requires CTA_* attributes defined in nfnetlink_conntrack.h */
|
||||||
|
#include <linux/netfilter/nfnetlink_conntrack.h>
|
||||||
|
|
||||||
|
static struct mnl_socket *nl;
|
||||||
|
|
||||||
|
static void
|
||||||
|
nfq_send_verdict(int queue_num, uint32_t id)
|
||||||
|
{
|
||||||
|
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
struct nlattr *nest;
|
||||||
|
|
||||||
|
nlh = nfq_nlmsg_put(buf, NFQNL_MSG_VERDICT, queue_num);
|
||||||
|
nfq_nlmsg_verdict_put(nlh, id, NF_ACCEPT);
|
||||||
|
|
||||||
|
/* example to set the connmark. First, start NFQA_CT section: */
|
||||||
|
nest = mnl_attr_nest_start(nlh, NFQA_CT);
|
||||||
|
|
||||||
|
/* then, add the connmark attribute: */
|
||||||
|
mnl_attr_put_u32(nlh, CTA_MARK, htonl(42));
|
||||||
|
/* more conntrack attributes, e.g. CTA_LABELS could be set here */
|
||||||
|
|
||||||
|
/* end conntrack section */
|
||||||
|
mnl_attr_nest_end(nlh, nest);
|
||||||
|
|
||||||
|
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||||
|
perror("mnl_socket_send");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int queue_cb(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
struct nfqnl_msg_packet_hdr *ph = NULL;
|
||||||
|
struct nlattr *attr[NFQA_MAX+1] = {};
|
||||||
|
uint32_t id = 0, skbinfo;
|
||||||
|
struct nfgenmsg *nfg;
|
||||||
|
uint16_t plen;
|
||||||
|
|
||||||
|
/* Parse netlink message received from the kernel, the array of
|
||||||
|
* attributes is set up to store metadata and the actual packet.
|
||||||
|
*/
|
||||||
|
if (nfq_nlmsg_parse(nlh, attr) < 0) {
|
||||||
|
perror("problems parsing");
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
nfg = mnl_nlmsg_get_payload(nlh);
|
||||||
|
|
||||||
|
if (attr[NFQA_PACKET_HDR] == NULL) {
|
||||||
|
fputs("metaheader not set\n", stderr);
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Access packet metadata, which provides unique packet ID, hook number
|
||||||
|
* and ethertype. See struct nfqnl_msg_packet_hdr for details.
|
||||||
|
*/
|
||||||
|
ph = mnl_attr_get_payload(attr[NFQA_PACKET_HDR]);
|
||||||
|
|
||||||
|
/* Access actual packet data length. */
|
||||||
|
plen = mnl_attr_get_payload_len(attr[NFQA_PAYLOAD]);
|
||||||
|
|
||||||
|
/* Access actual packet data */
|
||||||
|
/* void *payload = mnl_attr_get_payload(attr[NFQA_PAYLOAD]); */
|
||||||
|
|
||||||
|
/* Fetch metadata flags, possible flags values are:
|
||||||
|
*
|
||||||
|
* - NFQA_SKB_CSUMNOTREADY:
|
||||||
|
* Kernel performed partial checksum validation, see CHECKSUM_PARTIAL.
|
||||||
|
* - NFQA_SKB_CSUM_NOTVERIFIED:
|
||||||
|
* Kernel already verified checksum.
|
||||||
|
* - NFQA_SKB_GSO:
|
||||||
|
* Not the original packet received from the wire. Kernel has
|
||||||
|
* aggregated several packets into one single packet via GSO.
|
||||||
|
*/
|
||||||
|
skbinfo = attr[NFQA_SKB_INFO] ? ntohl(mnl_attr_get_u32(attr[NFQA_SKB_INFO])) : 0;
|
||||||
|
|
||||||
|
/* Kernel has truncated the packet, fetch original packet length. */
|
||||||
|
if (attr[NFQA_CAP_LEN]) {
|
||||||
|
uint32_t orig_len = ntohl(mnl_attr_get_u32(attr[NFQA_CAP_LEN]));
|
||||||
|
if (orig_len != plen)
|
||||||
|
printf("truncated ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skbinfo & NFQA_SKB_GSO)
|
||||||
|
printf("GSO ");
|
||||||
|
|
||||||
|
id = ntohl(ph->packet_id);
|
||||||
|
printf("packet received (id=%u hw=0x%04x hook=%u, payload len %u",
|
||||||
|
id, ntohs(ph->hw_protocol), ph->hook, plen);
|
||||||
|
|
||||||
|
/* Fetch ethernet destination address. */
|
||||||
|
if (attr[NFQA_HWADDR]) {
|
||||||
|
struct nfqnl_msg_packet_hw *hw = mnl_attr_get_payload(attr[NFQA_HWADDR]);
|
||||||
|
unsigned int hwlen = ntohs(hw->hw_addrlen);
|
||||||
|
const unsigned char *addr = hw->hw_addr;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
printf(", hwaddr %02x", addr[0]);
|
||||||
|
for (i = 1; i < hwlen; i++) {
|
||||||
|
if (i >= sizeof(hw->hw_addr)) {
|
||||||
|
printf("[truncated]");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf(":%02x", (unsigned char)addr[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" len %u", hwlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ip/tcp checksums are not yet valid, e.g. due to GRO/GSO.
|
||||||
|
* The application should behave as if the checksums are correct.
|
||||||
|
*
|
||||||
|
* If these packets are later forwarded/sent out, the checksums will
|
||||||
|
* be corrected by kernel/hardware.
|
||||||
|
*/
|
||||||
|
if (skbinfo & NFQA_SKB_CSUMNOTREADY)
|
||||||
|
printf(", checksum not ready");
|
||||||
|
puts(")");
|
||||||
|
|
||||||
|
nfq_send_verdict(ntohs(nfg->res_id), id);
|
||||||
|
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
/* largest possible packet payload, plus netlink data overhead: */
|
||||||
|
size_t sizeof_buf = 0xffff + (MNL_SOCKET_BUFFER_SIZE/2);
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
int ret;
|
||||||
|
unsigned int portid, queue_num;
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
printf("Usage: %s [queue_num]\n", argv[0]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
queue_num = atoi(argv[1]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up netlink socket to communicate with the netfilter subsystem.
|
||||||
|
*/
|
||||||
|
nl = mnl_socket_open(NETLINK_NETFILTER);
|
||||||
|
if (nl == NULL) {
|
||||||
|
perror("mnl_socket_open");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||||
|
perror("mnl_socket_bind");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
portid = mnl_socket_get_portid(nl);
|
||||||
|
|
||||||
|
buf = malloc(sizeof_buf);
|
||||||
|
if (!buf) {
|
||||||
|
perror("allocate receive buffer");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure the pipeline between kernel and userspace, build and send
|
||||||
|
* a netlink message to specify queue number to bind to. Your ruleset
|
||||||
|
* has to use this queue number to deliver packets to userspace.
|
||||||
|
*/
|
||||||
|
nlh = nfq_nlmsg_put(buf, NFQNL_MSG_CONFIG, queue_num);
|
||||||
|
nfq_nlmsg_cfg_put_cmd(nlh, AF_INET, NFQNL_CFG_CMD_BIND);
|
||||||
|
|
||||||
|
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||||
|
perror("mnl_socket_send");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build and send a netlink message to specify how many bytes are
|
||||||
|
* copied from kernel to userspace for this queue.
|
||||||
|
*/
|
||||||
|
nlh = nfq_nlmsg_put(buf, NFQNL_MSG_CONFIG, queue_num);
|
||||||
|
nfq_nlmsg_cfg_put_params(nlh, NFQNL_COPY_PACKET, 0xffff);
|
||||||
|
|
||||||
|
mnl_attr_put_u32(nlh, NFQA_CFG_FLAGS, htonl(NFQA_CFG_F_GSO));
|
||||||
|
mnl_attr_put_u32(nlh, NFQA_CFG_MASK, htonl(NFQA_CFG_F_GSO));
|
||||||
|
|
||||||
|
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
||||||
|
perror("mnl_socket_send");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ENOBUFS is signalled to userspace when packets were lost
|
||||||
|
* on kernel side. In most cases, userspace isn't interested
|
||||||
|
* in this information, so turn it off.
|
||||||
|
*/
|
||||||
|
ret = 1;
|
||||||
|
mnl_socket_setsockopt(nl, NETLINK_NO_ENOBUFS, &ret, sizeof(int));
|
||||||
|
|
||||||
|
/* Loop forever on packets received from the kernel and run the
|
||||||
|
* callback handler.
|
||||||
|
*/
|
||||||
|
for (;;) {
|
||||||
|
ret = mnl_socket_recvfrom(nl, buf, sizeof_buf);
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("mnl_socket_recvfrom");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mnl_cb_run(buf, ret, 0, portid, queue_cb, NULL);
|
||||||
|
if (ret < 0){
|
||||||
|
perror("mnl_cb_run");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mnl_socket_close(nl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
1
deps/libnetfilter_queue/include/Makefile.am
vendored
Normal file
1
deps/libnetfilter_queue/include/Makefile.am
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
SUBDIRS= libnetfilter_queue linux
|
||||||
8
deps/libnetfilter_queue/include/libnetfilter_queue/Makefile.am
vendored
Normal file
8
deps/libnetfilter_queue/include/libnetfilter_queue/Makefile.am
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
pkginclude_HEADERS = libnetfilter_queue.h \
|
||||||
|
linux_nfnetlink_queue.h \
|
||||||
|
libnetfilter_queue_icmp.h \
|
||||||
|
libnetfilter_queue_ipv4.h \
|
||||||
|
libnetfilter_queue_ipv6.h \
|
||||||
|
libnetfilter_queue_tcp.h \
|
||||||
|
libnetfilter_queue_udp.h \
|
||||||
|
pktbuff.h
|
||||||
160
deps/libnetfilter_queue/include/libnetfilter_queue/libnetfilter_queue.h
vendored
Normal file
160
deps/libnetfilter_queue/include/libnetfilter_queue/libnetfilter_queue.h
vendored
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
/* libnfqnetlink.h: Header file for the Netfilter Queue library.
|
||||||
|
*
|
||||||
|
* (C) 2005 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Changelog :
|
||||||
|
* (2005/08/11) added parsing function (Eric Leblond <regit@inl.fr>)
|
||||||
|
*
|
||||||
|
* This software may be used and distributed according to the terms
|
||||||
|
* of the GNU General Public License, incorporated herein by reference.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LIBCTNETLINK_H
|
||||||
|
#define __LIBCTNETLINK_H
|
||||||
|
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <libnfnetlink/libnfnetlink.h>
|
||||||
|
|
||||||
|
#include <libnetfilter_queue/linux_nfnetlink_queue.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct nfq_handle;
|
||||||
|
struct nfq_q_handle;
|
||||||
|
struct nfq_data;
|
||||||
|
|
||||||
|
extern int nfq_errno;
|
||||||
|
|
||||||
|
extern struct nfnl_handle *nfq_nfnlh(struct nfq_handle *h);
|
||||||
|
extern int nfq_fd(struct nfq_handle *h);
|
||||||
|
|
||||||
|
typedef int nfq_callback(struct nfq_q_handle *gh, struct nfgenmsg *nfmsg,
|
||||||
|
struct nfq_data *nfad, void *data);
|
||||||
|
|
||||||
|
|
||||||
|
extern struct nfq_handle *nfq_open(void);
|
||||||
|
extern struct nfq_handle *nfq_open_nfnl(struct nfnl_handle *nfnlh);
|
||||||
|
extern int nfq_close(struct nfq_handle *h);
|
||||||
|
|
||||||
|
extern int nfq_bind_pf(struct nfq_handle *h, uint16_t pf);
|
||||||
|
extern int nfq_unbind_pf(struct nfq_handle *h, uint16_t pf);
|
||||||
|
|
||||||
|
extern struct nfq_q_handle *nfq_create_queue(struct nfq_handle *h,
|
||||||
|
uint16_t num,
|
||||||
|
nfq_callback *cb,
|
||||||
|
void *data);
|
||||||
|
extern int nfq_destroy_queue(struct nfq_q_handle *qh);
|
||||||
|
|
||||||
|
extern int nfq_handle_packet(struct nfq_handle *h, char *buf, int len);
|
||||||
|
|
||||||
|
extern int nfq_set_mode(struct nfq_q_handle *qh,
|
||||||
|
uint8_t mode, unsigned int len);
|
||||||
|
|
||||||
|
int nfq_set_queue_maxlen(struct nfq_q_handle *qh,
|
||||||
|
uint32_t queuelen);
|
||||||
|
|
||||||
|
extern int nfq_set_queue_flags(struct nfq_q_handle *qh,
|
||||||
|
uint32_t mask, uint32_t flags);
|
||||||
|
|
||||||
|
extern int nfq_set_verdict(struct nfq_q_handle *qh,
|
||||||
|
uint32_t id,
|
||||||
|
uint32_t verdict,
|
||||||
|
uint32_t data_len,
|
||||||
|
const unsigned char *buf);
|
||||||
|
|
||||||
|
extern int nfq_set_verdict2(struct nfq_q_handle *qh,
|
||||||
|
uint32_t id,
|
||||||
|
uint32_t verdict,
|
||||||
|
uint32_t mark,
|
||||||
|
uint32_t datalen,
|
||||||
|
const unsigned char *buf);
|
||||||
|
|
||||||
|
extern int nfq_set_verdict_batch(struct nfq_q_handle *qh,
|
||||||
|
uint32_t id,
|
||||||
|
uint32_t verdict);
|
||||||
|
|
||||||
|
extern int nfq_set_verdict_batch2(struct nfq_q_handle *qh,
|
||||||
|
uint32_t id,
|
||||||
|
uint32_t verdict,
|
||||||
|
uint32_t mark);
|
||||||
|
|
||||||
|
extern __attribute__((deprecated))
|
||||||
|
int nfq_set_verdict_mark(struct nfq_q_handle *qh,
|
||||||
|
uint32_t id,
|
||||||
|
uint32_t verdict,
|
||||||
|
uint32_t mark,
|
||||||
|
uint32_t datalen,
|
||||||
|
const unsigned char *buf);
|
||||||
|
|
||||||
|
/* message parsing function */
|
||||||
|
|
||||||
|
extern struct nfqnl_msg_packet_hdr *
|
||||||
|
nfq_get_msg_packet_hdr(struct nfq_data *nfad);
|
||||||
|
|
||||||
|
extern uint32_t nfq_get_nfmark(struct nfq_data *nfad);
|
||||||
|
|
||||||
|
extern int nfq_get_timestamp(struct nfq_data *nfad, struct timeval *tv);
|
||||||
|
|
||||||
|
/* return 0 if not set */
|
||||||
|
extern uint32_t nfq_get_indev(struct nfq_data *nfad);
|
||||||
|
extern uint32_t nfq_get_physindev(struct nfq_data *nfad);
|
||||||
|
extern uint32_t nfq_get_outdev(struct nfq_data *nfad);
|
||||||
|
extern uint32_t nfq_get_physoutdev(struct nfq_data *nfad);
|
||||||
|
extern uint32_t nfq_get_skbinfo(struct nfq_data *nfad);
|
||||||
|
extern int nfq_get_uid(struct nfq_data *nfad, uint32_t *uid);
|
||||||
|
extern int nfq_get_gid(struct nfq_data *nfad, uint32_t *gid);
|
||||||
|
extern int nfq_get_secctx(struct nfq_data *nfad, unsigned char **secdata);
|
||||||
|
|
||||||
|
extern int nfq_get_indev_name(struct nlif_handle *nlif_handle,
|
||||||
|
struct nfq_data *nfad, char *name);
|
||||||
|
extern int nfq_get_physindev_name(struct nlif_handle *nlif_handle,
|
||||||
|
struct nfq_data *nfad, char *name);
|
||||||
|
extern int nfq_get_outdev_name(struct nlif_handle *nlif_handle,
|
||||||
|
struct nfq_data *nfad, char *name);
|
||||||
|
extern int nfq_get_physoutdev_name(struct nlif_handle *nlif_handle,
|
||||||
|
struct nfq_data *nfad, char *name);
|
||||||
|
|
||||||
|
extern struct nfqnl_msg_packet_hw *nfq_get_packet_hw(struct nfq_data *nfad);
|
||||||
|
|
||||||
|
/* return -1 if problem, length otherwise */
|
||||||
|
extern int nfq_get_payload(struct nfq_data *nfad, unsigned char **data);
|
||||||
|
|
||||||
|
enum {
|
||||||
|
NFQ_XML_HW = (1 << 0),
|
||||||
|
NFQ_XML_MARK = (1 << 1),
|
||||||
|
NFQ_XML_DEV = (1 << 2),
|
||||||
|
NFQ_XML_PHYSDEV = (1 << 3),
|
||||||
|
NFQ_XML_PAYLOAD = (1 << 4),
|
||||||
|
NFQ_XML_TIME = (1 << 5),
|
||||||
|
NFQ_XML_UID = (1 << 6),
|
||||||
|
NFQ_XML_GID = (1 << 7),
|
||||||
|
NFQ_XML_SECCTX = (1 << 8),
|
||||||
|
NFQ_XML_ALL = ~0U,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int nfq_snprintf_xml(char *buf, size_t len, struct nfq_data *tb, int flags);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* New API based on libmnl
|
||||||
|
*/
|
||||||
|
|
||||||
|
void nfq_nlmsg_cfg_put_cmd(struct nlmsghdr *nlh, uint16_t pf, uint8_t cmd);
|
||||||
|
void nfq_nlmsg_cfg_put_params(struct nlmsghdr *nlh, uint8_t mode, int range);
|
||||||
|
void nfq_nlmsg_cfg_put_qmaxlen(struct nlmsghdr *nlh, uint32_t qmaxlen);
|
||||||
|
|
||||||
|
void nfq_nlmsg_verdict_put(struct nlmsghdr *nlh, int id, int verdict);
|
||||||
|
void nfq_nlmsg_verdict_put_mark(struct nlmsghdr *nlh, uint32_t mark);
|
||||||
|
void nfq_nlmsg_verdict_put_pkt(struct nlmsghdr *nlh, const void *pkt, uint32_t pktlen);
|
||||||
|
|
||||||
|
int nfq_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr **attr);
|
||||||
|
struct nlmsghdr *nfq_nlmsg_put(char *buf, int type, uint32_t queue_num);
|
||||||
|
struct nlmsghdr *nfq_nlmsg_put2(char *buf, int type, uint32_t queue_num, uint16_t flags);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __LIBNFQNETLINK_H */
|
||||||
8
deps/libnetfilter_queue/include/libnetfilter_queue/libnetfilter_queue_icmp.h
vendored
Normal file
8
deps/libnetfilter_queue/include/libnetfilter_queue/libnetfilter_queue_icmp.h
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef _LIBNFQUEUE_ICMP_H_
|
||||||
|
#define _LIBNFQUEUE_ICMP_H_
|
||||||
|
|
||||||
|
struct pkt_buff;
|
||||||
|
|
||||||
|
struct icmphdr *nfq_icmp_get_hdr(struct pkt_buff *pktb);
|
||||||
|
|
||||||
|
#endif
|
||||||
13
deps/libnetfilter_queue/include/libnetfilter_queue/libnetfilter_queue_ipv4.h
vendored
Normal file
13
deps/libnetfilter_queue/include/libnetfilter_queue/libnetfilter_queue_ipv4.h
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#ifndef _LIBNFQUEUE_IPV4_
|
||||||
|
#define _LIBNFQUEUE_IPV4_
|
||||||
|
|
||||||
|
struct pkt_buff;
|
||||||
|
struct iphdr;
|
||||||
|
|
||||||
|
struct iphdr *nfq_ip_get_hdr(struct pkt_buff *pktb);
|
||||||
|
int nfq_ip_set_transport_header(struct pkt_buff *pktb, struct iphdr *iph);
|
||||||
|
void nfq_ip_set_checksum(struct iphdr *iph);
|
||||||
|
int nfq_ip_mangle(struct pkt_buff *pktb, unsigned int dataoff, unsigned int match_offset, unsigned int match_len, const char *rep_buffer, unsigned int rep_len);
|
||||||
|
int nfq_ip_snprintf(char *buf, size_t size, const struct iphdr *iph);
|
||||||
|
|
||||||
|
#endif
|
||||||
12
deps/libnetfilter_queue/include/libnetfilter_queue/libnetfilter_queue_ipv6.h
vendored
Normal file
12
deps/libnetfilter_queue/include/libnetfilter_queue/libnetfilter_queue_ipv6.h
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#ifndef _LIBNFQUEUE_H_
|
||||||
|
#define _LIBNFQUEUE_H_
|
||||||
|
|
||||||
|
struct pkt_buff;
|
||||||
|
struct ip6_hdr;
|
||||||
|
|
||||||
|
struct ip6_hdr *nfq_ip6_get_hdr(struct pkt_buff *pktb);
|
||||||
|
int nfq_ip6_set_transport_header(struct pkt_buff *pktb, struct ip6_hdr *iph, uint8_t target);
|
||||||
|
int nfq_ip6_mangle(struct pkt_buff *pktb, unsigned int dataoff,unsigned int match_offset, unsigned int match_len,const char *rep_buffer, unsigned int rep_len);
|
||||||
|
int nfq_ip6_snprintf(char *buf, size_t size, const struct ip6_hdr *ip6h);
|
||||||
|
|
||||||
|
#endif
|
||||||
21
deps/libnetfilter_queue/include/libnetfilter_queue/libnetfilter_queue_tcp.h
vendored
Normal file
21
deps/libnetfilter_queue/include/libnetfilter_queue/libnetfilter_queue_tcp.h
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#ifndef _LIBNFQUEUE_TCP_H_
|
||||||
|
#define _LIBNFQUEUE_TCP_H_
|
||||||
|
|
||||||
|
struct pkt_buff;
|
||||||
|
|
||||||
|
struct tcphdr *nfq_tcp_get_hdr(struct pkt_buff *pktb);
|
||||||
|
void *nfq_tcp_get_payload(struct tcphdr *tcph, struct pkt_buff *pktb);
|
||||||
|
unsigned int nfq_tcp_get_payload_len(struct tcphdr *tcph, struct pkt_buff *pktb);
|
||||||
|
|
||||||
|
struct iphdr;
|
||||||
|
struct ip6_hdr;
|
||||||
|
|
||||||
|
void nfq_tcp_compute_checksum_ipv4(struct tcphdr *tcph, struct iphdr *iph);
|
||||||
|
void nfq_tcp_compute_checksum_ipv6(struct tcphdr *tcph, struct ip6_hdr *ip6h);
|
||||||
|
|
||||||
|
int nfq_tcp_mangle_ipv4(struct pkt_buff *pktb, unsigned int match_offset, unsigned int match_len, const char *rep_buffer, unsigned int rep_len);
|
||||||
|
int nfq_tcp_mangle_ipv6(struct pkt_buff *pktb, unsigned int match_offset, unsigned int match_len, const char *rep_buffer, unsigned int rep_len);
|
||||||
|
|
||||||
|
int nfq_tcp_snprintf(char *buf, size_t size, const struct tcphdr *tcp);
|
||||||
|
|
||||||
|
#endif
|
||||||
18
deps/libnetfilter_queue/include/libnetfilter_queue/libnetfilter_queue_udp.h
vendored
Normal file
18
deps/libnetfilter_queue/include/libnetfilter_queue/libnetfilter_queue_udp.h
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef _LIBNFQUEUE_UDP_H_
|
||||||
|
#define _LIBNFQUEUE_UDP_H_
|
||||||
|
|
||||||
|
struct pkt_buff;
|
||||||
|
|
||||||
|
struct udphdr *nfq_udp_get_hdr(struct pkt_buff *pktb);
|
||||||
|
void *nfq_udp_get_payload(struct udphdr *udph, struct pkt_buff *pktb);
|
||||||
|
unsigned int nfq_udp_get_payload_len(struct udphdr *udph, struct pkt_buff *pktb);
|
||||||
|
|
||||||
|
void nfq_udp_compute_checksum_ipv4(struct udphdr *udph, struct iphdr *iph);
|
||||||
|
void nfq_udp_compute_checksum_ipv6(struct udphdr *udph, struct ip6_hdr *ip6h);
|
||||||
|
|
||||||
|
int nfq_udp_mangle_ipv4(struct pkt_buff *pktb, unsigned int match_offset, unsigned int match_len, const char *rep_buffer, unsigned int rep_len);
|
||||||
|
int nfq_udp_mangle_ipv6(struct pkt_buff *pktb, unsigned int match_offset, unsigned int match_len, const char *rep_buffer, unsigned int rep_len);
|
||||||
|
|
||||||
|
int nfq_udp_snprintf(char *buf, size_t size, const struct udphdr *udp);
|
||||||
|
|
||||||
|
#endif
|
||||||
123
deps/libnetfilter_queue/include/libnetfilter_queue/linux_nfnetlink_queue.h
vendored
Normal file
123
deps/libnetfilter_queue/include/libnetfilter_queue/linux_nfnetlink_queue.h
vendored
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
#ifndef _NFNETLINK_QUEUE_H
|
||||||
|
#define _NFNETLINK_QUEUE_H
|
||||||
|
|
||||||
|
#warning "libnetfilter_queue/linux_nfnetlink_queue.h is deprecated, add #include <linux/netfilter/nfnetlink_queue.h> to your source code before #include <libnetfilter_queue/libnetfilter_queue.h>"
|
||||||
|
|
||||||
|
#ifndef aligned_u64
|
||||||
|
#define aligned_u64 unsigned long long __attribute__((aligned(8)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <libnfnetlink/linux_nfnetlink.h>
|
||||||
|
|
||||||
|
enum nfqnl_msg_types {
|
||||||
|
NFQNL_MSG_PACKET, /* packet from kernel to userspace */
|
||||||
|
NFQNL_MSG_VERDICT, /* verdict from userspace to kernel */
|
||||||
|
NFQNL_MSG_CONFIG, /* connect to a particular queue */
|
||||||
|
NFQNL_MSG_VERDICT_BATCH, /* batchv from userspace to kernel */
|
||||||
|
|
||||||
|
NFQNL_MSG_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nfqnl_msg_packet_hdr {
|
||||||
|
__be32 packet_id; /* unique ID of packet in queue */
|
||||||
|
__be16 hw_protocol; /* hw protocol (network order) */
|
||||||
|
__u8 hook; /* netfilter hook */
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct nfqnl_msg_packet_hw {
|
||||||
|
__be16 hw_addrlen;
|
||||||
|
__u16 _pad;
|
||||||
|
__u8 hw_addr[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nfqnl_msg_packet_timestamp {
|
||||||
|
__aligned_be64 sec;
|
||||||
|
__aligned_be64 usec;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum nfqnl_attr_type {
|
||||||
|
NFQA_UNSPEC,
|
||||||
|
NFQA_PACKET_HDR,
|
||||||
|
NFQA_VERDICT_HDR, /* nfqnl_msg_verdict_hrd */
|
||||||
|
NFQA_MARK, /* __u32 nfmark */
|
||||||
|
NFQA_TIMESTAMP, /* nfqnl_msg_packet_timestamp */
|
||||||
|
NFQA_IFINDEX_INDEV, /* __u32 ifindex */
|
||||||
|
NFQA_IFINDEX_OUTDEV, /* __u32 ifindex */
|
||||||
|
NFQA_IFINDEX_PHYSINDEV, /* __u32 ifindex */
|
||||||
|
NFQA_IFINDEX_PHYSOUTDEV, /* __u32 ifindex */
|
||||||
|
NFQA_HWADDR, /* nfqnl_msg_packet_hw */
|
||||||
|
NFQA_PAYLOAD, /* opaque data payload */
|
||||||
|
NFQA_CT, /* nfnetlink_conntrack.h */
|
||||||
|
NFQA_CT_INFO, /* enum ip_conntrack_info */
|
||||||
|
NFQA_CAP_LEN, /* __u32 length of captured packet */
|
||||||
|
NFQA_SKB_INFO, /* __u32 skb meta information */
|
||||||
|
NFQA_EXP, /* nfnetlink_conntrack.h */
|
||||||
|
NFQA_UID, /* __u32 sk uid */
|
||||||
|
NFQA_GID, /* __u32 sk gid */
|
||||||
|
NFQA_SECCTX, /* security context string */
|
||||||
|
|
||||||
|
__NFQA_MAX
|
||||||
|
};
|
||||||
|
#define NFQA_MAX (__NFQA_MAX - 1)
|
||||||
|
|
||||||
|
struct nfqnl_msg_verdict_hdr {
|
||||||
|
__be32 verdict;
|
||||||
|
__be32 id;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum nfqnl_msg_config_cmds {
|
||||||
|
NFQNL_CFG_CMD_NONE,
|
||||||
|
NFQNL_CFG_CMD_BIND,
|
||||||
|
NFQNL_CFG_CMD_UNBIND,
|
||||||
|
NFQNL_CFG_CMD_PF_BIND,
|
||||||
|
NFQNL_CFG_CMD_PF_UNBIND,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nfqnl_msg_config_cmd {
|
||||||
|
__u8 command; /* nfqnl_msg_config_cmds */
|
||||||
|
__u8 _pad;
|
||||||
|
__be16 pf; /* AF_xxx for PF_[UN]BIND */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum nfqnl_config_mode {
|
||||||
|
NFQNL_COPY_NONE,
|
||||||
|
NFQNL_COPY_META,
|
||||||
|
NFQNL_COPY_PACKET,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nfqnl_msg_config_params {
|
||||||
|
__be32 copy_range;
|
||||||
|
__u8 copy_mode; /* enum nfqnl_config_mode */
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
|
||||||
|
enum nfqnl_attr_config {
|
||||||
|
NFQA_CFG_UNSPEC,
|
||||||
|
NFQA_CFG_CMD, /* nfqnl_msg_config_cmd */
|
||||||
|
NFQA_CFG_PARAMS, /* nfqnl_msg_config_params */
|
||||||
|
NFQA_CFG_QUEUE_MAXLEN, /* __u32 */
|
||||||
|
NFQA_CFG_MASK, /* identify which flags to change */
|
||||||
|
NFQA_CFG_FLAGS, /* value of these flags (__u32) */
|
||||||
|
__NFQA_CFG_MAX
|
||||||
|
};
|
||||||
|
#define NFQA_CFG_MAX (__NFQA_CFG_MAX-1)
|
||||||
|
|
||||||
|
/* Flags for NFQA_CFG_FLAGS */
|
||||||
|
#define NFQA_CFG_F_FAIL_OPEN (1 << 0)
|
||||||
|
#define NFQA_CFG_F_CONNTRACK (1 << 1)
|
||||||
|
#define NFQA_CFG_F_GSO (1 << 2)
|
||||||
|
#define NFQA_CFG_F_UID_GID (1 << 3)
|
||||||
|
#define NFQA_CFG_F_SECCTX (1 << 4)
|
||||||
|
#define NFQA_CFG_F_MAX (1 << 5)
|
||||||
|
|
||||||
|
/* flags for NFQA_SKB_INFO */
|
||||||
|
/* packet appears to have wrong checksums, but they are ok */
|
||||||
|
#define NFQA_SKB_CSUMNOTREADY (1 << 0)
|
||||||
|
/* packet is GSO (i.e., exceeds device mtu) */
|
||||||
|
#define NFQA_SKB_GSO (1 << 1)
|
||||||
|
/* csum not validated (incoming device doesn't support hw checksum, etc.) */
|
||||||
|
#define NFQA_SKB_CSUM_NOTVERIFIED (1 << 2)
|
||||||
|
|
||||||
|
#endif /* _NFNETLINK_QUEUE_H */
|
||||||
31
deps/libnetfilter_queue/include/libnetfilter_queue/pktbuff.h
vendored
Normal file
31
deps/libnetfilter_queue/include/libnetfilter_queue/pktbuff.h
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#ifndef _PKTBUFF_H_
|
||||||
|
#define _PKTBUFF_H_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
struct pkt_buff;
|
||||||
|
|
||||||
|
struct pkt_buff *pktb_alloc(int family, void *data, size_t len, size_t extra);
|
||||||
|
void pktb_free(struct pkt_buff *pktb);
|
||||||
|
|
||||||
|
struct pkt_buff *pktb_setup_raw(void *pktb, int family, void *data, size_t len, size_t extra);
|
||||||
|
size_t pktb_head_size(void);
|
||||||
|
|
||||||
|
uint8_t *pktb_data(struct pkt_buff *pktb);
|
||||||
|
uint32_t pktb_len(struct pkt_buff *pktb);
|
||||||
|
|
||||||
|
void pktb_push(struct pkt_buff *pktb, unsigned int len);
|
||||||
|
void pktb_pull(struct pkt_buff *pktb, unsigned int len);
|
||||||
|
void pktb_put(struct pkt_buff *pktb, unsigned int len);
|
||||||
|
void pktb_trim(struct pkt_buff *pktb, unsigned int len);
|
||||||
|
unsigned int pktb_tailroom(struct pkt_buff *pktb);
|
||||||
|
|
||||||
|
uint8_t *pktb_mac_header(struct pkt_buff *pktb);
|
||||||
|
uint8_t *pktb_network_header(struct pkt_buff *pktb);
|
||||||
|
uint8_t *pktb_transport_header(struct pkt_buff *pktb);
|
||||||
|
|
||||||
|
int pktb_mangle(struct pkt_buff *pktb, int dataoff, unsigned int match_offset, unsigned int match_len, const char *rep_buffer, unsigned int rep_len);
|
||||||
|
|
||||||
|
bool pktb_mangled(const struct pkt_buff *pktb);
|
||||||
|
|
||||||
|
#endif
|
||||||
1
deps/libnetfilter_queue/include/linux/Makefile.am
vendored
Normal file
1
deps/libnetfilter_queue/include/linux/Makefile.am
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
SUBDIRS = netfilter
|
||||||
1
deps/libnetfilter_queue/include/linux/netfilter/Makefile.am
vendored
Normal file
1
deps/libnetfilter_queue/include/linux/netfilter/Makefile.am
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
noinst_HEADERS = nfnetlink_queue.h
|
||||||
115
deps/libnetfilter_queue/include/linux/netfilter/nfnetlink_queue.h
vendored
Normal file
115
deps/libnetfilter_queue/include/linux/netfilter/nfnetlink_queue.h
vendored
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
#ifndef _NFNETLINK_QUEUE_H
|
||||||
|
#define _NFNETLINK_QUEUE_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/netfilter/nfnetlink.h>
|
||||||
|
|
||||||
|
enum nfqnl_msg_types {
|
||||||
|
NFQNL_MSG_PACKET, /* packet from kernel to userspace */
|
||||||
|
NFQNL_MSG_VERDICT, /* verdict from userspace to kernel */
|
||||||
|
NFQNL_MSG_CONFIG, /* connect to a particular queue */
|
||||||
|
NFQNL_MSG_VERDICT_BATCH, /* batchv from userspace to kernel */
|
||||||
|
|
||||||
|
NFQNL_MSG_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nfqnl_msg_packet_hdr {
|
||||||
|
__be32 packet_id; /* unique ID of packet in queue */
|
||||||
|
__be16 hw_protocol; /* hw protocol (network order) */
|
||||||
|
__u8 hook; /* netfilter hook */
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct nfqnl_msg_packet_hw {
|
||||||
|
__be16 hw_addrlen;
|
||||||
|
__u16 _pad;
|
||||||
|
__u8 hw_addr[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nfqnl_msg_packet_timestamp {
|
||||||
|
__aligned_be64 sec;
|
||||||
|
__aligned_be64 usec;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum nfqnl_attr_type {
|
||||||
|
NFQA_UNSPEC,
|
||||||
|
NFQA_PACKET_HDR,
|
||||||
|
NFQA_VERDICT_HDR, /* nfqnl_msg_verdict_hrd */
|
||||||
|
NFQA_MARK, /* __u32 nfmark */
|
||||||
|
NFQA_TIMESTAMP, /* nfqnl_msg_packet_timestamp */
|
||||||
|
NFQA_IFINDEX_INDEV, /* __u32 ifindex */
|
||||||
|
NFQA_IFINDEX_OUTDEV, /* __u32 ifindex */
|
||||||
|
NFQA_IFINDEX_PHYSINDEV, /* __u32 ifindex */
|
||||||
|
NFQA_IFINDEX_PHYSOUTDEV, /* __u32 ifindex */
|
||||||
|
NFQA_HWADDR, /* nfqnl_msg_packet_hw */
|
||||||
|
NFQA_PAYLOAD, /* opaque data payload */
|
||||||
|
NFQA_CT, /* nfnetlink_conntrack.h */
|
||||||
|
NFQA_CT_INFO, /* enum ip_conntrack_info */
|
||||||
|
NFQA_CAP_LEN, /* __u32 length of captured packet */
|
||||||
|
NFQA_SKB_INFO, /* __u32 skb meta information */
|
||||||
|
NFQA_EXP, /* nfnetlink_conntrack.h */
|
||||||
|
NFQA_UID, /* __u32 sk uid */
|
||||||
|
NFQA_GID, /* __u32 sk gid */
|
||||||
|
NFQA_SECCTX,
|
||||||
|
|
||||||
|
__NFQA_MAX
|
||||||
|
};
|
||||||
|
#define NFQA_MAX (__NFQA_MAX - 1)
|
||||||
|
|
||||||
|
struct nfqnl_msg_verdict_hdr {
|
||||||
|
__be32 verdict;
|
||||||
|
__be32 id;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum nfqnl_msg_config_cmds {
|
||||||
|
NFQNL_CFG_CMD_NONE,
|
||||||
|
NFQNL_CFG_CMD_BIND,
|
||||||
|
NFQNL_CFG_CMD_UNBIND,
|
||||||
|
NFQNL_CFG_CMD_PF_BIND,
|
||||||
|
NFQNL_CFG_CMD_PF_UNBIND,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nfqnl_msg_config_cmd {
|
||||||
|
__u8 command; /* nfqnl_msg_config_cmds */
|
||||||
|
__u8 _pad;
|
||||||
|
__be16 pf; /* AF_xxx for PF_[UN]BIND */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum nfqnl_config_mode {
|
||||||
|
NFQNL_COPY_NONE,
|
||||||
|
NFQNL_COPY_META,
|
||||||
|
NFQNL_COPY_PACKET,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nfqnl_msg_config_params {
|
||||||
|
__be32 copy_range;
|
||||||
|
__u8 copy_mode; /* enum nfqnl_config_mode */
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
|
||||||
|
enum nfqnl_attr_config {
|
||||||
|
NFQA_CFG_UNSPEC,
|
||||||
|
NFQA_CFG_CMD, /* nfqnl_msg_config_cmd */
|
||||||
|
NFQA_CFG_PARAMS, /* nfqnl_msg_config_params */
|
||||||
|
NFQA_CFG_QUEUE_MAXLEN, /* __u32 */
|
||||||
|
NFQA_CFG_MASK, /* identify which flags to change */
|
||||||
|
NFQA_CFG_FLAGS, /* value of these flags (__u32) */
|
||||||
|
__NFQA_CFG_MAX
|
||||||
|
};
|
||||||
|
#define NFQA_CFG_MAX (__NFQA_CFG_MAX-1)
|
||||||
|
|
||||||
|
/* Flags for NFQA_CFG_FLAGS */
|
||||||
|
#define NFQA_CFG_F_FAIL_OPEN (1 << 0)
|
||||||
|
#define NFQA_CFG_F_CONNTRACK (1 << 1)
|
||||||
|
#define NFQA_CFG_F_GSO (1 << 2)
|
||||||
|
#define NFQA_CFG_F_UID_GID (1 << 3)
|
||||||
|
#define NFQA_CFG_F_SECCTX (1 << 4)
|
||||||
|
#define NFQA_CFG_F_MAX (1 << 5)
|
||||||
|
|
||||||
|
/* flags for NFQA_SKB_INFO */
|
||||||
|
/* packet appears to have wrong checksums, but they are ok */
|
||||||
|
#define NFQA_SKB_CSUMNOTREADY (1 << 0)
|
||||||
|
/* packet is GSO (i.e., exceeds device mtu) */
|
||||||
|
#define NFQA_SKB_GSO (1 << 1)
|
||||||
|
|
||||||
|
#endif /* _NFNETLINK_QUEUE_H */
|
||||||
16
deps/libnetfilter_queue/libnetfilter_queue.pc.in
vendored
Normal file
16
deps/libnetfilter_queue/libnetfilter_queue.pc.in
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# libnetfilter_queue pkg-config file
|
||||||
|
|
||||||
|
prefix=@prefix@
|
||||||
|
exec_prefix=@exec_prefix@
|
||||||
|
libdir=@libdir@
|
||||||
|
includedir=@includedir@
|
||||||
|
|
||||||
|
Name: libnetfilter_queue
|
||||||
|
Description: netfilter userspace packet queueing library
|
||||||
|
URL: http://netfilter.org/projects/libnetfilter_queue/
|
||||||
|
Version: @VERSION@
|
||||||
|
Requires: libnfnetlink
|
||||||
|
Conflicts:
|
||||||
|
Libs: -L${libdir} -lnetfilter_queue
|
||||||
|
Libs.private: @LIBNFNETLINK_LIBS@
|
||||||
|
Cflags: -I${includedir}
|
||||||
2
deps/libnetfilter_queue/m4/.gitignore
vendored
Normal file
2
deps/libnetfilter_queue/m4/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/libtool.m4
|
||||||
|
/lt*.m4
|
||||||
21
deps/libnetfilter_queue/m4/gcc4_visibility.m4
vendored
Normal file
21
deps/libnetfilter_queue/m4/gcc4_visibility.m4
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
# GCC 4.x -fvisibility=hidden
|
||||||
|
|
||||||
|
AC_DEFUN([CHECK_GCC_FVISIBILITY], [
|
||||||
|
AC_LANG_PUSH([C])
|
||||||
|
saved_CFLAGS="$CFLAGS"
|
||||||
|
CFLAGS="$saved_CFLAGS -fvisibility=hidden"
|
||||||
|
AC_CACHE_CHECK([whether compiler accepts -fvisibility=hidden],
|
||||||
|
[ac_cv_fvisibility_hidden], AC_COMPILE_IFELSE(
|
||||||
|
[AC_LANG_SOURCE()],
|
||||||
|
[ac_cv_fvisibility_hidden=yes],
|
||||||
|
[ac_cv_fvisibility_hidden=no]
|
||||||
|
))
|
||||||
|
if test "$ac_cv_fvisibility_hidden" = "yes"; then
|
||||||
|
AC_DEFINE([HAVE_VISIBILITY_HIDDEN], [1],
|
||||||
|
[True if compiler supports -fvisibility=hidden])
|
||||||
|
AC_SUBST([GCC_FVISIBILITY_HIDDEN], [-fvisibility=hidden])
|
||||||
|
fi
|
||||||
|
CFLAGS="$saved_CFLAGS"
|
||||||
|
AC_LANG_POP([C])
|
||||||
|
])
|
||||||
41
deps/libnetfilter_queue/src/Makefile.am
vendored
Normal file
41
deps/libnetfilter_queue/src/Makefile.am
vendored
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# This is _NOT_ the library release version, it's an API version.
|
||||||
|
# Extracted from Chapter 6 "Library interface versions" of the libtool docs.
|
||||||
|
#
|
||||||
|
# <snippet>
|
||||||
|
# Here are a set of rules to help you update your library version information:
|
||||||
|
#
|
||||||
|
# 1. Start with version information of `0:0:0' for each libtool library.
|
||||||
|
# 2. Update the version information only immediately before a public release
|
||||||
|
# of your software. More frequent updates are unnecessary, and only guarantee
|
||||||
|
# that the current interface number gets larger faster.
|
||||||
|
# 3. If the library source code has changed at all since the last update,
|
||||||
|
# then increment revision (`c:r:a' becomes `c:r+1:a').
|
||||||
|
# 4. If any interfaces have been added, removed, or changed since the last
|
||||||
|
# update, increment current, and set revision to 0.
|
||||||
|
# 5. If any interfaces have been added since the last public release, then
|
||||||
|
# increment age.
|
||||||
|
# 6. If any interfaces have been removed since the last public release, then
|
||||||
|
# set age to 0.
|
||||||
|
# </snippet>
|
||||||
|
#
|
||||||
|
LIBVERSION=6:0:5
|
||||||
|
|
||||||
|
include ${top_srcdir}/Make_global.am
|
||||||
|
|
||||||
|
lib_LTLIBRARIES = libnetfilter_queue.la
|
||||||
|
|
||||||
|
noinst_HEADERS = internal.h
|
||||||
|
|
||||||
|
libnetfilter_queue_la_LDFLAGS = -Wc,-nostartfiles \
|
||||||
|
-version-info $(LIBVERSION)
|
||||||
|
libnetfilter_queue_la_SOURCES = libnetfilter_queue.c \
|
||||||
|
nlmsg.c \
|
||||||
|
extra/checksum.c \
|
||||||
|
extra/icmp.c \
|
||||||
|
extra/ipv6.c \
|
||||||
|
extra/tcp.c \
|
||||||
|
extra/ipv4.c \
|
||||||
|
extra/pktbuff.c \
|
||||||
|
extra/udp.c
|
||||||
|
|
||||||
|
libnetfilter_queue_la_LIBADD = ${LIBNFNETLINK_LIBS} ${LIBMNL_LIBS}
|
||||||
83
deps/libnetfilter_queue/src/extra/checksum.c
vendored
Normal file
83
deps/libnetfilter_queue/src/extra/checksum.c
vendored
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This code has been sponsored by Vyatta Inc. <http://www.vyatta.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <endian.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <netinet/ip6.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
|
||||||
|
#include <linux/netfilter/nfnetlink_queue.h>
|
||||||
|
#include <libnetfilter_queue/libnetfilter_queue.h>
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
uint16_t nfq_checksum(uint32_t sum, uint16_t *buf, int size)
|
||||||
|
{
|
||||||
|
while (size > 1) {
|
||||||
|
sum += *buf++;
|
||||||
|
size -= sizeof(uint16_t);
|
||||||
|
}
|
||||||
|
if (size) {
|
||||||
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||||
|
sum += (uint16_t)*(uint8_t *)buf << 8;
|
||||||
|
#else
|
||||||
|
sum += (uint16_t)*(uint8_t *)buf;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
sum = (sum >> 16) + (sum & 0xffff);
|
||||||
|
sum += (sum >>16);
|
||||||
|
|
||||||
|
return (uint16_t)(~sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t nfq_checksum_tcpudp_ipv4(struct iphdr *iph, uint16_t protonum)
|
||||||
|
{
|
||||||
|
uint32_t sum = 0;
|
||||||
|
uint32_t iph_len = iph->ihl*4;
|
||||||
|
uint32_t len = ntohs(iph->tot_len) - iph_len;
|
||||||
|
uint8_t *payload = (uint8_t *)iph + iph_len;
|
||||||
|
|
||||||
|
sum += (iph->saddr >> 16) & 0xFFFF;
|
||||||
|
sum += (iph->saddr) & 0xFFFF;
|
||||||
|
sum += (iph->daddr >> 16) & 0xFFFF;
|
||||||
|
sum += (iph->daddr) & 0xFFFF;
|
||||||
|
sum += htons(protonum);
|
||||||
|
sum += htons(len);
|
||||||
|
|
||||||
|
return nfq_checksum(sum, (uint16_t *)payload, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t nfq_checksum_tcpudp_ipv6(struct ip6_hdr *ip6h, void *transport_hdr,
|
||||||
|
uint16_t protonum)
|
||||||
|
{
|
||||||
|
uint32_t sum = 0;
|
||||||
|
uint32_t hdr_len = (uint8_t *)transport_hdr - (uint8_t *)ip6h;
|
||||||
|
/* Allow for extra headers before the UDP header */
|
||||||
|
/* TODO: Deal with routing headers */
|
||||||
|
uint32_t len = ntohs(ip6h->ip6_plen) - (hdr_len - sizeof *ip6h);
|
||||||
|
uint8_t *payload = (uint8_t *)ip6h + hdr_len;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; i<8; i++) {
|
||||||
|
sum += (ip6h->ip6_src.s6_addr16[i]);
|
||||||
|
}
|
||||||
|
for (i=0; i<8; i++) {
|
||||||
|
sum += (ip6h->ip6_dst.s6_addr16[i]);
|
||||||
|
}
|
||||||
|
sum += htons(protonum);
|
||||||
|
sum += htons(len);
|
||||||
|
|
||||||
|
return nfq_checksum(sum, (uint16_t *)payload, len);
|
||||||
|
}
|
||||||
57
deps/libnetfilter_queue/src/extra/icmp.c
vendored
Normal file
57
deps/libnetfilter_queue/src/extra/icmp.c
vendored
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This code has been sponsored by Vyatta Inc. <http://www.vyatta.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <netinet/ip_icmp.h>
|
||||||
|
|
||||||
|
#include <libnetfilter_queue/libnetfilter_queue_icmp.h>
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup icmp ICMP helper functions
|
||||||
|
*
|
||||||
|
* \manonly
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.nf
|
||||||
|
\fB
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <libnetfilter_queue/libnetfilter_queue_icmp.h>
|
||||||
|
\endmanonly
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_icmp_get_hdr - get the ICMP header.
|
||||||
|
* \param pktb: pointer to user-space network packet buffer
|
||||||
|
* \returns validated pointer to the ICMP header or NULL if the ICMP header was
|
||||||
|
* not set or if a minimal length check fails.
|
||||||
|
* \note You have to call nfq_ip_set_transport_header() or
|
||||||
|
* nfq_ip6_set_transport_header() first to set the ICMP header.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
struct icmphdr *nfq_icmp_get_hdr(struct pkt_buff *pktb)
|
||||||
|
{
|
||||||
|
if (pktb->transport_header == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* No room for the ICMP header. */
|
||||||
|
if (pktb_tail(pktb) - pktb->transport_header < sizeof(struct icmphdr))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return (struct icmphdr *)pktb->transport_header;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
194
deps/libnetfilter_queue/src/extra/ipv4.c
vendored
Normal file
194
deps/libnetfilter_queue/src/extra/ipv4.c
vendored
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
/*
|
||||||
|
* (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This code has been sponsored by Vyatta Inc. <http://www.vyatta.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
|
||||||
|
#include <linux/netfilter/nfnetlink_queue.h>
|
||||||
|
#include <libnetfilter_queue/libnetfilter_queue.h>
|
||||||
|
#include <libnetfilter_queue/libnetfilter_queue_ipv4.h>
|
||||||
|
#include <libnetfilter_queue/pktbuff.h>
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup ipv4 IPv4 helper functions
|
||||||
|
*
|
||||||
|
* \manonly
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.nf
|
||||||
|
\fB
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <libnetfilter_queue/libnetfilter_queue_ipv4.h>
|
||||||
|
\endmanonly
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_ip_get_hdr - get the IPv4 header
|
||||||
|
* \param pktb: Pointer to user-space network packet buffer
|
||||||
|
* \returns validated pointer to the IPv4 header or NULL if IP is malformed or
|
||||||
|
* not version 4
|
||||||
|
*
|
||||||
|
* Many programs will not need to call this function. A possible use is to
|
||||||
|
* determine the layer 4 protocol. The validation is that the buffer is big
|
||||||
|
* enough for the declared lengths in the header, i.e. an extra check for packet
|
||||||
|
* truncation.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
struct iphdr *nfq_ip_get_hdr(struct pkt_buff *pktb)
|
||||||
|
{
|
||||||
|
struct iphdr *iph;
|
||||||
|
unsigned int pktlen = pktb_tail(pktb) - pktb->network_header;
|
||||||
|
|
||||||
|
/* Not enough room for IPv4 header. */
|
||||||
|
if (pktlen < sizeof(struct iphdr))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
iph = (struct iphdr *)pktb->network_header;
|
||||||
|
|
||||||
|
/* Not IPv4 packet. */
|
||||||
|
if (iph->version != 4)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Malformed IPv4 total length field. */
|
||||||
|
if (ntohs(iph->tot_len) > pktlen)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return iph;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_ip_set_transport_header - set the \b transport_header field in \b pktb
|
||||||
|
* \param pktb: Pointer to user-space network packet buffer
|
||||||
|
* \param iph: Pointer to the IPv4 header
|
||||||
|
* \returns 0 on success or -1 if a minimal validation check fails
|
||||||
|
* \note
|
||||||
|
* Most programs should call __nfq_ip_set_transport_header__ as soon as
|
||||||
|
* possible, since most layer 4 helper functions assume the
|
||||||
|
* \b transport_header field is valid.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
int nfq_ip_set_transport_header(struct pkt_buff *pktb, struct iphdr *iph)
|
||||||
|
{
|
||||||
|
int doff = iph->ihl * 4;
|
||||||
|
|
||||||
|
/* Wrong offset to IPv4 payload. */
|
||||||
|
if ((int)pktb->len - doff <= 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
pktb->transport_header = pktb->network_header + doff;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup ip_internals Internal IP functions
|
||||||
|
*
|
||||||
|
* Most user-space programs will never need these.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* \manonly
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.nf
|
||||||
|
\fB
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <libnetfilter_queue/libnetfilter_queue_ipv4.h>
|
||||||
|
\endmanonly
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_ip_set_checksum - set IPv4 checksum
|
||||||
|
* \param iph: Pointer to the IPv4 header
|
||||||
|
* \note
|
||||||
|
* nfq_ip_mangle() invokes this function.
|
||||||
|
* As long as developers always use the appropriate mangler for the layer being
|
||||||
|
* mangled, there is no need to call __nfq_ip_set_checksum__.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
void nfq_ip_set_checksum(struct iphdr *iph)
|
||||||
|
{
|
||||||
|
uint32_t iph_len = iph->ihl * 4;
|
||||||
|
|
||||||
|
iph->check = 0;
|
||||||
|
iph->check = nfq_checksum(0, (uint16_t *)iph, iph_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_ip_mangle - mangle IPv4 packet buffer
|
||||||
|
* \param pktb: Pointer to user-space network packet buffer
|
||||||
|
* \param dataoff: Offset to layer 4 header, or zero to mangle IP header
|
||||||
|
* \param match_offset: Offset to content that you want to mangle
|
||||||
|
* \param match_len: Length of the existing content you want to mangle
|
||||||
|
* \param rep_buffer: Pointer to data you want to use to replace current content
|
||||||
|
* \param rep_len: Length of data you want to use to replace current content
|
||||||
|
* \returns 1 for success and 0 for failure. See pktb_mangle() for failure case
|
||||||
|
* \note This function updates the IPv4 length if necessary and recalculates the
|
||||||
|
* IPv4 checksum.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
int nfq_ip_mangle(struct pkt_buff *pktb, unsigned int dataoff,
|
||||||
|
unsigned int match_offset, unsigned int match_len,
|
||||||
|
const char *rep_buffer, unsigned int rep_len)
|
||||||
|
{
|
||||||
|
struct iphdr *iph = (struct iphdr *) pktb->network_header;
|
||||||
|
|
||||||
|
if (!pktb_mangle(pktb, dataoff, match_offset, match_len, rep_buffer,
|
||||||
|
rep_len))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* fix IP hdr checksum information */
|
||||||
|
iph->tot_len = htons(pktb_tail(pktb) - pktb->network_header);
|
||||||
|
nfq_ip_set_checksum(iph);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_ip_snprintf - print IPv4 header into buffer in iptables LOG format
|
||||||
|
* \param buf: Pointer to buffer that will be used to print the header
|
||||||
|
* \param size: Size of the buffer (or remaining room in it)
|
||||||
|
* \param iph: Pointer to a valid IPv4 header
|
||||||
|
* \returns same as snprintf
|
||||||
|
* \sa **snprintf**(3)
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
int nfq_ip_snprintf(char *buf, size_t size, const struct iphdr *iph)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct in_addr src = { iph->saddr };
|
||||||
|
struct in_addr dst = { iph->daddr };
|
||||||
|
|
||||||
|
char src_str[INET_ADDRSTRLEN];
|
||||||
|
char dst_str[INET_ADDRSTRLEN];
|
||||||
|
|
||||||
|
ret = snprintf(buf, size, "SRC=%s DST=%s LEN=%u TOS=0x%X "
|
||||||
|
"PREC=0x%X TTL=%u ID=%u PROTO=%u ",
|
||||||
|
inet_ntop(AF_INET, &src, src_str, INET_ADDRSTRLEN),
|
||||||
|
inet_ntop(AF_INET, &dst, dst_str, INET_ADDRSTRLEN),
|
||||||
|
ntohs(iph->tot_len), IPTOS_TOS(iph->tos),
|
||||||
|
IPTOS_PREC(iph->tos), iph->ttl, ntohs(iph->id),
|
||||||
|
iph->protocol);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
203
deps/libnetfilter_queue/src/extra/ipv6.c
vendored
Normal file
203
deps/libnetfilter_queue/src/extra/ipv6.c
vendored
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
/*
|
||||||
|
* (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This code has been sponsored by Vyatta Inc. <http://www.vyatta.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/ip6.h>
|
||||||
|
|
||||||
|
#include <linux/netfilter/nfnetlink_queue.h>
|
||||||
|
#include <libnetfilter_queue/libnetfilter_queue.h>
|
||||||
|
#include <libnetfilter_queue/libnetfilter_queue_ipv6.h>
|
||||||
|
#include <libnetfilter_queue/pktbuff.h>
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup ipv6 IPv6 helper functions
|
||||||
|
*
|
||||||
|
* \manonly
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.nf
|
||||||
|
\fB
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <linux/netfilter/nfnetlink_queue.h>
|
||||||
|
#include <libnetfilter_queue/libnetfilter_queue.h>
|
||||||
|
#include <libnetfilter_queue/libnetfilter_queue_ipv6.h>
|
||||||
|
\endmanonly
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_ip6_get_hdr - get IPv6 header
|
||||||
|
* \param pktb: Pointer to user-space network packet buffer
|
||||||
|
*
|
||||||
|
* \returns pointer to IPv6 header if a valid header found, else NULL.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
struct ip6_hdr *nfq_ip6_get_hdr(struct pkt_buff *pktb)
|
||||||
|
{
|
||||||
|
struct ip6_hdr *ip6h;
|
||||||
|
unsigned int pktlen = pktb_tail(pktb) - pktb->network_header;
|
||||||
|
|
||||||
|
/* Not enough room for IPv6 header. */
|
||||||
|
if (pktlen < sizeof(struct ip6_hdr))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ip6h = (struct ip6_hdr *)pktb->network_header;
|
||||||
|
|
||||||
|
/* Not IPv6 packet. */
|
||||||
|
if ((*(uint8_t *)ip6h & 0xf0) != 0x60)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return ip6h;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_ip6_set_transport_header - set transport header pointer for IPv6 packet
|
||||||
|
* \param pktb: Pointer to user-space network packet buffer
|
||||||
|
* \param ip6h: Pointer to IPv6 header
|
||||||
|
* \param target: Protocol number to find transport header (ie. IPPROTO_*)
|
||||||
|
*
|
||||||
|
* \returns 1 if the protocol has been found and the transport
|
||||||
|
* header has been set, else 0.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
int nfq_ip6_set_transport_header(struct pkt_buff *pktb, struct ip6_hdr *ip6h,
|
||||||
|
uint8_t target)
|
||||||
|
{
|
||||||
|
uint8_t nexthdr = ip6h->ip6_nxt;
|
||||||
|
uint8_t *cur = (uint8_t *)ip6h + sizeof(struct ip6_hdr);
|
||||||
|
|
||||||
|
while (nexthdr == IPPROTO_HOPOPTS ||
|
||||||
|
nexthdr == IPPROTO_ROUTING ||
|
||||||
|
nexthdr == IPPROTO_FRAGMENT ||
|
||||||
|
nexthdr == IPPROTO_AH ||
|
||||||
|
nexthdr == IPPROTO_NONE ||
|
||||||
|
nexthdr == IPPROTO_DSTOPTS) {
|
||||||
|
struct ip6_ext *ip6_ext;
|
||||||
|
uint32_t hdrlen;
|
||||||
|
|
||||||
|
/* Extension header was requested, we're done. */
|
||||||
|
if (nexthdr == target)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* No more extensions, we're done. */
|
||||||
|
if (nexthdr == IPPROTO_NONE) {
|
||||||
|
cur = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* No room for extension, bad packet. */
|
||||||
|
if (pktb_tail(pktb) - cur < sizeof(struct ip6_ext)) {
|
||||||
|
cur = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ip6_ext = (struct ip6_ext *)cur;
|
||||||
|
|
||||||
|
if (nexthdr == IPPROTO_FRAGMENT) {
|
||||||
|
uint16_t *frag_off;
|
||||||
|
|
||||||
|
/* No room for full fragment header, bad packet. */
|
||||||
|
if (pktb_tail(pktb) - cur < sizeof(struct ip6_frag)) {
|
||||||
|
cur = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
frag_off = (uint16_t *)(cur +
|
||||||
|
offsetof(struct ip6_frag, ip6f_offlg));
|
||||||
|
|
||||||
|
/* Fragment offset is only 13 bits long. */
|
||||||
|
if (htons(*frag_off) & ~0x7) {
|
||||||
|
/* Not the first fragment, it does not contain
|
||||||
|
* any headers.
|
||||||
|
*/
|
||||||
|
cur = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
hdrlen = sizeof(struct ip6_frag);
|
||||||
|
} else if (nexthdr == IPPROTO_AH)
|
||||||
|
hdrlen = (ip6_ext->ip6e_len + 2) << 2;
|
||||||
|
else
|
||||||
|
hdrlen = (ip6_ext->ip6e_len + 1) << 3;
|
||||||
|
|
||||||
|
nexthdr = ip6_ext->ip6e_nxt;
|
||||||
|
cur += hdrlen;
|
||||||
|
}
|
||||||
|
if (nexthdr != target)
|
||||||
|
cur = NULL;
|
||||||
|
pktb->transport_header = cur;
|
||||||
|
return cur ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_ip6_mangle - mangle IPv6 packet buffer
|
||||||
|
* \param pktb: Pointer to user-space network packet buffer
|
||||||
|
* \param dataoff: Offset to layer 4 header
|
||||||
|
* \param match_offset: Offset to content that you want to mangle
|
||||||
|
* \param match_len: Length of the existing content you want to mangle
|
||||||
|
* \param rep_buffer: Pointer to data you want to use to replace current content
|
||||||
|
* \param rep_len: Length of data you want to use to replace current content
|
||||||
|
* \returns 1 for success and 0 for failure. See pktb_mangle() for failure case
|
||||||
|
* \note This function updates the IPv6 length (if necessary)
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
int nfq_ip6_mangle(struct pkt_buff *pktb, unsigned int dataoff,
|
||||||
|
unsigned int match_offset, unsigned int match_len,
|
||||||
|
const char *rep_buffer, unsigned int rep_len)
|
||||||
|
{
|
||||||
|
struct ip6_hdr *ip6h = (struct ip6_hdr *)pktb->network_header;
|
||||||
|
|
||||||
|
if (!pktb_mangle(pktb, dataoff, match_offset, match_len, rep_buffer,
|
||||||
|
rep_len))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Fix IPv6 hdr length information */
|
||||||
|
ip6h->ip6_plen =
|
||||||
|
htons(pktb_tail(pktb) - pktb->network_header - sizeof *ip6h);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_ip6_snprintf - print IPv6 header into one buffer in iptables LOG format
|
||||||
|
* \param buf: Pointer to buffer that is used to print the object
|
||||||
|
* \param size: Size of the buffer (or remaining room in it).
|
||||||
|
* \param ip6h: Pointer to a valid IPv6 header.
|
||||||
|
* \returns same as snprintf
|
||||||
|
* \sa **snprintf**(3)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
int nfq_ip6_snprintf(char *buf, size_t size, const struct ip6_hdr *ip6h)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char src[INET6_ADDRSTRLEN];
|
||||||
|
char dst[INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
|
inet_ntop(AF_INET6, &ip6h->ip6_src, src, INET6_ADDRSTRLEN);
|
||||||
|
inet_ntop(AF_INET6, &ip6h->ip6_dst, dst, INET6_ADDRSTRLEN);
|
||||||
|
|
||||||
|
ret = snprintf(buf, size, "SRC=%s DST=%s LEN=%zu TC=0x%X "
|
||||||
|
"HOPLIMIT=%u FLOWLBL=%u ",
|
||||||
|
src, dst,
|
||||||
|
ntohs(ip6h->ip6_plen) + sizeof(struct ip6_hdr),
|
||||||
|
(ip6h->ip6_flow & 0x0ff00000) >> 20,
|
||||||
|
ip6h->ip6_hlim,
|
||||||
|
(ip6h->ip6_flow & 0x000fffff));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
455
deps/libnetfilter_queue/src/extra/pktbuff.c
vendored
Normal file
455
deps/libnetfilter_queue/src/extra/pktbuff.c
vendored
Normal file
@@ -0,0 +1,455 @@
|
|||||||
|
/*
|
||||||
|
* (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This code has been sponsored by Vyatta Inc. <http://www.vyatta.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h> /* for memcpy */
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <netinet/if_ether.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup pktbuff User-space network packet buffer
|
||||||
|
*
|
||||||
|
* These functions provide the user-space network packet buffer.
|
||||||
|
* This abstraction is strongly inspired by Linux kernel network buffer,
|
||||||
|
* the so-called sk_buff.
|
||||||
|
*
|
||||||
|
* \manonly
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.nf
|
||||||
|
\fB
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <libnetfilter_queue/pktbuff.h>
|
||||||
|
\endmanonly
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int __pktb_setup(int family, struct pkt_buff *pktb)
|
||||||
|
{
|
||||||
|
struct ethhdr *ethhdr;
|
||||||
|
|
||||||
|
switch (family) {
|
||||||
|
case AF_INET:
|
||||||
|
case AF_INET6:
|
||||||
|
pktb->network_header = pktb->data;
|
||||||
|
break;
|
||||||
|
case AF_BRIDGE:
|
||||||
|
ethhdr = (struct ethhdr *)pktb->data;
|
||||||
|
pktb->mac_header = pktb->data;
|
||||||
|
|
||||||
|
switch(ethhdr->h_proto) {
|
||||||
|
case ETH_P_IP:
|
||||||
|
case ETH_P_IPV6:
|
||||||
|
pktb->network_header = pktb->data + ETH_HLEN;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* This protocol is unsupported. */
|
||||||
|
errno = EPROTONOSUPPORT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pktb_setup_metadata(struct pkt_buff *pktb, void *pkt_data,
|
||||||
|
size_t len, size_t extra)
|
||||||
|
{
|
||||||
|
pktb->len = len;
|
||||||
|
pktb->data_len = len + extra;
|
||||||
|
pktb->data = pkt_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pktb_alloc - allocate a new packet buffer
|
||||||
|
* \param family Indicate what family. Currently supported families are
|
||||||
|
* AF_BRIDGE, AF_INET & AF_INET6.
|
||||||
|
* \param data Pointer to packet data
|
||||||
|
* \param len Packet length
|
||||||
|
* \param extra Extra memory in the tail to be allocated (for mangling)
|
||||||
|
*
|
||||||
|
* This function returns a packet buffer that contains the packet data and
|
||||||
|
* some extra memory room in the tail (if requested). This function copies
|
||||||
|
* the memory area provided as a pointer to packet data into the packet buffer
|
||||||
|
* structure.
|
||||||
|
*
|
||||||
|
* The extra length provides extra packet data room at the tail of the packet
|
||||||
|
* buffer in case you need to mangle it.
|
||||||
|
*
|
||||||
|
* \return Pointer to a new userspace packet buffer or NULL on failure.
|
||||||
|
* \par Errors
|
||||||
|
* __ENOMEM__ From __calloc__()
|
||||||
|
* \n
|
||||||
|
* __EPROTONOSUPPORT__ _family_ was __AF_BRIDGE__ and this is not an IP packet
|
||||||
|
* (v4 or v6)
|
||||||
|
* \sa __calloc__(3)
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
struct pkt_buff *pktb_alloc(int family, void *data, size_t len, size_t extra)
|
||||||
|
{
|
||||||
|
struct pkt_buff *pktb;
|
||||||
|
void *pkt_data;
|
||||||
|
|
||||||
|
pktb = calloc(1, sizeof(struct pkt_buff) + len + extra);
|
||||||
|
if (pktb == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Better make sure alignment is correct. */
|
||||||
|
pkt_data = (uint8_t *)pktb + sizeof(struct pkt_buff);
|
||||||
|
memcpy(pkt_data, data, len);
|
||||||
|
|
||||||
|
pktb_setup_metadata(pktb, pkt_data, len, extra);
|
||||||
|
|
||||||
|
if (__pktb_setup(family, pktb) < 0) {
|
||||||
|
free(pktb);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pktb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pktb_setup_raw - set up a packet buffer from memory area
|
||||||
|
* \param pktb Pointer to memory of length pktb_head_size() bytes
|
||||||
|
* \param family Supported families are AF_BRIDGE, AF_INET & AF_INET6.
|
||||||
|
* \param data Pointer to packet data
|
||||||
|
* \param len Packet data length
|
||||||
|
* \param extra Extra memory available after packet data (for mangling).
|
||||||
|
*
|
||||||
|
* Use this function to set up a packet buffer from a memory area, minimum size
|
||||||
|
* of such memory area must be pktb_head_size(). This function attaches the
|
||||||
|
* packet data that is provided to the packet buffer (data is not copied). Use
|
||||||
|
* this function as an alternative to the pktb_alloc() interface for more
|
||||||
|
* control on memory management.
|
||||||
|
*
|
||||||
|
* \return Pointer to a new userspace packet buffer or NULL on failure.
|
||||||
|
* \par Errors
|
||||||
|
* __EPROTONOSUPPORT__ _family_ was __AF_BRIDGE__ and this is not an IP packet
|
||||||
|
* (v4 or v6)
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
struct pkt_buff *pktb_setup_raw(void *pktb, int family, void *data,
|
||||||
|
size_t len, size_t extra)
|
||||||
|
{
|
||||||
|
memset(pktb, 0, sizeof (struct pkt_buff));
|
||||||
|
pktb_setup_metadata(pktb, data, len, extra);
|
||||||
|
if (__pktb_setup(family, pktb) < 0)
|
||||||
|
pktb = NULL;
|
||||||
|
|
||||||
|
return pktb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pktb_data - get pointer to network packet
|
||||||
|
* \param pktb Pointer to userspace packet buffer
|
||||||
|
* \return Pointer to start of network packet data within __pktb__
|
||||||
|
* \par
|
||||||
|
* It is appropriate to use _pktb_data_ as the second argument of
|
||||||
|
* nfq_nlmsg_verdict_put_pkt()
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
uint8_t *pktb_data(struct pkt_buff *pktb)
|
||||||
|
{
|
||||||
|
return pktb->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pktb_len - get length of packet buffer
|
||||||
|
* \param pktb Pointer to userspace packet buffer
|
||||||
|
* \return Length of packet contained within __pktb__
|
||||||
|
* \par
|
||||||
|
* It is appropriate to use _pktb_len_ as the third argument of
|
||||||
|
* nfq_nlmsg_verdict_put_pkt()
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
uint32_t pktb_len(struct pkt_buff *pktb)
|
||||||
|
{
|
||||||
|
return pktb->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pktb_free - release packet buffer
|
||||||
|
* \param pktb Pointer to userspace packet buffer
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
void pktb_free(struct pkt_buff *pktb)
|
||||||
|
{
|
||||||
|
free(pktb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup otherfns Other functions
|
||||||
|
*
|
||||||
|
* The library provides a number of other functions which many user-space
|
||||||
|
* programs will never need. These divide into 2 groups:
|
||||||
|
* \n
|
||||||
|
* 1. Functions to get values of members of opaque __struct pktbuff__, described
|
||||||
|
* below
|
||||||
|
*
|
||||||
|
* 2. Internal functions, described in Module __Internal functions__
|
||||||
|
*
|
||||||
|
* \manonly
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.nf
|
||||||
|
\fB
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <libnetfilter_queue/pktbuff.h>
|
||||||
|
\endmanonly
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup do_not_use Internal functions
|
||||||
|
*
|
||||||
|
* Do not use these functions. Instead, always use the mangle
|
||||||
|
* function appropriate to the level at which you are working.
|
||||||
|
* \n
|
||||||
|
* pktb_mangle() uses all the below functions except _pktb_pull_, which is not
|
||||||
|
* used by anything.
|
||||||
|
*
|
||||||
|
* \manonly
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.nf
|
||||||
|
\fB
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <libnetfilter_queue/pktbuff.h>
|
||||||
|
\endmanonly
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pktb_push - decrement pointer to packet buffer
|
||||||
|
* \param pktb Pointer to userspace packet buffer
|
||||||
|
* \param len Number of bytes to subtract from packet start address
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
void pktb_push(struct pkt_buff *pktb, unsigned int len)
|
||||||
|
{
|
||||||
|
pktb->data -= len;
|
||||||
|
pktb->len += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pktb_pull - increment pointer to packet buffer
|
||||||
|
* \param pktb Pointer to userspace packet buffer
|
||||||
|
* \param len Number of bytes to add to packet start address
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
void pktb_pull(struct pkt_buff *pktb, unsigned int len)
|
||||||
|
{
|
||||||
|
pktb->data += len;
|
||||||
|
pktb->len -= len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pktb_put - add extra bytes to the tail of the packet buffer
|
||||||
|
* \param pktb Pointer to userspace packet buffer
|
||||||
|
* \param len Number of bytes to add to packet tail (and length)
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
void pktb_put(struct pkt_buff *pktb, unsigned int len)
|
||||||
|
{
|
||||||
|
pktb->len += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pktb_trim - set new length for this packet buffer
|
||||||
|
* \param pktb Pointer to userspace packet buffer
|
||||||
|
* \param len New packet length (tail is adjusted to reflect this)
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
void pktb_trim(struct pkt_buff *pktb, unsigned int len)
|
||||||
|
{
|
||||||
|
pktb->len = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pktb_tailroom - get room available for packet expansion
|
||||||
|
* \param pktb Pointer to userspace packet buffer
|
||||||
|
* \return room in bytes after the tail of the packet buffer
|
||||||
|
* \n
|
||||||
|
* This starts off as the __extra__ argument to pktb_alloc().
|
||||||
|
* Programmers should ensure this __extra__ argument is sufficient for any
|
||||||
|
* packet mangle, as packet buffers cannot be expanded dynamically.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
unsigned int pktb_tailroom(struct pkt_buff *pktb)
|
||||||
|
{
|
||||||
|
return pktb->data_len - pktb->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pktb_mac_header - get address of layer 2 header (if any)
|
||||||
|
* \param pktb Pointer to userspace packet buffer
|
||||||
|
* \return Pointer to MAC header or NULL if no such header present.
|
||||||
|
* \n
|
||||||
|
* Only packet buffers in family __AF_BRIDGE__ have a non-NULL MAC header.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
uint8_t *pktb_mac_header(struct pkt_buff *pktb)
|
||||||
|
{
|
||||||
|
return pktb->mac_header;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pktb_network_header - get address of layer 3 header
|
||||||
|
* \param pktb Pointer to userspace packet buffer
|
||||||
|
* \return Pointer to layer 3 header or NULL if the packet buffer was created
|
||||||
|
* with an unsupported family
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
uint8_t *pktb_network_header(struct pkt_buff *pktb)
|
||||||
|
{
|
||||||
|
return pktb->network_header;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pktb_transport_header - get address of layer 4 header (if known)
|
||||||
|
* \param pktb Pointer to userspace packet buffer
|
||||||
|
* \return Pointer to layer 4 header or NULL if not (yet) set
|
||||||
|
* \note
|
||||||
|
* Unlike the lower-level headers, it is the programmer's responsibility to
|
||||||
|
* create the level 4 (transport) header pointer by caling e.g.
|
||||||
|
* nfq_ip_set_transport_header()
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
uint8_t *pktb_transport_header(struct pkt_buff *pktb)
|
||||||
|
{
|
||||||
|
return pktb->transport_header;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int pktb_expand_tail(struct pkt_buff *pktb, int extra)
|
||||||
|
{
|
||||||
|
/* No room in packet, cannot mangle it. We don't support dynamic
|
||||||
|
* reallocation. Instead, increase the size of the extra room in
|
||||||
|
* the tail in pktb_alloc.
|
||||||
|
*/
|
||||||
|
if (pktb->len + extra > pktb->data_len)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
pktb->len += extra;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int enlarge_pkt(struct pkt_buff *pktb, unsigned int extra)
|
||||||
|
{
|
||||||
|
if (pktb->len + extra > 65535)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!pktb_expand_tail(pktb, extra - pktb_tailroom(pktb)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pktb_mangle - adjust contents of a packet
|
||||||
|
* \param pktb Pointer to userspace packet buffer
|
||||||
|
* \param dataoff Supplementary offset, usually offset from layer 3 (IP) header
|
||||||
|
* to the layer 4 (TCP or UDP) header. Specify zero to access the layer 3
|
||||||
|
* header. If \b pktb was created in family \b AF_BRIDGE, specify
|
||||||
|
* \b -ETH_HLEN (a negative offset) to access the layer 2 (MAC) header.
|
||||||
|
* \param match_offset Further offset to content that you want to mangle
|
||||||
|
* \param match_len Length of the existing content you want to mangle
|
||||||
|
* \param rep_buffer Pointer to data you want to use to replace current content
|
||||||
|
* \param rep_len Length of data you want to use to replace current content
|
||||||
|
* \returns 1 for success and 0 for failure. Failure will occur if the \b extra
|
||||||
|
* argument to the pktb_alloc() call that created \b pktb is less than the
|
||||||
|
* excess of \b rep_len over \b match_len
|
||||||
|
\warning pktb_mangle does not update any checksums. Developers should use the
|
||||||
|
appropriate mangler for the protocol level: nfq_ip_mangle(),
|
||||||
|
nfq_tcp_mangle_ipv4(), nfq_udp_mangle_ipv4() or IPv6 variants.
|
||||||
|
\n
|
||||||
|
It is appropriate to use pktb_mangle to change the MAC header.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
int pktb_mangle(struct pkt_buff *pktb,
|
||||||
|
int dataoff,
|
||||||
|
unsigned int match_offset,
|
||||||
|
unsigned int match_len,
|
||||||
|
const char *rep_buffer,
|
||||||
|
unsigned int rep_len)
|
||||||
|
{
|
||||||
|
unsigned char *data;
|
||||||
|
|
||||||
|
if (rep_len > match_len &&
|
||||||
|
rep_len - match_len > pktb_tailroom(pktb) &&
|
||||||
|
!enlarge_pkt(pktb, rep_len - match_len))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
data = pktb->network_header + dataoff;
|
||||||
|
|
||||||
|
/* move post-replacement */
|
||||||
|
memmove(data + match_offset + rep_len,
|
||||||
|
data + match_offset + match_len,
|
||||||
|
pktb_tail(pktb) - (pktb->network_header + dataoff +
|
||||||
|
match_offset + match_len));
|
||||||
|
|
||||||
|
/* insert data from buffer */
|
||||||
|
memcpy(data + match_offset, rep_buffer, rep_len);
|
||||||
|
|
||||||
|
/* update packet info */
|
||||||
|
if (rep_len > match_len)
|
||||||
|
pktb_put(pktb, rep_len - match_len);
|
||||||
|
else
|
||||||
|
pktb_trim(pktb, pktb->len + rep_len - match_len);
|
||||||
|
|
||||||
|
pktb->mangled = true;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pktb_mangled - test whether packet has been mangled
|
||||||
|
* \param pktb Pointer to userspace packet buffer
|
||||||
|
* \return __true__ if packet has been mangled (modified), else __false__
|
||||||
|
* \par
|
||||||
|
* When assembling a verdict, it is not necessary to return the contents of
|
||||||
|
* un-modified packets. Use _pktb_mangled_ to decide whether packet contents
|
||||||
|
* need to be returned.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
bool pktb_mangled(const struct pkt_buff *pktb)
|
||||||
|
{
|
||||||
|
return pktb->mangled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pktb_head_size - get number of bytes needed for a packet buffer
|
||||||
|
* (control part only)
|
||||||
|
* \return size of struct pkt_buff
|
||||||
|
*/
|
||||||
|
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
size_t pktb_head_size(void)
|
||||||
|
{
|
||||||
|
return sizeof(struct pkt_buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
300
deps/libnetfilter_queue/src/extra/tcp.c
vendored
Normal file
300
deps/libnetfilter_queue/src/extra/tcp.c
vendored
Normal file
@@ -0,0 +1,300 @@
|
|||||||
|
/*
|
||||||
|
* (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This code has been sponsored by Vyatta Inc. <http://www.vyatta.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h> /* for memcpy */
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <netinet/ip6.h>
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
|
||||||
|
#include <linux/netfilter/nfnetlink_queue.h>
|
||||||
|
#include <libnetfilter_queue/libnetfilter_queue.h>
|
||||||
|
#include <libnetfilter_queue/libnetfilter_queue_tcp.h>
|
||||||
|
#include <libnetfilter_queue/libnetfilter_queue_ipv4.h>
|
||||||
|
#include <libnetfilter_queue/libnetfilter_queue_ipv6.h>
|
||||||
|
#include <libnetfilter_queue/pktbuff.h>
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup tcp TCP helper functions
|
||||||
|
*
|
||||||
|
* \manonly
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.nf
|
||||||
|
\fB
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <libnetfilter_queue/libnetfilter_queue_tcp.h>
|
||||||
|
\endmanonly
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_tcp_get_hdr - get the TCP header
|
||||||
|
* \param pktb: pointer to user-space network packet buffer
|
||||||
|
* \returns validated pointer to the TCP header or NULL if the TCP header was
|
||||||
|
* not set or if a minimal length check fails.
|
||||||
|
* \note You have to call nfq_ip_set_transport_header() or
|
||||||
|
* nfq_ip6_set_transport_header() first to set the TCP header.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
struct tcphdr *nfq_tcp_get_hdr(struct pkt_buff *pktb)
|
||||||
|
{
|
||||||
|
if (pktb->transport_header == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* No room for the TCP header. */
|
||||||
|
if (pktb_tail(pktb) - pktb->transport_header < sizeof(struct tcphdr))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return (struct tcphdr *)pktb->transport_header;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_tcp_get_payload - get the TCP packet payload
|
||||||
|
* \param tcph: pointer to the TCP header
|
||||||
|
* \param pktb: pointer to user-space network packet buffer
|
||||||
|
* \returns Pointer to the TCP payload, or NULL if malformed TCP packet.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
void *nfq_tcp_get_payload(struct tcphdr *tcph, struct pkt_buff *pktb)
|
||||||
|
{
|
||||||
|
unsigned int len = tcph->doff * 4;
|
||||||
|
|
||||||
|
/* TCP packet is too short */
|
||||||
|
if (len < sizeof(struct tcphdr))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* malformed TCP data offset. */
|
||||||
|
if (pktb->transport_header + len > pktb_tail(pktb))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return pktb->transport_header + len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_tcp_get_payload_len - get the tcp packet payload
|
||||||
|
* \param tcph: pointer to the TCP header
|
||||||
|
* \param pktb: pointer to user-space network packet buffer
|
||||||
|
* \returns Length of TCP payload (user data)
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
unsigned int nfq_tcp_get_payload_len(struct tcphdr *tcph, struct pkt_buff *pktb)
|
||||||
|
{
|
||||||
|
return pktb_tail(pktb) - pktb->transport_header - (tcph->doff * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup tcp_internals Internal TCP functions
|
||||||
|
*
|
||||||
|
* Most user-space programs will never need these.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* \manonly
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.nf
|
||||||
|
\fB
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <netinet/ip6.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
#include <libnetfilter_queue/libnetfilter_queue_tcp.h>
|
||||||
|
\endmanonly
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_tcp_compute_checksum_ipv4 - computes IPv4/TCP packet checksum
|
||||||
|
* \param tcph: pointer to the TCP header
|
||||||
|
* \param iph: pointer to the IPv4 header
|
||||||
|
* \note
|
||||||
|
* nfq_tcp_mangle_ipv4() invokes this function.
|
||||||
|
* As long as developers always use __nfq_tcp_mangle_ipv4__ when changing the
|
||||||
|
* content of a TCP message, there is no need to call
|
||||||
|
* __nfq_tcp_compute_checksum_ipv4__.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
void nfq_tcp_compute_checksum_ipv4(struct tcphdr *tcph, struct iphdr *iph)
|
||||||
|
{
|
||||||
|
/* checksum field in header needs to be zero for calculation. */
|
||||||
|
tcph->check = 0;
|
||||||
|
tcph->check = nfq_checksum_tcpudp_ipv4(iph, IPPROTO_TCP);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_tcp_compute_checksum_ipv6 - computes IPv6/TCP packet checksum
|
||||||
|
* \param tcph: pointer to the TCP header
|
||||||
|
* \param ip6h: pointer to the IPv6 header
|
||||||
|
* \note
|
||||||
|
* nfq_tcp_mangle_ipv6() invokes this function.
|
||||||
|
* As long as developers always use __nfq_tcp_mangle_ipv6__ when changing the
|
||||||
|
* content of a TCP message, there is no need to call
|
||||||
|
* __nfq_tcp_compute_checksum_ipv6__.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
void nfq_tcp_compute_checksum_ipv6(struct tcphdr *tcph, struct ip6_hdr *ip6h)
|
||||||
|
{
|
||||||
|
/* checksum field in header needs to be zero for calculation. */
|
||||||
|
tcph->check = 0;
|
||||||
|
tcph->check = nfq_checksum_tcpudp_ipv6(ip6h, tcph, IPPROTO_TCP);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The union cast uses a gcc extension to avoid aliasing problems
|
||||||
|
* (union is compatible to any of its members)
|
||||||
|
* This means this part of the code is -fstrict-aliasing safe now.
|
||||||
|
*/
|
||||||
|
union tcp_word_hdr {
|
||||||
|
struct tcphdr hdr;
|
||||||
|
uint32_t words[5];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define tcp_flag_word(tp) ( ((union tcp_word_hdr *)(tp))->words[3])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_pkt_snprintf_tcp_hdr - print tcp header into one buffer in a humnan
|
||||||
|
* readable way
|
||||||
|
* \param buf: pointer to buffer that is used to print the object
|
||||||
|
* \param size: size of the buffer (or remaining room in it).
|
||||||
|
* \param tcph: pointer to a valid tcp header.
|
||||||
|
* \returns Same as \b snprintf
|
||||||
|
* \sa __snprintf__(3)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
int nfq_tcp_snprintf(char *buf, size_t size, const struct tcphdr *tcph)
|
||||||
|
{
|
||||||
|
int ret, len = 0;
|
||||||
|
|
||||||
|
#define TCP_RESERVED_BITS htonl(0x0F000000)
|
||||||
|
|
||||||
|
ret = snprintf(buf, size, "SPT=%u DPT=%u SEQ=%u ACK=%u "
|
||||||
|
"WINDOW=%u RES=0x%02x ",
|
||||||
|
ntohs(tcph->source), ntohs(tcph->dest),
|
||||||
|
ntohl(tcph->seq), ntohl(tcph->ack_seq),
|
||||||
|
ntohs(tcph->window),
|
||||||
|
(uint8_t)
|
||||||
|
(ntohl(tcp_flag_word(tcph) & TCP_RESERVED_BITS) >> 22));
|
||||||
|
len += ret;
|
||||||
|
|
||||||
|
if (tcph->urg) {
|
||||||
|
ret = snprintf(buf+len, size-len, "URG ");
|
||||||
|
len += ret;
|
||||||
|
}
|
||||||
|
if (tcph->ack) {
|
||||||
|
ret = snprintf(buf+len, size-len, "ACK ");
|
||||||
|
len += ret;
|
||||||
|
}
|
||||||
|
if (tcph->psh) {
|
||||||
|
ret = snprintf(buf+len, size-len, "PSH ");
|
||||||
|
len += ret;
|
||||||
|
}
|
||||||
|
if (tcph->rst) {
|
||||||
|
ret = snprintf(buf+len, size-len, "RST ");
|
||||||
|
len += ret;
|
||||||
|
}
|
||||||
|
if (tcph->syn) {
|
||||||
|
ret = snprintf(buf+len, size-len, "SYN ");
|
||||||
|
len += ret;
|
||||||
|
}
|
||||||
|
if (tcph->fin) {
|
||||||
|
ret = snprintf(buf+len, size-len, "FIN ");
|
||||||
|
len += ret;
|
||||||
|
}
|
||||||
|
/* XXX: Not TCP options implemented yet, sorry. */
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_tcp_mangle_ipv4 - mangle TCP/IPv4 packet buffer
|
||||||
|
* \param pktb: pointer to network packet buffer
|
||||||
|
* \param match_offset: offset to content that you want to mangle
|
||||||
|
* \param match_len: length of the existing content you want to mangle
|
||||||
|
* \param rep_buffer: pointer to data you want to use to replace current content
|
||||||
|
* \param rep_len: length of data you want to use to replace current content
|
||||||
|
* \returns 1 for success and 0 for failure. See pktb_mangle() for failure case
|
||||||
|
* \note This function updates the IPv4 length and recalculates the IPv4 & TCP
|
||||||
|
* checksums for you.
|
||||||
|
* \warning After changing the length of a TCP message, the application will
|
||||||
|
* need to mangle sequence numbers in both directions until another change
|
||||||
|
* puts them in sync again
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
int nfq_tcp_mangle_ipv4(struct pkt_buff *pktb,
|
||||||
|
unsigned int match_offset, unsigned int match_len,
|
||||||
|
const char *rep_buffer, unsigned int rep_len)
|
||||||
|
{
|
||||||
|
struct iphdr *iph;
|
||||||
|
struct tcphdr *tcph;
|
||||||
|
|
||||||
|
iph = (struct iphdr *)pktb->network_header;
|
||||||
|
tcph = (struct tcphdr *)(pktb->network_header + iph->ihl*4);
|
||||||
|
|
||||||
|
if (!nfq_ip_mangle(pktb, iph->ihl*4 + tcph->doff*4,
|
||||||
|
match_offset, match_len, rep_buffer, rep_len))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nfq_tcp_compute_checksum_ipv4(tcph, iph);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_tcp_mangle_ipv6 - Mangle TCP/IPv6 packet buffer
|
||||||
|
* \param pktb: Pointer to network packet buffer
|
||||||
|
* \param match_offset: Offset from start of TCP data of content that you want
|
||||||
|
* to mangle
|
||||||
|
* \param match_len: Length of the existing content you want to mangle
|
||||||
|
* \param rep_buffer: Pointer to data you want to use to replace current content
|
||||||
|
* \param rep_len: Length of data you want to use to replace current content
|
||||||
|
* \returns 1 for success and 0 for failure. See pktb_mangle() for failure case
|
||||||
|
* \note This function updates the IPv6 length and recalculates the TCP
|
||||||
|
* checksum for you.
|
||||||
|
* \warning After changing the length of a TCP message, the application will
|
||||||
|
* need to mangle sequence numbers in both directions until another change
|
||||||
|
* puts them in sync again
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
int nfq_tcp_mangle_ipv6(struct pkt_buff *pktb,
|
||||||
|
unsigned int match_offset, unsigned int match_len,
|
||||||
|
const char *rep_buffer, unsigned int rep_len)
|
||||||
|
{
|
||||||
|
struct ip6_hdr *ip6h;
|
||||||
|
struct tcphdr *tcph;
|
||||||
|
|
||||||
|
ip6h = (struct ip6_hdr *)pktb->network_header;
|
||||||
|
tcph = (struct tcphdr *)(pktb->transport_header);
|
||||||
|
if (!tcph)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!nfq_ip6_mangle(pktb,
|
||||||
|
pktb->transport_header - pktb->network_header +
|
||||||
|
tcph->doff * 4,
|
||||||
|
match_offset, match_len, rep_buffer, rep_len))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nfq_tcp_compute_checksum_ipv6(tcph, ip6h);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
249
deps/libnetfilter_queue/src/extra/udp.c
vendored
Normal file
249
deps/libnetfilter_queue/src/extra/udp.c
vendored
Normal file
@@ -0,0 +1,249 @@
|
|||||||
|
/*
|
||||||
|
* (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This code has been sponsored by Vyatta Inc. <http://www.vyatta.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <netinet/ip6.h>
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <netinet/udp.h>
|
||||||
|
|
||||||
|
#include <linux/netfilter/nfnetlink_queue.h>
|
||||||
|
#include <libnetfilter_queue/libnetfilter_queue.h>
|
||||||
|
#include <libnetfilter_queue/libnetfilter_queue_udp.h>
|
||||||
|
#include <libnetfilter_queue/libnetfilter_queue_ipv4.h>
|
||||||
|
#include <libnetfilter_queue/libnetfilter_queue_ipv6.h>
|
||||||
|
#include <libnetfilter_queue/pktbuff.h>
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup udp UDP helper functions
|
||||||
|
*
|
||||||
|
* \manonly
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.nf
|
||||||
|
\fB
|
||||||
|
#include <libmnl/libmnl.h>
|
||||||
|
#include <libnetfilter_queue/libnetfilter_queue_udp.h>
|
||||||
|
\endmanonly
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_udp_get_hdr - get the UDP header.
|
||||||
|
* \param pktb: Pointer to userspace network packet buffer
|
||||||
|
*
|
||||||
|
* \returns validated pointer to the UDP header or NULL if the UDP header was
|
||||||
|
* not set or if a minimal length check fails.
|
||||||
|
* \note You have to call nfq_ip_set_transport_header() or
|
||||||
|
* nfq_ip6_set_transport_header() first to set the UDP header.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
struct udphdr *nfq_udp_get_hdr(struct pkt_buff *pktb)
|
||||||
|
{
|
||||||
|
if (pktb->transport_header == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* No room for the UDP header. */
|
||||||
|
if (pktb_tail(pktb) - pktb->transport_header < sizeof(struct udphdr))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return (struct udphdr *)pktb->transport_header;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_udp_get_payload - get the UDP packet payload.
|
||||||
|
* \param udph: Pointer to UDP header
|
||||||
|
* \param pktb: Pointer to userspace network packet buffer
|
||||||
|
* \returns Pointer to the UDP payload, or NULL if malformed UDP packet.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
void *nfq_udp_get_payload(struct udphdr *udph, struct pkt_buff *pktb)
|
||||||
|
{
|
||||||
|
uint16_t len = ntohs(udph->len);
|
||||||
|
|
||||||
|
/* the UDP packet is too short. */
|
||||||
|
if (len < sizeof(struct udphdr))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* malformed UDP packet. */
|
||||||
|
if (pktb->transport_header + len > pktb_tail(pktb))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return pktb->transport_header + sizeof(struct udphdr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_udp_get_payload_len - get the udp packet payload.
|
||||||
|
* \param udph: Pointer to UDP header
|
||||||
|
* \param pktb: Pointer to userspace network packet buffer
|
||||||
|
* \returns Length of UDP payload (user data)
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
unsigned int nfq_udp_get_payload_len(struct udphdr *udph, struct pkt_buff *pktb)
|
||||||
|
{
|
||||||
|
return pktb_tail(pktb) - pktb->transport_header - sizeof(struct udphdr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup udp_internals Internal UDP functions
|
||||||
|
*
|
||||||
|
* Most user-space programs will never need these.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* \manonly
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.nf
|
||||||
|
\fB
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <netinet/ip6.h>
|
||||||
|
#include <netinet/udp.h>
|
||||||
|
#include <libnetfilter_queue/libnetfilter_queue_udp.h>
|
||||||
|
\endmanonly
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_udp_compute_checksum_ipv4 - sets up the UDP checksum in a UDP/IPv4 packet
|
||||||
|
* \param udph: pointer to the UDP header
|
||||||
|
* \param iph: pointer to the IPv4 header
|
||||||
|
* \note
|
||||||
|
* nfq_udp_mangle_ipv4() invokes this function.
|
||||||
|
* As long as developers always use __nfq_udp_mangle_ipv4__ when changing the
|
||||||
|
* content of a UDP message, there is no need to call
|
||||||
|
* __nfq_udp_compute_checksum_ipv4__.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
void nfq_udp_compute_checksum_ipv4(struct udphdr *udph, struct iphdr *iph)
|
||||||
|
{
|
||||||
|
/* checksum field in header needs to be zero for calculation. */
|
||||||
|
udph->check = 0;
|
||||||
|
udph->check = nfq_checksum_tcpudp_ipv4(iph, IPPROTO_UDP);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_udp_compute_checksum_ipv6 - sets up the UDP checksum in a UDP/IPv6 packet
|
||||||
|
* \param udph: pointer to the UDP header
|
||||||
|
* \param ip6h: pointer to the IPv6 header
|
||||||
|
* \note
|
||||||
|
* nfq_udp_mangle_ipv6() invokes this function.
|
||||||
|
* As long as developers always use __nfq_udp_mangle_ipv6__ when changing the
|
||||||
|
* content of a UDP message, there is no need to call
|
||||||
|
* __nfq_udp_compute_checksum_ipv6__.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
void nfq_udp_compute_checksum_ipv6(struct udphdr *udph, struct ip6_hdr *ip6h)
|
||||||
|
{
|
||||||
|
/* checksum field in header needs to be zero for calculation. */
|
||||||
|
udph->check = 0;
|
||||||
|
udph->check = nfq_checksum_tcpudp_ipv6(ip6h, udph, IPPROTO_UDP);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_udp_mangle_ipv4 - Mangle UDP/IPv4 packet buffer
|
||||||
|
* \param pktb: Pointer to network packet buffer
|
||||||
|
* \param match_offset: Offset from start of UDP data of content that you want
|
||||||
|
* to mangle
|
||||||
|
* \param match_len: Length of the existing content you want to mangle
|
||||||
|
* \param rep_buffer: Pointer to data you want to use to replace current content
|
||||||
|
* \param rep_len: Length of data you want to use to replace current content
|
||||||
|
* \returns 1 for success and 0 for failure. See pktb_mangle() for failure case
|
||||||
|
* \note This function updates the IPv4 and UDP lengths and recalculates their
|
||||||
|
* checksums for you.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
int nfq_udp_mangle_ipv4(struct pkt_buff *pktb,
|
||||||
|
unsigned int match_offset, unsigned int match_len,
|
||||||
|
const char *rep_buffer, unsigned int rep_len)
|
||||||
|
{
|
||||||
|
struct iphdr *iph;
|
||||||
|
struct udphdr *udph;
|
||||||
|
|
||||||
|
iph = (struct iphdr *)pktb->network_header;
|
||||||
|
udph = (struct udphdr *)(pktb->network_header + iph->ihl*4);
|
||||||
|
|
||||||
|
udph->len = htons(ntohs(udph->len) + rep_len - match_len);
|
||||||
|
|
||||||
|
if (!nfq_ip_mangle(pktb, iph->ihl*4 + sizeof(struct udphdr),
|
||||||
|
match_offset, match_len, rep_buffer, rep_len))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nfq_udp_compute_checksum_ipv4(udph, iph);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_udp_mangle_ipv6 - Mangle UDP/IPv6 packet buffer
|
||||||
|
* \param pktb: Pointer to network packet buffer
|
||||||
|
* \param match_offset: Offset from start of UDP data of content that you want
|
||||||
|
* to mangle
|
||||||
|
* \param match_len: Length of the existing content you want to mangle
|
||||||
|
* \param rep_buffer: Pointer to data you want to use to replace current content
|
||||||
|
* \param rep_len: Length of data you want to use to replace current content
|
||||||
|
* \returns 1 for success and 0 for failure. See pktb_mangle() for failure case
|
||||||
|
* \note This function updates the IPv6 and UDP lengths and recalculates the UDP
|
||||||
|
* checksum for you.
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
int nfq_udp_mangle_ipv6(struct pkt_buff *pktb,
|
||||||
|
unsigned int match_offset, unsigned int match_len,
|
||||||
|
const char *rep_buffer, unsigned int rep_len)
|
||||||
|
{
|
||||||
|
struct ip6_hdr *ip6h;
|
||||||
|
struct udphdr *udph;
|
||||||
|
|
||||||
|
ip6h = (struct ip6_hdr *)pktb->network_header;
|
||||||
|
udph = (struct udphdr *)(pktb->transport_header);
|
||||||
|
if (!udph)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
udph->len = htons(ntohs(udph->len) + rep_len - match_len);
|
||||||
|
|
||||||
|
if (!nfq_ip6_mangle(pktb,
|
||||||
|
pktb->transport_header - pktb->network_header +
|
||||||
|
sizeof(struct udphdr),
|
||||||
|
match_offset, match_len, rep_buffer, rep_len))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nfq_udp_compute_checksum_ipv6(udph, ip6h);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfq_pkt_snprintf_udp_hdr - print udp header into one buffer in a humnan
|
||||||
|
* readable way
|
||||||
|
* \param buf: pointer to buffer that is used to print the object
|
||||||
|
* \param size: size of the buffer (or remaining room in it).
|
||||||
|
* \param udph: pointer to a valid udp header.
|
||||||
|
* \returns The number of characters notionally written (excluding trailing NUL)
|
||||||
|
* \sa __snprintf__(3)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
EXPORT_SYMBOL
|
||||||
|
int nfq_udp_snprintf(char *buf, size_t size, const struct udphdr *udph)
|
||||||
|
{
|
||||||
|
return snprintf(buf, size, "SPT=%u DPT=%u ",
|
||||||
|
htons(udph->source), htons(udph->dest));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
38
deps/libnetfilter_queue/src/internal.h
vendored
Normal file
38
deps/libnetfilter_queue/src/internal.h
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#ifndef INTERNAL_H
|
||||||
|
#define INTERNAL_H 1
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#ifdef HAVE_VISIBILITY_HIDDEN
|
||||||
|
# define EXPORT_SYMBOL __attribute__((visibility("default")))
|
||||||
|
#else
|
||||||
|
# define EXPORT_SYMBOL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct iphdr;
|
||||||
|
struct ip6_hdr;
|
||||||
|
|
||||||
|
uint16_t nfq_checksum(uint32_t sum, uint16_t *buf, int size);
|
||||||
|
uint16_t nfq_checksum_tcpudp_ipv4(struct iphdr *iph, uint16_t protonum);
|
||||||
|
uint16_t nfq_checksum_tcpudp_ipv6(struct ip6_hdr *ip6h, void *transport_hdr,
|
||||||
|
uint16_t protonum);
|
||||||
|
|
||||||
|
struct pkt_buff {
|
||||||
|
uint8_t *mac_header;
|
||||||
|
uint8_t *network_header;
|
||||||
|
uint8_t *transport_header;
|
||||||
|
|
||||||
|
uint8_t *data;
|
||||||
|
|
||||||
|
uint32_t len;
|
||||||
|
uint32_t data_len;
|
||||||
|
|
||||||
|
bool mangled;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline uint8_t *pktb_tail(struct pkt_buff *pktb)
|
||||||
|
{
|
||||||
|
return pktb->data + pktb->len;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
1581
deps/libnetfilter_queue/src/libnetfilter_queue.c
vendored
Normal file
1581
deps/libnetfilter_queue/src/libnetfilter_queue.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user