mirror of
https://github.com/neocturne/fastd.git
synced 2025-05-11 19:25:08 +02:00
Compare commits
85 commits
Author | SHA1 | Date | |
---|---|---|---|
071fdb165b | |||
c817360daa | |||
e0d59850b6 | |||
814aa2601a | |||
318c944f40 | |||
3940150e80 | |||
5f63fcfc18 | |||
9df7e51637 | |||
c1a07b3f2b | |||
d03a0a1734 | |||
1f233bee76 | |||
ce1b79b12d | |||
e21476b8b5 | |||
aa9b094a48 | |||
c4478dac60 | |||
bf582abad6 | |||
5e9c49ed26 | |||
cce04acd60 | |||
de0e0d5b5a | |||
fa88c739b9 | |||
c08a3d59de | |||
66798e84ce | |||
2456f767ed | |||
d9dd14045c | |||
baafee09eb | |||
69dabf6db9 | |||
09cc37f894 | |||
fc4e527762 | |||
221cdb58cf | |||
![]() |
7a6350a295 | ||
2817438e6a | |||
d95ae84384 | |||
0b544b89b1 | |||
851f98d0f6 | |||
dd7a70cec3 | |||
0f47d83eac | |||
de324f6e00 | |||
519d359d28 | |||
33defff0f5 | |||
49066121de | |||
e8d8162828 | |||
84a59b1f62 | |||
ec01ce0519 | |||
e87c09f506 | |||
1910c6d41a | |||
78bb809fab | |||
f6058a4d92 | |||
![]() |
f60f258bd3 | ||
7dc53ab69e | |||
35a6011b08 | |||
6d7799c762 | |||
cbcf3f44da | |||
e807590494 | |||
c4447560e0 | |||
5601acc098 | |||
5b2a5f4385 | |||
975646a018 | |||
ad8c7655d6 | |||
6dbcfb2991 | |||
f6fc1a39dd | |||
cc98d2fc97 | |||
4dc9c723ef | |||
66d2ecdf48 | |||
d2ddba5bab | |||
560fa47394 | |||
b0f78fbd6f | |||
6594c0194d | |||
06fbf6ccf6 | |||
d4b2be57c0 | |||
d96f75feee | |||
8134d5deb7 | |||
0b677cba54 | |||
450e439c43 | |||
df2b398ea5 | |||
cf9d706208 | |||
790be9105a | |||
c974ccee55 | |||
8a5717e73e | |||
9bb78a5ab9 | |||
![]() |
afebb8bc39 | ||
8391c1c8e2 | |||
ac5ffbf343 | |||
0d4045fb85 | |||
0780f1d816 | |||
65ec849141 |
147 changed files with 24170 additions and 20087 deletions
24
.readthedocs.yml
Normal file
24
.readthedocs.yml
Normal file
|
@ -0,0 +1,24 @@
|
|||
# .readthedocs.yaml
|
||||
# Read the Docs configuration file
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
|
||||
# Required
|
||||
version: 2
|
||||
|
||||
# Build documentation in the docs/ directory with Sphinx
|
||||
sphinx:
|
||||
configuration: doc/source/conf.py
|
||||
|
||||
# Optionally build your docs in additional formats such as PDF
|
||||
formats:
|
||||
- pdf
|
||||
|
||||
# Optionally set the version of Python and requirements required to build your docs
|
||||
python:
|
||||
install:
|
||||
- requirements: doc/requirements.txt
|
||||
|
||||
build:
|
||||
os: ubuntu-22.04
|
||||
tools:
|
||||
python: "3.11"
|
128
CODE_OF_CONDUCT.md
Normal file
128
CODE_OF_CONDUCT.md
Normal file
|
@ -0,0 +1,128 @@
|
|||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, religion, or sexual identity
|
||||
and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the
|
||||
overall community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or
|
||||
advances of any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement at
|
||||
mschiffer@universe-factory.net.
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series
|
||||
of actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or
|
||||
permanent ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within
|
||||
the community.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available at
|
||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||
|
||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||
enforcement ladder](https://github.com/mozilla/diversity).
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
https://www.contributor-covenant.org/faq. Translations are available at
|
||||
https://www.contributor-covenant.org/translations.
|
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2012-2020, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
|
||||
Contributors:
|
||||
|
@ -52,3 +52,14 @@ 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.
|
||||
|
||||
|
||||
libmnl ( https://www.netfilter.org/projects/libmnl/ )
|
||||
|
||||
The files in src/dep/libmnl were taken from libmnl 1.0.5 without changes, with
|
||||
the exception of internal.h, which was replaced with a fastd-specific file.
|
||||
libmnl is relased under LGPLv2.1+, which can be found in src/dep/libmnl/COYPING.
|
||||
|
||||
The embedded version of libmnl is used only when the `offload_l2tp' and
|
||||
`libmnl_builtin' build flags are enabled. The default behaviour is to link
|
||||
to a libmnl found in the build sysroot, usually dynamically.
|
12
README.md
12
README.md
|
@ -1,2 +1,12 @@
|
|||
# fastd - Fast and Secure Tunneling Daemon
|
||||
|
||||
fastd is a very small VPN daemon which tunnels IP packets and Ethernet frames
|
||||
over UDP. It supports various modern encryption and authentication schemes and
|
||||
can be used in many different network topologies (1:1, 1:n, meshed).
|
||||
|
||||
fastd runs on Linux, FreeBSD, OpenBSD and macOS. Android support exists in the
|
||||
code, but is currently unmaintained. Binary packages are provided by many major
|
||||
Linux distributions.
|
||||
|
||||
For more information, see the [documentation](https://fastd.readthedocs.io/) and
|
||||
the [project wiki](https://github.com/NeoRaider/fastd/wiki).
|
||||
the [project wiki](https://github.com/neocturne/fastd/wiki).
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
fastd for Android
|
||||
=================
|
||||
|
||||
Runtime Requirements
|
||||
--------------------
|
||||
* Android 4.1+
|
||||
* x86 / ARMv7a
|
||||
* NEON optimiazation is planned but not currently required
|
||||
* Not tested with x86\_64 or AArch64 but should work too
|
||||
|
||||
How to Build
|
||||
------------
|
||||
* Android NDK r10d+ (r10c or older versions won't work)
|
||||
* make sure ANDROID\_NDK\_HOME is set
|
||||
* Ubuntu 12.04+
|
||||
* `sudo apt-get install build-essential automake bison cmake libtool pkg-config`
|
||||
* For Ubuntu **12.04**: cmake 2.8.7 won't work; get a newer version from https://launchpad.net/~kalakris/+archive/ubuntu/cmake
|
||||
* or Mac OS X 10.10+ (older versions should work too)
|
||||
* Homebrew
|
||||
* `brew install automake libtool cmake bison`
|
||||
|
||||
Then run `doc/build-fastd-android.sh` from `fastd-android` folder. Be warned the script is not perfect; you may need to look into it should anything go wrong.
|
||||
|
|
@ -1,126 +0,0 @@
|
|||
# Helper script for building fastd-android and its dependencies
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ x${PWD##*/} == xdoc ]; then
|
||||
echo "Warning: it seems you're currently in the doc/ folder. This script needs to run under the top folder of fastd source code."
|
||||
echo "See README-Android.md for more info."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "This script downloads and builds dependencies for fastd-android, as well as fastd-android itself."
|
||||
echo "Make sure you have these packages installed:"
|
||||
echo " * Android NDK r10d or newer"
|
||||
echo " * for Debian/Ubuntu: sudo apt-get install curl build-eseentials automake bison cmake git libtool pkg-config"
|
||||
echo " - Ubuntu 12.04 users need to grab cmake 2.8.9 or newer. See README-Android.md for more info."
|
||||
echo " * for Mac OS X: brew install automake libtool cmake bison"
|
||||
echo "Hit ctrl-c now if you don't have all needed stuff yet."
|
||||
read
|
||||
|
||||
SODIUM_VER=1.0.8
|
||||
UECC_VER=7
|
||||
LIBUECC_DOWNLOAD_ID=85
|
||||
LIBSODIUM_PATH=libsodium-${SODIUM_VER}
|
||||
LIBUECC_PATH=libuecc-${UECC_VER}
|
||||
|
||||
ANDROID_NATIVE_LEVEL=16
|
||||
|
||||
if [ x$ANDROID_NDK_HOME = x ]; then
|
||||
echo "Set ANDROID_NDK_HOME first"; exit 1;
|
||||
fi
|
||||
|
||||
mkdir -p android
|
||||
|
||||
pushd android > /dev/null
|
||||
WORK_DIR=${PWD}
|
||||
|
||||
mkdir -p pkgconfig/armeabi-v7a pkgconfig/x86
|
||||
|
||||
if [ -d "${LIBSODIUM_PATH}" ]; then
|
||||
echo "It seems you already have libsodium downloaded.";
|
||||
else
|
||||
echo "Downloading libsodium ${SODIUM_VER}..."
|
||||
curl -L https://github.com/jedisct1/libsodium/releases/download/${SODIUM_VER}/libsodium-${SODIUM_VER}.tar.gz | tar zxf - || exit 1
|
||||
fi
|
||||
|
||||
pushd ${LIBSODIUM_PATH} > /dev/null
|
||||
|
||||
echo "Patching libsodium build scripts..."
|
||||
sed -i -e 's/--enable-minimal//' dist-build/android-build.sh
|
||||
|
||||
if [ ! -d "libsodium-android-armv7-a" ]; then
|
||||
NDK_PLATFORM=android-${ANDROID_NATIVE_LEVEL} dist-build/android-armv7-a.sh || exit 2
|
||||
# for static link using cmake
|
||||
rm libsodium-android-armv7-a/lib/libsodium.so
|
||||
cp libsodium-android-armv7-a/lib/pkgconfig/libsodium.pc ../pkgconfig/armeabi-v7a/
|
||||
fi
|
||||
if [ ! -d "libsodium-android-i686" ]; then
|
||||
NDK_PLATFORM=android-${ANDROID_NATIVE_LEVEL} dist-build/android-x86.sh || exit 2
|
||||
# for static link using cmake
|
||||
rm libsodium-android-i686/lib/libsodium.so
|
||||
cp libsodium-android-i686/lib/pkgconfig/libsodium.pc ../pkgconfig/x86/
|
||||
fi
|
||||
popd > /dev/null
|
||||
|
||||
if [ -d "android-cmake" ]; then
|
||||
echo "It seems you already have android-cmake downloaded.";
|
||||
else
|
||||
echo "Downloading android-cmake"
|
||||
git clone https://github.com/taka-no-me/android-cmake.git;
|
||||
fi
|
||||
CMAKE_TOOLCHAIN=${WORK_DIR}/android-cmake/android.toolchain.cmake
|
||||
ANDROID_CMAKE="cmake -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN}"
|
||||
echo ">> android-cmake ready."
|
||||
|
||||
CMAKE_COMMON_DEFS="-DCMAKE_BUILD_TYPE=Release -DANDROID_NDK=${ANDROID_NDK_HOME} -DANDROID_NATIVE_API_LEVEL=${ANDROID_NATIVE_LEVEL}"
|
||||
|
||||
if [ -d "${LIBUECC_PATH}" ]; then
|
||||
echo "It seems you already have libuecc downloaded.";
|
||||
else
|
||||
curl -k -L https://projects.universe-factory.net/attachments/download/${LIBUECC_DOWNLOAD_ID}/libuecc-${UECC_VER}.tar.xz | tar Jxf - || exit 4
|
||||
fi
|
||||
for ARCH in armeabi-v7a x86; do
|
||||
BUILD_DIR=libuecc-${ARCH}
|
||||
if [ ! -d "${BUILD_DIR}" ]; then
|
||||
mkdir ${BUILD_DIR} && pushd ${BUILD_DIR} > /dev/null
|
||||
${ANDROID_CMAKE} -DANDROID_ABI="${ARCH}" ${CMAKE_COMMON_DEFS} -DCMAKE_INSTALL_PREFIX=`pwd`/output ../${LIBUECC_PATH} || exit 5
|
||||
make && make install || exit 6
|
||||
# for static link using cmake
|
||||
rm output/lib/libuecc.so*
|
||||
cp output/lib/pkgconfig/libuecc.pc ../pkgconfig/${ARCH}
|
||||
popd > /dev/null
|
||||
echo ">> libuecc ${ARCH} built."
|
||||
fi
|
||||
done
|
||||
|
||||
# detect HomeBrew installed bison for OS X
|
||||
HOMEBREW_BISON_PATH="/usr/local/opt/bison/bin"
|
||||
if [ -x "${HOMEBREW_BISON_PATH}/bison" ]; then
|
||||
USE_PATH=${HOMEBREW_BISON_PATH}:$PATH
|
||||
else
|
||||
USE_PATH=$PATH
|
||||
fi
|
||||
|
||||
FASTD_ANDROID_DEFS="-DWITH_CAPABILITIES=OFF -DWITH_STATUS_SOCKET=OFF -DWITH_CIPHER_AES128_CTR=FALSE -DWITH_METHOD_GENERIC_POLY1305=FALSE -DWITH_CMDLINE_COMMANDS=FALSE"
|
||||
|
||||
for ARCH in armeabi-v7a x86; do
|
||||
BUILD_DIR=fastd-${ARCH}
|
||||
mkdir -p ${BUILD_DIR}
|
||||
pushd ${BUILD_DIR} > /dev/null
|
||||
if [ ! -f "Makefile" ]; then
|
||||
|
||||
PATH=${USE_PATH} PKG_CONFIG_LIBDIR=../pkgconfig/${ARCH} \
|
||||
${ANDROID_CMAKE} \
|
||||
-DANDROID_ABI="${ARCH}" ${CMAKE_COMMON_DEFS} \
|
||||
${FASTD_ANDROID_DEFS} \
|
||||
-DEXECUTABLE_OUTPUT_PATH=`pwd`/src -DCMAKE_INSTALL_PREFIX=`pwd` \
|
||||
../.. || exit 7
|
||||
fi
|
||||
|
||||
make install/strip && echo ">> fastd ${ARCH} build ready in build/${BUILD_DIR}/bin"
|
||||
popd > /dev/null
|
||||
done
|
||||
|
||||
popd > /dev/null
|
||||
|
|
@ -83,6 +83,9 @@ config fastd sample_config
|
|||
# If set to 0, peer-specific interfaces will only exist as long as there is an active connection
|
||||
# option persist_interface '1'
|
||||
|
||||
# If set to 1, null@l2tp sessions will be offloaded to the kernel implementation
|
||||
# option offload_l2tp '0'
|
||||
|
||||
# If fastd was compiled with libcap support, defines how capabilities are handled
|
||||
# Possible values: 1, 0, early, force (see fastd documentation for a description of the values)
|
||||
# option drop_capabilities '1'
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (c) 2012-2020, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
# Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
|
||||
set -o pipefail
|
||||
|
||||
|
@ -7,15 +7,26 @@ START=95
|
|||
|
||||
USE_PROCD=1
|
||||
|
||||
EXTRA_COMMANDS='up down show_key generate_key'
|
||||
|
||||
EXTRA_HELP='
|
||||
show_key shows the public keys of the instances given as
|
||||
additional arguments
|
||||
generate_key generates the private keys for the instances given as
|
||||
additional arguments and saves them in the configuration
|
||||
(when there in no key configured yet)
|
||||
# Backwards compatiblity with OpenWrt 19.07 and older
|
||||
if ! command -v extra_command >/dev/null; then
|
||||
EXTRA_HELP='
|
||||
'
|
||||
EXTRA_COMMANDS=''
|
||||
|
||||
extra_command() {
|
||||
local cmd="$1"
|
||||
local help="$2"
|
||||
|
||||
local extra="$(printf '\t%-16s%s' "${cmd}" "${help}")"
|
||||
EXTRA_HELP="${EXTRA_HELP}${extra}
|
||||
"
|
||||
EXTRA_COMMANDS="${EXTRA_COMMANDS} ${cmd}"
|
||||
}
|
||||
fi
|
||||
|
||||
extra_command 'show_key' 'show the public key of an instance'
|
||||
extra_command 'generate_key' 'generate key for an instance and store in UCI'
|
||||
|
||||
|
||||
LIST_SEP="
|
||||
|
@ -93,6 +104,7 @@ config_string_interface='interface $(escape_string "$value");'
|
|||
config_string_method='method $(escape_string "$value");'
|
||||
config_string_mode='mode $(guard_value "$value");'
|
||||
config_string_mtu='mtu $(guard_value "$value");'
|
||||
config_string_offload_l2tp='offload l2tp $(yes_no "$value");'
|
||||
config_string_peer_limit='peer limit $(guard_value "$value");'
|
||||
config_string_packet_mark='packet mark $(guard_value "$value");'
|
||||
config_string_persist_interface='persist interface $(yes_no "$value");'
|
||||
|
@ -252,7 +264,7 @@ generate_config() {
|
|||
|
||||
append_options "$s" config \
|
||||
bind config config_peer config_peer_dir drop_capabilities method syslog_level mode interface mtu peer_limit \
|
||||
user group status_socket forward hide_ip_addresses hide_mac_addresses packet_mark \
|
||||
user group status_socket forward hide_ip_addresses hide_mac_addresses offload_l2tp packet_mark \
|
||||
persist_interface on_pre_up on_post_down on_up on_down on_connect on_establish on_disestablish on_verify
|
||||
|
||||
config_get mode "$s" mode
|
||||
|
@ -327,8 +339,8 @@ reload_instance() {
|
|||
|
||||
update_peer_groups "$s" true
|
||||
|
||||
rc_procd start_service "$s"
|
||||
procd_send_signal fastd "$s"
|
||||
rc_procd start_service "$s"
|
||||
procd_send_signal fastd "$s"
|
||||
}
|
||||
|
||||
start_service() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.TH FASTD 1 "October 2020" "fastd v21" "User Commands"
|
||||
.TH FASTD 1 "January 2025" "fastd v23+" "User Commands"
|
||||
.SH NAME
|
||||
fastd \- Fast and Secure Tunnelling Daemon
|
||||
.SH SYNOPSIS
|
||||
|
@ -120,4 +120,4 @@ is available online at
|
|||
\fIhttps://gluon.readthedocs.io/\fR.
|
||||
|
||||
Additional resources can be found in the Wiki at
|
||||
\fIhttps://github.com/NeoRaider/fastd/wiki\fR.
|
||||
\fIhttps://github.com/neocturne/fastd/wiki\fR.
|
||||
|
|
2
doc/requirements.txt
Normal file
2
doc/requirements.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Sphinx==8.1.3
|
||||
sphinx-rtd-theme==3.0.2
|
|
@ -47,14 +47,14 @@ master_doc = 'index'
|
|||
|
||||
# General information about the project.
|
||||
project = 'fastd'
|
||||
copyright = '2012-2020, Matthias Schiffer'
|
||||
copyright = 'Matthias Schiffer'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '21'
|
||||
version = '23+'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = version
|
||||
|
||||
|
@ -90,6 +90,8 @@ exclude_patterns = []
|
|||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
highlight_language = 'text'
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
#modindex_common_prefix = []
|
||||
|
||||
|
@ -101,7 +103,7 @@ pygments_style = 'sphinx'
|
|||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'default'
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
|
|
|
@ -63,6 +63,14 @@ and makes the same security guarantees.
|
|||
|
||||
The method names have the form "<cipher>+poly1305".
|
||||
|
||||
null-l2tp
|
||||
~~~~~~~~~
|
||||
|
||||
The "null\@l2tp" method doesn't procide any encryption or authentication. Unlike the older
|
||||
"null" method, this method uses the L2TPv3 (`RFC3931 <https://tools.ietf.org/html/rfc3931>`_) protocol for its data
|
||||
packets. This allows to use the L2TPv3 Ethernet Pseudowire implementation of the Linux kernel
|
||||
to offload data forwarding to kernel space in Multi-TAP mode.
|
||||
|
||||
null
|
||||
~~~~
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ Dependencies
|
|||
Optional:
|
||||
|
||||
* libcap (if ``capabilities`` is enabled; Linux only; can be disabled if you don't need POSIX capability support)
|
||||
* libmnl (for L2TP offload support; Linux only)
|
||||
* libjson-c (if ``status_socket`` is enabled)
|
||||
* libssl (if ``cipher_aes128-ctr`` is enabled)
|
||||
|
||||
|
@ -23,7 +24,7 @@ Starting with v20, fastd uses the Meson build system.
|
|||
::
|
||||
|
||||
# Get fastd (or use the release tarballs)
|
||||
git clone https://github.com/NeoRaider/fastd.git
|
||||
git clone https://github.com/neocturne/fastd.git
|
||||
|
||||
# Set up a build dir
|
||||
meson setup fastd fastd-build -Dbuildtype=release
|
||||
|
@ -44,3 +45,7 @@ be passed to ``meson setup`` or ``meson configure`` using ``-DVARIABLE=VALUE``.
|
|||
* By default, fastd will build against libsodium. If you want to use NaCl instead, add ``-Duse_nacl=true``
|
||||
* If you have a recent enough toolchain (GCC 4.8 or higher recommended), you can enable link-time optimization by
|
||||
adding ``-Db_lto=true``
|
||||
* Instead of using an installed version of libmnl, it is possible to build it
|
||||
as part of fastd itself by setting ``-Dlibmnl_builtin=true``. This is
|
||||
recommended for constrained targets only and not for regular Linux
|
||||
distributions.
|
||||
|
|
|
@ -9,18 +9,69 @@ to simplify the deployment of multiple fastd instances on the same host using di
|
|||
UDP ports and allow passing through common NAT routers without explicit configuration.
|
||||
|
||||
The first byte of the UDP payload is used to discern the different packet types
|
||||
used by fastd. For now only two values for the first byte have been defined:
|
||||
``0x01`` indicates a handshake packet, and ``0x02`` a data packet. All other
|
||||
values are reserved for future use and must be ignored by current implementations.
|
||||
used by fastd. Since fastd v22, the following packet types are used:
|
||||
|
||||
- ``0x00`` Data packet (v22+)
|
||||
- ``0x01`` Handshake packet (pre-v22)
|
||||
- ``0x02`` Data packet (pre-v22)
|
||||
- ``0xC8`` L2TP control message header (v22+)
|
||||
|
||||
fastd v22 still supports the pre-v22 packet types, so communication between old
|
||||
and new versions is possible.
|
||||
|
||||
L2TP control message headers
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Since fastd v22, all handshake packets may be prefixed with an L2TP control message header to make
|
||||
sure these packets are not considered data packets by the L2TP kernel code even with potential
|
||||
future extensions of the L2TP protocol. The basic format of this header is the following
|
||||
(as specified in `RFC3931 <https://tools.ietf.org/html/rfc3931>`_)::
|
||||
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|T|L|x|x|S|x|x|x|x|x|x|x| Ver | Length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Control Connection ID |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Ns | Nr |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
When sending a packet with an L2TP header, the following rules apply:
|
||||
|
||||
- Only the *T*, *L*, and *S* flags are set (first byte is ``0xC8``)
|
||||
- *Ver* is set to 3 (second byte is ``0x03``)
|
||||
- *Length* is set to 12 (only the header itself is counted)
|
||||
- *Control Connection ID*, *Ns* and *Nr* are unused, they are set to 0
|
||||
|
||||
When receiving packets, only the first two bytes are verified. Packets with unexpected values in these bytes
|
||||
are discarded.
|
||||
|
||||
When replying to a handshake packet, fastd will insert the L2TP header when the peer has signaled that it
|
||||
supports such packets using the *L2TP_SUPPORT* flag. Initial handshakes will be sent twice at the same
|
||||
time, once with and once without an L2TP header, so both new and old versions of fastd can be supported.
|
||||
|
||||
fastd v22 and newer ignore handshake packets without L2TP header when the *L2TP_SUPPORT* flag is set, so
|
||||
only one of the two handshake packets with identical content will be handled.
|
||||
|
||||
In addition to handshakes, data packets may be prefixed with such L2TP control message headers as well, but
|
||||
this is rarely useful, as it reduces the usable MTU of a tunnel. The "null\@l2tp" method makes use of this
|
||||
for keepalive packets, so they are passed up to the fastd userspace when using the L2TP kernel offload feature.
|
||||
|
||||
Handshake format
|
||||
~~~~~~~~~~~~~~~~
|
||||
The initial ``0x01`` byte together with the next three bytes form the 4-byte handshake header; the rest of
|
||||
the packet after the header consists of a list of TLV records. The second header byte is reserved and must
|
||||
always be ``0x00``; the following two header bytes contain the length of the following TLV records in bytes
|
||||
encoded as Big Endian.
|
||||
The first 4 bytes (after the L2TP header if it exists, of the packet otherwise) form the handshake header::
|
||||
|
||||
The following TLV records start with a 2-byte type field, followed by a 2-byte length field and the
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| 0x01 | 0x00 | TLV Length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
The rest of the handshake packet consists of TLV records, the total length of which is given by the *TLV Length*
|
||||
header field (in big-endian byte order).
|
||||
|
||||
Each of the following TLV records starts with a 2-byte type field, followed by a 2-byte length field and the
|
||||
arbitrary-length value. There is no special alignment defined for the TLV records. All integers that are part of
|
||||
the TLV format (in particular, the type and length fields) are encoded in little-endian byte order.
|
||||
|
||||
|
@ -32,7 +83,7 @@ Record ID Value description Format Values
|
|||
``0x0000`` Handshake type 1-byte unsigned integer {1, 2, 3}
|
||||
``0x0001`` Reply code 1-byte unsigned integer {0 (success), 1 (mandatory record missing), 2 (unacceptable value)}
|
||||
``0x0002`` Error detail 1/2-byte unsigned integer Record type which caused an error
|
||||
``0x0003`` Flags (currently unused) variable-length bit field So far, no values are defined
|
||||
``0x0003`` Flags variable-length bit field L2TP_SUPPORT=0x01 (sender supports L2TP control message headers)
|
||||
``0x0004`` Mode 1-byte unsigned integer {0 (TAP mode), 1 (TUN mode)}
|
||||
``0x0005`` Protocol name variable-length string "ec25519-fhmqvc"
|
||||
``0x0006`` Sender key 32-byte public key
|
||||
|
@ -120,9 +171,12 @@ Payload packets
|
|||
~~~~~~~~~~~~~~~
|
||||
The payload packet structure is defined by the methods; at the moment most methods use the same format, starting with a 24 byte header, followed by the actual payload:
|
||||
|
||||
* Byte 1: Packet type (0x02)
|
||||
* Byte 2: Flags (method-specific; unused, always 0x00)
|
||||
* Byte 1: Packet type (``0x00`` when both sides of a connection are fastd v22 or newer, ``0x02`` otherwise)
|
||||
* Byte 2: Flags (method-specific; unused, always ``0x00``)
|
||||
* Bytes 3-8: Packet sequence number/nonce (big endian; incremented by 2 for each packet; one side of a connection uses the even sequence numbers and the other side the odd ones)
|
||||
* Bytes 9-24: Authentication tag (method-specific)
|
||||
|
||||
The ``null`` method uses only a 1 byte header: The packet type is directly followed by the payload data.
|
||||
The "null" method uses only a 1-byte header: The packet type is directly followed by the payload data.
|
||||
|
||||
The "null\@l2tp" method uses an 8-byte header, which is the same as the L2TPv3 Session Header over UDP, with no Cookie and
|
||||
no L2-Specific Sublayer (as specified in `RFC3931 <https://tools.ietf.org/html/rfc3931>`_). fastd always uses the L2TP Session ID 1.
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
Welcome to fastd's documentation!
|
||||
=================================
|
||||
|
||||
User manual
|
||||
-----------
|
||||
fastd is a very small VPN daemon which tunnels IP packets and Ethernet frames
|
||||
over UDP. It supports various modern encryption and authentication schemes and
|
||||
can be used in many different network topologies (1:1, 1:n, meshed).
|
||||
|
||||
fastd runs on Linux, FreeBSD, OpenBSD and macOS. Android support exists in the
|
||||
code, but is currently unmaintained. Binary packages are provided by many major
|
||||
Linux distributions.
|
||||
|
||||
.. toctree::
|
||||
:caption: User manual
|
||||
:maxdepth: 2
|
||||
|
||||
manual/cmdline
|
||||
|
@ -12,12 +18,12 @@ User manual
|
|||
manual/methods
|
||||
manual/mtu
|
||||
|
||||
Release notes
|
||||
-------------
|
||||
|
||||
.. toctree::
|
||||
:caption: Release notes
|
||||
:maxdepth: 2
|
||||
|
||||
releases/v23
|
||||
releases/v22
|
||||
releases/v21
|
||||
releases/v20
|
||||
releases/v19
|
||||
|
@ -26,10 +32,8 @@ Release notes
|
|||
releases/v16
|
||||
releases/v15
|
||||
|
||||
Cryptographic algorithms
|
||||
------------------------
|
||||
|
||||
.. toctree::
|
||||
:caption: Cryptographic algorithms
|
||||
:maxdepth: 2
|
||||
|
||||
crypto/ec25519
|
||||
|
@ -38,10 +42,8 @@ Cryptographic algorithms
|
|||
crypto/macs
|
||||
crypto/methods
|
||||
|
||||
Developer documentation
|
||||
-----------------------
|
||||
|
||||
.. toctree::
|
||||
:caption: Developer documentation
|
||||
:maxdepth: 2
|
||||
|
||||
devel/building
|
||||
|
|
|
@ -190,6 +190,30 @@ Example config:
|
|||
|
||||
Sets the MTU; must be at least 576. You should read the page :doc:`mtu` as the default 1500 is suboptimal in most setups.
|
||||
|
||||
.. _option-offload:
|
||||
|
||||
| ``offload l2tp yes|no;``
|
||||
|
||||
Use the L2TP kernel implementation for the "null\@l2tp" method. Enabling offloading allows for significantly higher
|
||||
throughput, as data packets don't need to be copied between kernel and userspace.
|
||||
|
||||
L2TP offloading is only avaiable when the following conditions are met:
|
||||
|
||||
* A Linux kernel with L2TP Ethernet Pseudowire support is required
|
||||
* L2TP offloading must be enabled in the fastd build (default on Linux)
|
||||
* ``mode`` must be set to ``multitap``
|
||||
* ``persist interface`` must be set to ``no``
|
||||
|
||||
Using the multi-TAP mode can be inconvenient with high numbers of peers, as it will create a separate network
|
||||
interface for each peer. As peers in TAP and multi-TAP modes can communicate with each other, using TAP mode
|
||||
without offloading on a powerful server, but multi-TAP on weak devices that only establish a single connection
|
||||
anyways is an option that combines convenience with high performance.
|
||||
|
||||
Using L2TP offloading requires fastd to set the *SO_REUSEADDR* flag flag on its sockets. This allows other local users
|
||||
to open a socket with the same address/port combination, making it possible to monitor and inject traffic on such
|
||||
unencrypted connections without special privileges. For this reason, using a privileged bind port (below 1024) is
|
||||
recommended when using the offload feature on hosts shared with other users.
|
||||
|
||||
| ``on pre-up [ sync | async ] "<command>";``
|
||||
| ``on up [ sync | async ] "<command>";``
|
||||
| ``on down [ sync | async ] "<command>";``
|
||||
|
@ -340,5 +364,6 @@ Example config:
|
|||
|
||||
| ``float yes|no;``
|
||||
|
||||
The float option can be used to accept connections from the peer with the specified key from
|
||||
other addresses that the configured ones.
|
||||
Set to ``yes`` to allow incoming connections from any IP address/port for this peer. By default,
|
||||
incoming connections are only accepted from the addresses/ports configured using the ``remote``
|
||||
option when such an option exists. Peers without ``remote`` are always floating.
|
||||
|
|
|
@ -4,7 +4,7 @@ fastd supports various combinations of ciphers and authentication schemes using
|
|||
different method providers. All ciphers, message authentication codes (MACs) and
|
||||
method providers can be disabled during compilation to reduce the binary size.
|
||||
|
||||
See `Benchmarks <https://projects.universe-factory.net/projects/fastd/wiki/Benchmarks>`_ for an
|
||||
See `Benchmarks <https://github.com/neocturne/fastd/wiki/Benchmarks>`_ for an
|
||||
overview of the performance of the different methods.
|
||||
|
||||
Recommended methods
|
||||
|
@ -18,21 +18,6 @@ It has been chosed for the software profile in the `eSTREAM <http://en.wikipedia
|
|||
`UMAC <http://en.wikipedia.org/wiki/UMAC>`_ is an extremely fast message authentication code which is provably
|
||||
secure and optimized for software implementations.
|
||||
|
||||
OpenWrt
|
||||
-------
|
||||
Too keep the binary as small as possible, only the following methods are enabled on OpenWrt
|
||||
by default:
|
||||
|
||||
* ``salsa2012+gmac``
|
||||
* ``salsa2012+umac``
|
||||
* ``null+salsa2012+gmac``
|
||||
* ``null+salsa2012+umac``
|
||||
* ``null``
|
||||
|
||||
Of these, the GMAC-based methods may be dropped in the future to further reduce the binary size, as UMAC is
|
||||
the superior authentication scheme (it is faster than GMAC, provably secure and its software implementation
|
||||
isn't suspect to timing side channels).
|
||||
|
||||
List of methods
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -71,11 +56,12 @@ Method Method provider Cipher MAC Notes
|
|||
|
||||
Methods without security
|
||||
------------------------
|
||||
======== =============== ====== ==== =====
|
||||
Method Method provider Cipher MAC Notes
|
||||
======== =============== ====== ==== =====
|
||||
``null`` null none none [5]_
|
||||
======== =============== ====== ==== =====
|
||||
============= =============== ====== ==== =====
|
||||
Method Method provider Cipher MAC Notes
|
||||
============= =============== ====== ==== =====
|
||||
``null@l2tp`` null-l2tp none none [5]_
|
||||
``null`` null none none [5]_
|
||||
============= =============== ====== ==== =====
|
||||
|
||||
|
||||
.. [1] The MAC is integrated in the method provider.
|
||||
|
|
|
@ -10,7 +10,8 @@ Unlike OpenVPN, fastd doesn't support fragmentation itself, but relies on the IP
|
|||
Guidelines
|
||||
----------
|
||||
|
||||
* The basic overhead of a fastd packet in TUN mode over IPv4 is 29 Bytes when only null crypto is used and 52 Bytes for all other crypto methods
|
||||
* The basic overhead of a fastd packet in TUN mode over IPv4 is 28 bytes plus method-specific overhead
|
||||
* Method "null" uses 1 additional header byte, "null\@l2tp" 8 bytes, and all other methods 24 bytes
|
||||
* TAP mode needs 14 bytes more than TUN mode
|
||||
* Tunneling over IPv6 needs 20 bytes more than IPv4
|
||||
|
||||
|
@ -18,13 +19,13 @@ Examples
|
|||
--------
|
||||
|
||||
Your base MTU is 1500 and you want to use TUN mode over IPv4 with any crypto method:
|
||||
Choose 1500 - 52 = 1448 bytes.
|
||||
Choose 1500 - 28 - 24 = 1448 bytes.
|
||||
|
||||
Your base MTU is 1492 (like most German DSL lines) and you want to use TAP mode over IPv4 with any crypto method:
|
||||
Choose 1492 - 52 - 14 = 1426 bytes.
|
||||
Choose 1492 - 28 - 24 - 14 = 1426 bytes.
|
||||
|
||||
Conservative choice when you want to transfer IPv6 inside the tunnel:
|
||||
Choose 1280 Bytes (not relevant when you use batman-adv inside the tunnel as batman-adv will take care of the inner fragmentation).
|
||||
Choose 1280 Bytes (not relevant when you use batman-adv inside the tunnel as batman-adv will take care of the inner fragmentation.)
|
||||
|
||||
Conservative choice when you don't know anything (but assume the base MTU is at least 1280 so IPv6 can be supported) and want to support tunnels over IPv4 and IPv6 in TAP mode with any crypto method:
|
||||
Choose 1280 - 52 - 14 - 20 = 1194 bytes.
|
||||
Choose 1280 - 28 - 24 - 14 - 20 = 1194 bytes.
|
||||
|
|
|
@ -32,7 +32,7 @@ Bugfixes
|
|||
environments like buildroot
|
||||
* Fix build on MacOS 10.12+
|
||||
* Fix fast reconnect when changing networks on recent Linux kernels
|
||||
* Fix segfault in *tun*/*multitap* mode with *persist iface no*
|
||||
* Fix segfault in *tun*/*multitap* mode with *persist interface no*
|
||||
* Fix segfault in resolver with musl libc 1.1.20+
|
||||
* Fix segfault when failing to create an interface on FreeBSD
|
||||
* Do not print local address as a v4-mapped IPv6 address in log messages and
|
||||
|
|
68
doc/source/releases/v22.rst
Normal file
68
doc/source/releases/v22.rst
Normal file
|
@ -0,0 +1,68 @@
|
|||
fastd v22
|
||||
=========
|
||||
|
||||
The main improvement of fastd v22 is the L2TP kernel offloading support, which
|
||||
brings fastd's throughput for unsecured connections on par with other L2TP
|
||||
solutions like `Tunneldigger <https://github.com/wlanslovenija/tunneldigger>`_,
|
||||
while maintaining most of fastd's flexibility. It is even possible to use fast
|
||||
L2TP connections for some peers and secure encryption for others in a single
|
||||
fastd instance.
|
||||
|
||||
New features
|
||||
~~~~~~~~~~~~
|
||||
|
||||
* Added new method "null\@l2tp"
|
||||
|
||||
Like the old "null" method, "null\@l2tp" doesn't provide any security. In
|
||||
TAP mode, it uses a packet format compatible with L2TPv3 Ethernet Pseudowires
|
||||
(`RFC3931 <https://datatracker.ietf.org/doc/html/rfc3931>`_ and
|
||||
`RFC4719 <https://datatracker.ietf.org/doc/html/rfc4719>`_) for payload data.
|
||||
|
||||
Using "null\@lt2p" for new unsecured deployments and migrating existing
|
||||
"null" setups is recommended for a number of reasons:
|
||||
|
||||
- "null" uses a 1-byte packet header, which can make data transfer between
|
||||
kernel and userspace slightly slower on platforms that care about alignment
|
||||
- The L2TP-compatible data format facilitates debugging, as packet sniffers
|
||||
like Wireshark can decode the payload
|
||||
- L2TP can be offloaded to the Linux kernel, significantly increasing
|
||||
throughput
|
||||
|
||||
See :ref:`offload configuration <option-offload>` for information on the setup
|
||||
and limitations of the L2TP offload feature.
|
||||
|
||||
* Added support for NetBSD (tested on NetBSD 9.2)
|
||||
|
||||
Bugfixes
|
||||
~~~~~~~~
|
||||
|
||||
* Fix build for MacOS
|
||||
|
||||
This issue was introduced during the move to the Meson build system in fastd
|
||||
v20.
|
||||
|
||||
* Fix TUN mode crash on FreeBSD/OpenBSD
|
||||
|
||||
This issue is a regression introduced in fastd v20. The buffer management
|
||||
optimization caused an assertion failure in many configurations upon
|
||||
reading packets from the TUN interface.
|
||||
|
||||
* Fix version number format
|
||||
|
||||
When not building from Git, fastd v21 would format its own version number as
|
||||
"21" rather than "v21", deviating from previous releases. This is fixed with
|
||||
v22.
|
||||
|
||||
Other changes
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
* A new handshake format has been introduced, prepending an L2TPv3 Control
|
||||
Message header to the actual fastd handshake. This improves certain
|
||||
interactions between fastd and the L2TP kernel module used for offloading.
|
||||
|
||||
To maintain compatibility with older fastd versions, both handshake formats
|
||||
are accepted. For the initial handshake packet, an old and a new format
|
||||
packet are sent at the same time.
|
||||
|
||||
Sessions established using the old handshake format are marked with "compat
|
||||
mode" in the log.
|
80
doc/source/releases/v23.rst
Normal file
80
doc/source/releases/v23.rst
Normal file
|
@ -0,0 +1,80 @@
|
|||
fastd v23
|
||||
=========
|
||||
|
||||
This release contains a number of small improvements and bugfixes, including
|
||||
mitigations for the LOW severity vulnerability ``CVE-2025-24356``.
|
||||
|
||||
Bugfixes
|
||||
~~~~~~~~
|
||||
|
||||
* Add mitigations for fast-reconnect amplification attacks
|
||||
|
||||
When receiving a data packet from an unknown IP address/port combination, fastd will assume that
|
||||
one of its connected peers has moved to a new address (for example due to internet lines with
|
||||
dynamic IP, or roaming between WWAN and a local internet connection) and initiate a reconnect by
|
||||
sending a handshake packet. This "fast reconnect" avoids having to wait for a session timeout
|
||||
(up to ~90s) until a new connection is established.
|
||||
|
||||
Even a 1-byte UDP packet just containing the fastd packet type header can trigger a much larger
|
||||
handshake packet (~150 bytes of UDP payload). With fastd v22, this number is doubled, because
|
||||
two handshakes are sent (one in a pre-v22-compatible format and one in a new L2TP-style format).
|
||||
Including IPv4 and UDP headers, the resulting amplification factor is roughly 12-13.
|
||||
|
||||
By sending data packets with a spoofed source address to fastd instances reachable on the
|
||||
internet, this amplification of UDP traffic might be used to facilitate a Distributed Denial
|
||||
of Service attack.
|
||||
|
||||
fastd has always implemented rate limiting for handshakes to unknown IP addresses and ports to
|
||||
1 handshake per 15s to avoid this kind of attack, however the rate is limited per-port and not
|
||||
per-address, thus still allowing handshakes to be sent to all 65535 UDP ports of the same IP
|
||||
address unlimited.
|
||||
|
||||
The issue has been mitigated in fastd v23 by a number of changes:
|
||||
|
||||
- Rate-limiting has been changed changed to be applied per-address instead of per-port
|
||||
- Only one handshake instead of two handshakes is sent for fast-reconnect (by determining from
|
||||
the format of the data packet whether a pre-v22 or L2TP-style handshake should be used)
|
||||
- Require at least a full method header instead of just a single byte for a data packet to be
|
||||
considered valid. This does not have an effect on instances that enable the ``null`` method
|
||||
(regardless of ``null`` being actually in use), as a single-byte UDP packet is a valid ``null``
|
||||
keepalive, but for all other methods the amplification factor is slightly reduced.
|
||||
|
||||
Only fastd instances that allow connections from arbitrary IP addresses are vulnerable. Instances
|
||||
in a "client" role that configure their peers using the ``remote`` config option (which includes
|
||||
the common deployment as part of the `Gluon <https://github.com/freifunk-gluon/gluon>`_ wireless
|
||||
mesh firmware) will not respond to unexpected data packets with a handshake and are therefore
|
||||
unaffected.
|
||||
|
||||
``CVE-2025-24356`` has been assigned to this issue. The severity of this
|
||||
vulnerability is considered LOW.
|
||||
|
||||
A GitHub security advisory can be found under
|
||||
`GHSA-pggg-vpfv-4rcv <https://github.com/neocturne/fastd/security/advisories/GHSA-pggg-vpfv-4rcv>`_.
|
||||
* Fix config loading to fail on ``offload l2tp no;`` when L2TP offloading is
|
||||
unsupported by the fastd build or the kernel
|
||||
* Fix assembly Salsa20(/12) implementations accidentally generating the Linux-
|
||||
specific ``.note.GNU-stack`` ELF section on non-Linux systems
|
||||
|
||||
This is unlikely to have caused any issues, as other systems should just
|
||||
ignore the unknown section.
|
||||
* Status socket:
|
||||
- Fix interface name information with L2TP offloading
|
||||
- Add per-peer MTU information
|
||||
* Documentation:
|
||||
- Fix incorrect "persist interface" examples
|
||||
- Improve explanation of ``float`` option
|
||||
* Build:
|
||||
- Fix build on macOS (again)
|
||||
- Fix build with Meson 0.49 (the minimum version marked as supported by fastd)
|
||||
|
||||
Other changes
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
* Add support for Indirect Branch Tracking and Shadow Stacks on x86
|
||||
|
||||
The assembly Salsa20(/12) implementations have been marked compatible with
|
||||
IBT and SHSTK, which are part of Intel CET (Control-flow Enforcement
|
||||
Technology) and can be enabled using the ``-fcf-protection`` GCC option.
|
||||
* The file ``COPYRIGHT`` has been renamed to ``LICENSE``
|
||||
* The vendored version of libmnl that is used with ``libmnl_builtin=true`` has
|
||||
been updated to 1.0.5
|
|
@ -1,7 +1,7 @@
|
|||
project(
|
||||
'fastd',
|
||||
'c',
|
||||
version : '21',
|
||||
version : '23+',
|
||||
default_options : [ 'c_std=c99', 'warning_level=2' ],
|
||||
meson_version: '>=0.49',
|
||||
)
|
||||
|
@ -24,7 +24,7 @@ custom_target(
|
|||
command : [
|
||||
'sh',
|
||||
'-c',
|
||||
'cd "$1" && find src test -type f -name "*.[ch]" | xargs "$2" -i --style=file',
|
||||
'cd "$1" && find src test -type f -name "*.[ch]" | grep -v "^src/dep/" | xargs "$2" -i --style=file',
|
||||
'-',
|
||||
meson.current_source_dir(),
|
||||
clang_format,
|
||||
|
|
|
@ -27,7 +27,11 @@ option('method_generic-gmac', type : 'feature', value : 'enabled')
|
|||
option('method_generic-poly1305', type : 'feature', value : 'enabled')
|
||||
option('method_generic-umac', type : 'feature', value : 'enabled')
|
||||
option('method_null', type : 'feature', value : 'enabled')
|
||||
option('method_null_l2tp', type : 'feature', value : 'enabled')
|
||||
|
||||
option('offload_l2tp', type : 'feature', value : 'auto')
|
||||
|
||||
option('libmnl_builtin', type : 'boolean', value : false)
|
||||
option('use_nacl', type : 'boolean', value : false)
|
||||
|
||||
option('build_tests', type : 'boolean', value : false)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2020, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2020, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
@ -87,6 +87,10 @@
|
|||
#mesondefine WITH_SYSTEMD
|
||||
|
||||
|
||||
/** Defined if L2TP offloading is enabled */
|
||||
#mesondefine WITH_OFFLOAD_L2TP
|
||||
|
||||
|
||||
/** Defined if libsodium is used */
|
||||
#mesondefine HAVE_LIBSODIUM
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
@ -65,6 +65,16 @@ static bool need_cap_net_admin(void) {
|
|||
return true;
|
||||
#endif
|
||||
|
||||
if (fastd_use_offload_l2tp())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool need_cap_net_bind_service(void) {
|
||||
if (fastd_use_offload_l2tp())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -76,6 +86,9 @@ static bool need_cap_net_raw(void) {
|
|||
if (!ctx.sock_default_v6 && conf.bind_addr_default_v6 && conf.bind_addr_default_v6->bindtodev)
|
||||
return true;
|
||||
|
||||
if (fastd_use_offload_l2tp())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -115,6 +128,9 @@ void fastd_cap_reacquire_drop(void) {
|
|||
if (need_cap_net_admin())
|
||||
set_cap(caps, CAP_NET_ADMIN);
|
||||
|
||||
if (need_cap_net_bind_service())
|
||||
set_cap(caps, CAP_NET_BIND_SERVICE);
|
||||
|
||||
if (need_cap_net_raw())
|
||||
set_cap(caps, CAP_NET_RAW);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
23
src/config.c
23
src/config.c
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2020, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
|
||||
Android port contributor:
|
||||
|
@ -467,7 +467,9 @@ static void configure_user(void) {
|
|||
|
||||
/** Initializes global configuration that depends on the configured methods */
|
||||
static void configure_method_parameters(void) {
|
||||
conf.overhead = 0;
|
||||
|
||||
conf.min_overhead = SIZE_MAX;
|
||||
conf.max_overhead = 0;
|
||||
conf.encrypt_headroom = 0;
|
||||
conf.decrypt_headroom = 0;
|
||||
|
||||
|
@ -475,7 +477,8 @@ static void configure_method_parameters(void) {
|
|||
for (i = 0; conf.methods[i].name; i++) {
|
||||
const fastd_method_provider_t *provider = conf.methods[i].provider;
|
||||
|
||||
conf.overhead = max_size_t(conf.overhead, provider->overhead);
|
||||
conf.min_overhead = min_size_t(conf.min_overhead, provider->overhead);
|
||||
conf.max_overhead = max_size_t(conf.max_overhead, provider->overhead);
|
||||
conf.encrypt_headroom = max_size_t(conf.encrypt_headroom, provider->encrypt_headroom);
|
||||
conf.decrypt_headroom = max_size_t(conf.decrypt_headroom, provider->decrypt_headroom);
|
||||
}
|
||||
|
@ -551,6 +554,14 @@ static void config_check_base(void) {
|
|||
if (!fastd_config_single_iface())
|
||||
exit_error("In Android integration mode exactly one peer must be configured");
|
||||
}
|
||||
|
||||
if (fastd_use_offload_l2tp()) {
|
||||
if (conf.mode != MODE_MULTITAP)
|
||||
exit_error("L2TP offload is available in multi-TAP mode only");
|
||||
|
||||
if (conf.iface_persist)
|
||||
exit_error("`persist iface' must be set to `no' for L2TP offload");
|
||||
}
|
||||
}
|
||||
|
||||
/** Performs more checks on the configuration */
|
||||
|
@ -583,7 +594,7 @@ bool fastd_config_single_iface(void) {
|
|||
return (VECTOR_LEN(ctx.peers) == 1);
|
||||
}
|
||||
|
||||
/** Determines of all interfaces are persistent (i.e. don't need to be created and destroyed dynamically) */
|
||||
/** Determines if all interfaces are persistent (i.e. don't need to be created and destroyed dynamically) */
|
||||
bool fastd_config_persistent_ifaces(void) {
|
||||
if (fastd_use_android_integration())
|
||||
return true;
|
||||
|
@ -659,7 +670,9 @@ static void configure_peers(bool dirs_only) {
|
|||
}
|
||||
}
|
||||
|
||||
size_t headroom = max_size_t(conf.encrypt_headroom, conf.decrypt_headroom + conf.overhead);
|
||||
/* Reserve one extra block of encrypt headroom for multiaf_tun targets */
|
||||
size_t headroom =
|
||||
max_size_t(conf.encrypt_headroom + sizeof(fastd_block128_t), conf.decrypt_headroom + conf.max_overhead);
|
||||
ctx.max_buffer = alignto(
|
||||
max_size_t(headroom + fastd_max_payload(ctx.max_mtu), MAX_HANDSHAKE_SIZE), sizeof(fastd_block128_t));
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2020, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
22
src/config.y
22
src/config.y
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2020, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
@ -14,7 +14,6 @@
|
|||
%code requires {
|
||||
#include "fastd.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
}
|
||||
|
||||
%union {
|
||||
|
@ -78,6 +77,7 @@
|
|||
%token TOK_IPV4
|
||||
%token TOK_IPV6
|
||||
%token TOK_KEY
|
||||
%token TOK_L2TP
|
||||
%token TOK_LEVEL
|
||||
%token TOK_LIMIT
|
||||
%token TOK_LOG
|
||||
|
@ -88,6 +88,7 @@
|
|||
%token TOK_MTU
|
||||
%token TOK_MULTITAP
|
||||
%token TOK_NO
|
||||
%token TOK_OFFLOAD
|
||||
%token TOK_ON
|
||||
%token TOK_PACKET
|
||||
%token TOK_PEER
|
||||
|
@ -179,6 +180,7 @@ statement: peer_group_statement
|
|||
| TOK_PMTU pmtu ';'
|
||||
| TOK_MODE mode ';'
|
||||
| TOK_PERSIST persist ';'
|
||||
| TOK_OFFLOAD offload ';'
|
||||
| TOK_PROTOCOL protocol ';'
|
||||
| TOK_SECRET secret ';'
|
||||
| TOK_ON TOK_PRE_UP on_pre_up ';'
|
||||
|
@ -276,6 +278,22 @@ persist: TOK_INTERFACE boolean {
|
|||
}
|
||||
;
|
||||
|
||||
offload: TOK_L2TP boolean {
|
||||
#ifdef WITH_OFFLOAD_L2TP
|
||||
conf.offload_l2tp = $2;
|
||||
#else
|
||||
if ($2) {
|
||||
# ifdef __linux__
|
||||
fastd_config_error(&@$, state, "L2TP offload is not supported by this build of fastd");
|
||||
# else
|
||||
fastd_config_error(&@$, state, "L2TP offload is not supported on this platform");
|
||||
# endif
|
||||
YYERROR;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
;
|
||||
|
||||
hide: TOK_IP TOK_ADDRESSES boolean {
|
||||
conf.hide_ip_addresses = $3;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2017, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -3,9 +3,9 @@ if get_option('cipher_salsa20_xmm').disabled()
|
|||
endif
|
||||
|
||||
if host_machine.cpu_family() == 'x86_64'
|
||||
asm_impl = 'salsa20_amd64_xmm6.s'
|
||||
asm_impl = 'salsa20_amd64_xmm6.S'
|
||||
elif host_machine.cpu_family() == 'x86'
|
||||
asm_impl = 'salsa20_x86_xmm5.s'
|
||||
asm_impl = 'salsa20_x86_xmm5.S'
|
||||
elif get_option('cipher_salsa20_xmm').auto()
|
||||
subdir_done()
|
||||
else
|
||||
|
|
4743
src/crypto/cipher/salsa20/xmm/salsa20_amd64_xmm6.S
Normal file
4743
src/crypto/cipher/salsa20/xmm/salsa20_amd64_xmm6.S
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
5008
src/crypto/cipher/salsa20/xmm/salsa20_x86_xmm5.S
Normal file
5008
src/crypto/cipher/salsa20/xmm/salsa20_x86_xmm5.S
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -3,9 +3,9 @@ if get_option('cipher_salsa2012_xmm').disabled()
|
|||
endif
|
||||
|
||||
if host_machine.cpu_family() == 'x86_64'
|
||||
asm_impl = 'salsa2012_amd64_xmm6.s'
|
||||
asm_impl = 'salsa2012_amd64_xmm6.S'
|
||||
elif host_machine.cpu_family() == 'x86'
|
||||
asm_impl = 'salsa2012_x86_xmm5.s'
|
||||
asm_impl = 'salsa2012_x86_xmm5.S'
|
||||
elif get_option('cipher_salsa2012_xmm').auto()
|
||||
subdir_done()
|
||||
else
|
||||
|
|
4743
src/crypto/cipher/salsa2012/xmm/salsa2012_amd64_xmm6.S
Normal file
4743
src/crypto/cipher/salsa2012/xmm/salsa2012_amd64_xmm6.S
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
5008
src/crypto/cipher/salsa2012/xmm/salsa2012_x86_xmm5.S
Normal file
5008
src/crypto/cipher/salsa2012/xmm/salsa2012_x86_xmm5.S
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2020, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
502
src/dep/libmnl/COPYING
Normal file
502
src/dep/libmnl/COPYING
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!
|
202
src/dep/libmnl/include/libmnl/libmnl.h
Normal file
202
src/dep/libmnl/include/libmnl/libmnl.h
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
|
11
src/dep/libmnl/meson.build
Normal file
11
src/dep/libmnl/meson.build
Normal file
|
@ -0,0 +1,11 @@
|
|||
libmnl = static_library(
|
||||
'libmnl',
|
||||
sources : [
|
||||
'src/attr.c',
|
||||
'src/callback.c',
|
||||
'src/nlmsg.c',
|
||||
'src/socket.c',
|
||||
],
|
||||
include_directories: include_directories('include'),
|
||||
c_args : '-Wno-unused-parameter',
|
||||
)
|
722
src/dep/libmnl/src/attr.c
Normal file
722
src/dep/libmnl/src/attr.c
Normal file
|
@ -0,0 +1,722 @@
|
|||
/*
|
||||
* (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
|
||||
*
|
||||
* This function returns 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
|
||||
*
|
||||
* This function returns the attribute length that is 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
|
||||
*
|
||||
* This function returns 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
|
||||
*
|
||||
* This function return a 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. Thus, it returns true on success and false on error.
|
||||
*
|
||||
* The len parameter may be negative in the case of malformed messages during
|
||||
* attribute iteration, that is why we use a signed integer.
|
||||
*/
|
||||
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
|
||||
*
|
||||
* This function returns a pointer to the next attribute after the one passed
|
||||
* as parameter. You have to use mnl_attr_ok() 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 to check if the attribute type is higher than the
|
||||
* maximum supported type. If the attribute type is invalid, this function
|
||||
* returns -1 and errno is explicitly set. On success, this function returns 1.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
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. This function
|
||||
* returns -1 in case of error, and errno is explicitly set.
|
||||
*/
|
||||
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 to perform a more accurate validation for attributes
|
||||
* whose size is variable. If the size of the attribute is not what we expect,
|
||||
* this functions returns -1 and errno is explicitly set.
|
||||
*/
|
||||
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 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).
|
||||
*
|
||||
* This function propagates the return value of the callback, which can be
|
||||
* MNL_CB_ERROR, MNL_CB_OK or MNL_CB_STOP.
|
||||
*/
|
||||
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 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).
|
||||
*
|
||||
* This function propagates the return value of the callback, which can be
|
||||
* MNL_CB_ERROR, MNL_CB_OK or MNL_CB_STOP.
|
||||
*/
|
||||
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).
|
||||
*
|
||||
* This function propagates the return value of the callback, which can be
|
||||
* MNL_CB_ERROR, MNL_CB_OK or MNL_CB_STOP.
|
||||
*/
|
||||
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 - returns 8-bit unsigned integer attribute payload
|
||||
* \param attr pointer to netlink attribute
|
||||
*
|
||||
* This function returns the 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 - returns 16-bit unsigned integer attribute payload
|
||||
* \param attr pointer to netlink attribute
|
||||
*
|
||||
* This function returns the 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 - returns 32-bit unsigned integer attribute payload
|
||||
* \param attr pointer to netlink attribute
|
||||
*
|
||||
* This function returns the 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 - returns 64-bit unsigned integer attribute.
|
||||
* \param attr pointer to netlink attribute
|
||||
*
|
||||
* This function returns the 64-bit value of the attribute payload. This
|
||||
* function is align-safe, since accessing 64-bit Netlink attributes is a
|
||||
* common source of alignment issues.
|
||||
*/
|
||||
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 - returns pointer to string attribute.
|
||||
* \param attr pointer to netlink attribute
|
||||
*
|
||||
* This function returns the payload of string attribute value.
|
||||
*/
|
||||
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. This function always returns a 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. The function returns true if the attribute could be added
|
||||
* to the message, otherwise false is returned.
|
||||
*/
|
||||
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. The function returns true if the attribute could be added
|
||||
* to the message, otherwise false is returned.
|
||||
*/
|
||||
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. The function returns true if the attribute could be added
|
||||
* to the message, otherwise false is returned.
|
||||
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||
* by adding the size (header + payload) of the new attribute.
|
||||
*/
|
||||
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. The function returns true if the attribute could be added
|
||||
* to the message, otherwise false is returned.
|
||||
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||
* by adding the size (header + payload) of the new attribute.
|
||||
*/
|
||||
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. The function returns true if the attribute could be added
|
||||
* to the message, otherwise false is returned.
|
||||
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||
* by adding the size (header + payload) of the new attribute.
|
||||
*/
|
||||
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. The function returns true if the attribute could be added
|
||||
* to the message, otherwise false is returned.
|
||||
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||
* by adding the size (header + payload) of the new attribute.
|
||||
*/
|
||||
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. The function returns true if the attribute could be added
|
||||
* to the message, otherwise false is returned.
|
||||
*/
|
||||
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. If the nested attribute cannot be added then NULL,
|
||||
* otherwise valid pointer to the beginning of the nest is returned.
|
||||
*/
|
||||
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
src/dep/libmnl/src/callback.c
Normal file
167
src/dep/libmnl/src/callback.c
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
9
src/dep/libmnl/src/internal.h
Normal file
9
src/dep/libmnl/src/internal.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define EXPORT_SYMBOL
|
557
src/dep/libmnl/src/nlmsg.c
Normal file
557
src/dep/libmnl/src/nlmsg.c
Normal file
|
@ -0,0 +1,557 @@
|
|||
/*
|
||||
* (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 <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)
|
||||
{
|
||||
return len >= (int)sizeof(struct nlmsghdr) &&
|
||||
nlh->nlmsg_len >= sizeof(struct nlmsghdr) &&
|
||||
(int)nlh->nlmsg_len <= len;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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_nlmsg_fprintf_payload(FILE *fd, const struct nlmsghdr *nlh,
|
||||
size_t extra_header_size)
|
||||
{
|
||||
int rem = 0;
|
||||
unsigned int i;
|
||||
|
||||
for (i=sizeof(struct nlmsghdr); i<nlh->nlmsg_len; i+=4) {
|
||||
char *b = (char *) nlh;
|
||||
struct nlattr *attr = (struct nlattr *) (b+i);
|
||||
|
||||
/* netlink control message. */
|
||||
if (nlh->nlmsg_type < NLMSG_MIN_TYPE) {
|
||||
fprintf(fd, "| %.2x %.2x %.2x %.2x |\t",
|
||||
0xff & b[i], 0xff & b[i+1],
|
||||
0xff & b[i+2], 0xff & b[i+3]);
|
||||
fprintf(fd, "| |\n");
|
||||
/* special handling for the extra header. */
|
||||
} else if (extra_header_size > 0) {
|
||||
extra_header_size -= 4;
|
||||
fprintf(fd, "| %.2x %.2x %.2x %.2x |\t",
|
||||
0xff & b[i], 0xff & b[i+1],
|
||||
0xff & b[i+2], 0xff & b[i+3]);
|
||||
fprintf(fd, "| extra header |\n");
|
||||
/* this seems like an attribute header. */
|
||||
} else if (rem == 0 && (attr->nla_type & NLA_TYPE_MASK) != 0) {
|
||||
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);
|
||||
fprintf(fd, "|len |flags| type|\n");
|
||||
|
||||
if (!(attr->nla_type & NLA_F_NESTED)) {
|
||||
rem = NLA_ALIGN(attr->nla_len) -
|
||||
sizeof(struct nlattr);
|
||||
}
|
||||
/* this is the attribute payload. */
|
||||
} else if (rem > 0) {
|
||||
rem -= 4;
|
||||
fprintf(fd, "| %.2x %.2x %.2x %.2x |\t",
|
||||
0xff & b[i], 0xff & b[i+1],
|
||||
0xff & b[i+2], 0xff & b[i+3]);
|
||||
fprintf(fd, "| data |");
|
||||
fprintf(fd, "\t %c %c %c %c\n",
|
||||
isprint(b[i]) ? b[i] : ' ',
|
||||
isprint(b[i+1]) ? b[i+1] : ' ',
|
||||
isprint(b[i+2]) ? b[i+2] : ' ',
|
||||
isprint(b[i+3]) ? b[i+3] : ' ');
|
||||
}
|
||||
}
|
||||
fprintf(fd, "----------------\t------------------\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_fprintf - print netlink message to file
|
||||
* \param fd pointer to file type
|
||||
* \param data pointer to the buffer that contains messages to be printed
|
||||
* \param datalen length of data stored in the buffer
|
||||
* \param extra_header_size size of the extra header (if any)
|
||||
*
|
||||
* This function prints the netlink header to a file handle.
|
||||
* It may be useful for debugging purposes. One example of the output
|
||||
* is the following:
|
||||
*
|
||||
*\verbatim
|
||||
---------------- ------------------
|
||||
| 0000000040 | | message length |
|
||||
| 00016 | R-A- | | type | flags |
|
||||
| 1289148991 | | sequence number|
|
||||
| 0000000000 | | port ID |
|
||||
---------------- ------------------
|
||||
| 00 00 00 00 | | extra header |
|
||||
| 00 00 00 00 | | extra header |
|
||||
| 01 00 00 00 | | extra header |
|
||||
| 01 00 00 00 | | extra header |
|
||||
|00008|--|00003| |len |flags| type|
|
||||
| 65 74 68 30 | | data | e t h 0
|
||||
---------------- ------------------
|
||||
\endverbatim
|
||||
*
|
||||
* This example above shows the netlink message that is send to kernel-space
|
||||
* to set up the link interface eth0. The netlink and attribute header data
|
||||
* are displayed in base 10 whereas the extra header and the attribute payload
|
||||
* are expressed in base 16. The possible flags in the netlink header are:
|
||||
*
|
||||
* - R, that indicates that NLM_F_REQUEST is set.
|
||||
* - M, that indicates that NLM_F_MULTI is set.
|
||||
* - A, that indicates that NLM_F_ACK is set.
|
||||
* - E, that indicates that NLM_F_ECHO is set.
|
||||
*
|
||||
* The lack of one flag is displayed with '-'. On the other hand, the possible
|
||||
* attribute flags available are:
|
||||
*
|
||||
* - N, that indicates that NLA_F_NESTED is set.
|
||||
* - B, that indicates that NLA_F_NET_BYTEORDER is set.
|
||||
*/
|
||||
EXPORT_SYMBOL void mnl_nlmsg_fprintf(FILE *fd, const void *data, size_t datalen,
|
||||
size_t extra_header_size)
|
||||
{
|
||||
const struct nlmsghdr *nlh = data;
|
||||
int len = datalen;
|
||||
|
||||
while (mnl_nlmsg_ok(nlh, len)) {
|
||||
mnl_nlmsg_fprintf_header(fd, nlh);
|
||||
mnl_nlmsg_fprintf_payload(fd, nlh, extra_header_size);
|
||||
nlh = mnl_nlmsg_next(nlh, &len);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* \defgroup batch Netlink message batch helpers
|
||||
*
|
||||
* This library provides helpers to batch several messages into one single
|
||||
* datagram. These helpers do not perform strict memory boundary checkings.
|
||||
*
|
||||
* The following figure represents a Netlink message batch:
|
||||
*\verbatim
|
||||
|<-------------- MNL_SOCKET_BUFFER_SIZE ------------->|
|
||||
|<-------------------- batch ------------------>| |
|
||||
|-----------|-----------|-----------|-----------|-----------|
|
||||
|<- nlmsg ->|<- nlmsg ->|<- nlmsg ->|<- nlmsg ->|<- nlmsg ->|
|
||||
|-----------|-----------|-----------|-----------|-----------|
|
||||
^ ^
|
||||
| |
|
||||
message N message N+1
|
||||
\endverbatim
|
||||
*
|
||||
* To start the batch, you have to call mnl_nlmsg_batch_start() and you can
|
||||
* use mnl_nlmsg_batch_stop() to release it.
|
||||
*
|
||||
* You have to invoke mnl_nlmsg_batch_next() to get room for a new message
|
||||
* in the batch. If this function returns NULL, it means that the last
|
||||
* message that was added (message N+1 in the figure above) does not fit the
|
||||
* batch. Thus, you have to send the batch (which includes until message N)
|
||||
* and, then, you have to call mnl_nlmsg_batch_reset() to re-initialize
|
||||
* the batch (this moves message N+1 to the head of the buffer). For that
|
||||
* reason, the buffer that you have to use to store the batch must be double
|
||||
* of MNL_SOCKET_BUFFER_SIZE to ensure that the last message (message N+1)
|
||||
* that did not fit into the batch is written inside valid memory boundaries.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
struct mnl_nlmsg_batch {
|
||||
/* the buffer that is used to store the batch. */
|
||||
void *buf;
|
||||
size_t limit;
|
||||
size_t buflen;
|
||||
/* the current netlink message in the batch. */
|
||||
void *cur;
|
||||
bool overflow;
|
||||
};
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_batch_start - initialize a batch
|
||||
* \param buf pointer to the buffer that will store this batch
|
||||
* \param limit maximum size of the batch (should be MNL_SOCKET_BUFFER_SIZE).
|
||||
*
|
||||
* The buffer that you pass must be double of MNL_SOCKET_BUFFER_SIZE. The
|
||||
* limit must be half of the buffer size, otherwise expect funny memory
|
||||
* corruptions 8-).
|
||||
*
|
||||
* You can allocate the buffer that you use to store the batch in the stack or
|
||||
* the heap, no restrictions in this regard. This function returns NULL on
|
||||
* error.
|
||||
*/
|
||||
EXPORT_SYMBOL struct mnl_nlmsg_batch *mnl_nlmsg_batch_start(void *buf,
|
||||
size_t limit)
|
||||
{
|
||||
struct mnl_nlmsg_batch *b;
|
||||
|
||||
b = malloc(sizeof(struct mnl_nlmsg_batch));
|
||||
if (b == NULL)
|
||||
return NULL;
|
||||
|
||||
b->buf = buf;
|
||||
b->limit = limit;
|
||||
b->buflen = 0;
|
||||
b->cur = buf;
|
||||
b->overflow = false;
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_batch_stop - release a batch
|
||||
* \param b pointer to batch
|
||||
*
|
||||
* This function releases the batch allocated by mnl_nlmsg_batch_start().
|
||||
*/
|
||||
EXPORT_SYMBOL void mnl_nlmsg_batch_stop(struct mnl_nlmsg_batch *b)
|
||||
{
|
||||
free(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_batch_next - get room for the next message in the batch
|
||||
* \param b pointer to batch
|
||||
*
|
||||
* This function returns false if the last message did not fit into the
|
||||
* batch. Otherwise, it prepares the batch to provide room for the new
|
||||
* Netlink message in the batch and returns true.
|
||||
*
|
||||
* You have to put at least one message in the batch before calling this
|
||||
* function, otherwise your application is likely to crash.
|
||||
*/
|
||||
EXPORT_SYMBOL bool mnl_nlmsg_batch_next(struct mnl_nlmsg_batch *b)
|
||||
{
|
||||
struct nlmsghdr *nlh = b->cur;
|
||||
|
||||
if (b->buflen + nlh->nlmsg_len > b->limit) {
|
||||
b->overflow = true;
|
||||
return false;
|
||||
}
|
||||
b->cur = b->buf + b->buflen + nlh->nlmsg_len;
|
||||
b->buflen += nlh->nlmsg_len;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_batch_reset - reset the batch
|
||||
* \param b pointer to batch
|
||||
*
|
||||
* This function allows to reset a batch, so you can reuse it to create a
|
||||
* new one. This function moves the last message which does not fit the
|
||||
* batch to the head of the buffer, if any.
|
||||
*/
|
||||
EXPORT_SYMBOL void mnl_nlmsg_batch_reset(struct mnl_nlmsg_batch *b)
|
||||
{
|
||||
if (b->overflow) {
|
||||
struct nlmsghdr *nlh = b->cur;
|
||||
memcpy(b->buf, b->cur, nlh->nlmsg_len);
|
||||
b->buflen = nlh->nlmsg_len;
|
||||
b->cur = b->buf + b->buflen;
|
||||
b->overflow = false;
|
||||
} else {
|
||||
b->buflen = 0;
|
||||
b->cur = b->buf;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_batch_size - get current size of the batch
|
||||
* \param b pointer to batch
|
||||
*
|
||||
* This function returns the current size of the batch.
|
||||
*/
|
||||
EXPORT_SYMBOL size_t mnl_nlmsg_batch_size(struct mnl_nlmsg_batch *b)
|
||||
{
|
||||
return b->buflen;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_batch_head - get head of this batch
|
||||
* \param b pointer to batch
|
||||
*
|
||||
* This function returns a pointer to the head of the batch, which is the
|
||||
* beginning of the buffer that is used.
|
||||
*/
|
||||
EXPORT_SYMBOL void *mnl_nlmsg_batch_head(struct mnl_nlmsg_batch *b)
|
||||
{
|
||||
return b->buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_batch_current - returns current position in the batch
|
||||
* \param b pointer to batch
|
||||
*
|
||||
* This function returns a pointer to the current position in the buffer
|
||||
* that is used to store the batch.
|
||||
*/
|
||||
EXPORT_SYMBOL void *mnl_nlmsg_batch_current(struct mnl_nlmsg_batch *b)
|
||||
{
|
||||
return b->cur;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_batch_is_empty - check if there is any message in the batch
|
||||
* \param b pointer to batch
|
||||
*
|
||||
* This function returns true if the batch is empty.
|
||||
*/
|
||||
EXPORT_SYMBOL bool mnl_nlmsg_batch_is_empty(struct mnl_nlmsg_batch *b)
|
||||
{
|
||||
return b->buflen == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
351
src/dep/libmnl/src/socket.c
Normal file
351
src/dep/libmnl/src/socket.c
Normal file
|
@ -0,0 +1,351 @@
|
|||
/*
|
||||
* (C) 2008-2010 by Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <libmnl/libmnl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include "internal.h"
|
||||
|
||||
/**
|
||||
* \mainpage
|
||||
*
|
||||
* libmnl is a minimalistic user-space library oriented to Netlink developers.
|
||||
* There are a lot of common tasks in parsing, validating, constructing of
|
||||
* both the Netlink header and TLVs that are repetitive and easy to get wrong.
|
||||
* This library aims to provide simple helpers that allows you to avoid
|
||||
* re-inventing the wheel in common Netlink tasks.
|
||||
*
|
||||
* \verbatim
|
||||
"Simplify, simplify" -- Henry David Thoureau. Walden (1854)
|
||||
\endverbatim
|
||||
*
|
||||
* The acronym libmnl stands for LIBrary Minimalistic NetLink.
|
||||
*
|
||||
* libmnl homepage is:
|
||||
* http://www.netfilter.org/projects/libmnl/
|
||||
*
|
||||
* \section features Main Features
|
||||
* - Small: the shared library requires around 30KB for an x86-based computer.
|
||||
* - Simple: this library avoids complex abstractions that tend to hide Netlink
|
||||
* details. It avoids elaborated object-oriented infrastructure and complex
|
||||
* callback-based workflow.
|
||||
* - Easy to use: the library simplifies the work for Netlink-wise developers.
|
||||
* It provides functions to make socket handling, message building,
|
||||
* validating, parsing and sequence tracking, easier.
|
||||
* - Easy to re-use: you can use this library to build your own abstraction
|
||||
* layer upon this library, if you want to provide another library that
|
||||
* hides Netlink details to your users.
|
||||
* - Decoupling: the interdependency of the main bricks that compose this
|
||||
* library is reduced, i.e. the library provides many helpers, but the
|
||||
* programmer is not forced to use them.
|
||||
*
|
||||
* \section licensing Licensing terms
|
||||
* This library is released under the LGPLv2.1 or any later (at your option).
|
||||
*
|
||||
* \section Dependencies
|
||||
* You have to install the Linux kernel headers that you want to use to develop
|
||||
* your application. Moreover, this library requires that you have some basics
|
||||
* on Netlink.
|
||||
*
|
||||
* \section scm Git Tree
|
||||
* The current development version of libmnl can be accessed at:
|
||||
* https://git.netfilter.org/libmnl/
|
||||
*
|
||||
* \section using Using libmnl
|
||||
* You can access several example files under examples/ in the libmnl source
|
||||
* code tree.
|
||||
*/
|
||||
|
||||
struct mnl_socket {
|
||||
int fd;
|
||||
struct sockaddr_nl addr;
|
||||
};
|
||||
|
||||
/**
|
||||
* \defgroup socket Netlink socket helpers
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* mnl_socket_get_fd - obtain file descriptor from netlink socket
|
||||
* \param nl netlink socket obtained via mnl_socket_open()
|
||||
*
|
||||
* This function returns the file descriptor of a given netlink socket.
|
||||
*/
|
||||
EXPORT_SYMBOL int mnl_socket_get_fd(const struct mnl_socket *nl)
|
||||
{
|
||||
return nl->fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_get_portid - obtain Netlink PortID from netlink socket
|
||||
* \param nl netlink socket obtained via mnl_socket_open()
|
||||
*
|
||||
* This function returns the Netlink PortID of a given netlink socket.
|
||||
* It's a common mistake to assume that this PortID equals the process ID
|
||||
* which is not always true. This is the case if you open more than one
|
||||
* socket that is binded to the same Netlink subsystem from the same process.
|
||||
*/
|
||||
EXPORT_SYMBOL unsigned int mnl_socket_get_portid(const struct mnl_socket *nl)
|
||||
{
|
||||
return nl->addr.nl_pid;
|
||||
}
|
||||
|
||||
static struct mnl_socket *__mnl_socket_open(int bus, int flags)
|
||||
{
|
||||
struct mnl_socket *nl;
|
||||
|
||||
nl = calloc(1, sizeof(struct mnl_socket));
|
||||
if (nl == NULL)
|
||||
return NULL;
|
||||
|
||||
nl->fd = socket(AF_NETLINK, SOCK_RAW | flags, bus);
|
||||
if (nl->fd == -1) {
|
||||
free(nl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return nl;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_open - open a netlink socket
|
||||
* \param bus the netlink socket bus ID (see NETLINK_* constants)
|
||||
*
|
||||
* On error, it returns NULL and errno is appropriately set. Otherwise, it
|
||||
* returns a valid pointer to the mnl_socket structure.
|
||||
*/
|
||||
EXPORT_SYMBOL struct mnl_socket *mnl_socket_open(int bus)
|
||||
{
|
||||
return __mnl_socket_open(bus, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_open2 - open a netlink socket with appropriate flags
|
||||
* \param bus the netlink socket bus ID (see NETLINK_* constants)
|
||||
* \param flags the netlink socket flags (see SOCK_* constants in socket(2))
|
||||
*
|
||||
* This is similar to mnl_socket_open(), but allows to set flags like
|
||||
* SOCK_CLOEXEC at socket creation time (useful for multi-threaded programs
|
||||
* performing exec calls).
|
||||
*
|
||||
* On error, it returns NULL and errno is appropriately set. Otherwise, it
|
||||
* returns a valid pointer to the mnl_socket structure.
|
||||
*/
|
||||
EXPORT_SYMBOL struct mnl_socket *mnl_socket_open2(int bus, int flags)
|
||||
{
|
||||
return __mnl_socket_open(bus, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_fdopen - associates a mnl_socket object with pre-existing socket.
|
||||
* \param fd pre-existing socket descriptor.
|
||||
*
|
||||
* On error, it returns NULL and errno is appropriately set. Otherwise, it
|
||||
* returns a valid pointer to the mnl_socket structure. It also sets the portID
|
||||
* if the socket fd is already bound and it is AF_NETLINK.
|
||||
*
|
||||
* Note that mnl_socket_get_portid() returns 0 if this function is used with
|
||||
* non-netlink socket.
|
||||
*/
|
||||
EXPORT_SYMBOL struct mnl_socket *mnl_socket_fdopen(int fd)
|
||||
{
|
||||
int ret;
|
||||
struct mnl_socket *nl;
|
||||
struct sockaddr_nl addr;
|
||||
socklen_t addr_len = sizeof(struct sockaddr_nl);
|
||||
|
||||
ret = getsockname(fd, (struct sockaddr *) &addr, &addr_len);
|
||||
if (ret == -1)
|
||||
return NULL;
|
||||
|
||||
nl = calloc(1, sizeof(struct mnl_socket));
|
||||
if (nl == NULL)
|
||||
return NULL;
|
||||
|
||||
nl->fd = fd;
|
||||
if (addr.nl_family == AF_NETLINK)
|
||||
nl->addr = addr;
|
||||
|
||||
return nl;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_bind - bind netlink socket
|
||||
* \param nl netlink socket obtained via mnl_socket_open()
|
||||
* \param groups the group of message you're interested in
|
||||
* \param pid the port ID you want to use (use zero for automatic selection)
|
||||
*
|
||||
* On error, this function returns -1 and errno is appropriately set. On
|
||||
* success, 0 is returned. You can use MNL_SOCKET_AUTOPID which is 0 for
|
||||
* automatic port ID selection.
|
||||
*/
|
||||
EXPORT_SYMBOL int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups,
|
||||
pid_t pid)
|
||||
{
|
||||
int ret;
|
||||
socklen_t addr_len;
|
||||
|
||||
nl->addr.nl_family = AF_NETLINK;
|
||||
nl->addr.nl_groups = groups;
|
||||
nl->addr.nl_pid = pid;
|
||||
|
||||
ret = bind(nl->fd, (struct sockaddr *) &nl->addr, sizeof (nl->addr));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
addr_len = sizeof(nl->addr);
|
||||
ret = getsockname(nl->fd, (struct sockaddr *) &nl->addr, &addr_len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (addr_len != sizeof(nl->addr)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (nl->addr.nl_family != AF_NETLINK) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_sendto - send a netlink message of a certain size
|
||||
* \param nl netlink socket obtained via mnl_socket_open()
|
||||
* \param buf buffer containing the netlink message to be sent
|
||||
* \param len number of bytes in the buffer that you want to send
|
||||
*
|
||||
* On error, it returns -1 and errno is appropriately set. Otherwise, it
|
||||
* returns the number of bytes sent.
|
||||
*/
|
||||
EXPORT_SYMBOL ssize_t mnl_socket_sendto(const struct mnl_socket *nl,
|
||||
const void *buf, size_t len)
|
||||
{
|
||||
static const struct sockaddr_nl snl = {
|
||||
.nl_family = AF_NETLINK
|
||||
};
|
||||
return sendto(nl->fd, buf, len, 0,
|
||||
(struct sockaddr *) &snl, sizeof(snl));
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_recvfrom - receive a netlink message
|
||||
* \param nl netlink socket obtained via mnl_socket_open()
|
||||
* \param buf buffer that you want to use to store the netlink message
|
||||
* \param bufsiz size of the buffer passed to store the netlink message
|
||||
*
|
||||
* On error, it returns -1 and errno is appropriately set. If errno is set
|
||||
* to ENOSPC, it means that the buffer that you have passed to store the
|
||||
* netlink message is too small, so you have received a truncated message.
|
||||
* To avoid this, you have to allocate a buffer of MNL_SOCKET_BUFFER_SIZE
|
||||
* (which is 8KB, see linux/netlink.h for more information). Using this
|
||||
* buffer size ensures that your buffer is big enough to store the netlink
|
||||
* message without truncating it.
|
||||
*/
|
||||
EXPORT_SYMBOL ssize_t mnl_socket_recvfrom(const struct mnl_socket *nl,
|
||||
void *buf, size_t bufsiz)
|
||||
{
|
||||
ssize_t ret;
|
||||
struct sockaddr_nl addr;
|
||||
struct iovec iov = {
|
||||
.iov_base = buf,
|
||||
.iov_len = bufsiz,
|
||||
};
|
||||
struct msghdr msg = {
|
||||
.msg_name = &addr,
|
||||
.msg_namelen = sizeof(struct sockaddr_nl),
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
.msg_control = NULL,
|
||||
.msg_controllen = 0,
|
||||
.msg_flags = 0,
|
||||
};
|
||||
ret = recvmsg(nl->fd, &msg, 0);
|
||||
if (ret == -1)
|
||||
return ret;
|
||||
|
||||
if (msg.msg_flags & MSG_TRUNC) {
|
||||
errno = ENOSPC;
|
||||
return -1;
|
||||
}
|
||||
if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_close - close a given netlink socket
|
||||
* \param nl netlink socket obtained via mnl_socket_open()
|
||||
*
|
||||
* On error, this function returns -1 and errno is appropriately set.
|
||||
* On success, it returns 0.
|
||||
*/
|
||||
EXPORT_SYMBOL int mnl_socket_close(struct mnl_socket *nl)
|
||||
{
|
||||
int ret = close(nl->fd);
|
||||
free(nl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_setsockopt - set Netlink socket option
|
||||
* \param nl netlink socket obtained via mnl_socket_open()
|
||||
* \param type type of Netlink socket options
|
||||
* \param buf the buffer that contains the data about this option
|
||||
* \param len the size of the buffer passed
|
||||
*
|
||||
* This function allows you to set some Netlink socket option. As of writing
|
||||
* this (see linux/netlink.h), the existing options are:
|
||||
*
|
||||
* - \#define NETLINK_ADD_MEMBERSHIP 1
|
||||
* - \#define NETLINK_DROP_MEMBERSHIP 2
|
||||
* - \#define NETLINK_PKTINFO 3
|
||||
* - \#define NETLINK_BROADCAST_ERROR 4
|
||||
* - \#define NETLINK_NO_ENOBUFS 5
|
||||
*
|
||||
* In the early days, Netlink only supported 32 groups expressed in a
|
||||
* 32-bits mask. However, since 2.6.14, Netlink may have up to 2^32 multicast
|
||||
* groups but you have to use setsockopt() with NETLINK_ADD_MEMBERSHIP to
|
||||
* join a given multicast group. This function internally calls setsockopt()
|
||||
* to join a given netlink multicast group. You can still use mnl_bind()
|
||||
* and the 32-bit mask to join a set of Netlink multicast groups.
|
||||
*
|
||||
* On error, this function returns -1 and errno is appropriately set.
|
||||
*/
|
||||
EXPORT_SYMBOL int mnl_socket_setsockopt(const struct mnl_socket *nl, int type,
|
||||
void *buf, socklen_t len)
|
||||
{
|
||||
return setsockopt(nl->fd, SOL_NETLINK, type, buf, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_getsockopt - get a Netlink socket option
|
||||
* \param nl netlink socket obtained via mnl_socket_open()
|
||||
* \param type type of Netlink socket options
|
||||
* \param buf pointer to the buffer to store the value of this option
|
||||
* \param len size of the information written in the buffer
|
||||
*
|
||||
* On error, this function returns -1 and errno is appropriately set.
|
||||
*/
|
||||
EXPORT_SYMBOL int mnl_socket_getsockopt(const struct mnl_socket *nl, int type,
|
||||
void *buf, socklen_t *len)
|
||||
{
|
||||
return getsockopt(nl->fd, SOL_NETLINK, type, buf, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
17
src/fastd.c
17
src/fastd.c
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2020, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
|
||||
Android port contributor:
|
||||
|
@ -19,6 +19,7 @@
|
|||
#include "async.h"
|
||||
#include "config.h"
|
||||
#include "crypto.h"
|
||||
#include "offload/l2tp/l2tp.h"
|
||||
#include "peer.h"
|
||||
#include "peer_group.h"
|
||||
#include "peer_hashtable.h"
|
||||
|
@ -182,7 +183,7 @@ static inline void on_pre_up(void) {
|
|||
/** Calls the on-up command */
|
||||
static inline void on_up(fastd_iface_t *iface) {
|
||||
fastd_shell_env_t *env = fastd_shell_env_alloc();
|
||||
fastd_shell_env_set_iface(env, iface);
|
||||
fastd_shell_env_set_iface(env, iface->name, iface->mtu);
|
||||
fastd_shell_command_exec_sync(&conf.peer_group->on_up, env, NULL);
|
||||
fastd_shell_env_free(env);
|
||||
}
|
||||
|
@ -190,7 +191,7 @@ static inline void on_up(fastd_iface_t *iface) {
|
|||
/** Calls the on-down command */
|
||||
static inline void on_down(fastd_iface_t *iface) {
|
||||
fastd_shell_env_t *env = fastd_shell_env_alloc();
|
||||
fastd_shell_env_set_iface(env, iface);
|
||||
fastd_shell_env_set_iface(env, iface->name, iface->mtu);
|
||||
fastd_shell_command_exec_sync(&conf.peer_group->on_down, env, NULL);
|
||||
fastd_shell_env_free(env);
|
||||
}
|
||||
|
@ -400,6 +401,8 @@ static inline void notify_systemd(void) {
|
|||
static inline void init_early(void) {
|
||||
fastd_close_all_fds();
|
||||
|
||||
fastd_random_init();
|
||||
|
||||
unsigned int seed;
|
||||
fastd_random_bytes(&seed, sizeof(seed), false);
|
||||
srandom(seed);
|
||||
|
@ -472,6 +475,9 @@ static inline void init(int argc, char *argv[]) {
|
|||
fastd_sem_init(&ctx.verify_limit, VERIFY_LIMIT);
|
||||
#endif
|
||||
|
||||
if (fastd_use_offload_l2tp())
|
||||
fastd_offload_l2tp_init();
|
||||
|
||||
if (pthread_attr_init(&ctx.detached_thread))
|
||||
exit_errno("pthread_attr_init");
|
||||
if (pthread_attr_setdetachstate(&ctx.detached_thread, PTHREAD_CREATE_DETACHED))
|
||||
|
@ -624,6 +630,9 @@ static inline void cleanup(void) {
|
|||
|
||||
fastd_peer_hashtable_free();
|
||||
|
||||
if (fastd_use_offload_l2tp())
|
||||
fastd_offload_l2tp_cleanup();
|
||||
|
||||
pthread_attr_destroy(&ctx.detached_thread);
|
||||
|
||||
VECTOR_FREE(ctx.async_pids);
|
||||
|
@ -636,6 +645,8 @@ static inline void cleanup(void) {
|
|||
|
||||
close_log();
|
||||
fastd_config_release();
|
||||
|
||||
fastd_random_cleanup();
|
||||
}
|
||||
|
||||
/** Terminates fastd by re-raising the received signal */
|
||||
|
|
60
src/fastd.h
60
src/fastd.h
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2020, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
|
||||
Android port contributor:
|
||||
|
@ -37,6 +37,8 @@
|
|||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
|
||||
/** An ethernet address */
|
||||
struct __attribute__((packed)) fastd_eth_addr {
|
||||
|
@ -66,7 +68,7 @@ struct fastd_protocol {
|
|||
/** Sends a handshake to the given peer */
|
||||
void (*handshake_init)(
|
||||
fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr,
|
||||
fastd_peer_t *peer);
|
||||
fastd_peer_t *peer, unsigned flags);
|
||||
|
||||
/** Handles a handshake for the given peer */
|
||||
void (*handshake_handle)(
|
||||
|
@ -146,14 +148,24 @@ struct fastd_bind_address {
|
|||
char *bindtodev; /**< May contain an interface name to limit the bind to */
|
||||
};
|
||||
|
||||
/** A socket descriptor */
|
||||
/**
|
||||
* A socket descriptor
|
||||
*
|
||||
* Sockets come in three flavours:
|
||||
*
|
||||
* - Global sockets stored in \e ctx.socks. \e addr references a global bind
|
||||
* address, \e peer and \e parent are NULL.
|
||||
* - Dynamic peer sockets used for a single connection (attempt).
|
||||
* \e peer points at the peer, \e addr and \e parent are NULL.
|
||||
* - L2TP offload sockets. \e addr and peer are NULL,
|
||||
* \e parent is the original socket which was used before offload setup.
|
||||
*/
|
||||
struct fastd_socket {
|
||||
fastd_poll_fd_t fd; /**< The file descriptor for the socket */
|
||||
const fastd_bind_address_t *addr; /**< The address this socket is supposed to be bound to (or NULL) */
|
||||
fastd_peer_address_t *bound_addr; /**< The actual address that was bound to (may differ from addr when addr has
|
||||
a random port) */
|
||||
fastd_peer_t *peer; /**< If the socket belongs to a single peer (as it was create dynamically when sending a
|
||||
handshake), contains that peer */
|
||||
fastd_peer_address_t *bound_addr; /**< Address that was bound to (differs from addr when it has random port) */
|
||||
fastd_peer_t *peer; /**< If the socket belongs to a single peer, contains that peer */
|
||||
fastd_socket_t *parent; /**< Original of L2TP offload socket */
|
||||
};
|
||||
|
||||
/** A TUN/TAP interface */
|
||||
|
@ -236,7 +248,8 @@ struct fastd_config {
|
|||
fastd_string_stack_t *method_list; /**< The list of configured method names */
|
||||
fastd_method_info_t *methods; /**< The list of configured methods */
|
||||
|
||||
size_t overhead; /**< The maximum overhead of all configured methods */
|
||||
size_t min_overhead; /**< The minimum overhead of all configured methods */
|
||||
size_t max_overhead; /**< The maximum overhead of all configured methods */
|
||||
size_t encrypt_headroom; /**< The minimum space a configured methods needs a the beginning of a source buffer to
|
||||
* encrypt */
|
||||
size_t decrypt_headroom; /**< The minimum space a configured methods needs a the beginning of a source buffer to
|
||||
|
@ -261,6 +274,10 @@ struct fastd_config {
|
|||
char *status_socket; /**< The path of the status socket */
|
||||
#endif
|
||||
|
||||
#ifdef WITH_OFFLOAD_L2TP
|
||||
bool offload_l2tp; /**< Enable L2TP offloading */
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
bool android_integration; /**< Enable Android GUI integration features */
|
||||
#endif
|
||||
|
@ -306,6 +323,10 @@ struct fastd_context {
|
|||
fastd_poll_fd_t status_fd; /**< The file descriptor of the status socket */
|
||||
#endif
|
||||
|
||||
#ifdef WITH_OFFLOAD_L2TP
|
||||
fastd_offload_l2tp_t *offload_l2tp; /**< Global L2TP offload state */
|
||||
#endif
|
||||
|
||||
bool has_floating; /**< Specifies if any of the configured peers have floating remotes */
|
||||
uint16_t max_mtu; /**< The maximum MTU of all peer-specific interfaces */
|
||||
size_t max_buffer; /**< Maximum buffer size needed for any combination of peer MTU, method, or handshake */
|
||||
|
@ -329,6 +350,7 @@ struct fastd_context {
|
|||
int android_ctrl_sock_fd; /**< The unix domain socket for communicating with Android GUI */
|
||||
#endif
|
||||
|
||||
FILE *urandom; /**< /dev/urandom FILE */
|
||||
int ioctl_sock; /**< The global ioctl socket */
|
||||
|
||||
size_t n_socks; /**< The number of sockets in socks */
|
||||
|
@ -365,11 +387,12 @@ void fastd_main(int argc, char *argv[]);
|
|||
|
||||
void fastd_send(
|
||||
const fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr,
|
||||
fastd_peer_t *peer, fastd_buffer_t *buffer, size_t stat_size);
|
||||
fastd_peer_t *peer, const fastd_buffer_t *buffer, size_t stat_size);
|
||||
void fastd_send_data(fastd_buffer_t *buffer, fastd_peer_t *source, fastd_peer_t *dest);
|
||||
|
||||
void fastd_receive_unknown_init(void);
|
||||
void fastd_receive_unknown_free(void);
|
||||
void fastd_receive_unknown_purge(fastd_peer_address_t addr);
|
||||
void fastd_receive(fastd_socket_t *sock);
|
||||
void fastd_handle_receive(fastd_peer_t *peer, fastd_buffer_t *buffer, bool reordered);
|
||||
|
||||
|
@ -377,17 +400,25 @@ void fastd_close_all_fds(void);
|
|||
|
||||
void fastd_socket_bind_all(void);
|
||||
fastd_socket_t *fastd_socket_open(fastd_peer_t *peer, int af);
|
||||
fastd_socket_t *fastd_socket_open_offload(fastd_socket_t *sock, const fastd_peer_address_t *local_addr);
|
||||
void fastd_socket_close(fastd_socket_t *sock);
|
||||
void fastd_socket_error(fastd_socket_t *sock);
|
||||
void fastd_socket_error(const fastd_socket_t *sock);
|
||||
|
||||
void fastd_resolve_peer(fastd_peer_t *peer, fastd_remote_t *remote);
|
||||
|
||||
bool fastd_iface_format_name(char ifname[IFNAMSIZ], const fastd_peer_t *peer);
|
||||
fastd_iface_t *fastd_iface_open(fastd_peer_t *peer);
|
||||
void fastd_iface_handle(fastd_iface_t *iface);
|
||||
void fastd_iface_write(fastd_iface_t *iface, fastd_buffer_t *buffer);
|
||||
void fastd_iface_close(fastd_iface_t *iface);
|
||||
#ifdef __linux__
|
||||
bool fastd_iface_set_mtu(const char *ifname, uint16_t mtu);
|
||||
#endif
|
||||
|
||||
void fastd_random_init(void);
|
||||
void fastd_random_bytes(void *buffer, size_t len, bool secure);
|
||||
void fastd_random_cleanup(void);
|
||||
|
||||
int64_t fastd_get_time(void);
|
||||
|
||||
|
||||
|
@ -580,6 +611,15 @@ static inline bool fastd_allow_verify(void) {
|
|||
#endif
|
||||
}
|
||||
|
||||
/** Returns true if L2TP offloading is enabled */
|
||||
static inline bool fastd_use_offload_l2tp(void) {
|
||||
#ifdef WITH_OFFLOAD_L2TP
|
||||
return conf.offload_l2tp;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Returns true if android integration is enabled */
|
||||
static inline bool fastd_use_android_integration(void) {
|
||||
#ifdef __ANDROID__
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2020, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
@ -163,7 +163,8 @@ static fastd_buffer_t *new_handshake(
|
|||
if (methods)
|
||||
method_list = create_method_list(methods, &method_list_len);
|
||||
|
||||
size_t buffer_space = 3 * RECORD_LEN(1) + /* handshake type, mode, reply code */
|
||||
size_t buffer_space = sizeof(fastd_control_packet_t) + sizeof(fastd_handshake_packet_t) +
|
||||
4 * RECORD_LEN(1) + /* handshake type, flags, mode, reply code */
|
||||
(mtu ? RECORD_LEN(2) : 0) + /* MTU */
|
||||
RECORD_LEN(version_len) + /* version name */
|
||||
RECORD_LEN(protocol_len) + /* protocol name */
|
||||
|
@ -172,18 +173,21 @@ static fastd_buffer_t *new_handshake(
|
|||
tail_space;
|
||||
|
||||
/* TODO: Make this a soft error */
|
||||
if (sizeof(fastd_handshake_packet_t) + buffer_space > MAX_HANDSHAKE_SIZE)
|
||||
if (buffer_space > MAX_HANDSHAKE_SIZE)
|
||||
exit_bug("oversized handshake packet");
|
||||
|
||||
fastd_buffer_t *buffer = fastd_buffer_alloc(sizeof(fastd_handshake_packet_t) + buffer_space, 0);
|
||||
fastd_buffer_t *buffer = fastd_buffer_alloc(buffer_space, 0);
|
||||
|
||||
fastd_buffer_pull(buffer, sizeof(fastd_control_packet_t));
|
||||
|
||||
fastd_handshake_packet_t *packet = buffer->data;
|
||||
packet->packet_type = PACKET_HANDSHAKE;
|
||||
packet->rsv = 0;
|
||||
packet->tlv_len = 0;
|
||||
*packet = (fastd_handshake_packet_t){
|
||||
.packet_type = PACKET_HANDSHAKE,
|
||||
};
|
||||
buffer->len = sizeof(*packet);
|
||||
|
||||
fastd_handshake_add_uint8(buffer, RECORD_HANDSHAKE_TYPE, type);
|
||||
fastd_handshake_add_uint8(buffer, RECORD_FLAGS, FLAG_L2TP_SUPPORT);
|
||||
fastd_handshake_add_uint8(buffer, RECORD_MODE, get_mode_id());
|
||||
|
||||
if (mtu)
|
||||
|
@ -271,6 +275,31 @@ static void print_error(
|
|||
}
|
||||
}
|
||||
|
||||
/** Sends and frees a handshake packet */
|
||||
void fastd_handshake_send_free(
|
||||
const fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr,
|
||||
fastd_peer_t *peer, fastd_buffer_t *buffer, unsigned flags) {
|
||||
|
||||
/* For the initial handshake, we send two handshakes: one for old
|
||||
* and one for new fastd versions */
|
||||
|
||||
if (flags == FLAG_INITIAL || !(flags & FLAG_L2TP_SUPPORT))
|
||||
fastd_send(sock, local_addr, remote_addr, peer, buffer, 0);
|
||||
|
||||
if (flags == FLAG_INITIAL || (flags & FLAG_L2TP_SUPPORT)) {
|
||||
const fastd_control_packet_t header = {
|
||||
.packet_type = PACKET_CONTROL,
|
||||
.flags_ver = PACKET_L2TP_VERSION,
|
||||
.length = htobe16(sizeof(header)),
|
||||
};
|
||||
fastd_buffer_push_from(buffer, &header, sizeof(header));
|
||||
|
||||
fastd_send(sock, local_addr, remote_addr, peer, buffer, 0);
|
||||
}
|
||||
|
||||
fastd_buffer_free(buffer);
|
||||
}
|
||||
|
||||
/** Sends an error reply to a peer */
|
||||
void fastd_handshake_send_error(
|
||||
fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr,
|
||||
|
@ -278,21 +307,25 @@ void fastd_handshake_send_error(
|
|||
print_error("sending", peer, remote_addr, reply_code, error_detail);
|
||||
|
||||
fastd_buffer_t *buffer = fastd_buffer_alloc(
|
||||
sizeof(fastd_handshake_packet_t) +
|
||||
3 * RECORD_LEN(1) /* enough space for handshake type, reply code and error detail */,
|
||||
sizeof(fastd_control_packet_t) + sizeof(fastd_handshake_packet_t) +
|
||||
4 * RECORD_LEN(1) /* enough space for handshake type, flags, reply code and error detail */,
|
||||
0);
|
||||
|
||||
fastd_buffer_pull(buffer, sizeof(fastd_control_packet_t));
|
||||
|
||||
fastd_handshake_packet_t *reply = buffer->data;
|
||||
reply->packet_type = PACKET_HANDSHAKE;
|
||||
reply->rsv = 0;
|
||||
reply->tlv_len = 0;
|
||||
*reply = (fastd_handshake_packet_t){
|
||||
.packet_type = PACKET_HANDSHAKE,
|
||||
};
|
||||
|
||||
buffer->len = sizeof(*reply);
|
||||
|
||||
fastd_handshake_add_uint8(buffer, RECORD_HANDSHAKE_TYPE, handshake->type + 1);
|
||||
fastd_handshake_add_uint8(buffer, RECORD_FLAGS, FLAG_L2TP_SUPPORT);
|
||||
fastd_handshake_add_uint8(buffer, RECORD_REPLY_CODE, reply_code);
|
||||
fastd_handshake_add_uint(buffer, RECORD_ERROR_DETAIL, error_detail);
|
||||
|
||||
fastd_send(sock, local_addr, remote_addr, peer, buffer, 0);
|
||||
fastd_handshake_send_free(sock, local_addr, remote_addr, peer, buffer, handshake->flags);
|
||||
}
|
||||
|
||||
/** Parses the TLV records of a handshake */
|
||||
|
@ -351,6 +384,14 @@ static inline void print_error_reply(
|
|||
static inline bool check_records(
|
||||
fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr,
|
||||
fastd_peer_t *peer, const fastd_handshake_t *handshake) {
|
||||
if (handshake->records[RECORD_FLAGS].data) {
|
||||
if (handshake->records[RECORD_FLAGS].length != 1 || (handshake->flags & ~FLAG_ALL)) {
|
||||
fastd_handshake_send_error(
|
||||
sock, local_addr, remote_addr, peer, handshake, REPLY_UNACCEPTABLE_VALUE, RECORD_FLAGS);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (handshake->records[RECORD_PROTOCOL_NAME].data) {
|
||||
if (!record_equal(conf.protocol->name, &handshake->records[RECORD_PROTOCOL_NAME])) {
|
||||
fastd_handshake_send_error(
|
||||
|
@ -455,25 +496,34 @@ fastd_handshake_get_method_by_name(const fastd_peer_t *peer, const fastd_handsha
|
|||
/** Handles a handshake packet */
|
||||
void fastd_handshake_handle(
|
||||
fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr,
|
||||
fastd_peer_t *peer, fastd_buffer_t *buffer) {
|
||||
char *peer_version = NULL;
|
||||
fastd_peer_t *peer, fastd_buffer_t *buffer, bool has_control_header) {
|
||||
|
||||
fastd_handshake_t handshake = parse_tlvs(buffer);
|
||||
|
||||
if (!handshake.tlv_data) {
|
||||
pr_warn("received a short handshake from %I", remote_addr);
|
||||
goto end_free;
|
||||
return;
|
||||
}
|
||||
|
||||
if (handshake.records[RECORD_HANDSHAKE_TYPE].length != 1) {
|
||||
pr_debug("received handshake without handshake type from %I", remote_addr);
|
||||
goto end_free;
|
||||
return;
|
||||
}
|
||||
|
||||
handshake.type = as_uint8(&handshake.records[RECORD_HANDSHAKE_TYPE]);
|
||||
|
||||
if (handshake.records[RECORD_FLAGS].length >= 1)
|
||||
handshake.flags = as_uint8(&handshake.records[RECORD_FLAGS]);
|
||||
|
||||
/* If the peer has L2TP support, it has sent two handshakes, one for
|
||||
* old fastd versions and one for new ones. Ignore the old handshake. */
|
||||
if (!has_control_header && (handshake.flags & FLAG_L2TP_SUPPORT))
|
||||
return;
|
||||
|
||||
if (!check_records(sock, local_addr, remote_addr, peer, &handshake))
|
||||
goto end_free;
|
||||
return;
|
||||
|
||||
char *peer_version = NULL;
|
||||
|
||||
if (handshake.type > 1) {
|
||||
if (handshake.records[RECORD_VERSION_NAME].data)
|
||||
|
@ -484,7 +534,5 @@ void fastd_handshake_handle(
|
|||
|
||||
conf.protocol->handshake_handle(sock, local_addr, remote_addr, peer, &handshake);
|
||||
|
||||
end_free:
|
||||
free(peer_version);
|
||||
fastd_buffer_free(buffer);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2020, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
@ -63,8 +63,17 @@ typedef enum fastd_reply_code {
|
|||
#define RECORD_LEN(len) ((len) + 4)
|
||||
|
||||
|
||||
/** fastd supports the new L2TP-compatible packet types; ignore packets using the old types */
|
||||
#define FLAG_L2TP_SUPPORT 0x01
|
||||
/** Union of all defined flags */
|
||||
#define FLAG_ALL 0x01
|
||||
|
||||
/** Passed to fastd_handshake_send_free() for the initial handshake */
|
||||
#define FLAG_INITIAL ((unsigned)-1)
|
||||
|
||||
|
||||
/** The handshake packet structure */
|
||||
typedef struct __attribute__((packed)) fastd_handshake_packet {
|
||||
typedef struct fastd_handshake_packet {
|
||||
uint8_t packet_type; /**< Packet type (must be PACKET_HANDSHAKE) */
|
||||
uint8_t rsv; /**< Reserved (must be 0) */
|
||||
uint16_t tlv_len; /**< Length of the TLV records */
|
||||
|
@ -80,6 +89,7 @@ typedef struct fastd_handshake_record {
|
|||
/** Describes a handshake packet */
|
||||
struct fastd_handshake {
|
||||
uint8_t type; /**< The handshake type */
|
||||
uint8_t flags; /**< Handshake flags */
|
||||
const char *peer_version; /**< The fastd version of the peer */
|
||||
fastd_handshake_record_t records[RECORD_MAX]; /**< The TLV records of the handshake */
|
||||
uint16_t tlv_len; /**< The length of the TLV record data */
|
||||
|
@ -92,6 +102,9 @@ fastd_buffer_t *fastd_handshake_new_reply(
|
|||
uint8_t type, uint16_t mtu, const fastd_method_info_t *method, const fastd_string_stack_t *methods,
|
||||
size_t tail_space);
|
||||
|
||||
void fastd_handshake_send_free(
|
||||
const fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr,
|
||||
fastd_peer_t *peer, fastd_buffer_t *buffer, unsigned flags);
|
||||
void fastd_handshake_send_error(
|
||||
fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr,
|
||||
fastd_peer_t *peer, const fastd_handshake_t *handshake, uint8_t reply_code, uint16_t error_detail);
|
||||
|
@ -106,7 +119,7 @@ fastd_handshake_get_method_by_name(const fastd_peer_t *peer, const fastd_handsha
|
|||
|
||||
void fastd_handshake_handle(
|
||||
fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr,
|
||||
fastd_peer_t *peer, fastd_buffer_t *buffer);
|
||||
fastd_peer_t *peer, fastd_buffer_t *buffer, bool has_control_header);
|
||||
|
||||
|
||||
/** Returns the TLV data of a handshake packet in a given buffer */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
144
src/iface.c
144
src/iface.c
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
|
||||
Android port contributor:
|
||||
|
@ -19,7 +19,6 @@
|
|||
#include "peer.h"
|
||||
#include "polling.h"
|
||||
|
||||
#include <net/if.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#ifdef __linux__
|
||||
|
@ -75,6 +74,23 @@ static void cleanup_iface(fastd_iface_t *iface);
|
|||
|
||||
#ifdef __linux__
|
||||
|
||||
bool fastd_iface_set_mtu(const char *ifname, uint16_t mtu) {
|
||||
struct ifreq ifr = {};
|
||||
strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
|
||||
|
||||
if (ioctl(ctx.ioctl_sock, SIOCGIFMTU, &ifr) < 0)
|
||||
return false;
|
||||
|
||||
if (ifr.ifr_mtu == mtu)
|
||||
return true;
|
||||
|
||||
ifr.ifr_mtu = mtu;
|
||||
if (ioctl(ctx.ioctl_sock, SIOCSIFMTU, &ifr) < 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Opens the TUN/TAP device helper shared by Android and Linux targets */
|
||||
static bool open_iface_linux(fastd_iface_t *iface, const char *ifname, uint16_t mtu, const char *dev_name) {
|
||||
struct ifreq ifr = {};
|
||||
|
@ -107,15 +123,9 @@ static bool open_iface_linux(fastd_iface_t *iface, const char *ifname, uint16_t
|
|||
|
||||
iface->name = fastd_strndup(ifr.ifr_name, IFNAMSIZ - 1);
|
||||
|
||||
if (ioctl(ctx.ioctl_sock, SIOCGIFMTU, &ifr) < 0)
|
||||
exit_errno("SIOCGIFMTU ioctl failed");
|
||||
|
||||
if (ifr.ifr_mtu != mtu) {
|
||||
ifr.ifr_mtu = mtu;
|
||||
if (ioctl(ctx.ioctl_sock, SIOCSIFMTU, &ifr) < 0) {
|
||||
pr_error_errno("unable to set TUN/TAP interface MTU: SIOCSIFMTU ioctl failed");
|
||||
return false;
|
||||
}
|
||||
if (!fastd_iface_set_mtu(iface->name, mtu)) {
|
||||
pr_error_errno("failed to set TUN/TAP interface MTU");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -338,7 +348,19 @@ static void cleanup_iface(UNUSED fastd_iface_t *iface) {}
|
|||
|
||||
#endif
|
||||
|
||||
#elif __APPLE__
|
||||
#elif defined(__APPLE__) || defined(__NetBSD__)
|
||||
|
||||
/** Sets up the TUN device */
|
||||
static bool setup_tun(fastd_iface_t *iface) {
|
||||
#if defined(__NetBSD__)
|
||||
int one = 1;
|
||||
if (ioctl(iface->fd.fd, TUNSIFHEAD, &one) < 0) {
|
||||
pr_error_errno("TUNSIFHEAD ioctl failed");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Opens the TUN/TAP device */
|
||||
static bool open_iface(fastd_iface_t *iface, const char *ifname, uint16_t mtu) {
|
||||
|
@ -375,6 +397,11 @@ static bool open_iface(fastd_iface_t *iface, const char *ifname, uint16_t mtu) {
|
|||
|
||||
iface->name = fastd_strndup(ifname, IFNAMSIZ - 1);
|
||||
|
||||
if (get_iface_type() == IFACE_TYPE_TUN) {
|
||||
if (!setup_tun(iface))
|
||||
return false;
|
||||
}
|
||||
|
||||
struct ifreq ifr = {};
|
||||
strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
|
||||
ifr.ifr_mtu = mtu;
|
||||
|
@ -402,7 +429,7 @@ void fastd_iface_handle(fastd_iface_t *iface) {
|
|||
|
||||
fastd_buffer_t *buffer;
|
||||
if (multiaf_tun && get_iface_type() == IFACE_TYPE_TUN)
|
||||
buffer = fastd_buffer_alloc(max_len + 4, conf.encrypt_headroom + 12);
|
||||
buffer = fastd_buffer_alloc(max_len + 4, conf.encrypt_headroom + (sizeof(fastd_block128_t) - 4));
|
||||
else
|
||||
buffer = fastd_buffer_alloc(max_len, conf.encrypt_headroom);
|
||||
|
||||
|
@ -450,55 +477,72 @@ void fastd_iface_write(fastd_iface_t *iface, fastd_buffer_t *buffer) {
|
|||
pr_debug2_errno("write");
|
||||
}
|
||||
|
||||
/** Opens a new TUN/TAP interface, optionally associated with a specific peer */
|
||||
fastd_iface_t *fastd_iface_open(fastd_peer_t *peer) {
|
||||
const char *ifname = conf.ifname;
|
||||
char ifnamebuf[IFNAMSIZ];
|
||||
bool fastd_iface_format_name(char ifname[IFNAMSIZ], const fastd_peer_t *peer) {
|
||||
const char *pattern = conf.ifname;
|
||||
|
||||
if (peer) {
|
||||
if (peer->ifname)
|
||||
ifname = peer->ifname;
|
||||
else if (!fastd_config_single_iface() && !(ifname && strchr(ifname, '%')))
|
||||
ifname = NULL;
|
||||
pattern = peer->ifname;
|
||||
else if (!fastd_config_single_iface() && !(pattern && strchr(pattern, '%')))
|
||||
pattern = NULL;
|
||||
}
|
||||
|
||||
const char *percent = ifname ? strchr(ifname, '%') : NULL;
|
||||
if (percent) {
|
||||
if (peer) {
|
||||
char prefix[percent - ifname + 1];
|
||||
memcpy(prefix, ifname, percent - ifname);
|
||||
prefix[percent - ifname] = 0;
|
||||
if (!pattern) {
|
||||
ifname[0] = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
ifname = NULL;
|
||||
const char *percent = strchr(pattern, '%');
|
||||
if (!percent) {
|
||||
strncpy(ifname, pattern, IFNAMSIZ - 1);
|
||||
ifname[IFNAMSIZ - 1] = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (percent[1]) {
|
||||
case 'n':
|
||||
if (peer->name) {
|
||||
snprintf(
|
||||
ifnamebuf, sizeof(ifnamebuf), "%s%s%s", prefix, peer->name,
|
||||
percent + 2);
|
||||
ifname = ifnamebuf;
|
||||
}
|
||||
if (!peer) {
|
||||
pr_error("invalid TUN/TAP device name: `%%n' and `%%k' patterns can't be used in TAP mode");
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
char prefix[percent - pattern + 1];
|
||||
memcpy(prefix, pattern, percent - pattern);
|
||||
prefix[percent - pattern] = 0;
|
||||
|
||||
case 'k': {
|
||||
char buf[17];
|
||||
if (conf.protocol->describe_peer(peer, buf, sizeof(buf))) {
|
||||
snprintf(ifnamebuf, sizeof(ifnamebuf), "%s%s%s", prefix, buf, percent + 2);
|
||||
ifname = ifnamebuf;
|
||||
}
|
||||
} break;
|
||||
char buf[17];
|
||||
|
||||
default:
|
||||
exit_bug("fastd_iface_open: invalid interface pattern");
|
||||
}
|
||||
} else {
|
||||
pr_error("invalid TUN/TAP device name: `%%n' and `%%k' patterns can't be used in TAP mode");
|
||||
return NULL;
|
||||
switch (percent[1]) {
|
||||
case 'n':
|
||||
if (!peer->name) {
|
||||
pr_error("invalid `%%n' interface pattern for peer without name");
|
||||
return false;
|
||||
}
|
||||
|
||||
snprintf(ifname, IFNAMSIZ, "%s%s%s", prefix, peer->name, percent + 2);
|
||||
break;
|
||||
|
||||
case 'k':
|
||||
if (!conf.protocol->describe_peer(peer, buf, sizeof(buf))) {
|
||||
pr_error("invalid `%%k' interface pattern for peer without key");
|
||||
return false;
|
||||
}
|
||||
|
||||
snprintf(ifname, IFNAMSIZ, "%s%s%s", prefix, buf, percent + 2);
|
||||
break;
|
||||
|
||||
default:
|
||||
exit_bug("fastd_iface_open: invalid interface pattern");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Opens a new TUN/TAP interface, optionally associated with a specific peer */
|
||||
fastd_iface_t *fastd_iface_open(fastd_peer_t *peer) {
|
||||
char ifname[IFNAMSIZ];
|
||||
|
||||
if (!fastd_iface_format_name(ifname, peer))
|
||||
return NULL;
|
||||
|
||||
fastd_iface_t *iface = fastd_new0(fastd_iface_t);
|
||||
iface->peer = peer;
|
||||
iface->mtu = fastd_peer_get_mtu(peer);
|
||||
|
@ -506,7 +550,7 @@ fastd_iface_t *fastd_iface_open(fastd_peer_t *peer) {
|
|||
|
||||
pr_debug("initializing TUN/TAP device...");
|
||||
|
||||
if (!open_iface(iface, ifname, iface->mtu)) {
|
||||
if (!open_iface(iface, ifname[0] ? ifname : NULL, iface->mtu)) {
|
||||
if (iface->fd.fd >= 0) {
|
||||
if (close(iface->fd.fd) == 0)
|
||||
cleanup_iface(iface);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2020, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
@ -75,6 +75,7 @@ static const keyword_t keywords[] = {
|
|||
{ "ipv4", TOK_IPV4 },
|
||||
{ "ipv6", TOK_IPV6 },
|
||||
{ "key", TOK_KEY },
|
||||
{ "l2tp", TOK_L2TP },
|
||||
{ "level", TOK_LEVEL },
|
||||
{ "limit", TOK_LIMIT },
|
||||
{ "log", TOK_LOG },
|
||||
|
@ -85,6 +86,7 @@ static const keyword_t keywords[] = {
|
|||
{ "mtu", TOK_MTU },
|
||||
{ "multitap", TOK_MULTITAP },
|
||||
{ "no", TOK_NO },
|
||||
{ "offload", TOK_OFFLOAD },
|
||||
{ "on", TOK_ON },
|
||||
{ "packet", TOK_PACKET },
|
||||
{ "peer", TOK_PEER },
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2020, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
29
src/log.c
29
src/log.c
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
|||
#include "peer.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
#include <syslog.h>
|
||||
|
||||
|
||||
|
@ -37,41 +36,53 @@ size_t fastd_snprint_peer_address(
|
|||
char *buffer, size_t size, const fastd_peer_address_t *address, const char *iface, bool bind_address,
|
||||
bool hide) {
|
||||
char addr_buf[INET6_ADDRSTRLEN] = "";
|
||||
uint16_t port;
|
||||
size_t ret;
|
||||
|
||||
switch (address->sa.sa_family) {
|
||||
case AF_UNSPEC:
|
||||
if (bind_address)
|
||||
return snprintf_safe(buffer, size, "any:%u", ntohs(address->in.sin_port));
|
||||
else
|
||||
return snprintf(buffer, size, "any");
|
||||
return snprintf_safe(buffer, size, "any");
|
||||
|
||||
case AF_INET:
|
||||
port = ntohs(address->in.sin_port);
|
||||
|
||||
if (!bind_address && hide)
|
||||
return snprintf_safe(buffer, size, "[hidden]:%u", ntohs(address->in.sin_port));
|
||||
ret = snprintf_safe(buffer, size, "[hidden]");
|
||||
else if (inet_ntop(AF_INET, &address->in.sin_addr, addr_buf, sizeof(addr_buf)))
|
||||
return snprintf_safe(buffer, size, "%s:%u", addr_buf, ntohs(address->in.sin_port));
|
||||
ret = snprintf_safe(buffer, size, "%s", addr_buf);
|
||||
else
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case AF_INET6:
|
||||
port = ntohs(address->in6.sin6_port);
|
||||
|
||||
if (!bind_address && hide)
|
||||
return snprintf_safe(buffer, size, "[hidden]:%u", ntohs(address->in6.sin6_port));
|
||||
ret = snprintf_safe(buffer, size, "[hidden]");
|
||||
if (inet_ntop(AF_INET6, &address->in6.sin6_addr, addr_buf, sizeof(addr_buf))) {
|
||||
char ifname_buf[IFNAMSIZ];
|
||||
if (!iface && IN6_IS_ADDR_LINKLOCAL(&address->in6.sin6_addr))
|
||||
iface = if_indextoname(address->in6.sin6_scope_id, ifname_buf);
|
||||
|
||||
if (iface)
|
||||
return snprintf_safe(
|
||||
buffer, size, "[%s%%%s]:%u", addr_buf, iface, ntohs(address->in6.sin6_port));
|
||||
ret = snprintf_safe(buffer, size, "[%s%%%s]", addr_buf, iface);
|
||||
else
|
||||
return snprintf_safe(buffer, size, "[%s]:%u", addr_buf, ntohs(address->in6.sin6_port));
|
||||
ret = snprintf_safe(buffer, size, "[%s]", addr_buf);
|
||||
} else
|
||||
return 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
exit_bug("unsupported address family");
|
||||
}
|
||||
|
||||
if (port)
|
||||
ret += snprintf_safe(buffer + ret, size - ret, ":%u", port);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Creates a string representation of a peer */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2020, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ cc = meson.get_compiler('c')
|
|||
default_args = [ '-D_GNU_SOURCE' ]
|
||||
|
||||
if host_machine.system() == 'darwin'
|
||||
default_args += '__APPLE_USE_RFC_3542'
|
||||
default_args += '-D__APPLE_USE_RFC_3542'
|
||||
endif
|
||||
|
||||
if cc.has_argument('-Wno-format-truncation')
|
||||
|
@ -30,11 +30,12 @@ version_h = vcs_tag(
|
|||
input : 'version.h.in',
|
||||
command : [
|
||||
'git',
|
||||
'--work-tree=' + meson.source_root(),
|
||||
'--git-dir=' + meson.source_root() / '.git',
|
||||
'--work-tree=' + meson.current_source_dir() / '..',
|
||||
'--git-dir=' + meson.current_source_dir() / '../.git',
|
||||
'describe',
|
||||
'--dirty=+',
|
||||
],
|
||||
fallback : 'v' + meson.project_version(),
|
||||
)
|
||||
|
||||
src = [
|
||||
|
@ -74,18 +75,21 @@ libs = []
|
|||
srcdir = include_directories('.')
|
||||
|
||||
need_libcrypto = false
|
||||
need_libmnl = false
|
||||
need_libsodium_nacl = false
|
||||
|
||||
subdir('crypto')
|
||||
subdir('methods')
|
||||
subdir('protocols')
|
||||
|
||||
|
||||
is_android = host_machine.system() == 'android'
|
||||
is_darwin = host_machine.system() == 'darwin'
|
||||
is_openbsd = host_machine.system() == 'openbsd'
|
||||
is_linux = host_machine.system() == 'linux'
|
||||
|
||||
|
||||
subdir('crypto')
|
||||
subdir('methods')
|
||||
subdir('offload')
|
||||
subdir('protocols')
|
||||
|
||||
|
||||
conf_data = configuration_data()
|
||||
|
||||
deps = []
|
||||
|
@ -114,6 +118,20 @@ if need_libcrypto
|
|||
deps += dependency('libcrypto')
|
||||
endif
|
||||
|
||||
if need_libmnl
|
||||
if get_option('libmnl_builtin')
|
||||
subdir('dep/libmnl')
|
||||
libmnl_dep = declare_dependency(
|
||||
link_with : libmnl,
|
||||
include_directories : include_directories('dep/libmnl/include'),
|
||||
)
|
||||
else
|
||||
libmnl_dep = dependency('libmnl')
|
||||
endif
|
||||
|
||||
deps += libmnl_dep
|
||||
endif
|
||||
|
||||
if need_libsodium_nacl
|
||||
if get_option('use_nacl')
|
||||
deps += cc.find_library('nacl')
|
||||
|
@ -210,6 +228,8 @@ conf_data.set('WITH_DYNAMIC_PEERS', not get_option('dynamic_peers').disabled())
|
|||
conf_data.set('WITH_STATUS_SOCKET', with_status_socket)
|
||||
conf_data.set('WITH_SYSTEMD', with_systemd)
|
||||
|
||||
conf_data.set('WITH_OFFLOAD_L2TP', with_offload_l2tp)
|
||||
|
||||
configure_file(
|
||||
input : 'build.h.in',
|
||||
output : 'build.h',
|
||||
|
|
11
src/method.h
11
src/method.h
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2020, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
@ -23,8 +23,12 @@ struct fastd_method_info {
|
|||
fastd_method_t *method; /**< Provider-specific method data */
|
||||
};
|
||||
|
||||
#define METHOD_FORCE_KEEPALIVE 0x01 /**< Send keepalives even in the presence of regular data transmissions */
|
||||
|
||||
/** Describes a method provider (an implementation of a class of encryption methods) */
|
||||
struct fastd_method_provider {
|
||||
unsigned flags;
|
||||
|
||||
size_t overhead; /**< The maximum number of bytes of overhead the methods may add */
|
||||
size_t encrypt_headroom; /**< The minimum head space needed for encrytion */
|
||||
size_t decrypt_headroom; /**< The minimum head space needed for decryption */
|
||||
|
@ -37,9 +41,12 @@ struct fastd_method_provider {
|
|||
/** Returns the key length used by a method */
|
||||
size_t (*key_length)(const fastd_method_t *method);
|
||||
|
||||
/** Returns an offload implementation, if used by the method */
|
||||
const fastd_offload_t *(*get_offload)(const fastd_method_t *method);
|
||||
|
||||
/** Initiates a session */
|
||||
fastd_method_session_state_t *(*session_init)(
|
||||
fastd_peer_t *peer, const fastd_method_t *method, const uint8_t *secret, bool initiator);
|
||||
fastd_peer_t *peer, const fastd_method_t *method, const uint8_t *secret, unsigned session_flags);
|
||||
/** Closes a session */
|
||||
void (*session_free)(fastd_method_session_state_t *session);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
@ -71,10 +71,10 @@ static size_t method_key_length(const fastd_method_t *method) {
|
|||
|
||||
/** Initializes a session */
|
||||
static fastd_method_session_state_t *
|
||||
method_session_init(fastd_peer_t *peer, const fastd_method_t *method, const uint8_t *secret, bool initiator) {
|
||||
method_session_init(fastd_peer_t *peer, const fastd_method_t *method, const uint8_t *secret, unsigned session_flags) {
|
||||
fastd_method_session_state_t *session = fastd_new(fastd_method_session_state_t);
|
||||
|
||||
fastd_method_common_init(&session->common, peer, initiator);
|
||||
fastd_method_common_init(&session->common, peer, session_flags);
|
||||
session->method = method;
|
||||
session->cipher = fastd_cipher_get(method->cipher_info);
|
||||
session->cipher_state = session->cipher->init(secret, 0);
|
||||
|
@ -131,8 +131,7 @@ static fastd_buffer_t *method_encrypt(fastd_method_session_state_t *session, fas
|
|||
|
||||
fastd_buffer_free(in);
|
||||
|
||||
fastd_method_put_common_header(out, session->common.send_nonce, 0);
|
||||
fastd_method_increment_nonce(&session->common);
|
||||
fastd_method_put_common_header(&session->common, out, 0);
|
||||
|
||||
return out;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
@ -15,15 +15,16 @@
|
|||
|
||||
|
||||
/** Common initialization for a new session */
|
||||
void fastd_method_common_init(fastd_method_common_t *session, fastd_peer_t *peer, bool initiator) {
|
||||
void fastd_method_common_init(fastd_method_common_t *session, fastd_peer_t *peer, unsigned session_flags) {
|
||||
memset(session, 0, sizeof(*session));
|
||||
|
||||
session->peer = peer;
|
||||
session->flags = session_flags;
|
||||
|
||||
session->valid_till = ctx.now + KEY_VALID;
|
||||
session->refresh_after = ctx.now + KEY_REFRESH - fastd_rand(0, KEY_REFRESH_SPLAY);
|
||||
|
||||
if (initiator) {
|
||||
if (session_flags & FASTD_SESSION_INITIATOR) {
|
||||
session->send_nonce[COMMON_NONCEBYTES - 1] = 3;
|
||||
} else {
|
||||
session->send_nonce[COMMON_NONCEBYTES - 1] = 2;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
@ -30,6 +30,8 @@
|
|||
typedef struct fastd_method_common {
|
||||
fastd_peer_t *peer;
|
||||
|
||||
unsigned flags; /**< Session flags */
|
||||
|
||||
fastd_timeout_t valid_till; /**< How long the session is valid */
|
||||
fastd_timeout_t refresh_after; /**< When to try refreshing the session */
|
||||
|
||||
|
@ -43,7 +45,7 @@ typedef struct fastd_method_common {
|
|||
} fastd_method_common_t;
|
||||
|
||||
|
||||
void fastd_method_common_init(fastd_method_common_t *session, fastd_peer_t *peer, bool initiator);
|
||||
void fastd_method_common_init(fastd_method_common_t *session, fastd_peer_t *peer, unsigned session_flags);
|
||||
bool fastd_method_is_nonce_valid(
|
||||
const fastd_method_common_t *session, const uint8_t nonce[COMMON_NONCEBYTES], int64_t *age);
|
||||
fastd_tristate_t
|
||||
|
@ -69,7 +71,7 @@ static inline bool fastd_method_session_common_is_valid(const fastd_method_commo
|
|||
The initiator of a session uses the odd nonces, the responder the even ones.
|
||||
*/
|
||||
static inline bool fastd_method_session_common_is_initiator(const fastd_method_common_t *session) {
|
||||
return (session->send_nonce[COMMON_NONCEBYTES - 1] & 1);
|
||||
return (session->flags & FASTD_SESSION_INITIATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -113,19 +115,34 @@ static inline void fastd_method_increment_nonce(fastd_method_common_t *session)
|
|||
}
|
||||
}
|
||||
|
||||
static inline uint8_t fastd_method_packet_type(unsigned session_flags) {
|
||||
if (session_flags & FASTD_SESSION_COMPAT)
|
||||
return PACKET_DATA_COMPAT;
|
||||
else
|
||||
return PACKET_DATA;
|
||||
}
|
||||
|
||||
/** Adds the common header to a packet buffer */
|
||||
static inline void
|
||||
fastd_method_put_common_header(fastd_buffer_t *buffer, const uint8_t nonce[COMMON_NONCEBYTES], uint8_t flags) {
|
||||
const uint8_t packet_type = PACKET_DATA;
|
||||
static inline void fastd_method_put_common_header_raw(
|
||||
fastd_buffer_t *buffer, const uint8_t nonce[COMMON_NONCEBYTES], uint8_t flags, unsigned session_flags) {
|
||||
const uint8_t packet_type = fastd_method_packet_type(session_flags);
|
||||
|
||||
fastd_buffer_push_from(buffer, nonce, COMMON_NONCEBYTES);
|
||||
fastd_buffer_push_from(buffer, &flags, 1);
|
||||
fastd_buffer_push_from(buffer, &packet_type, 1);
|
||||
}
|
||||
|
||||
/** Removes the common header from a view of a packet buffer */
|
||||
/** Adds the common header to a packet buffer and increments the nonce in the session state */
|
||||
static inline void
|
||||
fastd_method_take_common_header(fastd_buffer_view_t *buffer, uint8_t nonce[COMMON_NONCEBYTES], uint8_t *flags) {
|
||||
fastd_buffer_view_pull(buffer, 1);
|
||||
fastd_method_put_common_header(fastd_method_common_t *session, fastd_buffer_t *buffer, uint8_t flags) {
|
||||
fastd_method_put_common_header_raw(buffer, session->send_nonce, flags, session->flags);
|
||||
fastd_method_increment_nonce(session);
|
||||
}
|
||||
|
||||
/** Removes the common header from a view of a packet buffer */
|
||||
static inline void fastd_method_take_common_header(
|
||||
fastd_buffer_view_t *buffer, uint8_t nonce[COMMON_NONCEBYTES], uint8_t *packet_type, uint8_t *flags) {
|
||||
fastd_buffer_view_pull_to(buffer, packet_type, 1);
|
||||
fastd_buffer_view_pull_to(buffer, flags, 1);
|
||||
fastd_buffer_view_pull_to(buffer, nonce, COMMON_NONCEBYTES);
|
||||
}
|
||||
|
@ -134,8 +151,11 @@ fastd_method_take_common_header(fastd_buffer_view_t *buffer, uint8_t nonce[COMMO
|
|||
static inline bool fastd_method_handle_common_header(
|
||||
const fastd_method_common_t *session, fastd_buffer_view_t *buffer, uint8_t nonce[COMMON_NONCEBYTES],
|
||||
uint8_t *flags, int64_t *age) {
|
||||
fastd_method_take_common_header(buffer, nonce, flags);
|
||||
return fastd_method_is_nonce_valid(session, nonce, age);
|
||||
uint8_t packet_type;
|
||||
|
||||
fastd_method_take_common_header(buffer, nonce, &packet_type, flags);
|
||||
return (packet_type == fastd_method_packet_type(session->flags)) &&
|
||||
fastd_method_is_nonce_valid(session, nonce, age);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
@ -115,10 +115,10 @@ static size_t method_key_length(const fastd_method_t *method) {
|
|||
|
||||
/** Initializes a session */
|
||||
static fastd_method_session_state_t *
|
||||
method_session_init(fastd_peer_t *peer, const fastd_method_t *method, const uint8_t *secret, bool initiator) {
|
||||
method_session_init(fastd_peer_t *peer, const fastd_method_t *method, const uint8_t *secret, unsigned session_flags) {
|
||||
fastd_method_session_state_t *session = fastd_new(fastd_method_session_state_t);
|
||||
|
||||
fastd_method_common_init(&session->common, peer, initiator);
|
||||
fastd_method_common_init(&session->common, peer, session_flags);
|
||||
session->method = method;
|
||||
|
||||
session->cipher = fastd_cipher_get(method->cipher_info);
|
||||
|
@ -212,8 +212,7 @@ static fastd_buffer_t *method_encrypt(fastd_method_session_state_t *session, fas
|
|||
|
||||
fastd_buffer_free(in);
|
||||
|
||||
fastd_method_put_common_header(out, session->common.send_nonce, 0);
|
||||
fastd_method_increment_nonce(&session->common);
|
||||
fastd_method_put_common_header(&session->common, out, 0);
|
||||
|
||||
return out;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
@ -107,10 +107,10 @@ static size_t method_key_length(const fastd_method_t *method) {
|
|||
|
||||
/** Initializes a session */
|
||||
static fastd_method_session_state_t *
|
||||
method_session_init(fastd_peer_t *peer, const fastd_method_t *method, const uint8_t *secret, bool initiator) {
|
||||
method_session_init(fastd_peer_t *peer, const fastd_method_t *method, const uint8_t *secret, unsigned session_flags) {
|
||||
fastd_method_session_state_t *session = fastd_new(fastd_method_session_state_t);
|
||||
|
||||
fastd_method_common_init(&session->common, peer, initiator);
|
||||
fastd_method_common_init(&session->common, peer, session_flags);
|
||||
session->method = method;
|
||||
|
||||
session->cipher = fastd_cipher_get(method->cipher_info);
|
||||
|
@ -190,8 +190,7 @@ static fastd_buffer_t *method_encrypt(fastd_method_session_state_t *session, fas
|
|||
|
||||
fastd_buffer_free(in);
|
||||
|
||||
fastd_method_put_common_header(out, session->common.send_nonce, 0);
|
||||
fastd_method_increment_nonce(&session->common);
|
||||
fastd_method_put_common_header(&session->common, out, 0);
|
||||
|
||||
return out;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
@ -88,10 +88,10 @@ static size_t method_key_length(const fastd_method_t *method) {
|
|||
|
||||
/** Initializes a session */
|
||||
static fastd_method_session_state_t *
|
||||
method_session_init(fastd_peer_t *peer, const fastd_method_t *method, const uint8_t *secret, bool initiator) {
|
||||
method_session_init(fastd_peer_t *peer, const fastd_method_t *method, const uint8_t *secret, unsigned session_flags) {
|
||||
fastd_method_session_state_t *session = fastd_new(fastd_method_session_state_t);
|
||||
|
||||
fastd_method_common_init(&session->common, peer, initiator);
|
||||
fastd_method_common_init(&session->common, peer, session_flags);
|
||||
session->method = method;
|
||||
|
||||
session->cipher = fastd_cipher_get(method->cipher_info);
|
||||
|
@ -174,8 +174,7 @@ static fastd_buffer_t *method_encrypt(fastd_method_session_state_t *session, fas
|
|||
|
||||
fastd_buffer_free(in);
|
||||
|
||||
fastd_method_put_common_header(out, session->common.send_nonce, 0);
|
||||
fastd_method_increment_nonce(&session->common);
|
||||
fastd_method_put_common_header(&session->common, out, 0);
|
||||
|
||||
return out;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
@ -87,10 +87,10 @@ static size_t method_key_length(const fastd_method_t *method) {
|
|||
|
||||
/** Initializes a session */
|
||||
static fastd_method_session_state_t *
|
||||
method_session_init(fastd_peer_t *peer, const fastd_method_t *method, const uint8_t *secret, bool initiator) {
|
||||
method_session_init(fastd_peer_t *peer, const fastd_method_t *method, const uint8_t *secret, unsigned session_flags) {
|
||||
fastd_method_session_state_t *session = fastd_new(fastd_method_session_state_t);
|
||||
|
||||
fastd_method_common_init(&session->common, peer, initiator);
|
||||
fastd_method_common_init(&session->common, peer, session_flags);
|
||||
session->method = method;
|
||||
session->cipher = fastd_cipher_get(session->method->cipher_info);
|
||||
session->cipher_state = session->cipher->init(secret, 0);
|
||||
|
@ -155,8 +155,7 @@ static fastd_buffer_t *method_encrypt(fastd_method_session_state_t *session, fas
|
|||
|
||||
fastd_buffer_free(in);
|
||||
|
||||
fastd_method_put_common_header(out, session->common.send_nonce, 0);
|
||||
fastd_method_increment_nonce(&session->common);
|
||||
fastd_method_put_common_header(&session->common, out, 0);
|
||||
|
||||
return out;
|
||||
|
||||
|
@ -227,7 +226,7 @@ fail:
|
|||
|
||||
/* restore input buffer */
|
||||
fastd_buffer_push_from(in, tag, TAGBYTES);
|
||||
fastd_method_put_common_header(in, in_nonce, 0);
|
||||
fastd_method_put_common_header_raw(in, in_nonce, 0, session->common.flags);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
@ -81,10 +81,10 @@ static size_t method_key_length(const fastd_method_t *method) {
|
|||
|
||||
/** Initializes a session */
|
||||
static fastd_method_session_state_t *
|
||||
method_session_init(fastd_peer_t *peer, const fastd_method_t *method, const uint8_t *secret, bool initiator) {
|
||||
method_session_init(fastd_peer_t *peer, const fastd_method_t *method, const uint8_t *secret, unsigned session_flags) {
|
||||
fastd_method_session_state_t *session = fastd_new(fastd_method_session_state_t);
|
||||
|
||||
fastd_method_common_init(&session->common, peer, initiator);
|
||||
fastd_method_common_init(&session->common, peer, session_flags);
|
||||
session->method = method;
|
||||
|
||||
session->cipher = fastd_cipher_get(method->cipher_info);
|
||||
|
@ -154,8 +154,7 @@ static fastd_buffer_t *method_encrypt(fastd_method_session_state_t *session, fas
|
|||
|
||||
fastd_buffer_free(in);
|
||||
|
||||
fastd_method_put_common_header(out, session->common.send_nonce, 0);
|
||||
fastd_method_increment_nonce(&session->common);
|
||||
fastd_method_put_common_header(&session->common, out, 0);
|
||||
|
||||
return out;
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ subdir('generic_gmac')
|
|||
subdir('generic_poly1305')
|
||||
subdir('generic_umac')
|
||||
subdir('null')
|
||||
subdir('null-l2tp')
|
||||
|
||||
method_defs = ''
|
||||
method_list = ''
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
/*
|
||||
Copyright (c) 2012-2016, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
Copyright (c) Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
6
src/methods/null-l2tp/meson.build
Normal file
6
src/methods/null-l2tp/meson.build
Normal file
|
@ -0,0 +1,6 @@
|
|||
if get_option('method_null_l2tp').disabled()
|
||||
subdir_done()
|
||||
endif
|
||||
|
||||
methods += 'null_l2tp'
|
||||
src += files('null-l2tp.c')
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue