mirror of
https://github.com/Waujito/youtubeUnblock.git
synced 2025-05-20 17:25:28 +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:
parent
4a4519cbac
commit
822266b74b
61
Makefile
61
Makefile
@ -1,12 +1,10 @@
|
||||
BUILD_DIR := $(CURDIR)/build
|
||||
DEPSDIR := $(BUILD_DIR)/deps
|
||||
|
||||
CC := gcc
|
||||
CC_FLAGS:=-Wall -Wpedantic -Wno-unused-variable
|
||||
|
||||
LD_FLAGS:=-lmnl -lnetfilter_queue
|
||||
BUILD_DIR:=build
|
||||
APP:=$(BUILD_DIR)/youtubeUnblock
|
||||
|
||||
SRCS := youtubeUnblock.c
|
||||
OBJS := $(SRCS:%.c=$(BUILD_DIR)/%.o)
|
||||
LD := gcc
|
||||
CFLAGS:=-Wall -Wpedantic -Wno-unused-variable -I$(DEPSDIR)/include -Os
|
||||
LDFLAGS:=-L$(DEPSDIR)/lib -static
|
||||
|
||||
# PREFIX is environment variable, if not set default to /usr/local
|
||||
ifeq ($(PREFIX),)
|
||||
@ -15,46 +13,73 @@ else
|
||||
PREFIX := $(DESTDIR)
|
||||
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
|
||||
default: all
|
||||
|
||||
|
||||
run_dev: dev
|
||||
bash -c "sudo ./$(APP) 537"
|
||||
|
||||
|
||||
dev: dev_attrs all
|
||||
|
||||
dev_attrs:
|
||||
$(eval CC_FLAGS := $(CC_FLAGS) -DDEBUG -ggdb -g3)
|
||||
$(eval CFLAGS := $(CFLAGS) -DDEBUG -ggdb -g3)
|
||||
|
||||
all: prepare_dirs $(APP)
|
||||
|
||||
|
||||
prepare_dirs:
|
||||
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)'
|
||||
@$(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 $@'
|
||||
@$(CC) -c $(CC_FLAGS) $^ -o $@
|
||||
@$(CC) -c $(CFLAGS) $^ -o $@
|
||||
|
||||
install: all
|
||||
install -d $(PREFIX)/bin/
|
||||
install -m 755 $(APP) $(PREFIX)/bin/
|
||||
install -d $(PREFIX)/lib/systemd/system/
|
||||
|
||||
@cp youtubeUnblock.service $(BUILD_DIR)
|
||||
@sed -i 's/$$(PREFIX)/$(subst /,\/,$(PREFIX))/g' $(BUILD_DIR)/youtubeUnblock.service
|
||||
install -m 644 $(BUILD_DIR)/youtubeUnblock.service $(PREFIX)/lib/systemd/system/
|
||||
|
||||
uninstall:
|
||||
rm $(PREFIX)/bin/youtubeUnblock
|
||||
systemctl disable youtubeUnblock.service
|
||||
rm $(PREFIX)/lib/systemd/system/youtubeUnblock.service
|
||||
systemctl disable youtubeUnblock.service
|
||||
|
||||
clean:
|
||||
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)
|
||||