├── ChangeLog ├── m4 ├── .gitignore ├── mptcpd_kernel.m4 └── mptcpd_flags.m4 ├── include ├── Makefile.am ├── linux │ ├── Makefile.am │ ├── README │ ├── mptcp_upstream.h │ ├── mptcp_upstream_pm.h │ └── mptcp_org.h └── mptcpd │ ├── Makefile.am │ ├── private │ ├── mptcp_upstream.h │ ├── mptcp_org.h │ ├── listener_manager.h │ ├── id_manager.h │ ├── netlink_pm.h │ ├── murmur_hash.h │ ├── network_monitor.h │ ├── addr_info.h │ ├── configuration.h │ └── sockaddr.h │ ├── export.h │ ├── listener_manager.h │ ├── id_manager.h │ ├── addr_info.h │ └── types.h ├── plugins ├── Makefile.am └── path_managers │ ├── Makefile.am │ └── addr_adv.c ├── bootstrap ├── tests ├── plugins │ ├── Makefile.am │ ├── bad │ │ ├── failed_init.c │ │ ├── no_name.c │ │ ├── no_symbol.c │ │ └── Makefile.am │ ├── noop │ │ └── Makefile.am │ ├── security │ │ ├── Makefile.am │ │ ├── four.c │ │ └── three.c │ └── priority │ │ └── Makefile.am ├── test-bad-option ├── test-bad-log-empty ├── test-bad-log-short ├── test-bad-log-long ├── test-bad-plugin-dir ├── test-bad-path-manager ├── test-mptcpwrap ├── lib │ ├── Makefile.am │ ├── test-util.h │ ├── sockaddr.c │ ├── test-util.c │ ├── call_count.c │ └── call_plugin.c ├── test-murmur-hash.c ├── test-start-stop ├── test-addr-info.c ├── test-cxx-build.cpp ├── mptcpwrap-tester.c ├── test-id-manager.c ├── Makefile.am ├── test-configuration.c └── test-sockaddr.c ├── scripts ├── Makefile.am ├── check-permissions └── mptcp-get-debug ├── LICENSES ├── README └── Linux-syscall-note ├── AUTHORS ├── src ├── mptcp.service.in ├── path_manager.h ├── mptcpwrap.c ├── netlink_pm.h ├── netlink_pm.c ├── commands.c ├── Makefile.am ├── mptcpd.c └── commands.h ├── .github ├── workflows │ ├── multipath-tcp.org.yml │ ├── coverage.yml │ ├── ccpp.yml │ ├── ell-min.yml │ └── ell-master.yml └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── man ├── Makefile.am ├── mptcpize.8.in └── mptcpd.8.in ├── lib ├── mptcpd.pc.in ├── Makefile.am ├── addr_info.c ├── sockaddr.c ├── hash_sockaddr.h ├── hash_sockaddr.c └── murmur_hash.c ├── Makefile.am ├── .gitignore ├── etc ├── Makefile.am └── mptcpd.conf.in ├── SECURITY.md ├── COPYING ├── mptcpd.dox ├── .clang-format └── CODE_OF_CONDUCT.md /ChangeLog: -------------------------------------------------------------------------------- 1 | See the NEWS files for change descriptions at a high level, and the git 2 | log for low level descriptions. 3 | -------------------------------------------------------------------------------- /m4/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except these files 4 | !.gitignore 5 | !mptcpd_flags.m4 6 | -------------------------------------------------------------------------------- /include/Makefile.am: -------------------------------------------------------------------------------- 1 | ## SPDX-License-Identifier: BSD-3-Clause 2 | ## 3 | ## Copyright (c) 2017-2019, Intel Corporation 4 | 5 | SUBDIRS = mptcpd linux 6 | -------------------------------------------------------------------------------- /plugins/Makefile.am: -------------------------------------------------------------------------------- 1 | ## SPDX-License-Identifier: BSD-3-Clause 2 | ## 3 | ## Copyright (c) 2017, Intel Corporation 4 | 5 | SUBDIRS = path_managers 6 | -------------------------------------------------------------------------------- /bootstrap: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | # Copyright (c) 2019, Intel Corporation 5 | 6 | autoreconf --install --symlink --force 7 | -------------------------------------------------------------------------------- /tests/plugins/Makefile.am: -------------------------------------------------------------------------------- 1 | ## SPDX-License-Identifier: BSD-3-Clause 2 | ## 3 | ## Copyright (c) 2020, 2022, Intel Corporation 4 | 5 | SUBDIRS = bad noop priority security 6 | -------------------------------------------------------------------------------- /scripts/Makefile.am: -------------------------------------------------------------------------------- 1 | ## SPDX-License-Identifier: BSD-3-Clause 2 | ## 3 | ## Copyright (c) 2018, 2019, Intel Corporation 4 | 5 | dist_noinst_SCRIPTS = check-permissions 6 | 7 | dist_libexec_SCRIPTS = mptcp-get-debug 8 | -------------------------------------------------------------------------------- /include/linux/Makefile.am: -------------------------------------------------------------------------------- 1 | ## SPDX-License-Identifier: BSD-3-Clause 2 | ## 3 | ## Copyright (c) 2018, 2020, Intel Corporation 4 | 5 | noinst_HEADERS = mptcp_upstream.h mptcp_upstream_pm.h mptcp_org.h 6 | 7 | EXTRA_DIST = README 8 | -------------------------------------------------------------------------------- /LICENSES/README: -------------------------------------------------------------------------------- 1 | The `include/linux/mptcp.h' header file is licensed under the GPL 2.0 2 | license with the Linux system call exception. Full terms are 3 | available under: 4 | 5 | LICENSES/COPYING.GPL 6 | LICENSES/Linux-syscall-note 7 | -------------------------------------------------------------------------------- /tests/test-bad-option: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | # Test unknown command line option. 5 | # 6 | # Copyright (c) 2018-2019, 2021, Intel Corporation 7 | 8 | 9 | ../src/mptcpd --foo 10 | 11 | # Command line usage error exit code. See 12 | EX_USAGE=64 13 | 14 | # mptcpd should have exited with an EX_USAGE exit code. 15 | test $? != $EX_USAGE 16 | -------------------------------------------------------------------------------- /tests/test-bad-log-empty: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | # Test empty mptcpd "--log" command line option. 5 | # 6 | # Copyright (c) 2019, 2021, Intel Corporation 7 | 8 | 9 | ../src/mptcpd --log= 10 | 11 | # Command line usage error exit code. See 12 | EX_USAGE=64 13 | 14 | # mptcpd should have exited with an EX_USAGE exit code. 15 | test $? != $EX_USAGE 16 | -------------------------------------------------------------------------------- /tests/test-bad-log-short: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | # Test bad mptcpd "-l" short command line option. 5 | # 6 | # Copyright (c) 2019, 2021, Intel Corporation 7 | 8 | 9 | ../src/mptcpd -l foo 10 | 11 | # Command line usage error exit code. See 12 | EX_USAGE=64 13 | 14 | # mptcpd should have exited with an EX_USAGE exit code. 15 | test $? != $EX_USAGE 16 | -------------------------------------------------------------------------------- /tests/test-bad-log-long: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | # Test bad mptcpd "--log" long command line option. 5 | # 6 | # Copyright (c) 2019, 2021, Intel Corporation 7 | 8 | 9 | ../src/mptcpd --log=foo 10 | 11 | # Command line usage error exit code. See 12 | EX_USAGE=64 13 | 14 | # mptcpd should have exited with an EX_USAGE exit code. 15 | test $? != $EX_USAGE 16 | -------------------------------------------------------------------------------- /tests/test-bad-plugin-dir: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | # Test bad mptcpd "--plugin-dir" command line option. 5 | # 6 | # Copyright (c) 2019, 2021, Intel Corporation 7 | 8 | 9 | ../src/mptcpd --plugin-dir= 10 | 11 | # Command line usage error exit code. See . 12 | EX_USAGE=64 13 | 14 | # mptcpd should have exited with an EX_USAGE exit code. 15 | test $? != $EX_USAGE 16 | -------------------------------------------------------------------------------- /tests/test-bad-path-manager: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | # Test bad mptcpd "--path-manager" command line option. 5 | # 6 | # Copyright (c) 2019, 2021, Intel Corporation 7 | 8 | 9 | ../src/mptcpd --path-manager= 10 | 11 | # Command line usage error exit code. See 12 | EX_USAGE=64 13 | 14 | # mptcpd should have exited with an EX_USAGE exit code. 15 | test $? != $EX_USAGE 16 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Multipath TCP Daemon - mptcpd - Contributors 2 | ============================================ 3 | 4 | Ossama Othman 5 | Mat Martineau > 6 | Paolo Abeni 7 | Davide Caratti 8 | Daniel Danzberger 9 | João Meira 10 | Matthieu Baerts 11 | marco-a-itl 12 | -------------------------------------------------------------------------------- /src/mptcp.service.in: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # 3 | # Copyright (c) 2017-2019, 2022, Intel Corporation 4 | 5 | [Unit] 6 | Description=Multipath TCP service 7 | Documentation=man:mptcpd(8) 8 | 9 | [Service] 10 | Type=simple 11 | DynamicUser=yes 12 | Environment=LD_LIBRARY_PATH=@libdir@ 13 | ExecStart=@libexecdir@/mptcpd --log=journal 14 | CapabilityBoundingSet=CAP_NET_ADMIN 15 | AmbientCapabilities=CAP_NET_ADMIN 16 | LimitNPROC=1 17 | 18 | [Install] 19 | WantedBy=multi-user.target 20 | -------------------------------------------------------------------------------- /include/linux/README: -------------------------------------------------------------------------------- 1 | This directory contains copies of the header in the 2 | upstream Linux kernel, as well as the multipath-tcp.org kernel. They 3 | are only used if the mptcpd `configure' script doesn't detect them. 4 | Mptcpd supports the MPTCP path management generic netlink APIs defined 5 | in both headers, and refers to the upstream kernel header as 6 | "mptcp_upstream.h", and the multipath-tcp.org header as 7 | "mptcp_org.h". 8 | 9 | The licensing terms for both headers is the same as their in-kernel 10 | source tree counterparts. 11 | -------------------------------------------------------------------------------- /.github/workflows/multipath-tcp.org.yml: -------------------------------------------------------------------------------- 1 | name: multipath-tcp.org kernel 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v4 16 | - name: dependencies 17 | run: sudo apt-get -y install autoconf-archive git libell-dev 18 | - name: bootstrap 19 | run: ./bootstrap 20 | - name: configure 21 | run: ./configure --with-kernel=multipath-tcp.org 22 | - name: make 23 | run: make -j$(nproc) 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always 9 | frustrated when [...] 10 | 11 | **Describe the solution you'd like** 12 | A clear and concise description of what you want to happen. 13 | 14 | **Describe alternatives you've considered** 15 | A clear and concise description of any alternative solutions or 16 | features you've considered. 17 | 18 | **Additional context** 19 | Add any other context or screenshots about the feature request here. 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior: 12 | 1. '...' 13 | 14 | **Expected behavior** 15 | A clear and concise description of what you expected to happen. 16 | 17 | **Screenshots** 18 | If applicable, add screenshots to help explain your problem. 19 | 20 | **Desktop (please complete the following information):** 21 | - Linux Kernel: [e.g. 4.15] 22 | - Compiler: [e.g. gcc 7.0] 23 | 24 | **Additional context** 25 | Add any other context about the problem here. 26 | -------------------------------------------------------------------------------- /include/mptcpd/Makefile.am: -------------------------------------------------------------------------------- 1 | ## SPDX-License-Identifier: BSD-3-Clause 2 | ## 3 | ## Copyright (c) 2017-2022, Intel Corporation 4 | 5 | pkginclude_HEADERS = \ 6 | addr_info.h \ 7 | export.h \ 8 | id_manager.h \ 9 | listener_manager.h \ 10 | network_monitor.h \ 11 | path_manager.h \ 12 | plugin.h \ 13 | types.h 14 | 15 | noinst_HEADERS = \ 16 | private/addr_info.h \ 17 | private/config.h \ 18 | private/configuration.h \ 19 | private/id_manager.h \ 20 | private/listener_manager.h \ 21 | private/mptcp_org.h \ 22 | private/mptcp_upstream.h \ 23 | private/murmur_hash.h \ 24 | private/netlink_pm.h \ 25 | private/network_monitor.h \ 26 | private/path_manager.h \ 27 | private/plugin.h \ 28 | private/sockaddr.h 29 | -------------------------------------------------------------------------------- /man/Makefile.am: -------------------------------------------------------------------------------- 1 | ## SPDX-License-Identifier: BSD-3-Clause 2 | ## 3 | ## Copyright (c) 2017-2019, 2021, Intel Corporation 4 | 5 | man_MANS = mptcpd.8 mptcpize.8 6 | 7 | pkgsysconfdir = @sysconfdir@/@PACKAGE@ 8 | 9 | ## The configure script won't fully expand ${prefix} so leverage 10 | ## `make' based variable expansion instead. 11 | %.8: Makefile %.8.in 12 | $(AM_V_GEN)rm -f $@ $@.tmp; \ 13 | srcdir=''; \ 14 | test -f ./$@.in || srcdir=$(srcdir)/; \ 15 | sed \ 16 | -e 's,@pkgsysconfdir[@],$(pkgsysconfdir),g' \ 17 | -e 's,@PACKAGE_BUGREPORT[@],$(PACKAGE_BUGREPORT),g' \ 18 | $${srcdir}$@.in >$@.tmp; \ 19 | chmod 644 $@.tmp; \ 20 | mv $@.tmp $@ 21 | 22 | EXTRA_DIST = mptcpd.8.in mptcpize.8.in 23 | 24 | CLEANFILES = $(man_MANS) 25 | -------------------------------------------------------------------------------- /tests/plugins/bad/failed_init.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file failed_init.c 4 | * 5 | * @brief MPTCP test plugin with @c init function that fails. 6 | * 7 | * Copyright (c) 2022, Intel Corporation 8 | */ 9 | 10 | #include 11 | 12 | 13 | static int plugin_failed_init(struct mptcpd_pm *pm) 14 | { 15 | (void) pm; 16 | 17 | return -1; 18 | } 19 | 20 | MPTCPD_PLUGIN_DEFINE(plugin_failed_init, 21 | "test plugin for failed init", 22 | MPTCPD_PLUGIN_PRIORITY_DEFAULT, 23 | plugin_failed_init, 24 | NULL) // exit 25 | 26 | 27 | 28 | /* 29 | Local Variables: 30 | c-file-style: "linux" 31 | End: 32 | */ 33 | -------------------------------------------------------------------------------- /lib/mptcpd.pc.in: -------------------------------------------------------------------------------- 1 | # Basic package variables. 2 | prefix=@prefix@ 3 | exec_prefix=@exec_prefix@ 4 | libdir=@libdir@ 5 | includedir=@includedir@ 6 | 7 | # Mptcpd package library directory. 8 | # 9 | # This corresponds to the default plugin directory set when mptcpd was 10 | # built. It may differ from the actual site-specific plugin directory 11 | # if the default directory was overridden in the mptcpd configuration 12 | # file or on the command line. 13 | plugindir=@libdir@/@PACKAGE@ 14 | 15 | # Package keywords. 16 | Name: @PACKAGE_NAME@ 17 | Description: The Multipath TCP Daemon library 18 | URL: @PACKAGE_URL@ 19 | Version: @VERSION@ 20 | Requires.private: ell >= @ELL_VERSION@ 21 | Cflags: -I${includedir} 22 | Libs: -L${libdir} -lmptcpd 23 | Libs.private: @LIBS@ 24 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | ## SPDX-License-Identifier: BSD-3-Clause 2 | ## 3 | ## Copyright (c) 2017-2019, Intel Corporation 4 | 5 | SUBDIRS = etc man include lib src plugins tests scripts 6 | 7 | ACLOCAL_AMFLAGS = -I m4 8 | 9 | DISTCHECK_CONFIGURE_FLAGS = \ 10 | --with-systemdsystemunitdir='$$(prefix)/$(systemdsystemunitdir)' 11 | 12 | ## Doxygen stuff 13 | @DX_RULES@ 14 | MOSTLYCLEANFILES = $(DX_CLEANFILES) 15 | 16 | EXTRA_DIST = README.md Doxyfile mptcpd.dox LICENSES 17 | 18 | README: $(top_srcdir)/README.md 19 | @test -z "$(PANDOC)" || $(PANDOC) --from gfm --to plain --reference-links --reference-location=block --output=$@ $< 20 | 21 | dist-hook: README 22 | 23 | MAINTAINERCLEANFILES = README 24 | 25 | include $(top_srcdir)/aminclude_static.am 26 | 27 | clean-local: code-coverage-clean 28 | -------------------------------------------------------------------------------- /include/mptcpd/private/mptcp_upstream.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file mptcpd/private/mptcp_upstream.h 4 | * 5 | * @brief mptcpd convenience wrapper around upstream . 6 | * 7 | * Support for the upstream kernel header. 8 | * 9 | * Copyright (c) 2020-2021, Intel Corporation 10 | */ 11 | 12 | #ifndef MPTCPD_PRIVATE_MPTCP_UPSTREAM_H 13 | #define MPTCPD_PRIVATE_MPTCP_UPSTREAM_H 14 | 15 | #ifdef HAVE_CONFIG_H 16 | # include "mptcpd/private/config.h" 17 | #endif 18 | 19 | /* 20 | Platform might have upstream MPTCP path mangement generic netlink API, but 21 | always include a local copy which is synced with the supported features. 22 | */ 23 | #include "linux/mptcp_upstream.h" 24 | 25 | #endif // MPTCPD_PRIVATE_MPTCP_UPSTREAM_H 26 | -------------------------------------------------------------------------------- /tests/test-mptcpwrap: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | # Test that libmptcpwrap injects MPTCP into the socket() system call. 5 | # 6 | # Copyright (c) 2021-2022, Intel Corporation 7 | 8 | set -e 9 | 10 | # An exit status of 77 causes the Automake test driver to consider the 11 | # test as skipped. 12 | skip_exit_status=77 13 | 14 | # Check if we're using the upstream kernel. 15 | # 16 | # upstream: /proc/sys/net/mptcp/enabled 17 | # multipath-tcp.org: /proc/sys/net/mptcp/mptcp_enabled 18 | if [ ! -f /proc/sys/net/mptcp/enabled ]; then 19 | # Skip the test if we're not using the upstream kernel. 20 | echo Not running upstream kernel. libmptcpwrap will not be tested. 21 | exit $skip_exit_status 22 | fi 23 | 24 | LD_PRELOAD=../src/.libs/libmptcpwrap.so \ 25 | MPTCPWRAP_DEBUG=1 \ 26 | ./mptcpwrap-tester 27 | -------------------------------------------------------------------------------- /tests/lib/Makefile.am: -------------------------------------------------------------------------------- 1 | ## SPDX-License-Identifier: BSD-3-Clause 2 | ## 3 | ## Copyright (c) 2019-2020, Intel Corporation 4 | 5 | include $(top_srcdir)/aminclude_static.am 6 | 7 | AM_CPPFLAGS = \ 8 | -I$(top_srcdir)/include \ 9 | -I$(top_builddir)/include \ 10 | $(CODE_COVERAGE_CPPFLAGS) 11 | AM_CFLAGS = $(ELL_CFLAGS) $(CODE_COVERAGE_CFLAGS) 12 | 13 | ## Convenience library that contains utility functions used by the 14 | ## mptcpd tests. 15 | check_LTLIBRARIES = libmptcpd_test.la 16 | 17 | libmptcpd_test_la_SOURCES = \ 18 | call_count.c \ 19 | call_plugin.c \ 20 | sockaddr.c \ 21 | test-plugin.h \ 22 | test-util.c \ 23 | test-util.h 24 | libmptcpd_test_la_LIBADD = \ 25 | $(top_builddir)/lib/libmptcpd.la \ 26 | $(ELL_LIBS) \ 27 | $(CODE_COVERAGE_LIBS) 28 | 29 | # Clean up code coverage related generated files. 30 | clean-local: code-coverage-clean 31 | -------------------------------------------------------------------------------- /include/mptcpd/private/mptcp_org.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file mptcpd/private/mptcp_org.h 4 | * 5 | * @brief Convenience wrapper around multipath-tcp.org . 6 | * 7 | * Support for the multipath-tcp.org kernel header. 8 | * 9 | * Copyright (c) 2020-2021, Intel Corporation 10 | */ 11 | 12 | #ifndef MPTCPD_PRIVATE_MPTCP_ORG_H 13 | #define MPTCPD_PRIVATE_MPTCP_ORG_H 14 | 15 | #ifdef HAVE_CONFIG_H 16 | # include "mptcpd/private/config.h" 17 | #endif 18 | 19 | #ifdef HAVE_LINUX_MPTCP_H_MPTCP_ORG 20 | # include 21 | #else 22 | /* 23 | Platform does not have multipath-tcp.org MPTCP path mangement 24 | generic netlink API so include local copy of the multipath-tcp-org 25 | header. 26 | */ 27 | # include "linux/mptcp_org.h" 28 | #endif // HAVE_LINUX_MPTCP_H_MPTCP_ORG 29 | 30 | #endif // MPTCPD_PRIVATE_MPTCP_ORG_H 31 | -------------------------------------------------------------------------------- /tests/lib/test-util.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file test-util.h 4 | * 5 | * @brief mptcpd test utilities library. 6 | * 7 | * Copyright (c) 2020, 2022, Intel Corporation 8 | */ 9 | 10 | #ifndef MPTCP_TEST_UTIL_H 11 | #define MPTCP_TEST_UTIL_H 12 | 13 | 14 | /// Get MPTCP path management generic netlink API family name. 15 | char const *tests_get_pm_family_name(void); 16 | 17 | /** 18 | * @brief Exit test process if the kernel does not support MPTCP. 19 | * 20 | * If the kernel does not support MPTCP exit the current test process 21 | * with an exit status suitable for making the Automake @c test-driver 22 | * script interpret the test result as @c SKIP instead of @c PASS or 23 | * @c FAIL. This is useful for tests that need MPTCP but are run on 24 | * platforms with a non-MPTCP capable kernel. 25 | */ 26 | void tests_skip_if_no_mptcp(void); 27 | 28 | 29 | #endif // MPTCP_TEST_UTIL_H 30 | -------------------------------------------------------------------------------- /scripts/check-permissions: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | # 4 | # Copyright (c) 2018, 2019, Intel Corporation 5 | 6 | # Mptcpd expects key installation directories and files to only be 7 | # writable by the owner and group. This script verifies that the 8 | # write mode for "other" is not set. 9 | 10 | usage() 11 | { 12 | echo "Usage: $0 file|directory ... " 13 | exit 1 14 | } 15 | 16 | test -z "$1" && usage 17 | 18 | exit_status=0 19 | 20 | for p in $@; do 21 | # Access rights in human readable form (e.g. "drwxrwxr-x") 22 | perms=`stat -L -c %A $p` 23 | 24 | # The write mode for "others". 25 | other_write=`echo $perms | sed -e 's/.*\(.\).$/\1/'` 26 | 27 | # Check if the file or directory is writable by "other". 28 | if test $other_write != "-"; then 29 | echo "ERROR: incorrect permissions ($perms) for '$p'" 30 | echo "ERROR: '$p' should only be owner/group writable" 31 | exit_status=1 32 | fi 33 | done 34 | 35 | exit $exit_status 36 | -------------------------------------------------------------------------------- /lib/Makefile.am: -------------------------------------------------------------------------------- 1 | ## SPDX-License-Identifier: BSD-3-Clause 2 | ## 3 | ## Copyright (c) 2018-2020, 2022, Intel Corporation 4 | 5 | include $(top_srcdir)/aminclude_static.am 6 | 7 | if BUILDING_DLL 8 | AM_CPPFLAGS = -DMPTCPD_DLL -DMPTCPD_DLL_EXPORTS 9 | endif 10 | 11 | lib_LTLIBRARIES = libmptcpd.la 12 | 13 | libmptcpd_la_CPPFLAGS = \ 14 | -I$(top_srcdir)/include -I$(top_builddir)/include \ 15 | $(CODE_COVERAGE_CPPFLAGS) $(AM_CPPFLAGS) 16 | libmptcpd_la_CFLAGS = $(ELL_CFLAGS) $(CODE_COVERAGE_CFLAGS) 17 | libmptcpd_la_LIBADD = $(ELL_LIBS) $(CODE_COVERAGE_LIBS) 18 | libmptcpd_la_LDFLAGS = \ 19 | -version-info @LIB_CURRENT@:@LIB_REVISION@:@LIB_AGE@ 20 | 21 | libmptcpd_la_SOURCES = \ 22 | addr_info.c \ 23 | id_manager.c \ 24 | listener_manager.c \ 25 | network_monitor.c \ 26 | path_manager.c \ 27 | plugin.c \ 28 | sockaddr.c \ 29 | murmur_hash.c \ 30 | hash_sockaddr.c \ 31 | hash_sockaddr.h 32 | 33 | pkgconfigdir = $(libdir)/pkgconfig 34 | pkgconfig_DATA = mptcpd.pc 35 | 36 | clean-local: code-coverage-clean 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | *.o 3 | *.lo 4 | *.la 5 | *.so* 6 | *.a 7 | *~ 8 | *#*# 9 | .#* 10 | *.gcda 11 | *.gcno 12 | *-coverage* 13 | aminclude_static.am 14 | config.log 15 | config.status 16 | Makefile 17 | Makefile.in 18 | .deps 19 | INSTALL 20 | missing 21 | aclocal.m4 22 | ar-lib 23 | autom4te.cache/ 24 | compile 25 | configure 26 | depcomp 27 | .dirstamp 28 | install-sh 29 | libtool 30 | ltmain.sh 31 | .libs 32 | stamp* 33 | config.* 34 | private/config.h* 35 | mptcpd-*/ 36 | *.tar.* 37 | core* 38 | doc/ 39 | etc/*.conf 40 | lib/mptcpd.pc 41 | src/mptcpd 42 | src/mptcpize 43 | src/mptcp.service 44 | man/mptcpd.8 45 | man/mptcpize.8 46 | test-driver 47 | tests/test-network-monitor 48 | tests/test-plugin 49 | tests/test-path-manager 50 | tests/test-commands 51 | tests/test-configuration 52 | tests/test-cxx-build 53 | tests/test-id-manager 54 | tests/test-listener-manager 55 | tests/test-sockaddr 56 | tests/test-addr-info 57 | tests/test-murmur-hash 58 | tests/mptcpwrap-tester 59 | tests/*.log 60 | tests/*.trs 61 | tests/test-suite.log 62 | README 63 | compile_commands.json 64 | *.plist 65 | -------------------------------------------------------------------------------- /tests/plugins/bad/no_name.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file no_name.c 4 | * 5 | * @brief MPTCP test plugin missing a name. 6 | * 7 | * Copyright (c) 2022, Intel Corporation 8 | */ 9 | 10 | #include 11 | 12 | 13 | static int plugin_no_name_init(struct mptcpd_pm *pm) 14 | { 15 | (void) pm; 16 | 17 | return 0; 18 | } 19 | 20 | static void plugin_no_name_exit(struct mptcpd_pm *pm) 21 | { 22 | (void) pm; 23 | } 24 | 25 | /* 26 | Do not use the MPTCPD_PLUGIN_DEFINE() macro so that we can force the 27 | plugin name to be NULL. 28 | */ 29 | extern struct mptcpd_plugin_desc const MPTCPD_PLUGIN_SYM 30 | __attribute__((visibility("default"))); 31 | 32 | struct mptcpd_plugin_desc const MPTCPD_PLUGIN_SYM = { 33 | NULL, // plugin name 34 | "plugin with no name", 35 | 0, /* version */ 36 | MPTCPD_PLUGIN_PRIORITY_DEFAULT, 37 | plugin_no_name_init, 38 | plugin_no_name_exit 39 | }; 40 | 41 | 42 | /* 43 | Local Variables: 44 | c-file-style: "linux" 45 | End: 46 | */ 47 | -------------------------------------------------------------------------------- /.github/workflows/coverage.yml: -------------------------------------------------------------------------------- 1 | name: Coverage 2 | 3 | on: ["push", "pull_request"] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-22.04 9 | 10 | steps: 11 | - uses: actions/checkout@v4 12 | - name: dependencies 13 | run: sudo apt-get -y install autoconf-archive lcov git libell-dev 14 | - name: bootstrap 15 | run: ./bootstrap 16 | - name: configure 17 | run: ./configure --enable-code-coverage 18 | - name: make 19 | run: make -j$(nproc) 20 | - name: make check 21 | run: make check-code-coverage \ 22 | CODE_COVERAGE_OUTPUT_FILE=lcov.info \ 23 | CODE_COVERAGE_LCOV_OPTIONS="--no-external --exclude */tests/*" 24 | - name: sudo make check 25 | run: sudo make check-code-coverage \ 26 | CODE_COVERAGE_OUTPUT_FILE=lcov-sudo.info \ 27 | CODE_COVERAGE_LCOV_OPTIONS="--no-external --exclude */tests/*" 28 | - name: Coveralls 29 | uses: coverallsapp/github-action@v2 30 | with: 31 | github-token: ${{ secrets.GITHUB_TOKEN }} 32 | files: ./lcov.info ./lcov-sudo.info 33 | -------------------------------------------------------------------------------- /src/path_manager.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file src/path_manager.h 4 | * 5 | * @brief mptcpd user space path manager header file (internal). 6 | * 7 | * Copyright (c) 2017-2019, Intel Corporation 8 | */ 9 | 10 | #ifndef MPTCPD_PATH_MANAGER_H 11 | #define MPTCPD_PATH_MANAGER_H 12 | 13 | 14 | struct mptcpd_pm; 15 | struct mptcpd_config; 16 | 17 | /** 18 | * @brief Create a path manager. 19 | * 20 | * @param[in] config Mptcpd configuration. 21 | * 22 | * @todo As currently implemented, one could create multiple path 23 | * manager instances? Is that useful? 24 | * 25 | * @return Pointer to new path manager on success. @c NULL on 26 | * failure. 27 | */ 28 | struct mptcpd_pm * 29 | mptcpd_pm_create(struct mptcpd_config const *config); 30 | 31 | /** 32 | * Destroy a path manager. 33 | * 34 | * @param[in,out] pm Path manager to be destroyed. 35 | */ 36 | void mptcpd_pm_destroy(struct mptcpd_pm *pm); 37 | 38 | 39 | #endif /* MPTCPD_PATH_MANAGER_H */ 40 | 41 | 42 | /* 43 | Local Variables: 44 | c-file-style: "linux" 45 | End: 46 | */ 47 | -------------------------------------------------------------------------------- /etc/Makefile.am: -------------------------------------------------------------------------------- 1 | ## SPDX-License-Identifier: BSD-3-Clause 2 | ## 3 | ## Copyright (c) 2018, 2019, Intel Corporation 4 | 5 | EXTRA_DIST = mptcpd.conf.in 6 | 7 | pkgsysconf_DATA = mptcpd.conf 8 | pkgsysconfdir = $(sysconfdir)/@PACKAGE@ 9 | 10 | ## The configure script won't fully expand $pkglibdir so leverage 11 | ## `make' based variable expansion instead. 12 | mptcpd.conf: Makefile mptcpd.conf.in 13 | $(AM_V_GEN)rm -f $@ $@.tmp; \ 14 | srcdir=''; \ 15 | test -f ./$@.in || srcdir=$(srcdir)/; \ 16 | sed \ 17 | -e 's,@pkglibdir[@],$(pkglibdir),g' \ 18 | -e 's,@mptcpd_logger[@],$(mptcpd_logger),g' \ 19 | -e 's,@mptcpd_default_pm[@],$(mptcpd_default_pm),g' \ 20 | $${srcdir}$@.in >$@.tmp; \ 21 | chmod 644 $@.tmp; \ 22 | mv $@.tmp $@ 23 | 24 | CLEANFILES = mptcpd.conf 25 | 26 | # Make sure mptcpd system configuration directory is not world 27 | # writable. 28 | install-data-hook: installcheck-local 29 | chmod o-w $(DESTDIR)$(pkgsysconfdir) 30 | 31 | installcheck-local: 32 | $(top_srcdir)/scripts/check-permissions \ 33 | $(DESTDIR)$(pkgsysconfdir) \ 34 | $(DESTDIR)$(pkgsysconfdir)/mptcpd.conf 35 | -------------------------------------------------------------------------------- /include/mptcpd/export.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file export.h 4 | * 5 | * @brief mptcpd shared library symbol export/import macros. 6 | * 7 | * @internal The macros in this header are not part of the public 8 | * mptcpd library API. 9 | * 10 | * Copyright (c) 2018, 2019, Intel Corporation 11 | */ 12 | 13 | #ifndef MPTCPD_EXPORT_H 14 | #define MPTCPD_EXPORT_H 15 | 16 | // Internal macros 17 | #if __GNUC__ >= 4 18 | # define MPTCPD_DLL_IMPORT __attribute__((visibility ("default"))) 19 | # define MPTCPD_DLL_EXPORT __attribute__((visibility ("default"))) 20 | # define MPTCPD_DLL_LOCAL __attribute__((visibility ("hidden"))) 21 | #else 22 | # define MPTCPD_DLL_IMPORT 23 | # define MPTCPD_DLL_EXPORT 24 | # define MPTCPD_DLL_LOCAL 25 | #endif 26 | 27 | #ifdef MPTCPD_DLL 28 | # ifdef MPTCPD_DLL_EXPORTS 29 | # define MPTCPD_API MPTCPD_DLL_EXPORT 30 | # else 31 | # define MPTCPD_API MPTCPD_DLL_IMPORT 32 | # endif 33 | # define MPTCPD_LOCAL MPTCPD_DLL_LOCAL 34 | #else 35 | # define MPTCPD_API 36 | # define MPTCPD_LOCAL 37 | #endif 38 | 39 | #endif // MPTCPD_EXPORT_H 40 | -------------------------------------------------------------------------------- /include/mptcpd/private/listener_manager.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file private/listener_manager.h 4 | * 5 | * @brief Map of MPTCP local address to listener - private API. 6 | * 7 | * Copyright (c) 2022, Intel Corporation 8 | */ 9 | 10 | #ifndef MPTCPD_PRIVATE_LISTENER_MANAGER_H 11 | #define MPTCPD_PRIVATE_LISTENER_MANAGER_H 12 | 13 | #include 14 | 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | struct mptcpd_lm; 21 | 22 | /** 23 | * @brief Create a MPTCP listener manager. 24 | * 25 | * @return Pointer to a MPTCP listener manager on success. @c NULL on 26 | * failure. 27 | */ 28 | MPTCPD_API struct mptcpd_lm *mptcpd_lm_create(void); 29 | 30 | /** 31 | * @brief Destroy MPTCP listener manager. 32 | * 33 | * @param[in,out] lm The mptcpd address listener manager object. 34 | */ 35 | MPTCPD_API void mptcpd_lm_destroy(struct mptcpd_lm *lm); 36 | 37 | #ifdef __cplusplus 38 | } 39 | #endif 40 | 41 | 42 | #endif /* MPTCPD_PRIVATE_LISTENER_MANAGER_H */ 43 | 44 | 45 | /* 46 | Local Variables: 47 | c-file-style: "linux" 48 | End: 49 | */ 50 | -------------------------------------------------------------------------------- /.github/workflows/ccpp.yml: -------------------------------------------------------------------------------- 1 | name: C/C++ CI 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | strategy: 15 | matrix: 16 | debug: [enable-debug, disable-debug] 17 | 18 | steps: 19 | - uses: actions/checkout@v4 20 | - name: dependencies 21 | run: sudo apt-get -y install autoconf-archive pandoc git libell-dev 22 | - name: bootstrap 23 | run: ./bootstrap 24 | - name: configure 25 | run: ./configure --${{ matrix.debug }} 26 | - name: make 27 | run: make -j$(nproc) 28 | - name: make check 29 | run: make check || { cat tests/test-suite.log; exit 1; } 30 | - name: sudo make check 31 | run: sudo make check || { cat tests/test-suite.log; exit 1; } 32 | - name: make distcheck 33 | run: make distcheck 34 | - name: make install 35 | run: sudo make install 36 | - name: make installcheck 37 | run: LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH make installcheck 38 | - name: make uninstall 39 | run: sudo make uninstall 40 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 8 | 9 | | Version | Supported | 10 | | ------- | ------------------ | 11 | | < 1.0 | :x: | 12 | 13 | 15 | 16 | ## Reporting a Vulnerability 17 | 24 | 25 | Please report all security related issues through the Linux kernel 26 | MPTCP subsystem owner listed in the kernel 27 | [`MAINTAINERS`](https://www.kernel.org/doc/linux/MAINTAINERS) file. 28 | Include the following information: 29 | * Description of the security problem 30 | * Steps to reproduce 31 | * Expected behavior 32 | * Linux kernel, compiler, and mptcpd versions 33 | * Any additional information that may be relevant 34 | -------------------------------------------------------------------------------- /tests/plugins/noop/Makefile.am: -------------------------------------------------------------------------------- 1 | ## SPDX-License-Identifier: BSD-3-Clause 2 | ## 3 | ## Copyright (c) 2017-2020, Intel Corporation 4 | 5 | include $(top_srcdir)/aminclude_static.am 6 | 7 | AM_CPPFLAGS = \ 8 | -I$(top_srcdir)/include \ 9 | -I$(top_builddir)/include \ 10 | $(CODE_COVERAGE_CPPFLAGS) 11 | 12 | AM_CFLAGS = $(ELL_CFLAGS) $(CODE_COVERAGE_CFLAGS) 13 | 14 | ## -rpath is needed to force a DSO to be built when listing Libtool 15 | ## modules in the Automake check_LTLIBRARIES variable. Otherwise a 16 | ## convenience library would be built instead. 17 | AM_LDFLAGS = \ 18 | -no-undefined \ 19 | -module \ 20 | -avoid-version \ 21 | $(ELL_LIBS) \ 22 | -rpath $(abs_builddir) 23 | 24 | ## For mptcpd tests that require a plugin without testing the plugin 25 | ## itself. The plugin will be a no-op in this case. 26 | check_LTLIBRARIES = noop.la 27 | 28 | noop_la_SOURCES = noop.c 29 | noop_la_CPPFLAGS = \ 30 | $(AM_CPPFLAGS) \ 31 | -DTEST_PLUGIN=\"@TEST_PLUGIN_NOOP@\" 32 | noop_la_LIBADD = $(top_builddir)/lib/libmptcpd.la $(CODE_COVERAGE_LIBS) 33 | 34 | # Clean up code coverage related generated files. 35 | clean-local: code-coverage-clean 36 | -------------------------------------------------------------------------------- /tests/plugins/bad/no_symbol.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file no_symbol.c 4 | * 5 | * @brief MPTCP test plugin missing the expected plugin symbol. 6 | * 7 | * Copyright (c) 2022, Intel Corporation 8 | */ 9 | 10 | #include 11 | 12 | 13 | static int plugin_no_symbol_init(struct mptcpd_pm *pm) 14 | { 15 | (void) pm; 16 | 17 | return 0; 18 | } 19 | 20 | static void plugin_no_symbol_exit(struct mptcpd_pm *pm) 21 | { 22 | (void) pm; 23 | } 24 | 25 | /* 26 | Do not use the MPTCPD_PLUGIN_DEFINE() macro so that we can force the 27 | expected mptcpd plugin symbol, i.e. MPTCPD_PLUGIN_SYM, to be 28 | missing. 29 | */ 30 | extern struct mptcpd_plugin_desc const MPTCPD_BAD_PLUGIN_SYM 31 | __attribute__((visibility("default"))); 32 | 33 | struct mptcpd_plugin_desc const MPTCPD_BAD_PLUGIN_SYM = { 34 | NULL, // plugin name 35 | "plugin with no name", 36 | 0, /* version */ 37 | MPTCPD_PLUGIN_PRIORITY_DEFAULT, 38 | plugin_no_symbol_init, 39 | plugin_no_symbol_exit 40 | }; 41 | 42 | 43 | /* 44 | Local Variables: 45 | c-file-style: "linux" 46 | End: 47 | */ 48 | -------------------------------------------------------------------------------- /lib/addr_info.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file addr_info.c 4 | * 5 | * @brief @c mptcpd_addr_info related functions. 6 | * 7 | * Copyright (c) 2021, Intel Corporation 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | 14 | struct sockaddr const * 15 | mptcpd_addr_info_get_addr(struct mptcpd_addr_info const *info) 16 | { 17 | if (info == NULL) 18 | return NULL; 19 | 20 | return (struct sockaddr const *) &info->addr; 21 | } 22 | 23 | mptcpd_aid_t mptcpd_addr_info_get_id(struct mptcpd_addr_info const *info) 24 | { 25 | if (info == NULL) 26 | return 0; /// @todo Good value to return on error? 27 | 28 | return info->id; 29 | } 30 | 31 | mptcpd_flags_t 32 | mptcpd_addr_info_get_flags(struct mptcpd_addr_info const *info) 33 | { 34 | if (info == NULL) 35 | return 0; 36 | 37 | return info->flags; 38 | } 39 | 40 | int mptcpd_addr_info_get_index(struct mptcpd_addr_info const *info) 41 | { 42 | if (info == NULL) 43 | return -1; 44 | 45 | return info->index; 46 | } 47 | 48 | 49 | /* 50 | Local Variables: 51 | c-file-style: "linux" 52 | End: 53 | */ 54 | -------------------------------------------------------------------------------- /tests/plugins/bad/Makefile.am: -------------------------------------------------------------------------------- 1 | ## SPDX-License-Identifier: BSD-3-Clause 2 | ## 3 | ## Copyright (c) 2022, Intel Corporation 4 | 5 | include $(top_srcdir)/aminclude_static.am 6 | 7 | AM_CPPFLAGS = \ 8 | -I$(top_srcdir)/include \ 9 | -I$(top_builddir)/include \ 10 | $(CODE_COVERAGE_CPPFLAGS) 11 | 12 | AM_CFLAGS = $(ELL_CFLAGS) $(CODE_COVERAGE_CFLAGS) 13 | 14 | ## -rpath is needed to force a DSO to be built when listing Libtool 15 | ## modules in the Automake check_LTLIBRARIES variable. Otherwise a 16 | ## convenience library would be built instead. 17 | AM_LDFLAGS = \ 18 | -no-undefined \ 19 | -module \ 20 | -avoid-version \ 21 | $(ELL_LIBS) \ 22 | -rpath $(abs_builddir) 23 | 24 | ## For mptcpd tests that require a plugin without testing the plugin 25 | ## itself. The plugin will be a no-op in this case. 26 | check_LTLIBRARIES = no_name.la no_symbol.la failed_init.la 27 | 28 | no_name_la_SOURCES = no_name.c 29 | no_name_la_LIBADD = $(CODE_COVERAGE_LIBS) 30 | 31 | no_symbol_la_SOURCES = no_symbol.c 32 | no_symbol_la_LIBADD = $(CODE_COVERAGE_LIBS) 33 | 34 | failed_init_la_SOURCES = failed_init.c 35 | failed_init_la_LIBADD = $(CODE_COVERAGE_LIBS) 36 | 37 | # Clean up code coverage related generated files. 38 | clean-local: code-coverage-clean 39 | -------------------------------------------------------------------------------- /.github/workflows/ell-min.yml: -------------------------------------------------------------------------------- 1 | name: ELL min version 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | strategy: 15 | matrix: 16 | cc: [gcc, clang] 17 | 18 | steps: 19 | - uses: actions/checkout@v4 20 | - name: dependencies 21 | run: sudo apt-get -y install autoconf-archive git clang 22 | - name: build and install ELL 23 | run: | 24 | for i in $(seq 30); do 25 | git clone https://kernel.googlesource.com/pub/scm/libs/ell/ell && break 26 | echo "Attempt $i failed, retrying in 30 seconds..." 27 | sleep 30 28 | done 29 | cd ell 30 | git checkout 0.30 31 | ./bootstrap 32 | ./configure CC=${{ matrix.cc }} --prefix=/usr 33 | sudo make -j$(nproc) install 34 | - name: bootstrap 35 | run: ./bootstrap 36 | - name: configure 37 | run: ./configure CC=${{ matrix.cc }} 38 | - name: make 39 | run: make -j$(nproc) 40 | - name: make check 41 | run: make check || { cat tests/test-suite.log; exit 1; } 42 | - name: sudo make check 43 | run: sudo make check || { cat tests/test-suite.log; exit 1; } 44 | -------------------------------------------------------------------------------- /src/mptcpwrap.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file mptcpwrap.c 4 | * 5 | * @brief wrapper for socket() libcall hijacking 6 | * 7 | * Copyright (c) 2021, Red Hat, Inc. 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | // libtool will make every symbol hidden by default 20 | int __attribute__((visibility("default"))) socket(int family, int type, int protocol) 21 | { 22 | int ret, orig_protocol = protocol; 23 | 24 | // the 'type' field may encode socket flags 25 | if ((family != AF_INET && family != AF_INET6) || 26 | (type & 0xff) != SOCK_STREAM) 27 | goto do_socket; 28 | 29 | // socket(AF_INET, SOCK_STREAM, 0) maps to TCP, too 30 | if (protocol != 0 && protocol != IPPROTO_TCP) 31 | goto do_socket; 32 | 33 | protocol = IPPROTO_TCP + 256; 34 | 35 | do_socket: 36 | ret = syscall(__NR_socket, family, type, protocol); 37 | if (getenv("MPTCPWRAP_DEBUG") && protocol != orig_protocol) 38 | fprintf(stderr, "mptcpwrap: changing socket protocol from 0x%x " 39 | "to 0x%x (IPPROTO_MPTCP) for family 0x%x " 40 | "type 0x%x fd %d\n", orig_protocol, protocol, 41 | family, type, ret); 42 | return ret; 43 | } 44 | -------------------------------------------------------------------------------- /.github/workflows/ell-master.yml: -------------------------------------------------------------------------------- 1 | name: ELL master 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | schedule: 9 | - cron: '33 6 * * *' 10 | 11 | jobs: 12 | build: 13 | 14 | runs-on: ubuntu-latest 15 | 16 | strategy: 17 | matrix: 18 | cc: [gcc, clang] 19 | 20 | steps: 21 | - uses: actions/checkout@v4 22 | - name: dependencies 23 | run: sudo apt-get -y install autoconf-archive git clang 24 | - name: build and install ELL 25 | run: | 26 | for i in $(seq 30); do 27 | git clone https://kernel.googlesource.com/pub/scm/libs/ell/ell && break 28 | echo "Attempt $i failed, retrying in 30 seconds..." 29 | sleep 30 30 | done 31 | cd ell 32 | git log -1 --oneline --no-decorate 33 | ./bootstrap 34 | ./configure CC=${{ matrix.cc }} --prefix=/usr 35 | sudo make -j$(nproc) install 36 | - name: bootstrap 37 | run: ./bootstrap 38 | - name: configure 39 | run: ./configure CC=${{ matrix.cc }} 40 | - name: make 41 | run: make -j$(nproc) 42 | - name: make check 43 | run: make check || { cat tests/test-suite.log; exit 1; } 44 | - name: sudo make check 45 | run: sudo make check || { cat tests/test-suite.log; exit 1; } 46 | -------------------------------------------------------------------------------- /LICENSES/Linux-syscall-note: -------------------------------------------------------------------------------- 1 | SPDX-Exception-Identifier: Linux-syscall-note 2 | SPDX-URL: https://spdx.org/licenses/Linux-syscall-note.html 3 | SPDX-Licenses: GPL-2.0, GPL-2.0+, GPL-1.0+, LGPL-2.0, LGPL-2.0+, LGPL-2.1, LGPL-2.1+, GPL-2.0-only, GPL-2.0-or-later 4 | Usage-Guide: 5 | This exception is used together with one of the above SPDX-Licenses 6 | to mark user space API (uapi) header files so they can be included 7 | into non GPL compliant user space application code. 8 | To use this exception add it with the keyword WITH to one of the 9 | identifiers in the SPDX-Licenses tag: 10 | SPDX-License-Identifier: WITH Linux-syscall-note 11 | License-Text: 12 | 13 | NOTE! This copyright does *not* cover user programs that use kernel 14 | services by normal system calls - this is merely considered normal use 15 | of the kernel, and does *not* fall under the heading of "derived work". 16 | Also note that the GPL below is copyrighted by the Free Software 17 | Foundation, but the instance of code that it refers to (the Linux 18 | kernel) is copyrighted by me and others who actually wrote it. 19 | 20 | Also note that the only valid version of the GPL as far as the kernel 21 | is concerned is _this_ particular version of the license (ie v2, not 22 | v2.2 or v3.x or whatever), unless explicitly otherwise stated. 23 | 24 | Linus Torvalds 25 | 26 | -------------------------------------------------------------------------------- /include/mptcpd/private/id_manager.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file private/id_manager.h 4 | * 5 | * @brief Map of MPTCP address ID to network address - private API. 6 | * 7 | * Copyright (c) 2020, 2021, Intel Corporation 8 | */ 9 | 10 | #ifndef MPTCPD_PRIVATE_ID_MANAGER_H 11 | #define MPTCPD_PRIVATE_ID_MANAGER_H 12 | 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | struct mptcpd_idm; 24 | struct sockaddr; 25 | 26 | /** 27 | * @brief Map an IP address to a MPTCP address ID. 28 | * 29 | * Map an IP address to a MPTCP address ID. The MPTCP addresses ID 30 | * for an existing IP address will be updated with the new ID. 31 | * 32 | * @note This function is only meant for internal use by mptcpd. 33 | * 34 | * @param[in] idm The mptcpd address ID manager object. 35 | * @param[in] sa IP address information. 36 | * @param[in] id MPTCP address ID. 37 | * 38 | * @return @c true if mapping succeeded, and @c false otherwise. 39 | */ 40 | MPTCPD_API bool mptcpd_idm_map_id(struct mptcpd_idm *idm, 41 | struct sockaddr const *sa, 42 | mptcpd_aid_t id); 43 | 44 | 45 | #ifdef __cplusplus 46 | } 47 | #endif 48 | 49 | #endif // MPTCPD_PRIVATE_ID_MANAGER_H 50 | 51 | 52 | /* 53 | Local Variables: 54 | c-file-style: "linux" 55 | End: 56 | */ 57 | -------------------------------------------------------------------------------- /tests/lib/sockaddr.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file sockaddr.c 4 | * 5 | * @brief @c sockaddr related test functions. 6 | * 7 | * Copyright (c) 2019, Intel Corporation 8 | */ 9 | 10 | #include 11 | 12 | #include "test-plugin.h" 13 | 14 | 15 | bool sockaddr_is_equal(struct sockaddr const *lhs, 16 | struct sockaddr const *rhs) 17 | { 18 | if (lhs->sa_family != rhs->sa_family) 19 | return false; 20 | 21 | // IPv4 22 | if (lhs->sa_family == AF_INET) { 23 | struct sockaddr_in const *const l = 24 | (struct sockaddr_in const *) lhs; 25 | struct sockaddr_in const *const r = 26 | (struct sockaddr_in const *) rhs; 27 | 28 | return l->sin_port == r->sin_port 29 | && l->sin_addr.s_addr == r->sin_addr.s_addr; 30 | } 31 | 32 | // IPv6 33 | struct sockaddr_in6 const *const l = 34 | (struct sockaddr_in6 const *) lhs; 35 | struct sockaddr_in6 const *const r = 36 | (struct sockaddr_in6 const *) rhs; 37 | 38 | return l->sin6_port == r->sin6_port 39 | && memcmp(&l->sin6_addr, 40 | &r->sin6_addr, 41 | sizeof(l->sin6_addr)) == 0; 42 | } 43 | 44 | /* 45 | Local Variables: 46 | c-file-style: "linux" 47 | End: 48 | */ 49 | -------------------------------------------------------------------------------- /include/mptcpd/private/netlink_pm.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file private/netlink_pm.h 4 | * 5 | * @brief Kernel generic netlink path manager details. 6 | * 7 | * Copyright (c) 2021, Intel Corporation 8 | */ 9 | 10 | #ifndef MPTCPD_PRIVATE_NETLINK_PM_H 11 | #define MPTCPD_PRIVATE_NETLINK_PM_H 12 | 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | struct mptcpd_pm_cmd_ops; 19 | struct mptcpd_kpm_cmd_ops; 20 | 21 | /** 22 | * @struct mptcpd_netlink_pm 23 | * 24 | * Kernel-specific MPTCP generic netlink path manager 25 | * characteristics. 26 | */ 27 | struct mptcpd_netlink_pm 28 | { 29 | /// MPTCP generic netlink family name. 30 | char const *const name; 31 | 32 | /// MPTCP generic netlink multicast group. 33 | char const *const group; 34 | 35 | /// MPTCP path management generic netlink command functions. 36 | struct mptcpd_pm_cmd_ops const *const cmd_ops; 37 | 38 | /** 39 | * @brief In-kernel MPTCP path management generic netlink command 40 | * functions. 41 | * 42 | * Generic netlink command functions specific to the in-kernel 43 | * path manager. 44 | */ 45 | struct mptcpd_kpm_cmd_ops const *const kcmd_ops; 46 | }; 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | 52 | 53 | #endif /* MPTCPD_PRIVATE_NETLINK_PM_H */ 54 | 55 | /* 56 | Local Variables: 57 | c-file-style: "linux" 58 | End: 59 | */ 60 | -------------------------------------------------------------------------------- /tests/plugins/security/Makefile.am: -------------------------------------------------------------------------------- 1 | ## SPDX-License-Identifier: BSD-3-Clause 2 | ## 3 | ## Copyright (c) 2017-2020, Intel Corporation 4 | 5 | include $(top_srcdir)/aminclude_static.am 6 | 7 | AM_CPPFLAGS = \ 8 | -I$(top_srcdir)/include \ 9 | -I$(top_builddir)/include \ 10 | -I$(top_srcdir)/tests/lib \ 11 | $(CODE_COVERAGE_CPPFLAGS) 12 | 13 | AM_CFLAGS = $(ELL_CFLAGS) $(CODE_COVERAGE_CFLAGS) 14 | 15 | ## -rpath is needed to force a DSO to be built when listing Libtool 16 | ## modules in the Automake check_LTLIBRARIES variable. Otherwise a 17 | ## convenience library would be built instead. 18 | AM_LDFLAGS = \ 19 | -no-undefined \ 20 | -module \ 21 | -avoid-version \ 22 | $(ELL_LIBS) \ 23 | -rpath $(abs_builddir) 24 | 25 | ## For testing mptcpd plugin framework when default plugin is 26 | ## explicitly specified, as well as plugin security checks. 27 | check_LTLIBRARIES = three.la four.la 28 | 29 | three_la_SOURCES = three.c 30 | three_la_CPPFLAGS = \ 31 | $(AM_CPPFLAGS) \ 32 | -DTEST_PLUGIN=\"@TEST_PLUGIN_THREE@\" 33 | three_la_LIBADD = \ 34 | ../../lib/libmptcpd_test.la \ 35 | $(top_builddir)/lib/libmptcpd.la \ 36 | $(CODE_COVERAGE_LIBS) 37 | 38 | four_la_SOURCES = four.c 39 | four_la_CPPFLAGS = \ 40 | $(AM_CPPFLAGS) \ 41 | -DTEST_PLUGIN=\"@TEST_PLUGIN_FOUR@\" 42 | four_la_LIBADD = \ 43 | ../../lib/libmptcpd_test.la \ 44 | $(top_builddir)/lib/libmptcpd.la \ 45 | $(CODE_COVERAGE_LIBS) 46 | 47 | # Clean up code coverage related generated files. 48 | clean-local: code-coverage-clean 49 | -------------------------------------------------------------------------------- /plugins/path_managers/Makefile.am: -------------------------------------------------------------------------------- 1 | ## SPDX-License-Identifier: BSD-3-Clause 2 | ## 3 | ## Copyright (c) 2017-2019, Intel Corporation 4 | 5 | include $(top_srcdir)/aminclude_static.am 6 | 7 | MPTCPD_PLUGIN_CPPFLAGS = \ 8 | -I$(top_srcdir)/include -I$(top_builddir)/include 9 | 10 | pkglib_LTLIBRARIES = addr_adv.la sspi.la 11 | 12 | sspi_la_SOURCES = sspi.c 13 | sspi_la_CPPFLAGS = $(MPTCPD_PLUGIN_CPPFLAGS) $(CODE_COVERAGE_CPPFLAGS) 14 | sspi_la_CFLAGS = \ 15 | $(ELL_CFLAGS) \ 16 | $(MPTCPD_PLUGIN_CFLAGS) \ 17 | $(CODE_COVERAGE_CFLAGS) 18 | sspi_la_LDFLAGS = \ 19 | -no-undefined \ 20 | -module \ 21 | -avoid-version \ 22 | $(ELL_LIBS) 23 | sspi_la_LIBADD = \ 24 | $(top_builddir)/lib/libmptcpd.la \ 25 | $(CODE_COVERAGE_LIBS) 26 | 27 | addr_adv_la_SOURCES = addr_adv.c 28 | addr_adv_la_CPPFLAGS = $(MPTCPD_PLUGIN_CPPFLAGS) $(CODE_COVERAGE_CPPFLAGS) 29 | addr_adv_la_CFLAGS = \ 30 | $(ELL_CFLAGS) \ 31 | $(MPTCPD_PLUGIN_CFLAGS) \ 32 | $(CODE_COVERAGE_CFLAGS) 33 | addr_adv_la_LDFLAGS = \ 34 | -no-undefined \ 35 | -module \ 36 | -avoid-version \ 37 | $(ELL_LIBS) 38 | addr_adv_la_LIBADD = \ 39 | $(top_builddir)/lib/libmptcpd.la \ 40 | $(CODE_COVERAGE_LIBS) 41 | 42 | # Make sure mptcpd plugin directory is not world writable. 43 | install-exec-local: installdirs 44 | chmod o-w $(DESTDIR)$(pkglibdir) 45 | 46 | install-exec-hook: installcheck-local 47 | 48 | installcheck-local: 49 | $(top_srcdir)/scripts/check-permissions $(DESTDIR)$(pkglibdir) 50 | 51 | # Clean up code coverage related generated files. 52 | clean-local: code-coverage-clean 53 | -------------------------------------------------------------------------------- /tests/plugins/priority/Makefile.am: -------------------------------------------------------------------------------- 1 | ## SPDX-License-Identifier: BSD-3-Clause 2 | ## 3 | ## Copyright (c) 2017-2020, Intel Corporation 4 | 5 | include $(top_srcdir)/aminclude_static.am 6 | 7 | AM_CPPFLAGS = \ 8 | -I$(top_srcdir)/include \ 9 | -I$(top_builddir)/include \ 10 | -I$(top_srcdir)/tests/lib \ 11 | $(CODE_COVERAGE_CPPFLAGS) 12 | 13 | AM_CFLAGS = $(ELL_CFLAGS) $(CODE_COVERAGE_CFLAGS) 14 | 15 | ## -rpath is needed to force a DSO to be built when listing Libtool 16 | ## modules in the Automake check_LTLIBRARIES variable. Otherwise a 17 | ## convenience library would be built instead. 18 | AM_LDFLAGS = \ 19 | -no-undefined \ 20 | -module \ 21 | -avoid-version \ 22 | $(ELL_LIBS) \ 23 | -rpath $(abs_builddir) 24 | 25 | ## For testing mptcpd plugin framework when default plugin is 26 | ## is the first registered plugin, i.e. the one with the *lowest* 27 | ## plugin priority, as well as testing plugin operation dispatch. 28 | check_LTLIBRARIES = one.la two.la 29 | 30 | one_la_SOURCES = one.c 31 | one_la_CPPFLAGS = \ 32 | $(AM_CPPFLAGS) \ 33 | -DTEST_PLUGIN=\"@TEST_PLUGIN_ONE@\" 34 | one_la_LIBADD = \ 35 | ../../lib/libmptcpd_test.la \ 36 | $(top_builddir)/lib/libmptcpd.la \ 37 | $(CODE_COVERAGE_LIBS) 38 | 39 | two_la_SOURCES = two.c 40 | two_la_CPPFLAGS = \ 41 | $(AM_CPPFLAGS) \ 42 | -DTEST_PLUGIN=\"@TEST_PLUGIN_TWO@\" 43 | two_la_LIBADD = \ 44 | ../../lib/libmptcpd_test.la \ 45 | $(top_builddir)/lib/libmptcpd.la \ 46 | $(CODE_COVERAGE_LIBS) 47 | 48 | # Clean up code coverage related generated files. 49 | clean-local: code-coverage-clean 50 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2017-2021, Intel Corporation 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | * Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials provided 14 | with the distribution. 15 | * Neither the name of Intel Corporation nor the names of its 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /src/netlink_pm.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file src/netlink_pm.h 4 | * 5 | * @brief Kernel generic netlink path manager details. 6 | * 7 | * Copyright (c) 2021, Intel Corporation 8 | */ 9 | 10 | #ifndef MPTCPD_NETLINK_PM_H 11 | #define MPTCPD_NETLINK_PM_H 12 | 13 | #include 14 | 15 | #include 16 | 17 | #include 18 | 19 | /// Directory containing MPTCP sysctl variable entries. 20 | #define MPTCP_SYSCTL_BASE "/proc/sys/net/mptcp/" 21 | 22 | /// Constuct full path for MPTCP sysctl variable "@a name". 23 | #define MPTCP_SYSCTL_VARIABLE(name) MPTCP_SYSCTL_BASE #name 24 | 25 | struct sockaddr; 26 | struct mptcpd_pm; 27 | 28 | /// Get MPTCP generic netlink path manager characteristics. 29 | struct mptcpd_netlink_pm const *mptcpd_get_netlink_pm(void); 30 | 31 | /** 32 | * @brief Verify that MPTCP is enabled at run-time in the kernel. 33 | * 34 | * Check that MPTCP is enabled through the specified @c sysctl 35 | * variable. 36 | * 37 | * @param[in] path Path to file containing MPTCP sysctl "enable" 38 | * value, e.g. "/proc/sys/net/mptcp/enabled". 39 | * @param[in] variable Name of "enabled" variable. 40 | * @param[in] enable_val Value needed to enable MPTCP in the kernel. 41 | * 42 | * @return @c true if MPTCP is enabled in the kernel, and @c false 43 | * otherwise. 44 | */ 45 | bool mptcpd_is_kernel_mptcp_enabled(char const *path, 46 | char const *variable, 47 | int enable_val); 48 | 49 | 50 | #endif /* MPTCPD_NETLINK_PM_H */ 51 | 52 | 53 | /* 54 | Local Variables: 55 | c-file-style: "linux" 56 | End: 57 | */ 58 | -------------------------------------------------------------------------------- /man/mptcpize.8.in: -------------------------------------------------------------------------------- 1 | .\" SPDX-License-Identifier: BSD-3-Clause 2 | .\" 3 | .\" Copyright (c) 2021, Intel Corporation 4 | 5 | .\" Process this file with 6 | .\" groff -man -Tascii mptcpize.8 7 | .\" 8 | .TH MPTCPIZE 8 "2021-09-23" "Multipath TCP Daemon" "System Management Commands" 9 | .SH NAME 10 | mptcpize \- enable MPTCP on existing services 11 | .SH SYNOPSIS 12 | .SY mptcpize 13 | .OP \-?V 14 | .OP \-\-help 15 | .OP \-\-usage 16 | .OP \-\-version 17 | .B COMMAND 18 | .YS 19 | 20 | .SH DESCRIPTION 21 | .B mptcpize 22 | is a program that enables multipath TCP on existing legacy services, 23 | where 24 | .B COMMAND 25 | is one of the following: 26 | 27 | .SS 28 | .BI run\ [ -d ]\ prog \ [ args ] 29 | Run target program with the specified command line arguments, forcing 30 | MPTCP socket usage instead of TCP. If the 31 | .B -d 32 | argument is provided, dump messages on 33 | .B stderr 34 | when a TCP socket is forced to use MPTCP. 35 | 36 | .SS 37 | .BI enable\ unit 38 | Update the systemd 39 | .I unit 40 | file, forcing the given service to run under the above launcher. 41 | 42 | .SS 43 | .BI disable\ unit 44 | Update the systemd 45 | .I unit 46 | file, removing the above launcher. 47 | 48 | 49 | .SH OPTIONS 50 | .B mptcpize 51 | accepts the following command line options: 52 | 53 | .TP 54 | .BR \-? , \-\-help 55 | display 56 | .B mptcpize 57 | help information 58 | 59 | .TP 60 | .B \-\-usage 61 | display brief 62 | .B mptcpize 63 | usage information 64 | 65 | .TP 66 | .BR \-V , \-\-version 67 | display 68 | .B mptcpize 69 | version information 70 | 71 | .SH REPORTING BUGS 72 | Report bugs to 73 | .MT @PACKAGE_BUGREPORT@ 74 | .ME . 75 | 76 | .SH SEE ALSO 77 | ip-mptcp(8), mptcpd(8) 78 | 79 | .\" Local Variables: 80 | .\" mode: nroff 81 | .\" End: 82 | -------------------------------------------------------------------------------- /tests/lib/test-util.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file test-util.c 4 | * 5 | * @brief mptcpd test utilities library. 6 | * 7 | * Copyright (c) 2020-2022, Intel Corporation 8 | */ 9 | 10 | #ifdef HAVE_CONFIG_H 11 | # include 12 | #endif 13 | 14 | #include 15 | #include 16 | 17 | #if defined(HAVE_LINUX_MPTCP_H_UPSTREAM) \ 18 | || defined(HAVE_LINUX_MPTCP_H_MPTCP_ORG) 19 | # include 20 | #elif defined(HAVE_UPSTREAM_KERNEL) 21 | # include 22 | #else 23 | # include 24 | #endif 25 | 26 | #include "../src/netlink_pm.h" // For MPTCP_SYSCTL_BASE 27 | 28 | #include "test-util.h" 29 | 30 | 31 | char const *tests_get_pm_family_name(void) 32 | { 33 | #ifdef MPTCP_PM_NAME 34 | return MPTCP_PM_NAME; 35 | #else 36 | return MPTCP_GENL_NAME; 37 | #endif 38 | } 39 | 40 | static bool is_mptcp_kernel(void) 41 | { 42 | // Kernel supports MPTCP if /proc/sys/net/mptcp exists. 43 | return access(MPTCP_SYSCTL_BASE, R_OK | X_OK) == 0; 44 | } 45 | 46 | void tests_skip_if_no_mptcp(void) 47 | { 48 | /* 49 | An exit status of 77 causes the Automake test driver, 50 | i.e. the `test-driver' script, to consider the test result 51 | as SKIP rather than PASS or FAIL. 52 | 53 | Tests that should be skipped under some conditions, such as 54 | when not running a MPTCP capable kernel, should exit the 55 | process with this value. 56 | */ 57 | static int const SKIP_EXIT_STATUS = 77; 58 | 59 | if (!is_mptcp_kernel()) 60 | exit(SKIP_EXIT_STATUS); 61 | } 62 | 63 | 64 | 65 | /* 66 | Local Variables: 67 | c-file-style: "linux" 68 | End: 69 | */ 70 | -------------------------------------------------------------------------------- /src/netlink_pm.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file netlink_pm.c 4 | * 5 | * @brief Kernel generic netlink path manager details. 6 | * 7 | * Copyright (c) 2017-2021, Intel Corporation 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #include "netlink_pm.h" 16 | 17 | 18 | bool mptcpd_is_kernel_mptcp_enabled(char const *path, 19 | char const *variable, 20 | int enable_val) 21 | { 22 | FILE *const f = fopen(path, "r"); 23 | 24 | if (f == NULL) 25 | return false; // Not using kernel that supports given 26 | // MPTCP sysctl variable. 27 | 28 | int enabled = 0; 29 | int const n = fscanf(f, "%d", &enabled); 30 | 31 | fclose(f); 32 | 33 | if (n == 1) { 34 | if (enabled == 0) { 35 | l_error("MPTCP is not enabled in the kernel."); 36 | l_error("Try 'sysctl -w net.mptcp.%s=%d'.", 37 | variable, 38 | enable_val); 39 | 40 | /* 41 | Mptcpd should not set this variable since it 42 | would need to be run as root in order to 43 | gain write access to files in 44 | /proc/sys/net/mptcp/ owned by root. 45 | Ideally, mptcpd should not be run as the 46 | root user. 47 | */ 48 | } 49 | } else { 50 | l_error("Unable to determine if MPTCP is enabled."); 51 | } 52 | 53 | return enabled; 54 | } 55 | 56 | /* 57 | Local Variables: 58 | c-file-style: "linux" 59 | End: 60 | */ 61 | -------------------------------------------------------------------------------- /lib/sockaddr.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file lib/sockaddr.c 4 | * 5 | * @brief mptcpd @c struct @c sockaddr related utility functions. 6 | * 7 | * Copyright (c) 2019-2022, Intel Corporation 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #include 17 | 18 | 19 | bool mptcpd_sockaddr_storage_init(in_addr_t const *addr4, 20 | struct in6_addr const *addr6, 21 | in_port_t port, 22 | struct sockaddr_storage *addr) 23 | { 24 | if ((addr4 == NULL && addr6 == NULL) || addr == NULL) 25 | return false; 26 | 27 | if (addr4 != NULL) { 28 | struct sockaddr_in *const a = (struct sockaddr_in *) addr; 29 | 30 | a->sin_family = AF_INET; 31 | a->sin_port = port; 32 | a->sin_addr.s_addr = *addr4; 33 | } else { 34 | struct sockaddr_in6 *const a = 35 | (struct sockaddr_in6 *) addr; 36 | 37 | a->sin6_family = AF_INET6; 38 | a->sin6_port = port; 39 | 40 | memcpy(&a->sin6_addr, addr6, sizeof(*addr6)); 41 | } 42 | 43 | return true; 44 | } 45 | 46 | struct sockaddr * 47 | mptcpd_sockaddr_copy(struct sockaddr const *sa) 48 | { 49 | if (sa == NULL) 50 | return NULL; 51 | 52 | if (sa->sa_family == AF_INET) 53 | return l_memdup(sa, sizeof(struct sockaddr_in)); 54 | else if (sa->sa_family == AF_INET6) 55 | return l_memdup(sa, sizeof(struct sockaddr_in6)); 56 | 57 | // Not an IPv4 or IPv6 address. 58 | return NULL; 59 | } 60 | 61 | 62 | /* 63 | Local Variables: 64 | c-file-style: "linux" 65 | End: 66 | */ 67 | -------------------------------------------------------------------------------- /include/mptcpd/private/murmur_hash.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Intel Corporation 2 | // SPDX-License-Identifier: BSD-3-Clause 3 | /** 4 | * @file murmur_hash.h 5 | * 6 | * This file incorporates work covered by the following notice: 7 | * MurmurHash3 was written by Austin Appleby, and is placed in the 8 | * public domain. The author hereby disclaims copyright to this 9 | * source code. 10 | * 11 | * Changes relative to the original: 12 | * 13 | * @li 128 bit hash functions were removed. They are not needed by 14 | * mptcpd since the ELL l_hashmap expects hash values of type 15 | * @c unsigned @c int. 16 | * @li The @c MurmurHash3_x86_32() function was renamed to 17 | * @c mptcpd_murmur_hash3(). 18 | * @li The hash value is returned as an @ @c unsigned @c int return 19 | * value instead of a @c void* function "out" parameter. 20 | * @li The coding style was modified to conform to the mptcpd style. 21 | * 22 | * @see https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.h 23 | */ 24 | 25 | #ifndef MPTCPD_MURMUR_HASH_3_H 26 | #define MPTCPD_MURMUR_HASH_3_H 27 | 28 | #include 29 | 30 | #include 31 | 32 | 33 | #ifdef __cplusplus 34 | extern "C" { 35 | #endif 36 | 37 | /** 38 | * @brief Generate hash of @a key using the MurmurHash3 algorithm. 39 | * 40 | * @param[in] key Key value to be hashed. 41 | * @param[in] len Length of @a key in bytes. 42 | * @param[in] seed Initial value of hash prior to hashing @a key. 43 | * 44 | * @return Hash of @a key. 45 | * 46 | * @attention The generated hash value is not cryptographically 47 | * strong. 48 | * 49 | * @see https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp 50 | */ 51 | MPTCPD_API unsigned int mptcpd_murmur_hash3(void const *key, 52 | int len, 53 | uint32_t seed); 54 | 55 | #ifdef __cplusplus 56 | } 57 | #endif 58 | 59 | #endif // MPTCPD_MURMUR_HASH_3_H 60 | 61 | 62 | /* 63 | Local Variables: 64 | c-file-style: "linux" 65 | End: 66 | */ 67 | -------------------------------------------------------------------------------- /include/mptcpd/private/network_monitor.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file private/network_monitor.h 4 | * 5 | * @brief mptcpd network device monitoring - internal API. 6 | * 7 | * Copyright (c) 2017-2022, Intel Corporation 8 | */ 9 | 10 | #ifndef MPTCPD_PRIVATE_NETWORK_MONITOR_H 11 | #define MPTCPD_PRIVATE_NETWORK_MONITOR_H 12 | 13 | #include 14 | 15 | #include 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | struct mptcpd_nm; 22 | 23 | /** 24 | * @name Mptcpd Network Monitor Flags 25 | * 26 | * Flags controlling address notification in the mptcpd network 27 | * monitor. Pass to @c mptcpd_nm_create(). 28 | */ 29 | ///@{ 30 | /// Notify even the addresses already existing at startup-time. 31 | #define MPTCPD_NOTIFY_FLAG_EXISTING (1U << 0) 32 | 33 | /// Ignore link-local addresses. 34 | #define MPTCPD_NOTIFY_FLAG_SKIP_LL (1U << 1) 35 | 36 | /// Ignore host (loopback) addresses. 37 | #define MPTCPD_NOTIFY_FLAG_SKIP_HOST (1U << 2) 38 | 39 | /** 40 | * Notify address only if a default route is available from the given 41 | * interface. 42 | */ 43 | #define MPTCPD_NOTIFY_FLAG_ROUTE_CHECK (1U << 3) 44 | ///@} 45 | 46 | /** 47 | * @brief Create a network monitor. 48 | * 49 | * @param[in] flags Flags controlling address notification, any of: 50 | * MPTCPD_NOTIFY_FLAG_EXISTING, 51 | * MPTCPD_NOTIFY_FLAG_SKIP_LL, 52 | * MPTCPD_NOTIFY_FLAG_SKIP_HOST 53 | * 54 | * @todo As currently implemented, one could create multiple network 55 | * monitors. Is that useful? 56 | * 57 | * @return Pointer to new network monitor on success. @c NULL on 58 | * failure. 59 | */ 60 | MPTCPD_API struct mptcpd_nm *mptcpd_nm_create(uint32_t flags); 61 | 62 | /** 63 | * @brief Destroy a network monitor. 64 | * 65 | * @param[in,out] nm Network monitor to be destroyed. 66 | */ 67 | MPTCPD_API void mptcpd_nm_destroy(struct mptcpd_nm *nm); 68 | 69 | #ifdef __cplusplus 70 | } 71 | #endif 72 | 73 | #endif // MPTCPD_PRIVATE_NETWORK_MONITOR_H 74 | 75 | 76 | /* 77 | Local Variables: 78 | c-file-style: "linux" 79 | End: 80 | */ 81 | -------------------------------------------------------------------------------- /include/mptcpd/listener_manager.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file listener_manager.h 4 | * 5 | * @brief Map of MPTCP local address to listener. 6 | * 7 | * Copyright (c) 2022, Intel Corporation 8 | */ 9 | 10 | #ifndef MPTCPD_LISTENER_MANAGER_H 11 | #define MPTCPD_LISTENER_MANAGER_H 12 | 13 | #include 14 | 15 | #include 16 | 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | struct mptcpd_lm; 23 | struct sockaddr; 24 | 25 | /** 26 | * @brief Listen on the given MPTCP local address. 27 | * 28 | * Create a MPTCP listening socket for the given local address. This 29 | * is needed to accept subflows, e.g. during a @c MP_JOIN operation. 30 | * 31 | * @param[in] lm The mptcpd address listener manager object. 32 | * @param[in,out] sa The MPTCP local address. If the port is zero an 33 | * ephemeral port will be chosen, and assigned to 34 | * the appropriate underlying address 35 | * family-specific port member, e.g. @c sin_port or 36 | * @c sin6_port. The port will be in network byte 37 | * order. 38 | * 39 | * @return @c 0 if operation was successful. -1 or @c errno otherwise. 40 | */ 41 | MPTCPD_API int mptcpd_lm_listen(struct mptcpd_lm *lm, 42 | struct sockaddr *sa); 43 | 44 | /** 45 | * @brief Stop listening on a MPTCP local address. 46 | * 47 | * @param[in] lm The mptcpd address listener manager object. 48 | * @param[in] sa The MPTCP local address with a non-zero port, such as 49 | * the one assigned by @c mptcpd_lm_listen(), i.e. the 50 | * non-zero port provided by the user or the ephemeral 51 | * port chosen by the kernel. 52 | * 53 | * @return @c 0 if operation was successful. -1 or @c errno otherwise. 54 | */ 55 | MPTCPD_API int mptcpd_lm_close(struct mptcpd_lm *lm, 56 | struct sockaddr const *sa); 57 | 58 | #ifdef __cplusplus 59 | } 60 | #endif 61 | 62 | 63 | #endif /* MPTCPD_LISTENER_MANAGER_H */ 64 | 65 | 66 | /* 67 | Local Variables: 68 | c-file-style: "linux" 69 | End: 70 | */ 71 | -------------------------------------------------------------------------------- /include/mptcpd/id_manager.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file id_manager.h 4 | * 5 | * @brief Map of network address to MPTCP address ID. 6 | * 7 | * Copyright (c) 2020, Intel Corporation 8 | */ 9 | 10 | #ifndef MPTCPD_ID_MANAGER_H 11 | #define MPTCPD_ID_MANAGER_H 12 | 13 | #include 14 | #include 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | struct mptcpd_idm; 21 | struct sockaddr; 22 | 23 | /** 24 | * @brief Create MPTCP address ID manager. 25 | * 26 | * @return Pointer to MPTCP address ID manager on success. @c NULL on 27 | * failure. 28 | */ 29 | MPTCPD_API struct mptcpd_idm *mptcpd_idm_create(void); 30 | 31 | /** 32 | * @brief Destroy MPTCP address ID manager. 33 | * 34 | * @param[in,out] idm The mptcpd address ID manager object. 35 | */ 36 | MPTCPD_API void mptcpd_idm_destroy(struct mptcpd_idm *idm); 37 | 38 | /** 39 | * @brief Get MPTCP address ID. 40 | * 41 | * Map an IP address to a MPTCP address ID, and return that ID. 42 | * 43 | * @param[in] idm The mptcpd address ID manager object. 44 | * @param[in] sa IP address information. 45 | * 46 | * @return MPTCP address ID associated with the address @a sa, or zero 47 | * on error. 48 | */ 49 | MPTCPD_API mptcpd_aid_t mptcpd_idm_get_id(struct mptcpd_idm *idm, 50 | struct sockaddr const *sa); 51 | 52 | /** 53 | * @brief Remove MPTCP address ID. 54 | * 55 | * Stop associating the MPTCP address ID with the given IP address. 56 | * 57 | * @param[in] idm The mptcpd address ID manager object. 58 | * @param[in] sa IP address information. 59 | * 60 | * @return MPTCP address ID that was removed, or zero if no such ID is 61 | * associated with the IP address @a sa. Zero will also be 62 | * returned if either of the arguments are NULL. 63 | */ 64 | MPTCPD_API mptcpd_aid_t mptcpd_idm_remove_id(struct mptcpd_idm *idm, 65 | struct sockaddr const *sa); 66 | 67 | #ifdef __cplusplus 68 | } 69 | #endif 70 | 71 | #endif // MPTCPD_ID_MANAGER_H 72 | 73 | 74 | /* 75 | Local Variables: 76 | c-file-style: "linux" 77 | End: 78 | */ 79 | -------------------------------------------------------------------------------- /include/mptcpd/private/addr_info.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file private/addr_info.h 4 | * 5 | * @brief @c mptcpd_addr_info related code. 6 | * 7 | * Copyright (c) 2020-2021, Intel Corporation 8 | */ 9 | 10 | #ifndef MPTCPD_PRIVATE_ADDR_INFO_H 11 | #define MPTCPD_PRIVATE_ADDR_INFO_H 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | /** 27 | * @struct mptcpd_addr_info addr_info.h 28 | * 29 | * @brief Information associated with a network address. 30 | */ 31 | struct mptcpd_addr_info 32 | { 33 | /** 34 | * @privatesection 35 | */ 36 | 37 | /** 38 | * @brief Network address family and IP address. 39 | * 40 | * @note Cast to @c sockaddr_in or @c sockaddr_in6 depending 41 | * on the address family in the @c ss_family field. 42 | */ 43 | struct sockaddr_storage addr; 44 | 45 | /** 46 | * MPTCP address ID associated with the network address. 47 | * 48 | * @note This value will be zero if no ID is associated with 49 | * the address. 50 | */ 51 | mptcpd_aid_t id; 52 | 53 | /** 54 | * @brief MPTCP flags associated with the network address. 55 | * 56 | * Bitset of MPTCP flags associated with the network address, 57 | * e.g. @c MPTCPD_ADDR_FLAG_BACKUP @c | 58 | * @c MPTCP_PM_ADDR_FLAG_SUBFLOW. 59 | * 60 | * @note This value will be zero if no flag bits are set. 61 | */ 62 | uint32_t flags; 63 | 64 | /** 65 | * @brief Network interface index associated with network address. 66 | * 67 | * @todo Will this value ever be zero, i.e. not set? 68 | */ 69 | int index; 70 | }; 71 | 72 | #ifdef __cplusplus 73 | } 74 | #endif 75 | 76 | 77 | #endif /* MPTCPD_PRIVATE_ADDR_INFO_H */ 78 | 79 | 80 | /* 81 | Local Variables: 82 | c-file-style: "linux" 83 | End: 84 | */ 85 | -------------------------------------------------------------------------------- /mptcpd.dox: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-License-Identifier: BSD-3-Clause 3 | Copyright (c) 2017-2020, Intel Corporation 4 | */ 5 | 6 | /** 7 | * @mainpage @c mptcpd Code Documentation 8 | * 9 | * The Multipath TCP Daemon - `mptcpd` - is a daemon for Linux based 10 | * operating systems that performs [multipath 11 | * TCP](https://www.rfc-editor.org/rfc/rfc8684.html) [path 12 | * management](https://www.rfc-editor.org/rfc/rfc8684.html#section-3.4) 13 | * related operations in the user space. It interacts with the Linux 14 | * kernel through a generic netlink connection to track per-connection 15 | * information (e.g. available remote addresses), available network 16 | * interfaces, request new MPTCP subflows, handle requests for 17 | * subflows, etc. 18 | * 19 | * By default, this daemon will load the `addr_adv` plugin, which will 20 | * add MPTCP endpoints with the `subflow` flag ("client" mode) for the 21 | * default in-kernel path-manager. Note that this is something 22 | * [NetworkManager 1.40 or newer](https://networkmanager.dev/blog/networkmanager-1-40/#mptcp-support) 23 | * does by default. Having several daemons configuring the MPTCP 24 | * endpoints at the same time should be avoided. This daemon is usually 25 | * recommended when NetworkManager 1.40 or newer is not available, or 26 | * when advanced per-connection path management is needed, using the 27 | * userspace path-manager and a custom made 28 | * [plugin](https://github.com/multipath-tcp/mptcpd/wiki/Plugins) using 29 | * the C API that is described here. 30 | * 31 | * To change this behavior, with NetworkManager, look for the 32 | * `connection.mptcp-flags` option in the 33 | * [settings](https://networkmanager.dev/docs/api/latest/nm-settings-nmcli.html#nm-settings-nmcli.property.connection.mptcp-flags), 34 | * while for `mptcpd`, look at the `/etc/mptcpd/mptcpd.conf` config 35 | * file, or disable the service if it is not needed. Make sure not to 36 | * have both NetworkManager and `mptcpd` conflicting to configure the 37 | * MPTCP endpoints. 38 | * 39 | * @see Additional higher level documentation is available in the 40 | * [`mptcpd` Wiki](https://github.com/multipath-tcp/mptcpd/wiki/Plugins). 41 | */ 42 | 43 | /* 44 | Local Variables: 45 | mode: c 46 | c-file-style: "linux" 47 | End: 48 | */ 49 | -------------------------------------------------------------------------------- /lib/hash_sockaddr.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file hash_sockaddr.h 4 | * 5 | * @brief @c struct @c sockaddr hash related functions. 6 | * 7 | * Copyright (c) 2022, Intel Corporation 8 | */ 9 | 10 | #ifndef MPTCPD_HASH_SOCKADDR_H 11 | #define MPTCPD_HASH_SOCKADDR_H 12 | 13 | #include 14 | 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | struct sockaddr; 21 | 22 | /** 23 | * @name ELL Hash Functions For IP Addresses 24 | * 25 | * A set of types and functions for using an IP address through a 26 | * @c struct @c sockaddr as the key for an ELL hashmap (@c struct 27 | * @c l_hashmap). 28 | * 29 | * @note These functions are only used internally, and are not 30 | * exported from libmptcpd. 31 | */ 32 | ///@{ 33 | /** 34 | * @brief Hash key information. 35 | * 36 | * Bundle the values needed to generate a hash value based on an IP 37 | * address (@c struct @c sockaddr) using the MurmurHash3 algorithm. 38 | */ 39 | struct mptcpd_hash_sockaddr_key 40 | { 41 | /// IP address to be hashed. 42 | struct sockaddr const *sa; 43 | 44 | /// Hash algorithm (MurmurHash3) seed. 45 | uint32_t seed; 46 | }; 47 | 48 | /** 49 | * @brief Compare hash map keys based on IP address alone. 50 | * 51 | * @param[in] a Pointer @c struct @c sockaddr (left hand side). 52 | * @param[in] b Pointer @c struct @c sockaddr (right hand side). 53 | * 54 | * @return 0 if the IP addresses are equal, and -1 or 1 otherwise, 55 | * depending on IP address family and comparisons of IP 56 | * addresses of the same type. 57 | * 58 | * @note Ports are not compared. 59 | */ 60 | int mptcpd_hash_sockaddr_compare(void const *a, void const *b); 61 | 62 | /** 63 | * @brief Deep copy the hash map key @a p. 64 | * 65 | * @return The dynamically allocated deep copy of the hash map key 66 | * @a p. Deallocate with @c l_free(). 67 | */ 68 | void *mptcpd_hash_sockaddr_key_copy(void const *p); 69 | 70 | /// Deallocate @struct @c mptcpd_hash_sockaddr_key instance. 71 | void mptcpd_hash_sockaddr_key_free(void *p); 72 | ///@} 73 | 74 | #ifdef __cplusplus 75 | } 76 | #endif 77 | 78 | 79 | #endif // MPTCPD_HASH_SOCKADDR_H 80 | 81 | /* 82 | Local Variables: 83 | c-file-style: "linux" 84 | End: 85 | */ 86 | -------------------------------------------------------------------------------- /include/mptcpd/addr_info.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file addr_info.h 4 | * 5 | * @brief @c mptcpd_addr_info related functions. 6 | * 7 | * Copyright (c) 2020-2021, Intel Corporation 8 | */ 9 | 10 | #ifndef MPTCPD_ADDR_INFO_H 11 | #define MPTCPD_ADDR_INFO_H 12 | 13 | #include 14 | #include 15 | 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | struct sockaddr; 22 | struct mptcpd_addr_info; 23 | 24 | /** 25 | * @brief Get underlying network address related information. 26 | * 27 | * @param[in] info Mptcpd address information. 28 | * 29 | * @return @c sockaddr object containing the underlying network 30 | * address information. Cast to a @c const pointer to a 31 | * @c sockaddr_in or @c sockaddr_in6 depending on the address 32 | * family in the @c sa_family field. @c NULL is returned on 33 | * error. 34 | */ 35 | MPTCPD_API struct sockaddr const * 36 | mptcpd_addr_info_get_addr(struct mptcpd_addr_info const *info); 37 | 38 | /** 39 | * @brief Get MPTCP address ID. 40 | * 41 | * @param[in] info Mptcpd address information. 42 | * 43 | * @return MPTCP address ID corresponding to network address 44 | * encapsulated by @a info. 0 is returned on error. 45 | */ 46 | MPTCPD_API mptcpd_aid_t 47 | mptcpd_addr_info_get_id(struct mptcpd_addr_info const *info); 48 | 49 | /** 50 | * @brief Get mptcpd flags associated with a network address. 51 | * 52 | * @param[in] info Mptcpd address information. 53 | * 54 | * @return Mptcpd flags bitmask associated with the network address 55 | * encapsulated by @a info. 0 is returned on error. 56 | */ 57 | MPTCPD_API mptcpd_flags_t 58 | mptcpd_addr_info_get_flags(struct mptcpd_addr_info const *info); 59 | 60 | /** 61 | * @brief Get network interface index associated with an address. 62 | * 63 | * @param[in] info Mptcpd address information. 64 | * 65 | * @return Network interface index associated with the network address 66 | * encapsulated by @a info. -1 is returned on error. 67 | */ 68 | MPTCPD_API int 69 | mptcpd_addr_info_get_index(struct mptcpd_addr_info const *info); 70 | 71 | #ifdef __cplusplus 72 | } 73 | #endif 74 | 75 | 76 | #endif /* MPTCPD_ADDR_INFO_H */ 77 | 78 | 79 | /* 80 | Local Variables: 81 | c-file-style: "linux" 82 | End: 83 | */ 84 | -------------------------------------------------------------------------------- /src/commands.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file commands.c 4 | * 5 | * @brief mptcpd generic netlink command utilities. 6 | * 7 | * Copyright (c) 2017-2020, 2022, Intel Corporation 8 | */ 9 | 10 | #ifdef HAVE_CONFIG_H 11 | # include 12 | #endif 13 | 14 | #define _POSIX_C_SOURCE 200112L ///< For XSI-compliant strerror_r(). 15 | 16 | #include 17 | #include 18 | 19 | #include 20 | 21 | #include "commands.h" 22 | 23 | 24 | uint16_t mptcpd_get_port_number(struct sockaddr const *addr) 25 | { 26 | in_port_t port = 0; 27 | 28 | if (addr == NULL) 29 | return port; 30 | 31 | if (addr->sa_family == AF_INET) { 32 | struct sockaddr_in const *const addr4 = 33 | (struct sockaddr_in const*) addr; 34 | 35 | port = addr4->sin_port; 36 | 37 | } else if (addr->sa_family == AF_INET6) { 38 | struct sockaddr_in6 const *const addr6 = 39 | (struct sockaddr_in6 const*) addr; 40 | 41 | port = addr6->sin6_port; 42 | } 43 | 44 | return ntohs(port); 45 | } 46 | 47 | bool mptcpd_check_genl_error(struct l_genl_msg *msg, char const *fname) 48 | { 49 | int const error = l_genl_msg_get_error(msg); 50 | 51 | if (error < 0) { 52 | // Error during send. 53 | char const *const genl_errmsg = 54 | #ifdef HAVE_L_GENL_MSG_GET_EXTENDED_ERROR 55 | l_genl_msg_get_extended_error(msg); 56 | #else 57 | NULL; 58 | #endif 59 | 60 | char errmsg[80] = { 0 }; 61 | (void) strerror_r(-error, errmsg, L_ARRAY_SIZE(errmsg)); 62 | 63 | if (genl_errmsg != NULL) 64 | l_error("%s: %s: %s", fname, genl_errmsg, errmsg); 65 | else 66 | l_error("%s: %s", fname, errmsg); 67 | 68 | return false; 69 | } 70 | 71 | return true; 72 | } 73 | 74 | void mptcpd_family_send_callback(struct l_genl_msg *msg, void *user_data) 75 | { 76 | char const *const fname = user_data; 77 | 78 | (void) mptcpd_check_genl_error(msg, fname); 79 | } 80 | 81 | 82 | /* 83 | Local Variables: 84 | c-file-style: "linux" 85 | End: 86 | */ 87 | -------------------------------------------------------------------------------- /tests/test-murmur-hash.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file test-murmur-hash.c 4 | * 5 | * @brief mptcpd MurmurHash3 test. 6 | * 7 | * Copyright (c) 2022, Intel Corporation 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #include 16 | 17 | #undef NDEBUG 18 | #include 19 | 20 | 21 | static void test_hash_32(void const *test_data) 22 | { 23 | (void) test_data; 24 | 25 | /* 26 | This test is not meant to test the MurmurHash3 algorithm 27 | itself. It is only meant to perform a black box test of 28 | mptcpd_murmur_hash3() since an extensive test suite for the 29 | MurmurHash3 algorithm already exists upstream. 30 | See: https://github.com/aappleby/smhasher 31 | */ 32 | 33 | uint32_t const k1 = 0x010200C0; 34 | uint32_t const k2 = k1 + 1; 35 | uint8_t const k3[16] = { 36 | [0] = 0x20, 37 | [1] = 0x01, 38 | [2] = 0x0D, 39 | [3] = 0xB8, 40 | [14] = 0x01, 41 | [15] = 0x02 42 | }; 43 | 44 | uint32_t const seed = 0xc0ffee; 45 | 46 | unsigned int const hash1 = 47 | mptcpd_murmur_hash3(&k1, sizeof(k1), seed); 48 | assert(hash1 != 0); 49 | 50 | unsigned int const hash2 = 51 | mptcpd_murmur_hash3(&k2, sizeof(k2), seed); 52 | assert(hash2 != 0); 53 | assert(hash2 != hash1); 54 | 55 | unsigned int const hash3 = 56 | mptcpd_murmur_hash3(k3, sizeof(k3), seed); 57 | assert(hash3 != 0); 58 | assert(hash3 != hash2); 59 | assert(hash3 != hash1); 60 | 61 | uint8_t a[31] = { 1, 2, 3 }; 62 | unsigned int const hash4 = 63 | mptcpd_murmur_hash3(a, sizeof(a), seed); 64 | 65 | l_info("hash1: 0x%x", hash1); 66 | l_info("hash2: 0x%x", hash2); 67 | l_info("hash3: 0x%x", hash3); 68 | l_info("hash4: 0x%x", hash4); 69 | } 70 | 71 | int main(int argc, char *argv[]) 72 | { 73 | l_log_set_stderr(); 74 | 75 | l_test_init(&argc, &argv); 76 | 77 | l_test_add("test MurmurHash3 (x86_32)", test_hash_32, NULL); 78 | 79 | return l_test_run(); 80 | } 81 | 82 | 83 | /* 84 | Local Variables: 85 | c-file-style: "linux" 86 | End: 87 | */ 88 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | ## SPDX-License-Identifier: BSD-3-Clause 2 | ## 3 | ## Copyright (c) 2017-2019, 2021-2022, Intel Corporation 4 | 5 | include $(top_srcdir)/aminclude_static.am 6 | 7 | AM_CFLAGS = $(ELL_CFLAGS) $(EXECUTABLE_CFLAGS) $(CODE_COVERAGE_CFLAGS) 8 | AM_CPPFLAGS = \ 9 | -I$(top_srcdir)/include \ 10 | -I$(top_builddir)/include \ 11 | $(CODE_COVERAGE_CPPFLAGS) 12 | 13 | ## Expose an internal convenience library for testing purposes. 14 | noinst_LTLIBRARIES = libpath_manager.la 15 | 16 | libpath_manager_la_SOURCES = \ 17 | commands.c \ 18 | commands.h \ 19 | configuration.c \ 20 | netlink_pm.c \ 21 | netlink_pm.h \ 22 | path_manager.c \ 23 | path_manager.h 24 | 25 | if HAVE_UPSTREAM_KERNEL 26 | libpath_manager_la_SOURCES += netlink_pm_upstream.c 27 | else 28 | libpath_manager_la_SOURCES += netlink_pm_mptcp_org.c 29 | endif 30 | 31 | libpath_manager_la_LIBADD = \ 32 | $(top_builddir)/lib/libmptcpd.la \ 33 | $(ELL_LIBS) $(CODE_COVERAGE_LIBS) 34 | 35 | libpath_manager_la_CPPFLAGS = \ 36 | $(AM_CPPFLAGS) \ 37 | -DMPTCPD_CONFIG_FILE='"$(sysconfdir)/@PACKAGE@/@PACKAGE@.conf"' \ 38 | -DMPTCPD_DEFAULT_PLUGINDIR='"$(libdir)/@PACKAGE@"' 39 | 40 | EXTRA_DIST = mptcp.service.in 41 | 42 | if HAVE_SYSTEMD 43 | systemdsystemunit_DATA = mptcp.service 44 | libexec_PROGRAMS = mptcpd 45 | bin_PROGRAMS = mptcpize 46 | 47 | ## The configure script won't fully expand $libexecdir so leverage 48 | ## `make' based variable expansion instead. 49 | mptcp.service: Makefile mptcp.service.in 50 | $(AM_V_GEN)rm -f $@ $@.tmp; \ 51 | srcdir=''; \ 52 | test -f ./$@.in || srcdir=$(srcdir)/; \ 53 | sed \ 54 | -e 's,@libdir[@],$(libdir),g' \ 55 | -e 's,@libexecdir[@],$(libexecdir),g' \ 56 | $${srcdir}$@.in >$@.tmp; \ 57 | chmod 644 $@.tmp; \ 58 | mv $@.tmp $@ 59 | 60 | CLEANFILES = mptcp.service 61 | else 62 | bin_PROGRAMS = mptcpd mptcpize 63 | endif 64 | 65 | mptcpizelibdir = $(libdir)/mptcpize 66 | mptcpizelib_LTLIBRARIES = libmptcpwrap.la 67 | 68 | mptcpd_SOURCES = mptcpd.c 69 | mptcpd_LDADD = \ 70 | $(builddir)/libpath_manager.la \ 71 | $(ELL_LIBS) $(CODE_COVERAGE_LIBS) 72 | mptcpd_LDFLAGS = $(EXECUTABLE_LDFLAGS) 73 | 74 | librevision=1 75 | 76 | mptcpize_SOURCES = mptcpize.c 77 | mptcpize_CPPFLAGS = \ 78 | $(AM_CPPFLAGS) \ 79 | -DPKGLIBDIR=\"$(mptcpizelibdir)\" \ 80 | -DLIBREVISION=\"$(librevision)\" 81 | mptcpize_LDADD = $(CODE_COVERAGE_LIBS) 82 | mptcpize_LDFLAGS = $(EXECUTABLE_LDFLAGS) 83 | 84 | libmptcpwrap_la_SOURCES = mptcpwrap.c 85 | libmptcpwrap_la_CFLAGS = $(CODE_COVERAGE_CFLAGS) 86 | libmptcpwrap_la_LDFLAGS = -version-info 0:$(librevision):0 87 | libmptcpwrap_la_LIBADD = $(CODE_COVERAGE_LIBS) 88 | 89 | clean-local: code-coverage-clean 90 | -------------------------------------------------------------------------------- /etc/mptcpd.conf.in: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # 3 | # Copyright (c) 2018-2019, 2021-2022, Intel Corporation 4 | 5 | # ------------------------------------------------------------------ 6 | # mptcpd Configuration File 7 | # ------------------------------------------------------------------ 8 | 9 | [core] 10 | # ------------------------- 11 | # Default logging mechanism 12 | # ------------------------- 13 | # stderr - standard unbuffered I/O stream 14 | # syslog - POSIX based system logger 15 | # journal - systemd Journal 16 | # null - disable logging 17 | log=@mptcpd_logger@ 18 | 19 | # ---------------- 20 | # Plugin directory 21 | # ---------------- 22 | plugin-dir=@pkglibdir@ 23 | 24 | # ------------------- 25 | # Path manager plugin 26 | # --------------------- 27 | # The plugin found with the most favorable (lowest) priority will be 28 | # used if one is not specified. 29 | path-manager=@mptcpd_default_pm@ 30 | 31 | # -------------------------- 32 | # Address announcement flags 33 | # -------------------------- 34 | # A comma separated list containing one or more of the flags: 35 | # 36 | # subflow 37 | # signal (do not use with the "fullmesh" flag) 38 | # backup 39 | # fullmesh (do not use with the "signal" flag) 40 | # laminar 41 | # 42 | # Plugins that deal with the in-kernel path manager may use these 43 | # flags when advertising addresses. 44 | # 45 | # See the ip-mptcp(8) man page for details. 46 | # 47 | # addr-flags=subflow 48 | 49 | # -------------------------- 50 | # Address notification flags 51 | # -------------------------- 52 | # A comma separated list containing one or more of the flags: 53 | # 54 | # existing 55 | # Notify plugins of the addresses that exist at mptcpd start 56 | # 57 | # skip_link_local 58 | # Ignore (do not notify) [ipv6] link local address updates 59 | # 60 | # skip_loopback 61 | # Ignore (do not notify) host (loopback) address updates 62 | # 63 | # check_route 64 | # Notify address only if a default route is available from such 65 | # address and the related device. If the route check fails, it 66 | # will be re-done after a little timeout, to allow e.g. DHCP to 67 | # configure the host properly. Complex policy routing 68 | # configuration may confuse or circumvent this check. 69 | # 70 | # These flags determine whether mptpcd plugins will be notified when 71 | # related addresses are updated. 72 | # 73 | # notify-flags=existing,skip_link_local,skip_loopback,check_route 74 | 75 | # -------------------------- 76 | # Plugins to load 77 | # -------------------------- 78 | # A comma separated list containing one or more plugins to load. 79 | # 80 | # load-plugins=addr_adv,sspi 81 | -------------------------------------------------------------------------------- /tests/test-start-stop: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | # Minimal mptcpd start/stop test. 5 | # 6 | # Copyright (c) 2018, 2019, 2021, 2022, Intel Corporation 7 | 8 | if [ -z "$TEST_PLUGIN_DIR" ]; then 9 | echo TEST_PLUGIN_DIR environment variable is not set. 10 | exit 1 # failure 11 | fi 12 | 13 | # An exit status of 77 causes the Automake test driver to consider the 14 | # test as skipped. 15 | skip_exit_status=77 16 | 17 | # Skip the test if we're not using a kernel supporting MPTCP. 18 | if [ ! -d /proc/sys/net/mptcp ]; then 19 | echo Not running a kernel supporting MPTCP, skipping the test 20 | exit $skip_exit_status 21 | fi 22 | 23 | # Only run the individual enabled/disabled MPTCP test cases if the 24 | # "enabled" value can be set non-interactively, i.e. sudo can be 25 | # executed without a password. This is mostly useful for automated 26 | # builds. 27 | echo Running non-interactive sudo check... 28 | if ! sudo -n echo " succeeded"; then 29 | echo " fail, skipping the test" 30 | exit $skip_exit_status 31 | fi 32 | 33 | # Detect MPTCP "enabled" sysctl variable name and value. 34 | # upstream: net.mptcp.enabled 35 | # multipath-tcp.org: net.mptcp.mptcp_enabled 36 | variable=`sysctl --names --pattern 'mptcp.(|mptcp_)enabled' net.mptcp` 37 | old_value=`sysctl --values $variable` 38 | 39 | disable_value=0 40 | enable_value=1 41 | 42 | # "Disabled" value is always 0, but the "enabled" value could be 1 or 43 | # 2, depending on the kernel in use. For example, the 44 | # multipath-tcp.org kernel "enabled" value could be 1 or 2. Use the 45 | # old "enabled" value in case it is 2 instead of 1. 46 | if [ $old_value -ne 0 ] 47 | then 48 | enable_value=$old_value 49 | fi 50 | 51 | # @todo It would be better to have some sort of indication that 52 | # mptcpd is fully up and running rather than timeout after a 53 | # fixed amount of time like this. 54 | command="timeout --preserve-status \ 55 | --signal=TERM \ 56 | --kill-after=5s \ 57 | 1s ../src/mptcpd --plugin-dir=$TEST_PLUGIN_DIR" 58 | 59 | # Exit status/code 60 | status=0 61 | 62 | for value in $disable_value $enable_value 63 | do 64 | sudo -n sysctl -qw $variable=$value 65 | 66 | $command 67 | command_exit=$? 68 | 69 | echo -n "TEST CASE: $variable = $value ..." 70 | 71 | if ([ $value -eq $disable_value ] && [ $command_exit -eq 0 ]) \ 72 | || ([ $value -eq $enable_value ] && [ $command_exit -ne 0 ]) 73 | then 74 | echo failed 75 | status=1 # failure 76 | else 77 | echo passed 78 | fi 79 | done 80 | 81 | # Reset the "enabled" value to its original value. 82 | sudo -n sysctl -qw $variable=$old_value 83 | 84 | exit $status 85 | -------------------------------------------------------------------------------- /src/mptcpd.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file mptcpd.c 4 | * 5 | * @brief Main mptcpd source file. 6 | * 7 | * Copyright (c) 2017-2021, Intel Corporation 8 | */ 9 | 10 | #ifdef HAVE_CONFIG_H 11 | # include // For NDEBUG 12 | #endif 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | #include 21 | 22 | #include "path_manager.h" 23 | 24 | 25 | // Handle termination gracefully. 26 | static void signal_handler(uint32_t signo, void *user_data) 27 | { 28 | (void) user_data; 29 | 30 | assert(user_data != NULL); 31 | 32 | switch (signo) { 33 | case SIGINT: 34 | case SIGTERM: 35 | l_debug("\nTerminating %s", (char const *) user_data); 36 | l_main_quit(); 37 | break; 38 | } 39 | } 40 | 41 | int main(int argc, char *argv[]) 42 | { 43 | int result = EXIT_SUCCESS; 44 | 45 | struct mptcpd_config *const config = 46 | mptcpd_config_create(argc, argv); 47 | 48 | if (config == NULL) 49 | return EXIT_FAILURE; 50 | 51 | if (!l_main_init()) { 52 | mptcpd_config_destroy(config); 53 | return EXIT_FAILURE; 54 | } 55 | 56 | // Initialize the path manager. 57 | struct mptcpd_pm *const pm = mptcpd_pm_create(config); 58 | 59 | if (pm == NULL) { 60 | result = EXIT_FAILURE; 61 | goto exit; 62 | } 63 | 64 | /** 65 | * @todo Start D-Bus once we support a mptcpd D-Bus API. 66 | * 67 | * @todo Make this daemon socket-activatable when using 68 | * systemd. 69 | * 70 | * @todo Should we daemonize the the mptcpd process the 71 | * canonical way - fork() then orphan to make it owned by 72 | * the 'init' process, among other steps - when systemd 73 | * isn't used? 74 | */ 75 | 76 | // Start the main event loop. 77 | result = l_main_run_with_signal(signal_handler, argv[0]); 78 | 79 | if (result == EXIT_FAILURE) 80 | l_error("Main event loop failed."); 81 | 82 | mptcpd_pm_destroy(pm); 83 | 84 | exit: 85 | /** 86 | * @todo Call @c mptcpd_config_free() as soon we're done with 87 | * reading the configuration, e.g. after the path 88 | * manager has been initialized. 89 | */ 90 | mptcpd_config_destroy(config); 91 | 92 | if (!l_main_exit()) 93 | result = EXIT_FAILURE; 94 | 95 | return result; 96 | } 97 | 98 | 99 | /* 100 | Local Variables: 101 | c-file-style: "linux" 102 | End: 103 | */ 104 | -------------------------------------------------------------------------------- /include/mptcpd/private/configuration.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file configuration.h 4 | * 5 | * @brief Mptcpd configuration parser header. 6 | * 7 | * Copyright (c) 2018, 2019, 2021, Intel Corporation 8 | */ 9 | 10 | #ifndef MPTCPD_CONFIGURATION_H 11 | #define MPTCPD_CONFIGURATION_H 12 | 13 | #include 14 | 15 | 16 | /** 17 | * Function pointer corresponding to the ELL functions that set the 18 | * underlying logging mechanism, e.g. @c l_log_set_stderr, 19 | * @c l_log_set_syslog and @c l_log_set_journal. 20 | */ 21 | typedef void (*mptcpd_set_log_func_t)(void); 22 | 23 | /** 24 | * @brief mptcpd configuration parameters 25 | * 26 | * This structure defines a set of configuration parameters for 27 | * mptcpd. Only one instance of this structure is intended to exist 28 | * in a given mptcpd process. 29 | */ 30 | struct mptcpd_config 31 | { 32 | /** 33 | * @brief Function that configures the ELL logging mechanism. 34 | * 35 | * This function is called by mptcpd to configure the 36 | * underlying logging mechanism. In particular, it will be 37 | * any of the following: 38 | * 39 | * @li @c l_log_set_null 40 | * @li @c l_log_set_stderr 41 | * @li @c l_log_set_syslog 42 | * @li @c l_log_set_journal 43 | */ 44 | mptcpd_set_log_func_t log_set; 45 | 46 | /// Location of mptcpd plugins. 47 | char *plugin_dir; 48 | 49 | /** 50 | * @brief flags for addresses create 51 | * 52 | * Flags to be used when the plugin advertises an address. 53 | * Only relevant for the upstream kernel. 54 | */ 55 | uint32_t addr_flags; 56 | 57 | /// Various flags to control new address notification. 58 | uint32_t notify_flags; 59 | 60 | /** 61 | * @brief Name of default plugin. 62 | * 63 | * Use the operations associated with the plugin of this name 64 | * if a path management strategy wasn't configured for a given 65 | * MPTCP connection. 66 | */ 67 | char *default_plugin; 68 | 69 | /// A list of plugins to load. 70 | struct l_queue *plugins_to_load; 71 | }; 72 | 73 | /** 74 | * @brief Create a new mptcpd configuration. 75 | * 76 | * @param[in] argc Command line argument count. 77 | * @param[in,out] argv Command line argument vector. 78 | * 79 | * @return Mptcpd configuration information. 80 | */ 81 | struct mptcpd_config *mptcpd_config_create(int argc, char *argv[]); 82 | 83 | /** 84 | * @brief Destroy the mptcpd configuration. 85 | * 86 | * Deallocate all mptcpd configuration resources. 87 | * 88 | * @param[in,out] config Mptcpd configuration to be finalized. 89 | */ 90 | void mptcpd_config_destroy(struct mptcpd_config *config); 91 | 92 | #endif // MPTCPD_CONFIGURATION_H 93 | 94 | /* 95 | Local Variables: 96 | c-file-style: "linux" 97 | End: 98 | */ 99 | -------------------------------------------------------------------------------- /include/mptcpd/private/sockaddr.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file private/sockaddr.h 4 | * 5 | * @brief mptcpd @c struct @c sockaddr related utility functions. 6 | * 7 | * Copyright (c) 2019-2022, Intel Corporation 8 | */ 9 | 10 | #ifndef MPTCPD_PRIVATE_SOCKADDR_H 11 | #define MPTCPD_PRIVATE_SOCKADDR_H 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include // For in_addr_t. 18 | #include // For __constant_swab*. 19 | 20 | #include 21 | 22 | /** 23 | * @name Swap host ordered bytes in an integer to network byte order. 24 | * 25 | * These macros may be used in place of @c htons() or @c htonl() when 26 | * initializing an IPv4 address or TCP port constant at compile-time. 27 | */ 28 | ///@{ 29 | #if __BYTE_ORDER == __LITTLE_ENDIAN 30 | # define MPTCPD_CONSTANT_HTONS(hs) __swab16(hs) 31 | # define MPTCPD_CONSTANT_HTONL(hl) __swab32(hl) 32 | #else 33 | // No need to swap bytes on big endian platforms. 34 | // host byte order == network byte order 35 | # define MPTCPD_CONSTANT_HTONS(hs) hs 36 | # define MPTCPD_CONSTANT_HTONL(hl) hl 37 | #endif // __BYTE_ORDER == __LITTLE_ENDIAN 38 | ///@} 39 | 40 | 41 | #ifdef __cplusplus 42 | extern "C" { 43 | #endif 44 | 45 | struct in6_addr; 46 | struct sockaddr_storage; 47 | 48 | /** 49 | * @brief Initialize @c sockaddr_storage instance. 50 | * 51 | * Initialize a @c sockaddr_storage instance with the provided IPv4 or 52 | * IPv6 address. Only one is required and used. The @a port may be 53 | * zero in cases where it is optional. 54 | * 55 | * @param[in] addr4 IPv4 internet address (network byte order). 56 | * @param[in] addr6 IPv6 internet address. 57 | * @param[in] port TCP port (network byte order). 58 | * @param[in,out] addr mptcpd network address information. 59 | * 60 | * @return @c true on success. @c false otherwise. 61 | */ 62 | MPTCPD_API bool 63 | mptcpd_sockaddr_storage_init(in_addr_t const *addr4, 64 | struct in6_addr const *addr6, 65 | in_port_t port, 66 | struct sockaddr_storage *addr); 67 | 68 | /** 69 | * @brief Deep copy a @c sockaddr. 70 | * 71 | * Copy the address family-specific contents of a @c sockaddr. For an 72 | * @c AF_INET address family, a @c struct @c sockaddr_in will be 73 | * dynamically allocated and copied from @a sa. Similarly, @c struct 74 | * @c sockaddr_in6 will be allocated and copied from @a sa for the 75 | * @c AF_INET6 address family case. 76 | * 77 | * @return Dynamically allocated copy of @a sa if the @c sa_family 78 | * member is @c AF_INET or @c AF_INET6, and @c NULL otherwise. 79 | * Deallocate with @c l_free(). 80 | */ 81 | MPTCPD_API struct sockaddr * 82 | mptcpd_sockaddr_copy(struct sockaddr const *sa); 83 | 84 | #ifdef __cplusplus 85 | } 86 | #endif 87 | 88 | 89 | #endif /* MPTCPD_PRIVATE_SOCKADDR_H */ 90 | 91 | 92 | /* 93 | Local Variables: 94 | c-file-style: "linux" 95 | End: 96 | */ 97 | -------------------------------------------------------------------------------- /tests/test-addr-info.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file test-addr-info.c 4 | * 5 | * @brief mptcpd_addr_info related functions test. 6 | * 7 | * Copyright (c) 2021, 2022, Intel Corporation 8 | */ 9 | 10 | #include // htonl() and htons() 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #undef NDEBUG 18 | #include 19 | 20 | 21 | static void test_bad_addr_info(void const *test_data) 22 | { 23 | (void) test_data; 24 | 25 | // Check underlying sockaddr. 26 | struct sockaddr const *sa = mptcpd_addr_info_get_addr(NULL); 27 | assert(sa == NULL); 28 | 29 | // Check MPTCP address ID. 30 | mptcpd_aid_t const id = mptcpd_addr_info_get_id(NULL); 31 | assert(id == 0); 32 | 33 | // Check mptcpd flags. 34 | mptcpd_flags_t const flags = mptcpd_addr_info_get_flags(NULL); 35 | assert(flags == 0); 36 | 37 | // Check network interface index. 38 | int const index = mptcpd_addr_info_get_index(NULL); 39 | assert(index == -1); 40 | } 41 | 42 | static void test_addr_info(void const *test_data) 43 | { 44 | (void) test_data; 45 | 46 | in_addr_t const addr = htonl(0xC0000201); // 192.0.2.1 47 | in_port_t const port = htons(0x1234); 48 | 49 | struct mptcpd_addr_info info = { 50 | .id = 5, 51 | .flags = 10, 52 | .index = 2 53 | }; 54 | 55 | assert(mptcpd_sockaddr_storage_init(&addr, 56 | NULL, 57 | port, 58 | &info.addr)); 59 | 60 | 61 | // Check underlying sockaddr. 62 | struct sockaddr const *sa = mptcpd_addr_info_get_addr(&info); 63 | assert(sa != NULL && sa->sa_family == AF_INET); 64 | 65 | struct sockaddr_in const *sai = (struct sockaddr_in const *) sa; 66 | assert(sai->sin_addr.s_addr == addr); 67 | assert(sai->sin_port == port); 68 | 69 | // Check MPTCP address ID. 70 | mptcpd_aid_t const id = mptcpd_addr_info_get_id(&info); 71 | assert(id == info.id); 72 | 73 | // Check mptcpd flags. 74 | mptcpd_flags_t const flags = mptcpd_addr_info_get_flags(&info); 75 | assert(flags == info.flags); 76 | 77 | // Check network interface index. 78 | int const index = mptcpd_addr_info_get_index(&info); 79 | assert(index == info.index); 80 | } 81 | 82 | 83 | int main(int argc, char *argv[]) 84 | { 85 | l_log_set_stderr(); 86 | 87 | l_test_init(&argc, &argv); 88 | 89 | l_test_add("bad addr_info", test_bad_addr_info, NULL); 90 | l_test_add("good addr_info", test_addr_info, NULL); 91 | 92 | return l_test_run(); 93 | } 94 | 95 | 96 | /* 97 | Local Variables: 98 | c-file-style: "linux" 99 | End: 100 | */ 101 | -------------------------------------------------------------------------------- /scripts/mptcp-get-debug: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | # 4 | # Copyright (c) 2024, Matthieu Baerts 5 | 6 | SCRIPT="$(basename "${0}")" 7 | VERSION="1" 8 | PID_IP= 9 | 10 | EQ="========================================" 11 | 12 | title() { 13 | printf "\n%s\n%s\n%s\n" "${EQ}" "${*}" "${EQ}" 14 | } 15 | 16 | stdout() { 17 | printf "\n%s\n" "${*}" 18 | } 19 | 20 | stderr() { 21 | stdout "${@}" >&2 22 | } 23 | 24 | cmd() { 25 | title "${*}" 26 | "${@}" 2>&1 27 | } 28 | 29 | start_ip_mptcp_monitor() { 30 | title "ip mptcp monitor: start" 31 | ip mptcp monitor 2>&1 & # not using cmd to get the right PID 32 | PID_IP=$! 33 | 34 | sleep 0.1 2>/dev/null || sleep 1 35 | 36 | for _ in $(seq 20); do 37 | out="$(ss -f netlink -H "src = rtnl:${PID_IP}" 2>/dev/null)" || break 38 | [ "$(echo "${out}" | wc -l)" != 0 ] && return 0 39 | 40 | sleep 0.1 2>/dev/null || break 41 | done 42 | 43 | if [ ! -d "/proc/${PID_IP}" ]; then 44 | stdout "ip monitor has been killed" 45 | return 1 46 | fi 47 | } 48 | 49 | stop_ip_mptcp_monitor() { 50 | title "ip mptcp monitor: stop" 51 | 52 | if [ -n "${PID_IP}" ] && [ -d "/proc/${PID_IP}" ]; then 53 | kill "${PID_IP}" 54 | fi 55 | } 56 | 57 | collect_data_pre() { 58 | stdout "${SCRIPT}: version ${VERSION}" 59 | 60 | if [ "$(id -u)" != 0 ]; then 61 | stderr "This script is not executed as root, not all info can be collected." 62 | stderr "Press Enter to continue, Ctrl+C to stop" 63 | read -r _ 64 | fi 65 | 66 | cmd uname -a 67 | cmd cat /etc/os-release 68 | cmd sysctl net.mptcp 69 | cmd ip mptcp endpoint show 70 | cmd ip mptcp limits show 71 | } 72 | 73 | collect_data_post() { 74 | cmd ss -ManiH 75 | cmd nstat 76 | } 77 | 78 | collect_data() { 79 | collect_data_pre 80 | collect_data_post 81 | } 82 | 83 | collect_data_repro() { 84 | collect_data_pre 85 | 86 | cmd ss -ManiH 87 | nstat -n 2>&1 88 | start_ip_mptcp_monitor 89 | 90 | stderr "Please reproduce the issue now, then press the Enter key when it is done." 91 | read -r _ 92 | 93 | collect_data_post 94 | stop_ip_mptcp_monitor 95 | } 96 | 97 | version() { 98 | printf "%s: version %s\n" "${SCRIPT}" ${VERSION} 99 | } 100 | 101 | usage() { 102 | version 103 | printf "\n" 104 | printf " -c | --collect Collect info and exit.\n" 105 | printf " -r | --reproduce Collect info, start monitor, wait for user and exit.\n" 106 | printf " -h | --help Show this and exit.\n" 107 | printf " -v | --version Show the version and exit.\n" 108 | printf "\n" 109 | printf "Please check https://mptcp.dev website for more info.\n" 110 | } 111 | 112 | case "${1}" in 113 | "-c" | "--collect") 114 | collect_data 115 | ;; 116 | "-r" | "--reproduce") 117 | collect_data_repro 118 | ;; 119 | "-h" | "--help") 120 | usage 121 | ;; 122 | "-v" | "--version") 123 | version 124 | ;; 125 | *) 126 | usage >&2 127 | exit 1 128 | ;; 129 | esac 130 | 131 | exit 0 132 | -------------------------------------------------------------------------------- /m4/mptcpd_kernel.m4: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # 3 | # Copyright (c) 2021-2022, Intel Corporation 4 | 5 | #serial 2 6 | 7 | # MPTCPD_CHECK_KERNEL 8 | # 9 | # Check if a MPTCP capable kernel is in use. 10 | AC_DEFUN([MPTCPD_CHECK_KERNEL], 11 | [ 12 | # upstream: /proc/sys/net/mptcp/enabled 13 | # multipath-tcp.org: /proc/sys/net/mptcp/mptcp_enabled 14 | AS_IF([test "x$with_kernel" = "xauto"], 15 | [mptcp_sysctl_base="/proc/sys/net/mptcp/" 16 | AC_CHECK_FILE( 17 | [${mptcp_sysctl_base}enabled], 18 | [with_kernel=upstream], 19 | [AC_CHECK_FILE( 20 | [${mptcp_sysctl_base}mptcp_enabled], 21 | [with_kernel=multipath-tcp.org], 22 | [with_kernel=upstream 23 | AC_MSG_WARN( 24 | [No MPTCP capable kernel detected. Assuming upstream.]) 25 | ]) 26 | ]) 27 | ]) 28 | ]) 29 | 30 | # MPTCPD_CHECK_KERNEL_HEADER_UPSTREAM 31 | # 32 | # Check if the header exists, determine if it 33 | # corresponds the upstream or multipath-tcp.org kernel, and check if 34 | # it may be used by mptcpd since older versions may be missing 35 | # required preprocessor symbols or enumerators. 36 | AC_DEFUN([MPTCPD_CHECK_KERNEL_HEADER_UPSTREAM], 37 | [ 38 | AH_TEMPLATE([HAVE_LINUX_MPTCP_H_UPSTREAM], 39 | [Define to 1 if you have the upstream kernel 40 | header.]) 41 | 42 | AC_CACHE_CHECK([for MPTCP_ATTR_SERVER_SIDE in linux/mptcp.h], 43 | [mptcpd_cv_header_upstream], 44 | [ 45 | # Perform a compile-time test since MPTCP_ATTR_SERVER_SIDE is an 46 | # enumerator, not a preprocessor symbol. 47 | AC_COMPILE_IFELSE([ 48 | AC_LANG_SOURCE([ 49 | #include 50 | 51 | int get_mptcp_attr(void) { return (int) MPTCP_ATTR_SERVER_SIDE; } 52 | ]) 53 | ], 54 | [mptcpd_cv_header_upstream=yes], 55 | [mptcpd_cv_header_upstream=no]) 56 | ]) 57 | 58 | AS_IF([test "x$mptcpd_cv_header_upstream" = "xyes"], 59 | [AC_DEFINE([HAVE_LINUX_MPTCP_H_UPSTREAM], [1])], 60 | [AC_MSG_WARN([No usable upstream . Using fallback.])]) 61 | ]) 62 | 63 | # MPTCPD_CHECK_KERNEL_HEADER_MPTCP_ORG 64 | # 65 | # Check the multipath-tcp.org kernel-specific 66 | # /proc/sys/net/mptcp/mptcp_enabled file exists. The 67 | # multipath-tcp.org kernel is being used if it does. 68 | AC_DEFUN([MPTCPD_CHECK_KERNEL_HEADER_MPTCP_ORG], 69 | [ 70 | AH_TEMPLATE([HAVE_LINUX_MPTCP_H_MPTCP_ORG], 71 | [Define to 1 if you have the multipath-tcp.org kernel 72 | header.]) 73 | 74 | AX_CHECK_DEFINE( 75 | [linux/mptcp.h], 76 | [MPTCP_GENL_NAME], 77 | [AC_DEFINE([HAVE_LINUX_MPTCP_H_MPTCP_ORG], [1])], 78 | [AC_MSG_WARN([No usable multipath-tcp.org . Using fallback.])]) 79 | ]) 80 | 81 | # MPTCPD_CHECK_LINUX_MPTCP_H 82 | # 83 | # Check if the header is available in the system or 84 | # user-specified include path, taking into account the detected or 85 | # user-selected MPTCP capable kernel. 86 | AC_DEFUN([MPTCPD_CHECK_LINUX_MPTCP_H], 87 | [ 88 | AC_REQUIRE([MPTCPD_CHECK_KERNEL]) 89 | 90 | AC_CHECK_HEADERS([linux/mptcp.h], 91 | [ 92 | AS_IF([test "x$with_kernel" = "xupstream"], 93 | [MPTCPD_CHECK_KERNEL_HEADER_UPSTREAM]) 94 | 95 | AS_IF([test "x$with_kernel" = "xmultipath-tcp.org"], 96 | [MPTCPD_CHECK_KERNEL_HEADER_MPTCP_ORG]) 97 | ], 98 | [ 99 | AC_MSG_WARN([ header not found. Using fallback.]) 100 | ]) 101 | ]) 102 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | Language: Cpp 2 | # BasedOnStyle: LLVM 3 | AccessModifierOffset: -2 4 | AlignAfterOpenBracket: Align 5 | AlignConsecutiveAssignments: true 6 | AlignConsecutiveDeclarations: false 7 | AlignEscapedNewlines: Right 8 | AlignOperands: true 9 | AlignTrailingComments: true 10 | AllowAllParametersOfDeclarationOnNextLine: false 11 | AllowShortBlocksOnASingleLine: false 12 | AllowShortCaseLabelsOnASingleLine: false 13 | AllowShortFunctionsOnASingleLine: Inline 14 | AllowShortIfStatementsOnASingleLine: false 15 | AllowShortLoopsOnASingleLine: false 16 | AlwaysBreakAfterReturnType: None 17 | AlwaysBreakBeforeMultilineStrings: false 18 | AlwaysBreakTemplateDeclarations: false 19 | BinPackArguments: false 20 | BinPackParameters: false 21 | BraceWrapping: 22 | AfterClass: true 23 | AfterControlStatement: false 24 | AfterEnum: false 25 | AfterFunction: true 26 | AfterNamespace: true 27 | AfterObjCDeclaration: false 28 | AfterStruct: true 29 | AfterUnion: true 30 | AfterExternBlock: false 31 | BeforeCatch: false 32 | BeforeElse: false 33 | IndentBraces: false 34 | SplitEmptyFunction: true 35 | SplitEmptyRecord: true 36 | SplitEmptyNamespace: true 37 | BreakBeforeBinaryOperators: NonAssignment 38 | BreakBeforeBraces: Custom 39 | BreakBeforeInheritanceComma: false 40 | BreakBeforeTernaryOperators: true 41 | BreakConstructorInitializersBeforeComma: false 42 | BreakConstructorInitializers: BeforeComma 43 | BreakAfterJavaFieldAnnotations: false 44 | BreakStringLiterals: true 45 | ColumnLimit: 74 46 | CommentPragmas: '^ IWYU pragma:' 47 | CompactNamespaces: false 48 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 49 | ConstructorInitializerIndentWidth: 8 50 | ContinuationIndentWidth: 8 51 | Cpp11BracedListStyle: false 52 | DerivePointerAlignment: false 53 | DisableFormat: false 54 | ExperimentalAutoDetectBinPacking: false 55 | FixNamespaceComments: true 56 | ForEachMacros: 57 | - foreach 58 | - Q_FOREACH 59 | - BOOST_FOREACH 60 | IncludeBlocks: Preserve 61 | IncludeCategories: 62 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/' 63 | Priority: 2 64 | - Regex: '^(<|"(gtest|gmock|isl|json)/)' 65 | Priority: 3 66 | - Regex: '.*' 67 | Priority: 1 68 | IncludeIsMainRegex: '(Test)?$' 69 | IndentCaseLabels: false 70 | #IndentPPDirectives: AfterHash 71 | IndentWidth: 8 72 | IndentWrappedFunctionNames: false 73 | JavaScriptQuotes: Leave 74 | JavaScriptWrapImports: true 75 | KeepEmptyLinesAtTheStartOfBlocks: false 76 | MacroBlockBegin: '' 77 | MacroBlockEnd: '' 78 | MaxEmptyLinesToKeep: 1 79 | NamespaceIndentation: All 80 | ObjCBlockIndentWidth: 2 81 | ObjCSpaceAfterProperty: false 82 | ObjCSpaceBeforeProtocolList: true 83 | PenaltyBreakAssignment: 2 84 | PenaltyBreakBeforeFirstCallParameter: 19 85 | PenaltyBreakComment: 300 86 | PenaltyBreakFirstLessLess: 120 87 | PenaltyBreakString: 1000 88 | PenaltyExcessCharacter: 1000000 89 | PenaltyReturnTypeOnItsOwnLine: 60 90 | PointerAlignment: Right 91 | ReflowComments: true 92 | SortIncludes: false 93 | SortUsingDeclarations: true 94 | SpaceAfterCStyleCast: true 95 | SpaceAfterTemplateKeyword: false 96 | SpaceBeforeAssignmentOperators: true 97 | SpaceBeforeParens: ControlStatements 98 | SpaceInEmptyParentheses: false 99 | SpacesBeforeTrailingComments: 2 100 | SpacesInAngles: false 101 | SpacesInContainerLiterals: true 102 | SpacesInCStyleCastParentheses: false 103 | SpacesInParentheses: false 104 | SpacesInSquareBrackets: false 105 | Standard: Auto 106 | TabWidth: 8 107 | UseTab: Never 108 | -------------------------------------------------------------------------------- /tests/lib/call_count.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file call-count.c 4 | * 5 | * @brief mptcpd test plugin call count functions. 6 | * 7 | * Copyright (c) 2019, 2022, Intel Corporation 8 | */ 9 | 10 | #include "test-plugin.h" 11 | 12 | 13 | void call_count_reset(struct plugin_call_count *p) 14 | { 15 | p->new_connection = 0; 16 | p->connection_established = 0; 17 | p->connection_closed = 0; 18 | p->new_address = 0; 19 | p->address_removed = 0; 20 | p->new_subflow = 0; 21 | p->subflow_closed = 0; 22 | p->subflow_priority = 0; 23 | p->listener_created = 0; 24 | p->listener_closed = 0; 25 | p->new_interface = 0; 26 | p->update_interface = 0; 27 | p->delete_interface = 0; 28 | p->new_local_address = 0; 29 | p->delete_local_address = 0; 30 | } 31 | 32 | bool call_count_all_positive(struct plugin_call_count const *p) 33 | { 34 | return p->new_connection >= 0 35 | && p->connection_established >= 0 36 | && p->connection_closed >= 0 37 | && p->new_address >= 0 38 | && p->address_removed >= 0 39 | && p->new_subflow >= 0 40 | && p->subflow_closed >= 0 41 | && p->subflow_priority >= 0 42 | && p->listener_created >= 0 43 | && p->listener_closed >= 0 44 | && p->new_interface >= 0 45 | && p->update_interface >= 0 46 | && p->delete_interface >= 0 47 | && p->new_local_address >= 0 48 | && p->delete_local_address >= 0; 49 | } 50 | 51 | bool call_count_is_sane(struct plugin_call_count const *p) 52 | { 53 | return // non-negative counts 54 | call_count_all_positive(p) 55 | 56 | /* 57 | Some callbacks should not be called more than 58 | others. 59 | */ 60 | && p->connection_established <= p->new_connection 61 | && p->connection_closed <= p->new_connection 62 | && p->subflow_closed <= p->new_subflow; 63 | } 64 | 65 | bool call_count_is_equal(struct plugin_call_count const *lhs, 66 | struct plugin_call_count const *rhs) 67 | { 68 | return lhs->new_connection == rhs->new_connection 69 | && lhs->connection_established == rhs->connection_established 70 | && lhs->connection_closed == rhs->connection_closed 71 | && lhs->new_address == rhs->new_address 72 | && lhs->address_removed == rhs->address_removed 73 | && lhs->new_subflow == rhs->new_subflow 74 | && lhs->subflow_closed == rhs->subflow_closed 75 | && lhs->subflow_priority == rhs->subflow_priority 76 | && lhs->listener_created == rhs->listener_created 77 | && lhs->listener_closed == rhs->listener_closed 78 | && lhs->new_interface == rhs->new_interface 79 | && lhs->update_interface == rhs->update_interface 80 | && lhs->delete_interface == rhs->delete_interface 81 | && lhs->new_local_address == rhs->new_local_address 82 | && lhs->delete_local_address == rhs->delete_local_address; 83 | } 84 | 85 | 86 | /* 87 | Local Variables: 88 | c-file-style: "linux" 89 | End: 90 | */ 91 | -------------------------------------------------------------------------------- /tests/test-cxx-build.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file test-cxx-build.cpp 4 | * 5 | * @brief Verify mptcpd API can be used in C++ code. 6 | * 7 | * Copyright (c) 2019, 2021-2022, Intel Corporation 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include // Include to test build under C++. 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | 21 | #include "test-plugin.h" 22 | 23 | #undef NDEBUG 24 | #include 25 | 26 | 27 | /** 28 | * @class test_nm 29 | * 30 | * @brief Encapsulate a @c mptcpd_nm object. 31 | * 32 | * @note This class is only intended to exercise @c mptcpd network 33 | * monitor operations when using a C++ compiler. It is not 34 | * intended to be used as a model for how the operations should 35 | * be encapsulated in production code. 36 | */ 37 | class test_nm 38 | { 39 | public: 40 | 41 | test_nm() : nm_(mptcpd_nm_create(0)) { assert(this->nm_); } 42 | ~test_nm() { mptcpd_nm_destroy (this->nm_); } 43 | 44 | private: 45 | test_nm(test_nm const &); 46 | void operator=(test_nm const &); 47 | 48 | private: 49 | mptcpd_nm *const nm_; 50 | }; 51 | 52 | /** 53 | * @class test_plugin 54 | * 55 | * @brief Encapsulate @c mptcpd plugin operations. 56 | * 57 | * @note This class is only intended to exercise @c mptcpd plugin 58 | * operations when using a C++ compiler. It is not intended to 59 | * be used as a model for how the operations should be 60 | * encapsulated in production code. 61 | */ 62 | class test_plugin 63 | { 64 | public: 65 | test_plugin() 66 | : pm(NULL) 67 | { 68 | static char const dir[] = TEST_PLUGIN_DIR; 69 | static char const default_plugin[] = TEST_PLUGIN_FOUR; 70 | struct mptcpd_pm *const pm = NULL; 71 | 72 | bool const loaded = 73 | mptcpd_plugin_load(dir, default_plugin, NULL, this->pm); 74 | assert(loaded); 75 | 76 | static struct plugin_call_args const args = { 77 | .token = test_token_4, 78 | .raddr_id = test_raddr_id_4, 79 | .laddr = (struct sockaddr const *) &test_laddr_4, 80 | .raddr = (struct sockaddr const *) &test_raddr_4, 81 | .backup = test_backup_4 82 | }; 83 | 84 | call_plugin_ops(&test_count_4, &args); 85 | } 86 | 87 | ~test_plugin() { mptcpd_plugin_unload(this->pm); } 88 | 89 | private: 90 | test_plugin(test_plugin const &); 91 | void operator=(test_plugin const &); 92 | private: 93 | struct mptcpd_pm *const pm; 94 | }; 95 | 96 | 97 | int main() 98 | { 99 | if (!l_main_init()) 100 | return -1; 101 | 102 | l_log_set_stderr(); 103 | 104 | /** 105 | * @note As of ELL 0.17 uncommenting the below call to 106 | * l_debug_enable() causes link-time unresolved symbol 107 | * errors caused by the @c __start___ell_debug and 108 | * @c __stop___ell_debug symbols not being exported from 109 | * the ELL shared library. 110 | */ 111 | // l_debug_enable("*"); 112 | 113 | test_nm nm; 114 | test_plugin p; 115 | 116 | (void) nm; 117 | (void) p; 118 | 119 | return l_main_exit() ? 0 : -1; 120 | } 121 | 122 | 123 | /* 124 | Local Variables: 125 | c-file-style: "linux" 126 | End: 127 | */ 128 | -------------------------------------------------------------------------------- /lib/hash_sockaddr.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file hash_sockaddr.c 4 | * 5 | * @brief @c struct @c sockaddr hash related functions. 6 | * 7 | * Copyright (c) 2022, Intel Corporation 8 | */ 9 | 10 | #ifdef HAVE_CONFIG_H 11 | # include 12 | #endif 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | 21 | #include 22 | 23 | #include "hash_sockaddr.h" 24 | 25 | 26 | static int compare_sockaddr_in(struct sockaddr const *lsa, 27 | struct sockaddr const *rsa) 28 | { 29 | struct sockaddr_in const *const lin = 30 | (struct sockaddr_in const *) lsa; 31 | 32 | struct sockaddr_in const *const rin = 33 | (struct sockaddr_in const *) rsa; 34 | 35 | in_addr_t const lhs = lin->sin_addr.s_addr; 36 | in_addr_t const rhs = rin->sin_addr.s_addr; 37 | 38 | return lhs < rhs ? -1 : (lhs > rhs ? 1 : 0); 39 | } 40 | 41 | static int compare_sockaddr_in6(struct sockaddr const *lsa, 42 | struct sockaddr const *rsa) 43 | { 44 | /** 45 | * @todo Should we compare the other @c struct @c sockaddr_in6 46 | * fields as well? 47 | */ 48 | 49 | struct sockaddr_in6 const *const lin = 50 | (struct sockaddr_in6 const *) lsa; 51 | 52 | struct sockaddr_in6 const *const rin = 53 | (struct sockaddr_in6 const *) rsa; 54 | 55 | uint8_t const *const lhs = lin->sin6_addr.s6_addr; 56 | uint8_t const *const rhs = rin->sin6_addr.s6_addr; 57 | 58 | return memcmp(lhs, rhs, sizeof(lin->sin6_addr.s6_addr)); 59 | } 60 | 61 | int mptcpd_hash_sockaddr_compare(void const *a, void const *b) 62 | { 63 | struct mptcpd_hash_sockaddr_key const *const lkey = a; 64 | struct mptcpd_hash_sockaddr_key const *const rkey = b; 65 | 66 | struct sockaddr const *const lsa = lkey->sa; 67 | struct sockaddr const *const rsa = rkey->sa; 68 | 69 | if (lsa->sa_family == rsa->sa_family) { 70 | if (lsa->sa_family == AF_INET) { 71 | // IPv4 72 | return compare_sockaddr_in(lsa, rsa); 73 | } else { 74 | // IPv6 75 | return compare_sockaddr_in6(lsa, rsa); 76 | } 77 | } else if (lsa->sa_family == AF_INET) { 78 | return 1; // IPv4 > IPv6 79 | } else { 80 | return -1; // IPv6 < IPv4 81 | } 82 | } 83 | 84 | void *mptcpd_hash_sockaddr_key_copy(void const *p) 85 | { 86 | struct mptcpd_hash_sockaddr_key const *const src = p; 87 | struct mptcpd_hash_sockaddr_key *const key = 88 | l_new(struct mptcpd_hash_sockaddr_key, 1); 89 | 90 | struct sockaddr *sa = NULL; 91 | 92 | if (src->sa->sa_family == AF_INET) { 93 | sa = (struct sockaddr *) l_new(struct sockaddr_in, 1); 94 | 95 | memcpy(sa, src->sa, sizeof(struct sockaddr_in)); 96 | } else { 97 | sa = (struct sockaddr *) l_new(struct sockaddr_in6, 1); 98 | 99 | memcpy(sa, src->sa, sizeof(struct sockaddr_in6)); 100 | } 101 | 102 | key->sa = sa; 103 | key->seed = src->seed; 104 | 105 | return key; 106 | } 107 | 108 | void mptcpd_hash_sockaddr_key_free(void *p) 109 | { 110 | if (p == NULL) 111 | return; 112 | 113 | struct mptcpd_hash_sockaddr_key *const key = p; 114 | 115 | l_free((void *) key->sa); // Cast "const" away. 116 | l_free(key); 117 | } 118 | 119 | 120 | /* 121 | Local Variables: 122 | c-file-style: "linux" 123 | End: 124 | */ 125 | -------------------------------------------------------------------------------- /man/mptcpd.8.in: -------------------------------------------------------------------------------- 1 | .\" SPDX-License-Identifier: BSD-3-Clause 2 | .\" 3 | .\" Copyright (c) 2017-2022, Intel Corporation 4 | 5 | .\" Process this file with 6 | .\" groff -man -Tascii mptcpd.8 7 | .\" 8 | .TH MPTCPD 8 "2022-08-19" "Multipath TCP Daemon" "System Management Commands" 9 | .SH NAME 10 | mptcpd \- multipath TCP daemon 11 | .SH SYNOPSIS 12 | .SY mptcpd 13 | .OP \-d?V 14 | .OP \-l DEST 15 | .OP \-\-debug 16 | .BI [\-\-addr\-flags= FLAGS ] 17 | .BI [\-\-notify\-flags= FLAGS ] 18 | .BI [\-\-plugin\-dir= DIR ] 19 | .BI [\-\-path\-manager= PLUGIN ] 20 | .BI [\-\-load\-plugins= PLUGINS ] 21 | .OP \-\-help 22 | .OP \-\-usage 23 | .BI [\-\-log= DEST ] 24 | .OP --version 25 | .YS 26 | 27 | .SH DESCRIPTION 28 | .B mptcpd 29 | is a daemon for Linux based operating systems that performs multipath 30 | TCP (see IETF RFC 8684) path management related operations in the user 31 | space. It interacts with the Linux kernel through a generic netlink 32 | connection to track per-connection information, available network 33 | interfaces, request new MPTCP subflows, handle requests for subflows, 34 | etc. 35 | .SH OPTIONS 36 | .B mptcpd 37 | accepts the following command line options: 38 | 39 | .TP 40 | .BR \-d , \-\-debug 41 | enable debug log messages 42 | 43 | .TP 44 | .BR \-? , \-\-help 45 | display 46 | .B mptcpd 47 | help information 48 | 49 | .TP 50 | .B \-\-usage 51 | display brief 52 | .B mptcpd 53 | usage information 54 | 55 | .TP 56 | .BI \-l \ DEST ,\ \-\-log= DEST 57 | log output to 58 | .IR DEST , 59 | where 60 | .I DEST 61 | can be 62 | .IR stderr , 63 | .I syslog 64 | or 65 | .I journal 66 | 67 | .TP 68 | .BI \-\-addr\-flags= FLAGS 69 | set flags for announced address, where 70 | .I FLAGS 71 | is a comma separated list containing one or more of the flags 72 | .IR subflow , 73 | .IR signal , 74 | .IR backup , 75 | .IR fullmesh , 76 | and 77 | .IR laminar 78 | that plugins that deal with the in-kernel path manager may use when 79 | advertising addresses, e.g. 80 | .B --addr-flags=subflow 81 | 82 | .TP 83 | .BI \-\-notify\-flags= FLAGS 84 | address notification flags, where 85 | .I FLAGS 86 | is a comma separated list containing one or more of the following 87 | flags: 88 | .RS 89 | .TP 90 | .I existing 91 | notify plugins of the addresses that exist at mptcpd start 92 | .RE 93 | .RS 94 | .TP 95 | .I skip_link_local 96 | ignore (do not notify) [ipv6] link local address updates 97 | .RE 98 | .RS 99 | .TP 100 | .I skip_loopback 101 | ignore (do not notify) host (loopback) address updates 102 | .RE 103 | .RS 104 | .TP 105 | .I check_route 106 | notify address only if a default route is available from such address 107 | and the related device. If the route check fails, it will be re-done 108 | after a little timeout, to allow e.g. DHCP to configure the host 109 | properly. Complex policy routing configuration may confuse or 110 | circumvent this check. 111 | .RE 112 | .P 113 | .RS 114 | These flags determine whether mptpcd plugins will be notified when 115 | related addresses are updated, e.g. 116 | .B --notify-flags=existing,skip_link_local,skip_loopback,check_route 117 | .RE 118 | 119 | .TP 120 | .BI \-\-plugin\-dir= DIR 121 | set plugin directory to 122 | .IR DIR , 123 | which should not be world writable for security reasons. 124 | 125 | .TP 126 | .BI \-\-path\-manager= PLUGIN 127 | set default path manager plugin to 128 | .IR PLUGIN , 129 | overriding plugin priorities 130 | 131 | .TP 132 | .BI \-\-load\-plugins= PLUGINS 133 | set plugins to load on startup, where 134 | .I PLUGINS 135 | is a comma separated list containing one or more plugin names 136 | 137 | .TP 138 | .BR \-V , \-\-version 139 | display 140 | .B mptcpd 141 | version information 142 | 143 | .SH FILES 144 | .TP 145 | .I @pkgsysconfdir@/mptcpd.conf 146 | Location of the mptcpd system configuration file. 147 | .\" TODO: Describe systemd unit file 148 | 149 | .SH REPORTING BUGS 150 | Report bugs to 151 | .MT @PACKAGE_BUGREPORT@ 152 | .ME . 153 | 154 | .SH SEE ALSO 155 | ip-mptcp(8) 156 | 157 | .\" Local Variables: 158 | .\" mode: nroff 159 | .\" End: 160 | -------------------------------------------------------------------------------- /tests/mptcpwrap-tester.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file mptcpwrap-tester.c 4 | * 5 | * @brief Test wrapped socket() call for MPTCP protocol injection. 6 | * 7 | * Copyright (c) 2021, Intel Corporation 8 | */ 9 | 10 | #undef NDEBUG 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | 25 | struct socket_data 26 | { 27 | int domain; 28 | int type; 29 | int protocol; 30 | bool expect_mptcp; 31 | }; 32 | 33 | static bool verify_protocol(int fd, bool expect_mptcp) 34 | { 35 | int protocol = 0; 36 | socklen_t len = sizeof(protocol); 37 | 38 | int const ret = getsockopt(fd, 39 | SOL_SOCKET, 40 | SO_PROTOCOL, 41 | &protocol, 42 | &len); 43 | 44 | /* 45 | The MPTCP-ized protocol injected by the hijacked socket() 46 | call, i.e. IPPROTO_MPTCP. 47 | */ 48 | static int const mptcp_protocol = IPPROTO_TCP + 256; 49 | 50 | return ret == 0 51 | && (expect_mptcp ? protocol == mptcp_protocol : true); 52 | } 53 | 54 | static void test_socket_data(struct socket_data const *data) 55 | { 56 | int const fd = socket(data->domain, data->type, data->protocol); 57 | 58 | if (fd == -1) { 59 | if (errno == EPROTONOSUPPORT) { 60 | struct protoent const *const p = 61 | getprotobynumber(data->protocol); 62 | 63 | fprintf(stderr, 64 | "WARNING: Ignoring unsupported " 65 | "protocol: %d - %s\n", 66 | data->protocol, 67 | p ? p->p_name : "Unknown"); 68 | 69 | return; 70 | } 71 | 72 | fprintf(stderr, 73 | "ERROR: socket() call failed unexpectedly.\n"); 74 | 75 | exit(EXIT_FAILURE); 76 | } 77 | 78 | bool const verified = verify_protocol(fd, data->expect_mptcp); 79 | 80 | close(fd); 81 | 82 | assert(verified); 83 | } 84 | 85 | int main(void) 86 | { 87 | /* 88 | libmptcpwrap.so should be preloaded when running this 89 | program, e.g.: 90 | 91 | LD_PRELOAD=libmptcpwrap.so ./mptcpwrap-tester 92 | */ 93 | char const *const LD_PRELOAD = getenv("LD_PRELOAD"); 94 | assert(LD_PRELOAD != NULL); 95 | assert(strstr(LD_PRELOAD, "libmptcpwrap.so") != NULL); 96 | 97 | /* 98 | MPTCP is only injected when using the SOCK_STREAM socket 99 | type and a protocol value of 0 or IPPROTO_TCP. 100 | */ 101 | static struct socket_data const data[] = { 102 | { AF_LOCAL, SOCK_STREAM, 0, false }, 103 | { AF_INET, SOCK_STREAM, IPPROTO_SCTP, false }, 104 | { AF_INET, SOCK_DGRAM, 0, false }, 105 | { AF_INET, SOCK_STREAM, 0, true }, 106 | { AF_INET6, SOCK_STREAM, 0, true }, 107 | { AF_INET, SOCK_STREAM, IPPROTO_TCP, true }, 108 | { AF_INET6, SOCK_STREAM, IPPROTO_TCP, true } 109 | }; 110 | 111 | static size_t const len = sizeof(data) / sizeof(data[0]); 112 | 113 | for (size_t i = 0; i < len; ++i) { 114 | fprintf(stderr, "Test case %zu: ", i); 115 | test_socket_data(&data[i]); 116 | fprintf(stderr, "PASS\n"); 117 | } 118 | 119 | return 0; 120 | } 121 | 122 | 123 | /* 124 | Local Variables: 125 | c-file-style: "linux" 126 | End: 127 | */ 128 | -------------------------------------------------------------------------------- /tests/test-id-manager.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file test-id-manager.c 4 | * 5 | * @brief mptcpd ID manager test. 6 | * 7 | * Copyright (c) 2020-2021, Intel Corporation 8 | */ 9 | 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | 17 | #include "test-plugin.h" // For test sockaddrs 18 | 19 | #undef NDEBUG 20 | #include 21 | 22 | 23 | /// mptcpd ID manager. 24 | static struct mptcpd_idm *_idm; 25 | 26 | /// Obtained MPTCP address IDs 27 | static mptcpd_aid_t _id[4]; 28 | 29 | /// Expected MPTCP address ID after ID update. 30 | static mptcpd_aid_t const _updated_id = 222; 31 | 32 | static void test_create(void const *test_data) 33 | { 34 | (void) test_data; 35 | 36 | _idm = mptcpd_idm_create(); 37 | } 38 | 39 | static void test_map_id(void const *test_data) 40 | { 41 | (void) test_data; 42 | 43 | mptcpd_aid_t const id = 245; 44 | 45 | assert(id != _updated_id); // sanity check 46 | 47 | assert(mptcpd_idm_map_id(_idm, 48 | (struct sockaddr *) &test_laddr_4, 49 | id)); 50 | 51 | // Update previously set ID for the same IP address. 52 | assert(mptcpd_idm_map_id(_idm, 53 | (struct sockaddr *) &test_laddr_4, 54 | _updated_id)); 55 | 56 | // Attempt to map invalid (0) ID. 57 | mptcpd_aid_t const invalid_id = 0; 58 | assert(!mptcpd_idm_map_id(_idm, 59 | (struct sockaddr *) &test_laddr_4, 60 | invalid_id)); 61 | } 62 | 63 | static void test_get_id(void const *test_data) 64 | { 65 | (void) test_data; 66 | 67 | _id[0] = mptcpd_idm_get_id(_idm, 68 | (struct sockaddr *) &test_laddr_1); 69 | assert(_id[0] != 0); 70 | 71 | struct sockaddr_in laddr_1_diff_port = test_laddr_1; 72 | laddr_1_diff_port.sin_port = test_laddr_1.sin_port + 1; 73 | assert(mptcpd_idm_get_id(_idm, 74 | (struct sockaddr *) &laddr_1_diff_port) 75 | == _id[0]); 76 | 77 | _id[1] = mptcpd_idm_get_id(_idm, 78 | (struct sockaddr *) &test_laddr_2); 79 | assert(_id[1] != 0 && _id[1] != _id[0]); 80 | 81 | _id[2] = mptcpd_idm_get_id(_idm, 82 | (struct sockaddr *) &test_laddr_1); 83 | assert(_id[2] != 0 && _id[2] == _id[0]); 84 | 85 | _id[3] = mptcpd_idm_get_id(_idm, 86 | (struct sockaddr *) &test_raddr_1); 87 | assert(_id[3] != 0 && _id[3] != _id[0] && _id[3] != _id[1]); 88 | 89 | // ID that was updated in test_map_id(). 90 | mptcpd_aid_t const id = 91 | mptcpd_idm_get_id(_idm, 92 | (struct sockaddr *) &test_laddr_4); 93 | assert(id == _updated_id); 94 | } 95 | 96 | static void test_remove_id(void const *test_data) 97 | { 98 | (void) test_data; 99 | 100 | mptcpd_aid_t i = 0; 101 | 102 | i = mptcpd_idm_remove_id(_idm, 103 | (struct sockaddr *) &test_laddr_2); 104 | assert(i == _id[1]); 105 | 106 | i = mptcpd_idm_remove_id(_idm, 107 | (struct sockaddr *) &test_laddr_2); 108 | assert(i == 0); 109 | } 110 | 111 | 112 | static void test_destroy(void const *test_data) 113 | { 114 | (void) test_data; 115 | 116 | mptcpd_idm_destroy(_idm); 117 | } 118 | 119 | int main(int argc, char *argv[]) 120 | { 121 | l_log_set_stderr(); 122 | 123 | l_test_init(&argc, &argv); 124 | 125 | l_test_add("create ID manager", test_create, NULL); 126 | l_test_add("map ID", test_map_id, NULL); 127 | l_test_add("get ID", test_get_id, NULL); 128 | l_test_add("remove ID", test_remove_id, NULL); 129 | l_test_add("destroy ID manager", test_destroy, NULL); 130 | 131 | return l_test_run(); 132 | } 133 | 134 | 135 | /* 136 | Local Variables: 137 | c-file-style: "linux" 138 | End: 139 | */ 140 | -------------------------------------------------------------------------------- /lib/murmur_hash.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Intel Corporation 2 | // SPDX-License-Identifier: BSD-3-Clause 3 | /** 4 | * @file murmur_hash.c 5 | * 6 | * This file incorporates work covered by the following notice: 7 | * MurmurHash3 was written by Austin Appleby, and is placed in the 8 | * public domain. The author hereby disclaims copyright to this 9 | * source code. 10 | * 11 | * Changes relative to the original: 12 | * 13 | * @li 128 bit hash functions were removed. They are not needed by 14 | * mptcpd since the ELL l_hashmap expects hash values of type 15 | * @c unsigned @c int. 16 | * @li The @c MurmurHash3_x86_32() function was renamed to 17 | * @c mptcpd_murmur_hash3(). 18 | * @li The hash value is returned as an @c unsigned @c int return 19 | * value instead of a function "out" parameter of type @c void*. 20 | * @li The only compiler-specific support left in place is for gcc and 21 | * clang. 22 | * @li Declare @c inline functions as @c static @c inline. 23 | * @li The coding style was modified to conform to the mptcpd style. 24 | * @li gcc "implicit fallthrough" warnings for switch statement were 25 | * silenced. 26 | * 27 | * @see https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp 28 | */ 29 | 30 | #include 31 | 32 | #ifdef __GNUC__ 33 | # define FORCE_INLINE inline __attribute__((always_inline)) 34 | 35 | /* 36 | Silence gcc "implicit fallthrough" warnings for switch statement 37 | cases below. 38 | */ 39 | # define FALLTHROUGH __attribute__((fallthrough)) 40 | #else 41 | # define FORCE_INLINE inline 42 | # define FALLTHROUGH 43 | #endif // __GNUC__ 44 | 45 | 46 | //------------------------------------------------------------------------ 47 | 48 | static inline uint32_t rotl32(uint32_t x, int8_t r) 49 | { 50 | return (x << r) | (x >> (32 - r)); 51 | } 52 | 53 | //------------------------------------------------------------------------ 54 | 55 | /** 56 | * @brief Block read. 57 | * 58 | * If your platform needs to do endian-swapping or can only handle 59 | * aligned reads, do the conversion here. 60 | */ 61 | static FORCE_INLINE uint32_t getblock32 (uint32_t const *p, int i) 62 | { 63 | return p[i]; 64 | } 65 | 66 | //------------------------------------------------------------------------ 67 | 68 | /** 69 | * @brief Finalization mix. 70 | * 71 | * Force all bits of a hash block to avalanche. 72 | */ 73 | static FORCE_INLINE uint32_t fmix32(uint32_t h) 74 | { 75 | h ^= h >> 16; 76 | h *= 0x85ebca6b; 77 | h ^= h >> 13; 78 | h *= 0xc2b2ae35; 79 | h ^= h >> 16; 80 | 81 | return h; 82 | } 83 | 84 | //------------------------------------------------------------------------ 85 | 86 | unsigned int mptcpd_murmur_hash3(void const *key, 87 | int len, 88 | uint32_t seed) 89 | { 90 | uint8_t const *const data = (uint8_t const *) key; 91 | int const nblocks = len / 4; 92 | 93 | uint32_t h1 = seed; 94 | 95 | uint32_t const c1 = 0xcc9e2d51; 96 | uint32_t const c2 = 0x1b873593; 97 | 98 | //---------- 99 | // body 100 | 101 | uint32_t const *const blocks = 102 | (uint32_t const *)(data + nblocks * 4); 103 | 104 | for (int i = -nblocks; i; i++) { 105 | uint32_t k1 = getblock32(blocks, i); 106 | 107 | k1 *= c1; 108 | k1 = rotl32(k1, 15); 109 | k1 *= c2; 110 | 111 | h1 ^= k1; 112 | h1 = rotl32(h1, 13); 113 | h1 = h1 * 5 + 0xe6546b64; 114 | } 115 | 116 | //---------- 117 | // tail 118 | 119 | uint8_t const *const tail = (uint8_t const *)(data + nblocks * 4); 120 | 121 | uint32_t k1 = 0; 122 | 123 | switch (len & 3) { 124 | case 3: k1 ^= tail[2] << 16; FALLTHROUGH; 125 | case 2: k1 ^= tail[1] << 8; FALLTHROUGH; 126 | case 1: k1 ^= tail[0]; 127 | k1 *= c1; k1 = rotl32(k1,15); k1 *= c2; h1 ^= k1; 128 | }; 129 | 130 | //---------- 131 | // finalization 132 | 133 | h1 ^= len; 134 | 135 | h1 = fmix32(h1); 136 | 137 | return h1; 138 | } 139 | 140 | 141 | /* 142 | Local Variables: 143 | c-file-style: "linux" 144 | End: 145 | */ 146 | -------------------------------------------------------------------------------- /plugins/path_managers/addr_adv.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file addr_adv.c 4 | * 5 | * @brief MPTCP address advertiser path manager plugin. 6 | * 7 | * Copyright (c) 2020-2021, Intel Corporation 8 | */ 9 | 10 | #ifdef HAVE_CONFIG_H 11 | # include 12 | #endif 13 | 14 | #include 15 | 16 | #include 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | 26 | // Allow at least this number of additional subflows for each connection 27 | #define MPTCP_MIN_SUBFLOWS 2 28 | 29 | // Maximum number of subflows allowed by the kernel 30 | #define MPTCP_MAX_SUBFLOWS 8 31 | 32 | static struct mptcpd_limit _limits[] = { 33 | { 34 | .type = MPTCPD_LIMIT_SUBFLOWS, 35 | .limit = 0, 36 | }, 37 | { 38 | .type = MPTCPD_LIMIT_RCV_ADD_ADDRS, 39 | .limit = 0, 40 | } 41 | }; 42 | 43 | static void update_limits(struct mptcpd_pm *pm, int delta) 44 | { 45 | int subflows; 46 | 47 | _limits[0].limit += delta; 48 | subflows = _limits[0].limit; 49 | if (subflows < MPTCP_MIN_SUBFLOWS 50 | || subflows > MPTCP_MAX_SUBFLOWS) 51 | return; 52 | 53 | /* 54 | If the pm creates outgoing subflows, we assume this is 55 | the client side, and accepts add_addrs from the server. 56 | */ 57 | if (pm->config->addr_flags & 58 | (MPTCPD_ADDR_FLAG_SUBFLOW | MPTCPD_ADDR_FLAG_LAMINAR)) 59 | _limits[1].limit = _limits[0].limit; 60 | 61 | int const result = mptcpd_kpm_set_limits(pm, 62 | _limits, 63 | L_ARRAY_SIZE(_limits)); 64 | 65 | if (result != 0 && result != ENOTSUP) 66 | l_warn("can't update limit to %d: %d", subflows, result); 67 | } 68 | 69 | static void addr_adv_new_local_address(struct mptcpd_interface const *i, 70 | struct sockaddr const *sa, 71 | struct mptcpd_pm *pm) 72 | { 73 | struct mptcpd_idm *const idm = mptcpd_pm_get_idm(pm); 74 | mptcpd_aid_t const id = mptcpd_idm_get_id(idm, sa); 75 | 76 | if (id == 0) { 77 | l_error("Unable to map addr to ID."); 78 | return; 79 | } 80 | 81 | uint32_t const flags = pm->config->addr_flags; 82 | 83 | update_limits(pm, 1); 84 | 85 | if (mptcpd_kpm_add_addr(pm, sa, id, flags, i->index) != 0) 86 | l_error("Unable to advertise IP address."); 87 | } 88 | 89 | static void addr_adv_delete_local_address( 90 | struct mptcpd_interface const *i, 91 | struct sockaddr const *sa, 92 | struct mptcpd_pm *pm) 93 | { 94 | (void) i; 95 | 96 | struct mptcpd_idm *const idm = mptcpd_pm_get_idm(pm); 97 | mptcpd_aid_t const id = mptcpd_idm_remove_id(idm, sa); 98 | 99 | if (id == 0) { 100 | // Not necessarily an error. 101 | l_info("No address ID associated with addr."); 102 | return; 103 | } 104 | 105 | update_limits(pm, -1); 106 | 107 | if (mptcpd_kpm_remove_addr(pm, id) != 0) 108 | l_error("Unable to stop advertising IP address."); 109 | } 110 | 111 | static struct mptcpd_plugin_ops const pm_ops = { 112 | .new_local_address = addr_adv_new_local_address, 113 | .delete_local_address = addr_adv_delete_local_address 114 | }; 115 | 116 | static int addr_adv_init(struct mptcpd_pm *pm) 117 | { 118 | static char const name[] = "addr_adv"; 119 | 120 | update_limits(pm, MPTCP_MIN_SUBFLOWS); 121 | 122 | if (!mptcpd_plugin_register_ops(name, &pm_ops)) { 123 | l_error("Failed to initialize address advertiser " 124 | "path manager plugin."); 125 | 126 | return -1; 127 | } 128 | 129 | l_info("MPTCP address advertiser path manager initialized."); 130 | 131 | return 0; 132 | } 133 | 134 | static void addr_adv_exit(struct mptcpd_pm *pm) 135 | { 136 | (void) pm; 137 | 138 | l_info("MPTCP address advertiser path manager exited."); 139 | } 140 | 141 | MPTCPD_PLUGIN_DEFINE(addr_adv, 142 | "Address advertiser path manager", 143 | MPTCPD_PLUGIN_PRIORITY_DEFAULT, 144 | addr_adv_init, 145 | addr_adv_exit) 146 | 147 | 148 | /* 149 | Local Variables: 150 | c-file-style: "linux" 151 | End: 152 | */ 153 | -------------------------------------------------------------------------------- /include/linux/mptcp_upstream.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ 2 | #ifndef _UAPI_MPTCP_H 3 | #define _UAPI_MPTCP_H 4 | 5 | #ifndef __KERNEL__ 6 | #include /* for sockaddr_in and sockaddr_in6 */ 7 | #include /* for struct sockaddr */ 8 | #endif 9 | 10 | #include 11 | #include 12 | #include /* for sockaddr_in */ 13 | #include /* for sockaddr_in6 */ 14 | #include /* for sockaddr_storage and sa_family */ 15 | 16 | #define MPTCP_SUBFLOW_FLAG_MCAP_REM _BITUL(0) 17 | #define MPTCP_SUBFLOW_FLAG_MCAP_LOC _BITUL(1) 18 | #define MPTCP_SUBFLOW_FLAG_JOIN_REM _BITUL(2) 19 | #define MPTCP_SUBFLOW_FLAG_JOIN_LOC _BITUL(3) 20 | #define MPTCP_SUBFLOW_FLAG_BKUP_REM _BITUL(4) 21 | #define MPTCP_SUBFLOW_FLAG_BKUP_LOC _BITUL(5) 22 | #define MPTCP_SUBFLOW_FLAG_FULLY_ESTABLISHED _BITUL(6) 23 | #define MPTCP_SUBFLOW_FLAG_CONNECTED _BITUL(7) 24 | #define MPTCP_SUBFLOW_FLAG_MAPVALID _BITUL(8) 25 | 26 | #define MPTCP_PM_CMD_GRP_NAME "mptcp_pm_cmds" 27 | #define MPTCP_PM_EV_GRP_NAME "mptcp_pm_events" 28 | 29 | #include 30 | 31 | #define MPTCP_INFO_FLAG_FALLBACK _BITUL(0) 32 | #define MPTCP_INFO_FLAG_REMOTE_KEY_RECEIVED _BITUL(1) 33 | 34 | #define MPTCP_PM_EV_FLAG_DENY_JOIN_ID0 _BITUL(0) 35 | #define MPTCP_PM_EV_FLAG_SERVER_SIDE _BITUL(1) 36 | 37 | #define MPTCP_PM_ADDR_FLAG_SIGNAL _BITUL(0) 38 | #define MPTCP_PM_ADDR_FLAG_SUBFLOW _BITUL(1) 39 | #define MPTCP_PM_ADDR_FLAG_BACKUP _BITUL(2) 40 | #define MPTCP_PM_ADDR_FLAG_FULLMESH _BITUL(3) 41 | #define MPTCP_PM_ADDR_FLAG_IMPLICIT _BITUL(4) 42 | #define MPTCP_PM_ADDR_FLAG_LAMINAR _BITUL(5) 43 | 44 | struct mptcp_info { 45 | __u8 mptcpi_subflows; 46 | #define mptcpi_extra_subflows mptcpi_subflows 47 | __u8 mptcpi_add_addr_signal; 48 | __u8 mptcpi_add_addr_accepted; 49 | __u8 mptcpi_subflows_max; 50 | #define mptcpi_limit_extra_subflows mptcpi_subflows_max 51 | __u8 mptcpi_add_addr_signal_max; 52 | #define mptcpi_endp_signal_max mptcpi_add_addr_signal_max 53 | __u8 mptcpi_add_addr_accepted_max; 54 | #define mptcpi_limit_add_addr_accepted mptcpi_add_addr_accepted_max 55 | /* 16-bit hole that can no longer be filled */ 56 | __u32 mptcpi_flags; 57 | __u32 mptcpi_token; 58 | __u64 mptcpi_write_seq; 59 | __u64 mptcpi_snd_una; 60 | __u64 mptcpi_rcv_nxt; 61 | __u8 mptcpi_local_addr_used; 62 | __u8 mptcpi_local_addr_max; 63 | #define mptcpi_endp_subflow_max mptcpi_local_addr_max 64 | __u8 mptcpi_csum_enabled; 65 | /* 8-bit hole that can no longer be filled */ 66 | __u32 mptcpi_retransmits; 67 | __u64 mptcpi_bytes_retrans; 68 | __u64 mptcpi_bytes_sent; 69 | __u64 mptcpi_bytes_received; 70 | __u64 mptcpi_bytes_acked; 71 | __u8 mptcpi_subflows_total; 72 | __u8 mptcpi_endp_laminar_max; 73 | __u8 reserved[2]; 74 | __u32 mptcpi_last_data_sent; 75 | __u32 mptcpi_last_data_recv; 76 | __u32 mptcpi_last_ack_recv; 77 | }; 78 | 79 | /* MPTCP Reset reason codes, rfc8684 */ 80 | #define MPTCP_RST_EUNSPEC 0 81 | #define MPTCP_RST_EMPTCP 1 82 | #define MPTCP_RST_ERESOURCE 2 83 | #define MPTCP_RST_EPROHIBIT 3 84 | #define MPTCP_RST_EWQ2BIG 4 85 | #define MPTCP_RST_EBADPERF 5 86 | #define MPTCP_RST_EMIDDLEBOX 6 87 | 88 | struct mptcp_subflow_data { 89 | __u32 size_subflow_data; /* size of this structure in userspace */ 90 | __u32 num_subflows; /* must be 0, set by kernel */ 91 | __u32 size_kernel; /* must be 0, set by kernel */ 92 | __u32 size_user; /* size of one element in data[] */ 93 | } __attribute__((aligned(8))); 94 | 95 | struct mptcp_subflow_addrs { 96 | union { 97 | __kernel_sa_family_t sa_family; 98 | struct sockaddr sa_local; 99 | struct sockaddr_in sin_local; 100 | struct sockaddr_in6 sin6_local; 101 | struct __kernel_sockaddr_storage ss_local; 102 | }; 103 | union { 104 | struct sockaddr sa_remote; 105 | struct sockaddr_in sin_remote; 106 | struct sockaddr_in6 sin6_remote; 107 | struct __kernel_sockaddr_storage ss_remote; 108 | }; 109 | }; 110 | 111 | struct mptcp_subflow_info { 112 | __u32 id; 113 | struct mptcp_subflow_addrs addrs; 114 | }; 115 | 116 | struct mptcp_full_info { 117 | __u32 size_tcpinfo_kernel; /* must be 0, set by kernel */ 118 | __u32 size_tcpinfo_user; 119 | __u32 size_sfinfo_kernel; /* must be 0, set by kernel */ 120 | __u32 size_sfinfo_user; 121 | __u32 num_subflows; /* must be 0, set by kernel (real subflow count) */ 122 | __u32 size_arrays_user; /* max subflows that userspace is interested in; 123 | * the buffers at subflow_info/tcp_info 124 | * are respectively at least: 125 | * size_arrays * size_sfinfo_user 126 | * size_arrays * size_tcpinfo_user 127 | * bytes wide 128 | */ 129 | __aligned_u64 subflow_info; 130 | __aligned_u64 tcp_info; 131 | struct mptcp_info mptcp_info; 132 | }; 133 | 134 | /* MPTCP socket options */ 135 | #define MPTCP_INFO 1 136 | #define MPTCP_TCPINFO 2 137 | #define MPTCP_SUBFLOW_ADDRS 3 138 | #define MPTCP_FULL_INFO 4 139 | 140 | #endif /* _UAPI_MPTCP_H */ 141 | -------------------------------------------------------------------------------- /tests/lib/call_plugin.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file call_plugin.c 4 | * 5 | * @brief mptcpd test plugin call functions. 6 | * 7 | * Copyright (c) 2019-2022, Intel Corporation 8 | */ 9 | 10 | #include 11 | 12 | #include 13 | 14 | #include "test-plugin.h" 15 | 16 | #undef NDEBUG 17 | #include 18 | 19 | 20 | void call_plugin_ops(struct plugin_call_count const *count, 21 | struct plugin_call_args const *args) 22 | { 23 | assert(count != NULL); 24 | assert(args != NULL); 25 | 26 | for (int i = 0; i < count->new_connection; ++i) 27 | mptcpd_plugin_new_connection(args->name, 28 | args->token, 29 | args->laddr, 30 | args->raddr, 31 | args->server_side, 32 | args->deny_join_id0, 33 | args->pm); 34 | 35 | for (int i = 0; i < count->connection_established; ++i) 36 | mptcpd_plugin_connection_established(args->token, 37 | args->laddr, 38 | args->raddr, 39 | args->server_side, 40 | args->deny_join_id0, 41 | args->pm); 42 | 43 | for (int i = 0; i < count->new_address; ++i) 44 | mptcpd_plugin_new_address(args->token, 45 | args->raddr_id, 46 | args->raddr, 47 | args->pm); 48 | 49 | for (int i = 0; i < count->address_removed; ++i) 50 | mptcpd_plugin_address_removed(args->token, 51 | args->raddr_id, 52 | args->pm); 53 | 54 | for (int i = 0; i < count->new_subflow; ++i) 55 | mptcpd_plugin_new_subflow(args->token, 56 | args->laddr, 57 | args->raddr, 58 | args->backup, 59 | args->pm); 60 | 61 | for (int i = 0; i < count->subflow_closed; ++i) 62 | mptcpd_plugin_subflow_closed(args->token, 63 | args->laddr, 64 | args->raddr, 65 | args->backup, 66 | args->error, 67 | args->pm); 68 | 69 | for (int i = 0; i < count->subflow_priority; ++i) 70 | mptcpd_plugin_subflow_priority(args->token, 71 | args->laddr, 72 | args->raddr, 73 | args->backup, 74 | args->pm); 75 | 76 | for (int i = 0; i < count->listener_created; ++i) 77 | mptcpd_plugin_listener_created(args->name, 78 | args->laddr, 79 | args->pm); 80 | 81 | for (int i = 0; i < count->listener_closed; ++i) 82 | mptcpd_plugin_listener_closed(args->name, 83 | args->laddr, 84 | args->pm); 85 | 86 | for (int i = 0; i < count->connection_closed; ++i) 87 | mptcpd_plugin_connection_closed(args->token, args->pm); 88 | 89 | for (int i = 0; i < count->new_interface; ++i) 90 | mptcpd_plugin_new_interface(args->interface, args->pm); 91 | 92 | for (int i = 0; i < count->update_interface; ++i) 93 | mptcpd_plugin_update_interface(args->interface, args->pm); 94 | 95 | for (int i = 0; i < count->delete_interface; ++i) 96 | mptcpd_plugin_delete_interface(args->interface, args->pm); 97 | 98 | for (int i = 0; i < count->new_local_address; ++i) 99 | mptcpd_plugin_new_local_address(args->interface, 100 | args->laddr, 101 | args->pm); 102 | 103 | for (int i = 0; i < count->delete_local_address; ++i) 104 | mptcpd_plugin_delete_local_address(args->interface, 105 | args->laddr, 106 | args->pm); 107 | } 108 | 109 | 110 | /* 111 | Local Variables: 112 | c-file-style: "linux" 113 | End: 114 | */ 115 | -------------------------------------------------------------------------------- /src/commands.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file commands.h 4 | * 5 | * @brief mptcpd generic netlink command utilities. 6 | * 7 | * Copyright (c) 2017-2022, Intel Corporation 8 | */ 9 | 10 | #ifndef MPTCPD_COMMANDS_H 11 | #define MPTCPD_COMMANDS_H 12 | 13 | #ifdef HAVE_CONFIG_H 14 | # include 15 | #endif 16 | 17 | #include 18 | #include // For NULL. 19 | #include 20 | #include 21 | #include 22 | #include // For NLA_* macros. 23 | 24 | /** 25 | * @brief Return netlink aligned size of a variable or type. 26 | * 27 | * @param[in] v Variable or type to be aligned. 28 | */ 29 | #define MPTCPD_NLA_ALIGN(v) (NLA_HDRLEN + NLA_ALIGN(sizeof(v))) 30 | 31 | /** 32 | * @brief Return netlink aligned size of an optional variable. 33 | * 34 | * @param[in] v Variable to be aligned. 35 | * 36 | * @return The netlink aligned size of the variable @a v or @c 0 if 37 | * @a v is zero or implicitly convertible to zero (e.g. 38 | * @c NULL). 39 | */ 40 | #define MPTCPD_NLA_ALIGN_OPT(v) ((v) == 0 ? 0 : (MPTCPD_NLA_ALIGN(v))) 41 | 42 | /** 43 | * @brief Return netlink aligned size of an IP address. 44 | * 45 | * @param[in] v Pointer to @c struct @c sockaddr containing an IP address 46 | * (i.e., @c struct @c in_addr or @c struct @c in6_addr ) 47 | * to be aligned. 48 | * 49 | * @return The netlink aligned size of the IP address contained in the 50 | * @c sockaddr pointed to by @a v. 51 | */ 52 | #define MPTCPD_NLA_ALIGN_ADDR(v) \ 53 | (NLA_HDRLEN + NLA_ALIGN(mptcpd_get_addr_size(v))) 54 | 55 | 56 | #ifdef __cplusplus 57 | extern "C" { 58 | #endif 59 | 60 | struct l_genl_msg; 61 | 62 | /** 63 | * @brief Check for internet address family. 64 | * 65 | * @param[in] addr Network address information. 66 | * 67 | * @return @c true if the @a addr is an internet address, and @c false 68 | * otherwise. 69 | */ 70 | static inline bool mptcpd_is_inet_family(struct sockaddr const *addr) 71 | { 72 | return addr->sa_family == AF_INET || addr->sa_family == AF_INET6; 73 | } 74 | 75 | /** 76 | * @brief Get the underlying internet address size. 77 | * 78 | * @param[in] addr Network address information. 79 | * 80 | * @return Size of the underlying internet address (e.g., @c struct 81 | * @c in_addr6). 82 | */ 83 | static inline size_t mptcpd_get_addr_size(struct sockaddr const *addr) 84 | { 85 | assert(mptcpd_is_inet_family(addr)); 86 | 87 | return addr->sa_family == AF_INET 88 | ? sizeof(struct in_addr) 89 | : sizeof(struct in6_addr); 90 | } 91 | 92 | /** 93 | * @brief Get network address family. 94 | * 95 | * @param[in] addr Network address information. 96 | * 97 | * Get network address family suitably typed for use in MPTCP generic 98 | * netlink API calls, or zero if no address was provided. 99 | * 100 | * @return Network address family, or zero if no address family was 101 | * provided. 102 | */ 103 | static inline uint16_t mptcpd_get_addr_family(struct sockaddr const *addr) 104 | { 105 | sa_family_t const family = (addr == NULL ? 0 : addr->sa_family); 106 | 107 | return family; 108 | } 109 | 110 | /** 111 | * @brief Get TCP port number (host byte order). 112 | * 113 | * @param[in] addr Network address information. 114 | * 115 | * Get TCP port suitably typed for use in MPTCP generic netlink API 116 | * calls, or zero if no address was provided. 117 | * 118 | * @return TCP port number in host byte order, or zero if no IP 119 | * address was provided. 120 | */ 121 | uint16_t mptcpd_get_port_number(struct sockaddr const *addr); 122 | 123 | /** 124 | * @brief Get upstream kernel MPTCP generic netlink command 125 | * operations. 126 | */ 127 | struct mptcpd_pm_cmd_ops const *mptcpd_get_upstream_cmd_ops(void); 128 | 129 | /** 130 | * @brief Get multipath-tcp.org kernel MPTCP generic netlink command 131 | * operations. 132 | */ 133 | struct mptcpd_pm_cmd_ops const *mptcpd_get_mptcp_org_cmd_ops(void); 134 | 135 | /** 136 | * @brief Check for genl operation failure. 137 | * 138 | * Check for generic netlink operation failure, and log associated 139 | * error message. 140 | * 141 | * @param[in] msg Generic netlink message information. 142 | * @param[in] fname Name function from which the error check was 143 | * initiated. 144 | * 145 | * @return @c true if no error was found, and @c false otherwise. 146 | */ 147 | bool mptcpd_check_genl_error(struct l_genl_msg *msg, char const *fname); 148 | 149 | /** 150 | * @brief Generic error reporting callback. 151 | * 152 | * @param[in] msg Generic netlink message information. 153 | * @param[in] user_data Function name. 154 | */ 155 | void mptcpd_family_send_callback(struct l_genl_msg *msg, void *user_data); 156 | 157 | #ifdef __cplusplus 158 | } 159 | #endif 160 | 161 | 162 | #endif /* MPTCPD_COMMANDS_H */ 163 | 164 | 165 | /* 166 | Local Variables: 167 | c-file-style: "linux" 168 | End: 169 | */ 170 | -------------------------------------------------------------------------------- /tests/Makefile.am: -------------------------------------------------------------------------------- 1 | ## SPDX-License-Identifier: BSD-3-Clause 2 | ## 3 | ## Copyright (c) 2017-2021, Intel Corporation 4 | 5 | include $(top_srcdir)/aminclude_static.am 6 | 7 | SUBDIRS = lib plugins 8 | 9 | ## @todo Do not add the EXECUTABLE_* flags to test libraries (if any). 10 | AM_CPPFLAGS = \ 11 | -I$(top_srcdir)/include \ 12 | -I$(top_builddir)/include \ 13 | -I$(srcdir)/lib \ 14 | $(CODE_COVERAGE_CPPFLAGS) 15 | AM_CFLAGS = $(ELL_CFLAGS) $(EXECUTABLE_CFLAGS) $(CODE_COVERAGE_CFLAGS) 16 | AM_CXXFLAGS = $(ELL_CFLAGS) $(EXECUTABLE_CFLAGS) $(CODE_COVERAGE_CXXFLAGS) 17 | AM_LDFLAGS = $(EXECUTABLE_LDFLAGS) 18 | 19 | TEST_PLUGIN_DIR_SECURITY = $(abs_builddir)/plugins/security/.libs 20 | TEST_PLUGIN_DIR_PRIORITY = $(abs_builddir)/plugins/priority/.libs 21 | TEST_PLUGIN_DIR_NOOP = $(abs_builddir)/plugins/noop/.libs 22 | TEST_PLUGIN_DIR_BAD = $(abs_builddir)/plugins/bad/.libs 23 | 24 | check_PROGRAMS = \ 25 | test-plugin \ 26 | test-network-monitor \ 27 | test-path-manager \ 28 | test-commands \ 29 | test-configuration \ 30 | test-id-manager \ 31 | test-listener-manager \ 32 | test-sockaddr \ 33 | test-addr-info \ 34 | test-murmur-hash 35 | 36 | noinst_PROGRAMS = mptcpwrap-tester 37 | 38 | dist_check_SCRIPTS = \ 39 | test-bad-log-empty \ 40 | test-bad-log-long \ 41 | test-bad-log-short \ 42 | test-bad-option \ 43 | test-bad-path-manager \ 44 | test-bad-plugin-dir \ 45 | test-start-stop \ 46 | test-mptcpwrap 47 | 48 | test_plugin_SOURCES = test-plugin.c 49 | test_plugin_CPPFLAGS = \ 50 | $(AM_CPPFLAGS) \ 51 | -D_POSIX_C_SOURCE=200809L \ 52 | -DTEST_PLUGIN_DIR_SECURITY=\"$(TEST_PLUGIN_DIR_SECURITY)\" \ 53 | -DTEST_PLUGIN_DIR_PRIORITY=\"$(TEST_PLUGIN_DIR_PRIORITY)\" \ 54 | -DTEST_PLUGIN_DIR_NOOP=\"$(TEST_PLUGIN_DIR_NOOP)\" \ 55 | -DTEST_PLUGIN_DIR_BAD=\"$(TEST_PLUGIN_DIR_BAD)\" \ 56 | -DTEST_PLUGIN_ONE=\"@TEST_PLUGIN_ONE@\" \ 57 | -DTEST_PLUGIN_TWO=\"@TEST_PLUGIN_TWO@\" \ 58 | -DTEST_PLUGIN_FOUR=\"@TEST_PLUGIN_FOUR@\" 59 | test_plugin_LDADD = \ 60 | $(top_builddir)/lib/libmptcpd.la \ 61 | $(builddir)/lib/libmptcpd_test.la \ 62 | $(ELL_LIBS) \ 63 | $(CODE_COVERAGE_LIBS) 64 | 65 | test_network_monitor_SOURCES = test-network-monitor.c 66 | test_network_monitor_LDADD = \ 67 | $(top_builddir)/lib/libmptcpd.la \ 68 | $(ELL_LIBS) \ 69 | $(CODE_COVERAGE_LIBS) 70 | 71 | test_path_manager_SOURCES = test-path-manager.c 72 | test_path_manager_CPPFLAGS = \ 73 | $(AM_CPPFLAGS) \ 74 | -DTEST_PLUGIN_DIR=\"$(TEST_PLUGIN_DIR_NOOP)\" 75 | test_path_manager_LDADD = \ 76 | $(top_builddir)/src/libpath_manager.la \ 77 | $(top_builddir)/lib/libmptcpd.la \ 78 | $(builddir)/lib/libmptcpd_test.la \ 79 | $(ELL_LIBS) \ 80 | $(CODE_COVERAGE_LIBS) 81 | 82 | test_commands_SOURCES = test-commands.c 83 | test_commands_CPPFLAGS = \ 84 | $(AM_CPPFLAGS) \ 85 | -DTEST_PLUGIN_DIR=\"$(TEST_PLUGIN_DIR_NOOP)\" 86 | test_commands_LDADD = \ 87 | $(top_builddir)/src/libpath_manager.la \ 88 | $(top_builddir)/lib/libmptcpd.la \ 89 | $(builddir)/lib/libmptcpd_test.la \ 90 | $(ELL_LIBS) \ 91 | $(CODE_COVERAGE_LIBS) 92 | 93 | test_configuration_SOURCES = test-configuration.c 94 | test_configuration_LDADD = \ 95 | $(top_builddir)/src/libpath_manager.la \ 96 | $(top_builddir)/lib/libmptcpd.la \ 97 | $(ELL_LIBS) \ 98 | $(CODE_COVERAGE_LIBS) 99 | 100 | test_id_manager_SOURCES = test-id-manager.c 101 | test_id_manager_LDADD = \ 102 | $(top_builddir)/lib/libmptcpd.la \ 103 | $(ELL_LIBS) \ 104 | $(CODE_COVERAGE_LIBS) 105 | 106 | test_listener_manager_SOURCES = test-listener-manager.c 107 | test_listener_manager_LDADD = \ 108 | $(top_builddir)/lib/libmptcpd.la \ 109 | $(builddir)/lib/libmptcpd_test.la \ 110 | $(ELL_LIBS) \ 111 | $(CODE_COVERAGE_LIBS) 112 | 113 | test_sockaddr_SOURCES = test-sockaddr.c 114 | test_sockaddr_LDADD = \ 115 | $(top_builddir)/lib/libmptcpd.la \ 116 | $(builddir)/lib/libmptcpd_test.la \ 117 | $(ELL_LIBS) \ 118 | $(CODE_COVERAGE_LIBS) 119 | 120 | test_addr_info_SOURCES = test-addr-info.c 121 | test_addr_info_LDADD = \ 122 | $(top_builddir)/lib/libmptcpd.la \ 123 | $(ELL_LIBS) \ 124 | $(CODE_COVERAGE_LIBS) 125 | 126 | test_murmur_hash_SOURCES = test-murmur-hash.c 127 | test_murmur_hash_LDADD = \ 128 | $(top_builddir)/lib/libmptcpd.la \ 129 | $(ELL_LIBS) \ 130 | $(CODE_COVERAGE_LIBS) 131 | 132 | mptcpwrap_tester_SOURCES = mptcpwrap-tester.c 133 | mptcpwrap_tester_LDADD = $(CODE_COVERAGE_LIBS) 134 | 135 | if HAVE_CXX 136 | check_PROGRAMS += test-cxx-build 137 | test_cxx_build_SOURCES = test-cxx-build.cpp 138 | test_cxx_build_CPPFLAGS = \ 139 | $(AM_CPPFLAGS) \ 140 | -DTEST_PLUGIN_DIR=\"$(TEST_PLUGIN_DIR_SECURITY)\" \ 141 | -DTEST_PLUGIN_FOUR=\"@TEST_PLUGIN_FOUR@\" 142 | test_cxx_build_LDADD = \ 143 | $(top_builddir)/lib/libmptcpd.la \ 144 | $(builddir)/lib/libmptcpd_test.la \ 145 | $(ELL_LIBS) \ 146 | $(CODE_COVERAGE_LIBS) 147 | endif 148 | 149 | AM_TESTS_ENVIRONMENT = TEST_PLUGIN_DIR=$(TEST_PLUGIN_DIR_NOOP) 150 | TESTS = $(check_PROGRAMS) $(dist_check_SCRIPTS) 151 | 152 | # Clean up code coverage related generated files. 153 | clean-local: code-coverage-clean 154 | -------------------------------------------------------------------------------- /include/linux/mptcp_upstream_pm.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ 2 | /* Do not edit directly, auto-generated from: */ 3 | /* Documentation/netlink/specs/mptcp_pm.yaml */ 4 | /* YNL-GEN uapi header */ 5 | 6 | #ifndef _UAPI_LINUX_MPTCP_PM_H 7 | #define _UAPI_LINUX_MPTCP_PM_H 8 | 9 | #define MPTCP_PM_NAME "mptcp_pm" 10 | #define MPTCP_PM_VER 1 11 | 12 | /** 13 | * enum mptcp_event_type 14 | * @MPTCP_EVENT_UNSPEC: unused event 15 | * @MPTCP_EVENT_CREATED: A new MPTCP connection has been created. It is the 16 | * good time to allocate memory and send ADD_ADDR if needed. Depending on the 17 | * traffic-patterns it can take a long time until the MPTCP_EVENT_ESTABLISHED 18 | * is sent. Attributes: token, family, saddr4 | saddr6, daddr4 | daddr6, 19 | * sport, dport, [server-side], [flags]. 20 | * @MPTCP_EVENT_ESTABLISHED: A MPTCP connection is established (can start new 21 | * subflows). Attributes: token, family, saddr4 | saddr6, daddr4 | daddr6, 22 | * sport, dport, [server-side], [flags]. 23 | * @MPTCP_EVENT_CLOSED: A MPTCP connection has stopped. Attribute: token. 24 | * @MPTCP_EVENT_ANNOUNCED: A new address has been announced by the peer. 25 | * Attributes: token, rem_id, family, daddr4 | daddr6 [, dport]. 26 | * @MPTCP_EVENT_REMOVED: An address has been lost by the peer. Attributes: 27 | * token, rem_id. 28 | * @MPTCP_EVENT_SUB_ESTABLISHED: A new subflow has been established. 'error' 29 | * should not be set. Attributes: token, family, loc_id, rem_id, saddr4 | 30 | * saddr6, daddr4 | daddr6, sport, dport, backup, if-idx [, error]. 31 | * @MPTCP_EVENT_SUB_CLOSED: A subflow has been closed. An error (copy of 32 | * sk_err) could be set if an error has been detected for this subflow. 33 | * Attributes: token, family, loc_id, rem_id, saddr4 | saddr6, daddr4 | 34 | * daddr6, sport, dport, backup, if-idx [, error]. 35 | * @MPTCP_EVENT_SUB_PRIORITY: The priority of a subflow has changed. 'error' 36 | * should not be set. Attributes: token, family, loc_id, rem_id, saddr4 | 37 | * saddr6, daddr4 | daddr6, sport, dport, backup, if-idx [, error]. 38 | * @MPTCP_EVENT_LISTENER_CREATED: A new PM listener is created. Attributes: 39 | * family, sport, saddr4 | saddr6. 40 | * @MPTCP_EVENT_LISTENER_CLOSED: A PM listener is closed. Attributes: family, 41 | * sport, saddr4 | saddr6. 42 | */ 43 | enum mptcp_event_type { 44 | MPTCP_EVENT_UNSPEC, 45 | MPTCP_EVENT_CREATED, 46 | MPTCP_EVENT_ESTABLISHED, 47 | MPTCP_EVENT_CLOSED, 48 | MPTCP_EVENT_ANNOUNCED = 6, 49 | MPTCP_EVENT_REMOVED, 50 | MPTCP_EVENT_SUB_ESTABLISHED = 10, 51 | MPTCP_EVENT_SUB_CLOSED, 52 | MPTCP_EVENT_SUB_PRIORITY = 13, 53 | MPTCP_EVENT_LISTENER_CREATED = 15, 54 | MPTCP_EVENT_LISTENER_CLOSED, 55 | }; 56 | 57 | enum { 58 | MPTCP_PM_ADDR_ATTR_UNSPEC, 59 | MPTCP_PM_ADDR_ATTR_FAMILY, 60 | MPTCP_PM_ADDR_ATTR_ID, 61 | MPTCP_PM_ADDR_ATTR_ADDR4, 62 | MPTCP_PM_ADDR_ATTR_ADDR6, 63 | MPTCP_PM_ADDR_ATTR_PORT, 64 | MPTCP_PM_ADDR_ATTR_FLAGS, 65 | MPTCP_PM_ADDR_ATTR_IF_IDX, 66 | 67 | __MPTCP_PM_ADDR_ATTR_MAX 68 | }; 69 | #define MPTCP_PM_ADDR_ATTR_MAX (__MPTCP_PM_ADDR_ATTR_MAX - 1) 70 | 71 | enum { 72 | MPTCP_SUBFLOW_ATTR_UNSPEC, 73 | MPTCP_SUBFLOW_ATTR_TOKEN_REM, 74 | MPTCP_SUBFLOW_ATTR_TOKEN_LOC, 75 | MPTCP_SUBFLOW_ATTR_RELWRITE_SEQ, 76 | MPTCP_SUBFLOW_ATTR_MAP_SEQ, 77 | MPTCP_SUBFLOW_ATTR_MAP_SFSEQ, 78 | MPTCP_SUBFLOW_ATTR_SSN_OFFSET, 79 | MPTCP_SUBFLOW_ATTR_MAP_DATALEN, 80 | MPTCP_SUBFLOW_ATTR_FLAGS, 81 | MPTCP_SUBFLOW_ATTR_ID_REM, 82 | MPTCP_SUBFLOW_ATTR_ID_LOC, 83 | MPTCP_SUBFLOW_ATTR_PAD, 84 | 85 | __MPTCP_SUBFLOW_ATTR_MAX 86 | }; 87 | #define MPTCP_SUBFLOW_ATTR_MAX (__MPTCP_SUBFLOW_ATTR_MAX - 1) 88 | 89 | enum { 90 | MPTCP_PM_ENDPOINT_ADDR = 1, 91 | 92 | __MPTCP_PM_ENDPOINT_MAX 93 | }; 94 | #define MPTCP_PM_ENDPOINT_MAX (__MPTCP_PM_ENDPOINT_MAX - 1) 95 | 96 | enum { 97 | MPTCP_PM_ATTR_UNSPEC, 98 | MPTCP_PM_ATTR_ADDR, 99 | MPTCP_PM_ATTR_RCV_ADD_ADDRS, 100 | MPTCP_PM_ATTR_SUBFLOWS, 101 | MPTCP_PM_ATTR_TOKEN, 102 | MPTCP_PM_ATTR_LOC_ID, 103 | MPTCP_PM_ATTR_ADDR_REMOTE, 104 | 105 | __MPTCP_ATTR_AFTER_LAST 106 | }; 107 | #define MPTCP_PM_ATTR_MAX (__MPTCP_ATTR_AFTER_LAST - 1) 108 | 109 | enum mptcp_event_attr { 110 | MPTCP_ATTR_UNSPEC, 111 | MPTCP_ATTR_TOKEN, 112 | MPTCP_ATTR_FAMILY, 113 | MPTCP_ATTR_LOC_ID, 114 | MPTCP_ATTR_REM_ID, 115 | MPTCP_ATTR_SADDR4, 116 | MPTCP_ATTR_SADDR6, 117 | MPTCP_ATTR_DADDR4, 118 | MPTCP_ATTR_DADDR6, 119 | MPTCP_ATTR_SPORT, 120 | MPTCP_ATTR_DPORT, 121 | MPTCP_ATTR_BACKUP, 122 | MPTCP_ATTR_ERROR, 123 | MPTCP_ATTR_FLAGS, 124 | MPTCP_ATTR_TIMEOUT, 125 | MPTCP_ATTR_IF_IDX, 126 | MPTCP_ATTR_RESET_REASON, 127 | MPTCP_ATTR_RESET_FLAGS, 128 | MPTCP_ATTR_SERVER_SIDE, 129 | 130 | __MPTCP_ATTR_MAX 131 | }; 132 | #define MPTCP_ATTR_MAX (__MPTCP_ATTR_MAX - 1) 133 | 134 | enum { 135 | MPTCP_PM_CMD_UNSPEC, 136 | MPTCP_PM_CMD_ADD_ADDR, 137 | MPTCP_PM_CMD_DEL_ADDR, 138 | MPTCP_PM_CMD_GET_ADDR, 139 | MPTCP_PM_CMD_FLUSH_ADDRS, 140 | MPTCP_PM_CMD_SET_LIMITS, 141 | MPTCP_PM_CMD_GET_LIMITS, 142 | MPTCP_PM_CMD_SET_FLAGS, 143 | MPTCP_PM_CMD_ANNOUNCE, 144 | MPTCP_PM_CMD_REMOVE, 145 | MPTCP_PM_CMD_SUBFLOW_CREATE, 146 | MPTCP_PM_CMD_SUBFLOW_DESTROY, 147 | 148 | __MPTCP_PM_CMD_AFTER_LAST 149 | }; 150 | #define MPTCP_PM_CMD_MAX (__MPTCP_PM_CMD_AFTER_LAST - 1) 151 | 152 | #endif /* _UAPI_LINUX_MPTCP_PM_H */ 153 | -------------------------------------------------------------------------------- /include/linux/mptcp_org.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ 2 | /* 3 | * Netlink API for Multipath TCP 4 | * 5 | * Author: Gregory Detal 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * as published by the Free Software Foundation; either version 10 | * 2 of the License, or (at your option) any later version. 11 | */ 12 | 13 | #ifndef _LINUX_MPTCP_H 14 | #define _LINUX_MPTCP_H 15 | 16 | #define MPTCP_GENL_NAME "mptcp" 17 | #define MPTCP_GENL_EV_GRP_NAME "mptcp_events" 18 | #define MPTCP_GENL_CMD_GRP_NAME "mptcp_commands" 19 | #define MPTCP_GENL_VER 0x1 20 | 21 | /* 22 | * ATTR types defined for MPTCP 23 | */ 24 | enum { 25 | MPTCP_ATTR_UNSPEC = 0, 26 | 27 | MPTCP_ATTR_TOKEN, /* u32 */ 28 | MPTCP_ATTR_FAMILY, /* u16 */ 29 | MPTCP_ATTR_LOC_ID, /* u8 */ 30 | MPTCP_ATTR_REM_ID, /* u8 */ 31 | MPTCP_ATTR_SADDR4, /* u32 */ 32 | MPTCP_ATTR_SADDR6, /* struct in6_addr */ 33 | MPTCP_ATTR_DADDR4, /* u32 */ 34 | MPTCP_ATTR_DADDR6, /* struct in6_addr */ 35 | MPTCP_ATTR_SPORT, /* u16 */ 36 | MPTCP_ATTR_DPORT, /* u16 */ 37 | MPTCP_ATTR_BACKUP, /* u8 */ 38 | MPTCP_ATTR_ERROR, /* u8 */ 39 | MPTCP_ATTR_FLAGS, /* u16 */ 40 | MPTCP_ATTR_TIMEOUT, /* u32 */ 41 | MPTCP_ATTR_IF_IDX, /* s32 */ 42 | 43 | __MPTCP_ATTR_AFTER_LAST 44 | }; 45 | 46 | #define MPTCP_ATTR_MAX (__MPTCP_ATTR_AFTER_LAST - 1) 47 | 48 | /* 49 | * Events generated by MPTCP: 50 | * - MPTCP_EVENT_CREATED: token, family, saddr4 | saddr6, daddr4 | daddr6, 51 | * sport, dport 52 | * A new connection has been created. It is the good time to allocate 53 | * memory and send ADD_ADDR if needed. Depending on the traffic-patterns 54 | * it can take a long time until the MPTCP_EVENT_ESTABLISHED is sent. 55 | * 56 | * - MPTCP_EVENT_ESTABLISHED: token, family, saddr4 | saddr6, daddr4 | daddr6, 57 | * sport, dport 58 | * A connection is established (can start new subflows). 59 | * 60 | * - MPTCP_EVENT_CLOSED: token 61 | * A connection has stopped. 62 | * 63 | * - MPTCP_EVENT_ANNOUNCED: token, rem_id, family, daddr4 | daddr6 [, dport] 64 | * A new address has been announced by the peer. 65 | * 66 | * - MPTCP_EVENT_REMOVED: token, rem_id 67 | * An address has been lost by the peer. 68 | * 69 | * - MPTCP_EVENT_SUB_ESTABLISHED: token, family, loc_id, rem_id, 70 | * saddr4 | saddr6, daddr4 | daddr6, sport, 71 | * dport, backup, if_idx [, error] 72 | * A new subflow has been established. 'error' should not be set. 73 | * 74 | * - MPTCP_EVENT_SUB_CLOSED: token, family, loc_id, rem_id, saddr4 | saddr6, 75 | * daddr4 | daddr6, sport, dport, backup, if_idx 76 | * [, error] 77 | * A subflow has been closed. An error (copy of sk_err) could be set if an 78 | * error has been detected for this subflow. 79 | * 80 | * - MPTCP_EVENT_SUB_PRIORITY: token, family, loc_id, rem_id, saddr4 | saddr6, 81 | * daddr4 | daddr6, sport, dport, backup, if_idx 82 | * [, error] 83 | * The priority of a subflow has changed. 'error' should not be set. 84 | * 85 | * Commands for MPTCP: 86 | * - MPTCP_CMD_ANNOUNCE: token, loc_id, family, saddr4 | saddr6 [, sport] 87 | * Announce a new address to the peer. 88 | * 89 | * - MPTCP_CMD_REMOVE: token, loc_id 90 | * Announce that an address has been lost to the peer. 91 | * 92 | * - MPTCP_CMD_SUB_CREATE: token, family, loc_id, rem_id, daddr4 | daddr6, 93 | * dport [, saddr4 | saddr6, sport, backup, if_idx] 94 | * Create a new subflow. 95 | * 96 | * - MPTCP_CMD_SUB_DESTROY: token, family, saddr4 | saddr6, daddr4 | daddr6, 97 | * sport, dport 98 | * Close a subflow. 99 | * 100 | * - MPTCP_CMD_SUB_PRIORITY: token, family, saddr4 | saddr6, daddr4 | daddr6, 101 | * sport, dport, backup 102 | * Change the priority of a subflow. 103 | * 104 | * - MPTCP_CMD_SET_FILTER: flags 105 | * Set the filter on events. Set MPTCPF_* flags to only receive specific 106 | * events. Default is to receive all events. 107 | * 108 | * - MPTCP_CMD_EXIST: token 109 | * Check if this token is linked to an existing socket. 110 | */ 111 | enum { 112 | MPTCP_CMD_UNSPEC = 0, 113 | 114 | MPTCP_EVENT_CREATED, 115 | MPTCP_EVENT_ESTABLISHED, 116 | MPTCP_EVENT_CLOSED, 117 | 118 | MPTCP_CMD_ANNOUNCE, 119 | MPTCP_CMD_REMOVE, 120 | MPTCP_EVENT_ANNOUNCED, 121 | MPTCP_EVENT_REMOVED, 122 | 123 | MPTCP_CMD_SUB_CREATE, 124 | MPTCP_CMD_SUB_DESTROY, 125 | MPTCP_EVENT_SUB_ESTABLISHED, 126 | MPTCP_EVENT_SUB_CLOSED, 127 | 128 | MPTCP_CMD_SUB_PRIORITY, 129 | MPTCP_EVENT_SUB_PRIORITY, 130 | 131 | MPTCP_CMD_SET_FILTER, 132 | 133 | MPTCP_CMD_EXIST, 134 | 135 | __MPTCP_CMD_AFTER_LAST 136 | }; 137 | 138 | #define MPTCP_CMD_MAX (__MPTCP_CMD_AFTER_LAST - 1) 139 | 140 | enum { 141 | MPTCPF_EVENT_CREATED = (1 << 1), 142 | MPTCPF_EVENT_ESTABLISHED = (1 << 2), 143 | MPTCPF_EVENT_CLOSED = (1 << 3), 144 | MPTCPF_EVENT_ANNOUNCED = (1 << 4), 145 | MPTCPF_EVENT_REMOVED = (1 << 5), 146 | MPTCPF_EVENT_SUB_ESTABLISHED = (1 << 6), 147 | MPTCPF_EVENT_SUB_CLOSED = (1 << 7), 148 | MPTCPF_EVENT_SUB_PRIORITY = (1 << 8), 149 | }; 150 | 151 | #endif /* _LINUX_MPTCP_H */ 152 | -------------------------------------------------------------------------------- /m4/mptcpd_flags.m4: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: BSD-3-Clause 2 | # 3 | # Copyright (c) 2017-2019, Intel Corporation 4 | 5 | #serial 2 6 | 7 | # MPTCPD_ADD_COMPILE_FLAG(FLAG, [ACTION-FAILURE]) 8 | # 9 | # Check if the compiler accepts the given FLAG. If it does append it 10 | # to CFLAGS. Otherwise execute the given failure action. 11 | AC_DEFUN([MPTCPD_ADD_COMPILE_FLAG], 12 | [AX_CHECK_COMPILE_FLAG([$1], 13 | [AX_APPEND_FLAG([$1], [CFLAGS])], [$2]) 14 | ]) 15 | 16 | # MPTCPD_ADD_LINK_FLAG(FLAG, [ACTION-FAILURE]) 17 | # 18 | # Check if the linker accepts the given FLAG. If it does append it 19 | # to LDFLAGS. Otherwise execute the given failure action. 20 | AC_DEFUN([MPTCPD_ADD_LINK_FLAG], 21 | [AX_CHECK_LINK_FLAG([$1], 22 | [AX_APPEND_FLAG([$1], [LDFLAGS])], [$2]) 23 | ]) 24 | 25 | # MPTCPD_ADD_ASAN_FLAG 26 | # 27 | # Add support for enabling GCC/Clang memory error detector 28 | # (AddressSanitizer) instrumentation. 29 | # 30 | # @todo Reduce code duplication between the 31 | # MPTCPD_ADD_{A,L,UB}SAN_SUPPORT macros. 32 | AC_DEFUN([MPTCPD_ADD_ASAN_SUPPORT], 33 | [ 34 | AC_ARG_ENABLE([asan], 35 | [AS_HELP_STRING([--enable-asan], 36 | [Enable memory error detector])], 37 | [], 38 | [enable_asan=no]) 39 | 40 | AS_IF([test "x$enable_asan" = "xyes"], 41 | [ 42 | MPTCPD_ADD_COMPILE_FLAG( 43 | [-fsanitize=address], 44 | [AC_MSG_ERROR([Address sanitizer not supported by the compiler])]) 45 | 46 | dnl -fno-omit-frame-pointer to get nicer stack traces. 47 | MPTCPD_ADD_COMPILE_FLAG([-fno-omit-frame-pointer]) 48 | 49 | AS_IF([test "x$enable_shared" != "xyes"], 50 | [MPTCPD_ADD_COMPILE_FLAG([-static-libasan])]) 51 | 52 | dnl Explicitly check for libasan through AC_CHECK_LIB instead 53 | dnl of AC_SEARCH_LIBS since we're relying on the existence of 54 | dnl the _init symbol found in all libraries. We also don't 55 | dnl want to explicitly add -lasan to the link command line 56 | dnl since the compiler driver will do that automatically. 57 | AC_CHECK_LIB( 58 | [asan], 59 | [_init], 60 | [], 61 | [AC_MSG_ERROR([libasan is needed for memory error detector])]) 62 | ]) 63 | ]) 64 | 65 | # MPTCPD_ADD_LSAN_FLAG 66 | # 67 | # Add support for enabling GCC/Clang memory leak detector 68 | # (LeakSanitizer) instrumentation. This is the leak-only 69 | # functionality found in the address sanitizer. 70 | # 71 | # @todo Reduce code duplication between the 72 | # MPTCPD_ADD_{A,L,UB}SAN_SUPPORT macros. 73 | AC_DEFUN([MPTCPD_ADD_LSAN_SUPPORT], 74 | [ 75 | AC_ARG_ENABLE([lsan], 76 | [AS_HELP_STRING([--enable-lsan], 77 | [Enable memory leak detector])], 78 | [], 79 | [enable_lsan=no]) 80 | 81 | AS_IF([test "x$enable_lsan" = "xyes"], 82 | [ 83 | MPTCPD_ADD_COMPILE_FLAG( 84 | [-fsanitize=leak], 85 | [AC_MSG_ERROR([Leak sanitizer not supported by the compiler])]) 86 | 87 | dnl -fno-omit-frame-pointer to get nicer stack traces. 88 | MPTCPD_ADD_COMPILE_FLAG([-fno-omit-frame-pointer]) 89 | 90 | AS_IF([test "x$enable_shared" != "xyes"], 91 | [MPTCPD_ADD_COMPILE_FLAG([-static-liblsan])]) 92 | 93 | dnl Explicitly check for liblsan through AC_CHECK_LIB instead 94 | dnl of AC_SEARCH_LIBS since we're relying on the existence of 95 | dnl the _init symbol found in all libraries. We also don't 96 | dnl want to explicitly add -llsan to the link command line 97 | dnl since the compiler driver will do that automatically. 98 | AC_CHECK_LIB( 99 | [lsan], 100 | [_init], 101 | [], 102 | [AC_MSG_ERROR([liblsan is needed for memory leak detector])]) 103 | ]) 104 | ]) 105 | 106 | # MPTCPD_ADD_UBSAN_FLAG 107 | # 108 | # Add support for enabling GCC/Clang undefined behavior detector 109 | # (UndefinedBehaviorSanitizer) instrumentation. 110 | # 111 | # @todo Reduce code duplication between the 112 | # MPTCPD_ADD_{A,L,UB}SAN_SUPPORT macros. 113 | AC_DEFUN([MPTCPD_ADD_UBSAN_SUPPORT], 114 | [ 115 | AC_ARG_ENABLE([ubsan], 116 | [AS_HELP_STRING([--enable-ubsan], 117 | [Enable undefined behavior detector])], 118 | [], 119 | [enable_ubsan=no]) 120 | 121 | AS_IF([test "x$enable_ubsan" = "xyes"], 122 | [ 123 | MPTCPD_ADD_COMPILE_FLAG( 124 | [-fsanitize=undefined], 125 | [AC_MSG_ERROR([Undefined behavior sanitizer not supported by the compiler])]) 126 | 127 | dnl -fno-omit-frame-pointer to get nicer stack traces. 128 | MPTCPD_ADD_COMPILE_FLAG([-fno-omit-frame-pointer]) 129 | 130 | AS_IF([test "x$enable_shared" != "xyes"], 131 | [MPTCPD_ADD_COMPILE_FLAG([-static-libubsan])]) 132 | 133 | dnl Explicitly check for libubsan through AC_CHECK_LIB instead 134 | dnl of AC_SEARCH_LIBS since we're relying on the existence of 135 | dnl the _init symbol found in all libraries. We also don't 136 | dnl want to explicitly add -lubsan to the link command line 137 | dnl since the compiler driver will do that automatically. 138 | AC_CHECK_LIB( 139 | [ubsan], 140 | [_init], 141 | [], 142 | [AC_MSG_ERROR([libubsan is needed for undefined behavior detector])]) 143 | ]) 144 | ]) 145 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | 2 | # Contributor Covenant Code of Conduct 3 | 4 | ## Our Pledge 5 | 6 | We as members, contributors, and leaders pledge to make participation in our 7 | community a harassment-free experience for everyone, regardless of age, body 8 | size, visible or invisible disability, ethnicity, sex characteristics, gender 9 | identity and expression, level of experience, education, socio-economic status, 10 | nationality, personal appearance, race, caste, color, religion, or sexual identity 11 | and orientation. 12 | 13 | We pledge to act and interact in ways that contribute to an open, welcoming, 14 | diverse, inclusive, and healthy community. 15 | 16 | ## Our Standards 17 | 18 | Examples of behavior that contributes to a positive environment for our 19 | community include: 20 | 21 | * Demonstrating empathy and kindness toward other people 22 | * Being respectful of differing opinions, viewpoints, and experiences 23 | * Giving and gracefully accepting constructive feedback 24 | * Accepting responsibility and apologizing to those affected by our mistakes, 25 | and learning from the experience 26 | * Focusing on what is best not just for us as individuals, but for the 27 | overall community 28 | 29 | Examples of unacceptable behavior include: 30 | 31 | * The use of sexualized language or imagery, and sexual attention or 32 | advances of any kind 33 | * Trolling, insulting or derogatory comments, and personal or political attacks 34 | * Public or private harassment 35 | * Publishing others' private information, such as a physical or email 36 | address, without their explicit permission 37 | * Other conduct which could reasonably be considered inappropriate in a 38 | professional setting 39 | 40 | ## Enforcement Responsibilities 41 | 42 | Community leaders are responsible for clarifying and enforcing our standards of 43 | acceptable behavior and will take appropriate and fair corrective action in 44 | response to any behavior that they deem inappropriate, threatening, offensive, 45 | or harmful. 46 | 47 | Community leaders have the right and responsibility to remove, edit, or reject 48 | comments, commits, code, wiki edits, issues, and other contributions that are 49 | not aligned to this Code of Conduct, and will communicate reasons for moderation 50 | decisions when appropriate. 51 | 52 | ## Scope 53 | 54 | This Code of Conduct applies within all community spaces, and also applies when 55 | an individual is officially representing the community in public spaces. 56 | Examples of representing our community include using an official e-mail address, 57 | posting via an official social media account, or acting as an appointed 58 | representative at an online or offline event. 59 | 60 | ## Enforcement 61 | 62 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 63 | reported to the community leaders responsible for enforcement at the 64 | e-mail address for the Linux kernel MPTCP subsystem owner listed in 65 | the kernel 66 | [`MAINTAINERS`](https://www.kernel.org/doc/linux/MAINTAINERS) file. 67 | All complaints will be reviewed and investigated promptly and fairly. 68 | 69 | All community leaders are obligated to respect the privacy and security of the 70 | reporter of any incident. 71 | 72 | ## Enforcement Guidelines 73 | 74 | Community leaders will follow these Community Impact Guidelines in determining 75 | the consequences for any action they deem in violation of this Code of Conduct: 76 | 77 | ### 1. Correction 78 | 79 | **Community Impact**: Use of inappropriate language or other behavior deemed 80 | unprofessional or unwelcome in the community. 81 | 82 | **Consequence**: A private, written warning from community leaders, providing 83 | clarity around the nature of the violation and an explanation of why the 84 | behavior was inappropriate. A public apology may be requested. 85 | 86 | ### 2. Warning 87 | 88 | **Community Impact**: A violation through a single incident or series 89 | of actions. 90 | 91 | **Consequence**: A warning with consequences for continued behavior. No 92 | interaction with the people involved, including unsolicited interaction with 93 | those enforcing the Code of Conduct, for a specified period of time. This 94 | includes avoiding interactions in community spaces as well as external channels 95 | like social media. Violating these terms may lead to a temporary or 96 | permanent ban. 97 | 98 | ### 3. Temporary Ban 99 | 100 | **Community Impact**: A serious violation of community standards, including 101 | sustained inappropriate behavior. 102 | 103 | **Consequence**: A temporary ban from any sort of interaction or public 104 | communication with the community for a specified period of time. No public or 105 | private interaction with the people involved, including unsolicited interaction 106 | with those enforcing the Code of Conduct, is allowed during this period. 107 | Violating these terms may lead to a permanent ban. 108 | 109 | ### 4. Permanent Ban 110 | 111 | **Community Impact**: Demonstrating a pattern of violation of community 112 | standards, including sustained inappropriate behavior, harassment of an 113 | individual, or aggression toward or disparagement of classes of individuals. 114 | 115 | **Consequence**: A permanent ban from any sort of public interaction within 116 | the community. 117 | 118 | ## Attribution 119 | 120 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 121 | version 2.0, available at 122 | [https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0]. 123 | 124 | Community Impact Guidelines were inspired by 125 | [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. 126 | 127 | For answers to common questions about this code of conduct, see the FAQ at 128 | [https://www.contributor-covenant.org/faq][FAQ]. Translations are available 129 | at [https://www.contributor-covenant.org/translations][translations]. 130 | 131 | [homepage]: https://www.contributor-covenant.org 132 | [v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html 133 | [Mozilla CoC]: https://github.com/mozilla/diversity 134 | [FAQ]: https://www.contributor-covenant.org/faq 135 | [translations]: https://www.contributor-covenant.org/translations 136 | 137 | -------------------------------------------------------------------------------- /include/mptcpd/types.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file types.h 4 | * 5 | * @brief mptcpd user space path manager attribute types. 6 | * 7 | * Copyright (c) 2018-2021, Intel Corporation 8 | */ 9 | 10 | #ifndef MPTCPD_TYPES_H 11 | #define MPTCPD_TYPES_H 12 | 13 | #include 14 | #include 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | /** 21 | * @todo These rely on MPTCP genl related implementation details in 22 | * the kernel. Should we move these typedefs to 23 | * @c , e.g. 'typedef uint32_t mptcp_token_t'? 24 | */ 25 | /// MPTCP connection token type. 26 | typedef uint32_t mptcpd_token_t; 27 | 28 | /// MPTCP address ID type. 29 | typedef uint8_t mptcpd_aid_t; 30 | 31 | /// MPTCP address ID format specifier. 32 | #define MPTCPD_PRIxAID PRIx8 33 | 34 | /** 35 | * @name MPTCP Address Flags 36 | * 37 | * Each MPTCP address flag is meant to be set as a bit in a 38 | * @c mptcpd_flags_t variable as needed, e.g.: 39 | * 40 | * @code 41 | * mptcpd_flags_t flags = 42 | * MPTCPD_ADDR_FLAG_SUBFLOW | MPTCPD_ADDR_FLAG_BACKUP; 43 | * @endcode 44 | */ 45 | ///@{ 46 | /** 47 | * @brief MPTCP flags type. 48 | * 49 | * MPTCP address flags integer type that contains set of flag bits. 50 | */ 51 | typedef uint32_t mptcpd_flags_t; 52 | 53 | /** 54 | * @brief Trigger announcement of a new local IP address. 55 | * 56 | * @note Do not use with @c MPTCPD_ADDR_FLAG_FULLMESH. 57 | */ 58 | #define MPTCPD_ADDR_FLAG_SIGNAL (1U << 0) 59 | 60 | /// Create a new subflow. 61 | #define MPTCPD_ADDR_FLAG_SUBFLOW (1U << 1) 62 | 63 | /// Set backup priority on the subflow. 64 | #define MPTCPD_ADDR_FLAG_BACKUP (1U << 2) 65 | 66 | /** 67 | * @brief Add local address to in-kernel fullmesh path management. 68 | * 69 | * If this flag is set, create a subflow connection to each known remote 70 | * address, originating from this local address. The total number of 71 | * subflows is subject to the configured limits. 72 | * 73 | * @note Do not use with @c MPTCPD_ADDR_FLAG_SIGNAL. 74 | */ 75 | #define MPTCPD_ADDR_FLAG_FULLMESH (1U << 3) 76 | 77 | /** 78 | * @brief Endpoint implicitly created by the kernel PM. 79 | * 80 | * It exists because no userspace ones correspond to the associated address 81 | * and port. It can only be set by the kernel. 82 | * 83 | * @note Do not set from the userspace to the kernelspace. 84 | */ 85 | #define MPTCPD_ADDR_FLAG_IMPLICIT (1U << 4) 86 | 87 | /// Use this endpoint in reaction to ADD_ADDR, but only once. 88 | #define MPTCPD_ADDR_FLAG_LAMINAR (1U << 5) 89 | ///@} 90 | 91 | /** 92 | * @enum mptcpd_limit_types 93 | * 94 | * @brief MPTCP resource limit type identifiers. 95 | */ 96 | enum mptcpd_limit_types 97 | { 98 | /// Maximum number of address advertisements to receive. 99 | MPTCPD_LIMIT_RCV_ADD_ADDRS, 100 | 101 | /// Maximum number of subflows. 102 | MPTCPD_LIMIT_SUBFLOWS 103 | }; 104 | 105 | struct mptcpd_addr_info; 106 | 107 | /** 108 | * @struct mptcpd_limit 109 | * 110 | * @brief MPTCP resource type/limit pair. 111 | */ 112 | struct mptcpd_limit 113 | { 114 | /// MPTCP resource type, e.g. @c MPTCPD_LIMIT_SUBFLOWS. 115 | uint16_t type; 116 | 117 | /// MPTCP resource limit value. 118 | uint32_t limit; 119 | }; 120 | 121 | /** 122 | * @brief Type of function called when an address is available. 123 | * 124 | * The mptcpd path manager will call a function of this type when 125 | * the result of calling @c mptcpd_kpm_get_addr() or 126 | * @c mptcpd_kpm_dump_addrs() is available. 127 | * 128 | * @param[in] info Network address information. @c NULL 129 | * on error. 130 | * @param[in,out] callback_data Data provided by the caller of 131 | * @c mptcpd_kpm_get_addr() or 132 | * @c mptcpd_kpm_dump_addrs(). 133 | */ 134 | typedef void (*mptcpd_kpm_get_addr_cb_t)( 135 | struct mptcpd_addr_info const *info, 136 | void *callback_data); 137 | 138 | /** 139 | * @brief Type of function called on asynchronous call completion. 140 | * 141 | * The mptcpd path manager API has several functions that complete 142 | * asynchronously. Those functions accept a parameter of this type to 143 | * allow the caller to be notified of completion of the asynchronous 144 | * functions. 145 | * 146 | * Functions of this type differ from user provided callbacks that are 147 | * called when asynchronous results are available in that this type of 148 | * function is called regardless of whether or not asynchronous 149 | * results are available. Furthermore, they are only called once at 150 | * the very end of the asynchronous call, whereas those called upon 151 | * availability of results may be called multiple times for a single 152 | * asynchronous call, such as the @c mptcpd_kpm_dump_addrs() case. 153 | * 154 | * Functions of this type are suitable for deallocating dynamically 155 | * allocated user_data passed to asynchronous calls, for example. 156 | * 157 | * @param [in,out] user_data Data provided the user at the time of the 158 | * asynchronous call. 159 | */ 160 | typedef void (*mptcpd_complete_func_t)(void *user_data); 161 | 162 | /** 163 | * @brief Type of function called when MPTCP resource limits are 164 | * available. 165 | * 166 | * The mptcpd path manager will call a function of this type when 167 | * the result of calling @c mptcpd_kpm_get_limits() is available. 168 | * 169 | * @param[in] limits Array of MPTCP resource type/limit 170 | * pairs. @c NULL on error. 171 | * @param[in] len Length of the @a limits array. Zero 172 | * on error. 173 | * @param[in,out] callback_data Data provided by the caller of 174 | * @c mptcpd_kpm_get_limits(). 175 | */ 176 | typedef void (*mptcpd_pm_get_limits_cb)( 177 | struct mptcpd_limit const *limits, 178 | size_t len, 179 | void *callback_data); 180 | 181 | #ifdef __cplusplus 182 | } 183 | #endif 184 | 185 | #endif /* MPTCPD_TYPES_H */ 186 | 187 | /* 188 | Local Variables: 189 | c-file-style: "linux" 190 | End: 191 | */ 192 | -------------------------------------------------------------------------------- /tests/test-configuration.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file test-configuration.c 4 | * 5 | * @brief mptcpd configuration test. 6 | * 7 | * Copyright (c) 2019, 2021, Intel Corporation 8 | */ 9 | 10 | #include 11 | 12 | #include // INTERNAL! 13 | 14 | #undef NDEBUG 15 | #include 16 | 17 | #define TEST_PROGRAM_NAME "test-configuration" 18 | 19 | #define RUN_CONFIG(argv) run_config(L_ARRAY_SIZE(argv), (argv)) 20 | 21 | static void run_config(int argc, char **argv) 22 | { 23 | struct mptcpd_config *const config = 24 | mptcpd_config_create(argc, argv); 25 | assert(config != NULL); 26 | 27 | mptcpd_config_destroy(config); 28 | 29 | l_log_set_stderr(); 30 | } 31 | 32 | static void test_debug(void const *test_data) 33 | { 34 | (void) test_data; 35 | 36 | static char *argv1[] = { TEST_PROGRAM_NAME, "--debug" }; 37 | static char *argv2[] = { TEST_PROGRAM_NAME, "-d" }; 38 | 39 | RUN_CONFIG(argv1); 40 | RUN_CONFIG(argv2); 41 | } 42 | 43 | 44 | #define TEST_LOG(logger) \ 45 | do { \ 46 | static char *argv1[] = { TEST_PROGRAM_NAME, "--log=" logger }; \ 47 | static char *argv2[] = { TEST_PROGRAM_NAME, "-l", logger }; \ 48 | \ 49 | RUN_CONFIG(argv1); \ 50 | RUN_CONFIG(argv2); \ 51 | } while(0) 52 | 53 | static void test_log_stderr(void const *test_data) 54 | { 55 | (void) test_data; 56 | 57 | TEST_LOG("stderr"); 58 | } 59 | 60 | static void test_log_syslog(void const *test_data) 61 | { 62 | (void) test_data; 63 | 64 | TEST_LOG("syslog"); 65 | } 66 | 67 | static void test_log_journal(void const *test_data) 68 | { 69 | (void) test_data; 70 | 71 | TEST_LOG("journal"); 72 | } 73 | 74 | static void test_log_null(void const *test_data) 75 | { 76 | (void) test_data; 77 | 78 | TEST_LOG("null"); 79 | } 80 | 81 | static void test_plugin_dir(void const *test_data) 82 | { 83 | (void) test_data; 84 | 85 | static char *argv[] = 86 | { TEST_PROGRAM_NAME, "--plugin-dir", "/tmp/foo/bar" }; 87 | 88 | RUN_CONFIG(argv); 89 | } 90 | 91 | static void test_path_manager(void const *test_data) 92 | { 93 | (void) test_data; 94 | 95 | static char *argv[] = 96 | { TEST_PROGRAM_NAME, "--path-manager", "foo" }; 97 | 98 | RUN_CONFIG(argv); 99 | } 100 | 101 | static void test_load_plugins(void const *test_data) 102 | { 103 | (void) test_data; 104 | 105 | static char *argv[] = 106 | { TEST_PROGRAM_NAME, "--load-plugins", "foo,bar" }; 107 | 108 | RUN_CONFIG(argv); 109 | } 110 | 111 | static void test_addr_flags(void const *test_data) 112 | { 113 | (void) test_data; 114 | 115 | static char *argv[] = 116 | { TEST_PROGRAM_NAME, "--addr-flags", 117 | "signal,subflow,fullmesh,backup,laminar" }; 118 | 119 | RUN_CONFIG(argv); 120 | } 121 | 122 | static void test_multi_arg(void const *test_data) 123 | { 124 | (void) test_data; 125 | 126 | static char plugin_dir[] = "/tmp/foo/bar"; 127 | static char override_dir[] = "/tmp/foo/baz"; 128 | assert(strcmp(plugin_dir, override_dir) != 0); 129 | 130 | static char pm[] = "foo"; 131 | static char override_pm[] = "bar"; 132 | assert(strcmp(pm, override_pm) != 0); 133 | 134 | static char *argv[] = { 135 | TEST_PROGRAM_NAME, 136 | "--plugin-dir", plugin_dir, 137 | "--path-manager", pm, 138 | "--plugin-dir", override_dir, 139 | "--path-manager", override_pm 140 | }; 141 | 142 | struct mptcpd_config *const config = 143 | mptcpd_config_create(L_ARRAY_SIZE(argv), argv); 144 | assert(config != NULL); 145 | 146 | assert(config->plugin_dir != NULL); 147 | assert(strcmp(config->plugin_dir, override_dir) == 0); 148 | 149 | assert(config->default_plugin != NULL); 150 | assert(strcmp(config->default_plugin, override_pm) == 0); 151 | 152 | mptcpd_config_destroy(config); 153 | } 154 | 155 | 156 | static void test_config_file(void const *test_data) 157 | { 158 | (void) test_data; 159 | 160 | /** 161 | * @todo Test mptcpd configuration file parsing. The 162 | * configuration file location is currently compiled 163 | * into the program since mptcpd may be run with 164 | * elevated privileges. A test can't be performed until 165 | * mptcpd supports specifying the configuration file 166 | * location at run-time, perhaps through a XDG-style 167 | * approach (@c $XDG_CONFIG_DIRS and/or 168 | * @c $XDG_CONFIG_HOME). 169 | */ 170 | 171 | l_info("Configuration file test is unimplemented."); 172 | } 173 | 174 | int main(int argc, char *argv[]) 175 | { 176 | if (!l_main_init()) 177 | return -1; 178 | 179 | l_log_set_stderr(); 180 | 181 | l_test_init(&argc, &argv); 182 | 183 | l_test_add("log stderr", test_log_stderr, NULL); 184 | l_test_add("log syslog", test_log_syslog, NULL); 185 | l_test_add("log journal", test_log_journal, NULL); 186 | l_test_add("log null", test_log_null, NULL); 187 | l_test_add("plugin dir", test_plugin_dir, NULL); 188 | l_test_add("path manager", test_path_manager, NULL); 189 | l_test_add("load plugins", test_load_plugins, NULL); 190 | l_test_add("addr flags", test_addr_flags, NULL); 191 | l_test_add("multi arg", test_multi_arg, NULL); 192 | l_test_add("config file", test_config_file, NULL); 193 | l_test_add("debug", test_debug, NULL); 194 | 195 | l_test_run(); 196 | 197 | return l_main_exit() ? 0 : -1; 198 | } 199 | 200 | 201 | /* 202 | Local Variables: 203 | c-file-style: "linux" 204 | End: 205 | */ 206 | -------------------------------------------------------------------------------- /tests/test-sockaddr.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file test-sockaddr.c 4 | * 5 | * @brief mptcpd sockaddr utilities test. 6 | * 7 | * Copyright (c) 2021, 2022, Intel Corporation 8 | */ 9 | 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | 16 | #include "test-plugin.h" // For test sockaddrs 17 | 18 | #undef NDEBUG 19 | #include 20 | 21 | 22 | static void test_network_byte_swap(void const *test_data) 23 | { 24 | (void) test_data; 25 | 26 | uint16_t const hs = 0x1234; 27 | uint32_t const hl = 0x040200C0; 28 | 29 | #if __BYTE_ORDER == __LITTLE_ENDIAN 30 | uint16_t const ns = 0x3412; 31 | uint32_t const nl = 0xC0000204; 32 | 33 | assert(MPTCPD_CONSTANT_HTONS(hs) == ns); 34 | assert(MPTCPD_CONSTANT_HTONL(hl) == nl); 35 | #else 36 | assert(MPTCPD_CONSTANT_HTONS(hs) == hs); 37 | assert(MPTCPD_CONSTANT_HTONL(hl) == hl); 38 | #endif // __BYTE_ORDER == __LITTLE_ENDIAN 39 | } 40 | 41 | static void test_bad_sockaddr_init(void const *test_data) 42 | { 43 | (void) test_data; 44 | 45 | static in_addr_t const *const bad_addr4 = NULL; 46 | static struct in6_addr const *const bad_addr6 = NULL; 47 | static struct sockaddr_storage *const bad_addr = NULL; 48 | 49 | static in_addr_t const *const good_addr4 = 50 | &test_laddr_1.sin_addr.s_addr; 51 | static unsigned short const port = 0; 52 | 53 | struct sockaddr_storage good_addr = { .ss_family = AF_UNSPEC }; 54 | 55 | // No source in{6}_addrs. 56 | assert(!mptcpd_sockaddr_storage_init(bad_addr4, 57 | bad_addr6, 58 | port, 59 | &good_addr)); 60 | 61 | // No destination addr. 62 | assert(!mptcpd_sockaddr_storage_init(good_addr4, 63 | bad_addr6, 64 | port, 65 | bad_addr)); 66 | } 67 | 68 | 69 | static void test_sockaddr_in_init(void const *test_data) 70 | { 71 | (void) test_data; 72 | 73 | in_addr_t const *const addr4 = &test_laddr_1.sin_addr.s_addr; 74 | struct in6_addr const *const addr6 = NULL; 75 | unsigned short const port = test_laddr_1.sin_port; 76 | 77 | struct sockaddr_storage addr = { .ss_family = AF_UNSPEC }; 78 | 79 | bool const initialized = 80 | mptcpd_sockaddr_storage_init(addr4, addr6, port, &addr); 81 | 82 | assert(initialized 83 | && sockaddr_is_equal((struct sockaddr const *) &test_laddr_1, 84 | (struct sockaddr const *) &addr)); 85 | } 86 | 87 | static void test_sockaddr_in6_init(void const *test_data) 88 | { 89 | (void) test_data; 90 | 91 | in_addr_t const *const addr4 = NULL; 92 | struct in6_addr const *const addr6 = &test_laddr_2.sin6_addr; 93 | unsigned short const port = test_laddr_2.sin6_port; 94 | 95 | struct sockaddr_storage addr = { .ss_family = AF_UNSPEC }; 96 | 97 | bool const initialized = 98 | mptcpd_sockaddr_storage_init(addr4, addr6, port, &addr); 99 | 100 | assert(initialized 101 | && sockaddr_is_equal((struct sockaddr const *) &test_laddr_2, 102 | (struct sockaddr const *) &addr)); 103 | } 104 | 105 | static void test_copy_null(void const *test_data) 106 | { 107 | (void) test_data; 108 | 109 | assert(mptcpd_sockaddr_copy(NULL) == NULL); 110 | } 111 | 112 | static bool test_copy_inet(struct sockaddr const *src) 113 | { 114 | struct sockaddr *const dst = mptcpd_sockaddr_copy(src); 115 | 116 | bool const is_equal = sockaddr_is_equal(src, dst); 117 | 118 | l_free(dst); 119 | 120 | return is_equal; 121 | } 122 | 123 | static void test_copy_af_inet(void const *test_data) 124 | { 125 | (void) test_data; 126 | 127 | struct sockaddr_in const addr = { 128 | .sin_family = AF_INET, 129 | .sin_port = htons(0x1234), 130 | .sin_addr = { 131 | .s_addr = htonl(0xC0000201) // 192.0.2.1 132 | } 133 | }; 134 | 135 | struct sockaddr const *const src = (struct sockaddr const *) &addr; 136 | 137 | assert(test_copy_inet(src)); 138 | } 139 | 140 | static void test_copy_af_inet6(void const *test_data) 141 | { 142 | (void) test_data; 143 | 144 | struct sockaddr_in6 const addr = { 145 | .sin6_family = AF_INET6, 146 | .sin6_port = htons(0x5678), 147 | .sin6_addr = { 148 | .s6_addr = { [0] = 0x20, 149 | [1] = 0x01, 150 | [2] = 0x0D, 151 | [3] = 0xB8, 152 | [14] = 0x01, 153 | [15] = 0x02 } // 2001:DB8::102 154 | } 155 | }; 156 | 157 | struct sockaddr const *const src = 158 | (struct sockaddr const *) &addr; 159 | 160 | assert(test_copy_inet(src)); 161 | } 162 | 163 | static void test_copy_non_inet(void const *test_data) 164 | { 165 | (void) test_data; 166 | 167 | struct sockaddr const src = { .sa_family = AF_UNIX }; 168 | 169 | assert(mptcpd_sockaddr_copy(&src) == NULL); 170 | } 171 | 172 | int main(int argc, char *argv[]) 173 | { 174 | l_log_set_stderr(); 175 | 176 | l_test_init(&argc, &argv); 177 | 178 | l_test_add("network byte swap", test_network_byte_swap, NULL); 179 | l_test_add("bad sockaddr init", test_bad_sockaddr_init, NULL); 180 | l_test_add("sockaddr_in init", test_sockaddr_in_init, NULL); 181 | l_test_add("sockaddr_in6 init", test_sockaddr_in6_init, NULL); 182 | l_test_add("copy - NULL", test_copy_null, NULL); 183 | l_test_add("copy - AF_INET", test_copy_af_inet, NULL); 184 | l_test_add("copy - AF_INET6", test_copy_af_inet6, NULL); 185 | l_test_add("copy - non-INET", test_copy_non_inet, NULL); 186 | 187 | return l_test_run(); 188 | } 189 | 190 | 191 | /* 192 | Local Variables: 193 | c-file-style: "linux" 194 | End: 195 | */ 196 | -------------------------------------------------------------------------------- /tests/plugins/security/four.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file four.c 4 | * 5 | * @brief MPTCP test plugin. 6 | * 7 | * Copyright (c) 2019-2022, Intel Corporation 8 | */ 9 | 10 | #include 11 | 12 | #ifdef HAVE_CONFIG_H 13 | # include 14 | #endif 15 | 16 | #include 17 | 18 | #include "test-plugin.h" 19 | 20 | #undef NDEBUG 21 | #include 22 | 23 | 24 | // ---------------------------------------------------------------- 25 | 26 | static struct plugin_call_count call_count; 27 | 28 | // ---------------------------------------------------------------- 29 | 30 | static void plugin_four_new_connection(mptcpd_token_t token, 31 | struct sockaddr const *laddr, 32 | struct sockaddr const *raddr, 33 | bool server_side, 34 | bool deny_join_id0, 35 | struct mptcpd_pm *pm) 36 | { 37 | (void) token; 38 | (void) laddr; 39 | (void) raddr; 40 | (void) server_side; 41 | (void) deny_join_id0; 42 | (void) pm; 43 | 44 | ++call_count.new_connection; 45 | } 46 | 47 | static void plugin_four_connection_established( 48 | mptcpd_token_t token, 49 | struct sockaddr const *laddr, 50 | struct sockaddr const *raddr, 51 | bool server_side, 52 | bool deny_join_id0, 53 | struct mptcpd_pm *pm) 54 | { 55 | (void) token; 56 | (void) laddr; 57 | (void) raddr; 58 | (void) server_side; 59 | (void) deny_join_id0; 60 | (void) pm; 61 | 62 | ++call_count.connection_established; 63 | } 64 | 65 | static void plugin_four_connection_closed(mptcpd_token_t token, 66 | struct mptcpd_pm *pm) 67 | { 68 | (void) token; 69 | (void) pm; 70 | 71 | ++call_count.connection_closed; 72 | } 73 | 74 | static void plugin_four_new_address(mptcpd_token_t token, 75 | mptcpd_aid_t addr_id, 76 | struct sockaddr const *addr, 77 | struct mptcpd_pm *pm) 78 | { 79 | (void) token; 80 | (void) addr_id; 81 | (void) addr; 82 | (void) pm; 83 | 84 | ++call_count.new_address; 85 | } 86 | 87 | static void plugin_four_address_removed(mptcpd_token_t token, 88 | mptcpd_aid_t addr_id, 89 | struct mptcpd_pm *pm) 90 | { 91 | (void) token; 92 | (void) addr_id; 93 | (void) pm; 94 | 95 | ++call_count.address_removed; 96 | } 97 | 98 | static void plugin_four_new_subflow(mptcpd_token_t token, 99 | struct sockaddr const *laddr, 100 | struct sockaddr const *raddr, 101 | bool backup, 102 | struct mptcpd_pm *pm) 103 | { 104 | (void) token; 105 | (void) laddr; 106 | (void) raddr; 107 | (void) backup; 108 | (void) pm; 109 | 110 | ++call_count.new_subflow; 111 | } 112 | 113 | static void plugin_four_subflow_closed(mptcpd_token_t token, 114 | struct sockaddr const *laddr, 115 | struct sockaddr const *raddr, 116 | bool backup, 117 | uint8_t error, 118 | struct mptcpd_pm *pm) 119 | { 120 | (void) token; 121 | (void) laddr; 122 | (void) raddr; 123 | (void) backup; 124 | (void) error; 125 | (void) pm; 126 | 127 | ++call_count.subflow_closed; 128 | } 129 | 130 | static void plugin_four_subflow_priority(mptcpd_token_t token, 131 | struct sockaddr const *laddr, 132 | struct sockaddr const *raddr, 133 | bool backup, 134 | struct mptcpd_pm *pm) 135 | { 136 | (void) token; 137 | (void) laddr; 138 | (void) raddr; 139 | (void) backup; 140 | (void) pm; 141 | 142 | ++call_count.subflow_priority; 143 | } 144 | 145 | static void plugin_four_listener_created(struct sockaddr const *laddr, 146 | struct mptcpd_pm *pm) 147 | { 148 | (void) laddr; 149 | (void) pm; 150 | 151 | ++call_count.listener_created; 152 | } 153 | 154 | static void plugin_four_listener_closed(struct sockaddr const *laddr, 155 | struct mptcpd_pm *pm) 156 | { 157 | (void) laddr; 158 | (void) pm; 159 | 160 | ++call_count.listener_closed; 161 | } 162 | 163 | static struct mptcpd_plugin_ops const pm_ops = { 164 | .new_connection = plugin_four_new_connection, 165 | .connection_established = plugin_four_connection_established, 166 | .connection_closed = plugin_four_connection_closed, 167 | .new_address = plugin_four_new_address, 168 | .address_removed = plugin_four_address_removed, 169 | .new_subflow = plugin_four_new_subflow, 170 | .subflow_closed = plugin_four_subflow_closed, 171 | .subflow_priority = plugin_four_subflow_priority, 172 | .listener_created = plugin_four_listener_created, 173 | .listener_closed = plugin_four_listener_closed, 174 | }; 175 | 176 | static int plugin_four_init(struct mptcpd_pm *pm) 177 | { 178 | (void) pm; 179 | 180 | static char const name[] = TEST_PLUGIN; 181 | 182 | if (!mptcpd_plugin_register_ops(name, &pm_ops)) { 183 | l_error("Failed to initialize test " 184 | "plugin \"" TEST_PLUGIN "\"."); 185 | 186 | return -1; 187 | } 188 | 189 | return 0; 190 | } 191 | 192 | static void plugin_four_exit(struct mptcpd_pm *pm) 193 | { 194 | (void) pm; 195 | 196 | assert(call_count_is_sane(&call_count)); 197 | assert(call_count_is_equal(&call_count, &test_count_4)); 198 | 199 | call_count_reset(&call_count); 200 | } 201 | 202 | MPTCPD_PLUGIN_DEFINE(plugin_four, 203 | "test plugin four", 204 | MPTCPD_PLUGIN_PRIORITY_LOW, // Unfavorable priority. 205 | plugin_four_init, 206 | plugin_four_exit) 207 | 208 | 209 | /* 210 | Local Variables: 211 | c-file-style: "linux" 212 | End: 213 | */ 214 | -------------------------------------------------------------------------------- /tests/plugins/security/three.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: BSD-3-Clause 2 | /** 3 | * @file three.c 4 | * 5 | * @brief MPTCP test plugin. 6 | * 7 | * Copyright (c) 2019-2022, Intel Corporation 8 | */ 9 | 10 | #include 11 | 12 | #ifdef HAVE_CONFIG_H 13 | # include 14 | #endif 15 | 16 | #include 17 | 18 | #include "test-plugin.h" 19 | 20 | #undef NDEBUG 21 | #include 22 | 23 | 24 | // ---------------------------------------------------------------- 25 | 26 | static struct plugin_call_count call_count; 27 | 28 | // ---------------------------------------------------------------- 29 | 30 | static void plugin_three_new_connection(mptcpd_token_t token, 31 | struct sockaddr const *laddr, 32 | struct sockaddr const *raddr, 33 | bool server_side, 34 | bool deny_join_id0, 35 | struct mptcpd_pm *pm) 36 | { 37 | (void) token; 38 | (void) laddr; 39 | (void) raddr; 40 | (void) server_side; 41 | (void) deny_join_id0; 42 | (void) pm; 43 | 44 | ++call_count.new_connection; 45 | } 46 | 47 | static void plugin_three_connection_established( 48 | mptcpd_token_t token, 49 | struct sockaddr const *laddr, 50 | struct sockaddr const *raddr, 51 | bool server_side, 52 | bool deny_join_id0, 53 | struct mptcpd_pm *pm) 54 | { 55 | (void) token; 56 | (void) laddr; 57 | (void) raddr; 58 | (void) server_side; 59 | (void) deny_join_id0; 60 | (void) pm; 61 | 62 | ++call_count.connection_established; 63 | } 64 | 65 | static void plugin_three_connection_closed(mptcpd_token_t token, 66 | struct mptcpd_pm *pm) 67 | { 68 | (void) token; 69 | (void) pm; 70 | 71 | ++call_count.connection_closed; 72 | } 73 | 74 | static void plugin_three_new_address(mptcpd_token_t token, 75 | mptcpd_aid_t addr_id, 76 | struct sockaddr const *addr, 77 | struct mptcpd_pm *pm) 78 | { 79 | (void) token; 80 | (void) addr_id; 81 | (void) addr; 82 | (void) pm; 83 | 84 | ++call_count.new_address; 85 | } 86 | 87 | static void plugin_three_address_removed(mptcpd_token_t token, 88 | mptcpd_aid_t addr_id, 89 | struct mptcpd_pm *pm) 90 | { 91 | (void) token; 92 | (void) addr_id; 93 | (void) pm; 94 | 95 | ++call_count.address_removed; 96 | } 97 | 98 | static void plugin_three_new_subflow(mptcpd_token_t token, 99 | struct sockaddr const *laddr, 100 | struct sockaddr const *raddr, 101 | bool backup, 102 | struct mptcpd_pm *pm) 103 | { 104 | (void) token; 105 | (void) laddr; 106 | (void) raddr; 107 | (void) backup; 108 | (void) pm; 109 | 110 | ++call_count.new_subflow; 111 | } 112 | 113 | static void plugin_three_subflow_closed(mptcpd_token_t token, 114 | struct sockaddr const *laddr, 115 | struct sockaddr const *raddr, 116 | bool backup, 117 | uint8_t error, 118 | struct mptcpd_pm *pm) 119 | { 120 | (void) token; 121 | (void) laddr; 122 | (void) raddr; 123 | (void) backup; 124 | (void) error; 125 | (void) pm; 126 | 127 | ++call_count.subflow_closed; 128 | } 129 | 130 | static void plugin_three_subflow_priority(mptcpd_token_t token, 131 | struct sockaddr const *laddr, 132 | struct sockaddr const *raddr, 133 | bool backup, 134 | struct mptcpd_pm *pm) 135 | { 136 | (void) token; 137 | (void) laddr; 138 | (void) raddr; 139 | (void) backup; 140 | (void) pm; 141 | 142 | ++call_count.subflow_priority; 143 | } 144 | 145 | static void plugin_three_listener_created(struct sockaddr const *laddr, 146 | struct mptcpd_pm *pm) 147 | { 148 | (void) laddr; 149 | (void) pm; 150 | 151 | ++call_count.listener_created; 152 | } 153 | 154 | static void plugin_three_listener_closed(struct sockaddr const *laddr, 155 | struct mptcpd_pm *pm) 156 | { 157 | (void) laddr; 158 | (void) pm; 159 | 160 | ++call_count.listener_closed; 161 | } 162 | 163 | static struct mptcpd_plugin_ops const pm_ops = { 164 | .new_connection = plugin_three_new_connection, 165 | .connection_established = plugin_three_connection_established, 166 | .connection_closed = plugin_three_connection_closed, 167 | .new_address = plugin_three_new_address, 168 | .address_removed = plugin_three_address_removed, 169 | .new_subflow = plugin_three_new_subflow, 170 | .subflow_closed = plugin_three_subflow_closed, 171 | .subflow_priority = plugin_three_subflow_priority, 172 | .listener_created = plugin_three_listener_created, 173 | .listener_closed = plugin_three_listener_closed, 174 | }; 175 | 176 | static int plugin_three_init(struct mptcpd_pm *pm) 177 | { 178 | (void) pm; 179 | 180 | static char const name[] = TEST_PLUGIN; 181 | 182 | if (!mptcpd_plugin_register_ops(name, &pm_ops)) { 183 | l_error("Failed to initialize test " 184 | "plugin \"" TEST_PLUGIN "\"."); 185 | 186 | return -1; 187 | } 188 | 189 | return 0; 190 | } 191 | 192 | static void plugin_three_exit(struct mptcpd_pm *pm) 193 | { 194 | (void) pm; 195 | 196 | struct plugin_call_count const count = { .new_connection = 0 }; 197 | 198 | assert(call_count_is_sane(&call_count)); 199 | assert(call_count_is_equal(&call_count, &count)); 200 | 201 | call_count_reset(&call_count); 202 | } 203 | 204 | MPTCPD_PLUGIN_DEFINE(plugin_three, 205 | "test plugin three", 206 | MPTCPD_PLUGIN_PRIORITY_DEFAULT, // Between the 207 | // other plugins. 208 | plugin_three_init, 209 | plugin_three_exit) 210 | 211 | 212 | /* 213 | Local Variables: 214 | c-file-style: "linux" 215 | End: 216 | */ 217 | --------------------------------------------------------------------------------