1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter-feeds.git synced 2025-02-15 03:51:51 +00:00
This commit is contained in:
suyuan 2025-01-31 20:13:46 +08:00 committed by GitHub
commit 08d0788034
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
30 changed files with 702 additions and 853 deletions

View file

@ -120,7 +120,7 @@ build() {
if [ "$GO_GO_GENERATE" = 1 ]; then
log "Calling go generate"
# shellcheck disable=SC2086
GOOS='' GOARCH='' GO386='' GOARM='' GOMIPS='' GOMIPS64='' \
GOOS='' GOARCH='' GO386='' GOARM='' GOARM64='' GOMIPS='' GOMIPS64='' GORISCV64=''\
go generate -v $targets
log
fi

View file

@ -19,14 +19,11 @@ define GoCompiler/Default/CheckHost
endef
# $(1) source go root
# $(2) destination prefix
# $(3) go version id
# $(4) additional environment variables (optional)
# $(2) additional environment variables (optional)
define GoCompiler/Default/Make
( \
cd "$(1)/src" ; \
$(if $(2),GOROOT_FINAL="$(2)/lib/go-$(3)") \
$(4) \
$(2) \
$(BASH) make.bash \
$(if $(findstring s,$(OPENWRT_VERBOSE)),-v) \
--no-banner \
@ -156,7 +153,7 @@ define GoCompiler/AddProfile
# $$(1) additional environment variables (optional)
define GoCompiler/$(1)/Make
$$(call GoCompiler/Default/Make,$(2),$(3),$(4),$$(1))
$$(call GoCompiler/Default/Make,$(2),$$(1))
endef
# $$(1) override install prefix (optional)

View file

@ -59,11 +59,13 @@ unexport \
# Architecture-specific environment variables:
unexport \
GOARM \
GOARM64 \
GO386 \
GOAMD64 \
GOMIPS \
GOMIPS64 \
GOPPC64 \
GORISCV64 \
GOWASM
# Environment variables for use with code coverage:

View file

@ -7,8 +7,8 @@
include $(TOPDIR)/rules.mk
GO_VERSION_MAJOR_MINOR:=1.22
GO_VERSION_PATCH:=0
GO_VERSION_MAJOR_MINOR:=1.23
GO_VERSION_PATCH:=4
PKG_NAME:=golang
PKG_VERSION:=$(GO_VERSION_MAJOR_MINOR)$(if $(GO_VERSION_PATCH),.$(GO_VERSION_PATCH))
@ -20,7 +20,7 @@ GO_SOURCE_URLS:=https://dl.google.com/go/ \
PKG_SOURCE:=go$(PKG_VERSION).src.tar.gz
PKG_SOURCE_URL:=$(GO_SOURCE_URLS)
PKG_HASH:=4d196c3d41a0d6c1dfc64d04e3cc1f608b0c436bd87b7060ce3e23234e1f4d5c
PKG_HASH:=ad345ac421e90814293a9699cca19dd5238251c3f687980bbcae28495b263531
PKG_MAINTAINER:=Jeffery To <jeffery.to@gmail.com>
PKG_LICENSE:=BSD-3-Clause
@ -34,7 +34,6 @@ PKG_BUILD_FLAGS:=no-mips16
PKG_GO_PREFIX:=/usr
PKG_GO_VERSION_ID:=$(GO_VERSION_MAJOR_MINOR)
PKG_GO_ROOT:=$(PKG_GO_PREFIX)/lib/go-$(PKG_GO_VERSION_ID)
HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/go-$(PKG_VERSION)
HOST_BUILD_PARALLEL:=1
@ -65,6 +64,7 @@ HOST_GO_VALID_OS_ARCH:= \
wasip1_wasm \
\
freebsd_riscv64 \
openbsd_riscv64 \
\
linux_ppc64 linux_ppc64le \
linux_mips linux_mipsle linux_mips64 linux_mips64le \
@ -394,7 +394,6 @@ define Build/Compile
cd "$(PKG_BUILD_DIR)/bin" ; \
export $(GO_PKG_TARGET_VARS) ; \
$(CP) go go-host ; \
GOROOT_FINAL="$(PKG_GO_ROOT)" \
GO_GCC_HELPER_CC="$(TARGET_CC)" \
GO_GCC_HELPER_CXX="$(TARGET_CXX)" \
$(PKG_GO_VARS) \

View file

@ -8,15 +8,16 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=iperf
PKG_VERSION:=3.17.1
PKG_VERSION:=3.18
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://github.com/esnet/iperf/archive/refs/tags/
PKG_HASH:=105b4fe7fbce31c9b94a3fec10c46e3b4b298adc076e1e3af52b990e1faf2db9
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://downloads.es.net/pub/iperf
PKG_HASH:=c0618175514331e766522500e20c94bfb293b4424eb27d7207fb427b88d20bab
PKG_MAINTAINER:=Yannick Chabanois <ycarus@zugaina.org>
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
PKG_LICENSE:=BSD-3-Clause
PKG_CPE_ID:=cpe:/a:es:iperf3
PKG_BUILD_PARALLEL:=1
PKG_INSTALL:=1
@ -37,24 +38,36 @@ endef
define Package/iperf3
$(call Package/iperf3/default)
VARIANT:=nossl
DEPENDS:=+libiperf3
endef
define Package/iperf3-ssl
$(call Package/iperf3/default)
TITLE+= with iperf_auth support
VARIANT:=ssl
DEPENDS:= +libopenssl
DEPENDS:=+libopenssl +libatomic
CONFLICTS:=iperf3
endef
define Package/libiperf3
SECTION:=libs
CATEGORY:=Libraries
TITLE:=Internet Protocol bandwidth measuring library
URL:=https://github.com/esnet/iperf
DEPENDS+=+libatomic
endef
TARGET_CFLAGS += -D_GNU_SOURCE
CONFIGURE_ARGS += --disable-shared
TARGET_LDFLAGS += -latomic
ifeq ($(BUILD_VARIANT),ssl)
CONFIGURE_ARGS += --with-openssl="$(STAGING_DIR)/usr"
CONFIGURE_ARGS += --with-openssl="$(STAGING_DIR)/usr" --disable-shared
else
CONFIGURE_ARGS += --without-openssl
endif
CONFIGURE_ARGS += --without-sctp
MAKE_FLAGS += noinst_PROGRAMS=
define Package/iperf3/description
@ -63,6 +76,17 @@ define Package/iperf3/description
characteristics.
endef
define Package/libiperf3/description
Libiperf is a library providing an API for iperf3 functionality.
endef
define Build/InstallDev
$(INSTALL_DIR) $(1)/usr/lib
$(INSTALL_DIR) $(1)/usr/include
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libiperf.* $(1)/usr/lib/
$(CP) $(PKG_INSTALL_DIR)/usr/include/* $(1)/usr/include/
endef
# autoreconf fails if the README file isn't present
define Build/Prepare
$(call Build/Prepare/Default)
@ -79,5 +103,11 @@ define Package/iperf3-ssl/install
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/iperf3 $(1)/usr/bin/
endef
define Package/libiperf3/install
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libiperf.so.* $(1)/usr/lib
endef
$(eval $(call BuildPackage,iperf3))
$(eval $(call BuildPackage,iperf3-ssl))
$(eval $(call BuildPackage,libiperf3))

View file

@ -0,0 +1,21 @@
From fe09305eb6f907e4eb637b8edd0c8a986187d1dd Mon Sep 17 00:00:00 2001
From: Rosen Penev <rosenp@gmail.com>
Date: Sat, 8 Jun 2024 15:23:51 -0700
Subject: [PATCH] fix crash under big endian musl
iperf_printf is using an int format here but an int64_t variable. The format only needs the first 3 digits. Cast to int to fix it.
---
src/iperf_api.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/src/iperf_api.c
+++ b/src/iperf_api.c
@@ -4137,7 +4137,7 @@ iperf_print_results(struct iperf_test *t
iperf_printf(test, report_sender_not_available_summary_format, "SUM");
}
else {
- iperf_printf(test, report_sum_bw_retrans_format, mbuf, start_time, sender_time, ubuf, nbuf, total_retransmits, report_sender);
+ iperf_printf(test, report_sum_bw_retrans_format, mbuf, start_time, sender_time, ubuf, nbuf, (int)total_retransmits, report_sender);
}
} else {
/* Summary sum, TCP without retransmits. */

View file

@ -1,4 +1,4 @@
From 5f71968be8e8809e4e7b876ff04b4ef3f22eb141 Mon Sep 17 00:00:00 2001
From cf75cf46785871330717a6d2c889abeb7bbd7bfd Mon Sep 17 00:00:00 2001
From: Geliang Tang <geliang@kernel.org>
Date: Wed, 6 Mar 2024 11:23:33 +0800
Subject: [PATCH] add MPTCPv1 support
@ -17,10 +17,6 @@ be used like this:
> iperf3 -m -s
> iperf3 -m -c 127.0.0.1
There is no need to check for IPPROTO_MPTCP support in configure.ac
at build time, it is at runtime we will see if the kernel being use
supports or not MPTCP.
If IPPROTO_MPTCP is not supported by the kernel being tested, it is
normal to fail because the feature is not available and the user
explicitly asked to use MPTCP.
@ -29,20 +25,44 @@ Closes: https://github.com/esnet/iperf/pull/1659
Co-developed-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Geliang Tang <geliang@kernel.org>
---
configure.ac | 12 ++++++++++++
src/iperf.h | 1 +
src/iperf3.1 | 4 ++++
src/iperf_api.c | 19 ++++++++++++++++++-
src/iperf_locale.c | 3 +++
src/iperf_tcp.c | 22 +++++++++++++++++++---
src/iperf_tcp.c | 18 +++++++++++++++---
src/net.c | 10 +++++-----
src/net.h | 2 +-
7 files changed, 51 insertions(+), 10 deletions(-)
8 files changed, 59 insertions(+), 10 deletions(-)
diff --git a/configure.ac b/configure.ac
index 66c1e97a5..22c2a95cf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -337,6 +337,18 @@ if test "x$iperf3_cv_header_tcp_info_snd_wnd" = "xyes"; then
AC_DEFINE([HAVE_TCP_INFO_SND_WND], [1], [Have tcpi_snd_wnd field in tcp_info.])
fi
+# Check for IPPROTO_MPTCP (Linux)
+AC_CACHE_CHECK([MPTCP protocol],
+[iperf3_cv_header_ipproto_mptcp],
+AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[#include <netinet/in.h>]],
+ [[int foo = IPPROTO_MPTCP;]])],
+ iperf3_cv_header_ipproto_mptcp=yes,
+ iperf3_cv_header_ipproto_mptcp=no))
+if test "x$iperf3_cv_header_ipproto_mptcp" = "xyes"; then
+ AC_DEFINE([HAVE_IPPROTO_MPTCP], [1], [Have MPTCP protocol.])
+fi
+
# Check if we need -lrt for clock_gettime
AC_SEARCH_LIBS(clock_gettime, [rt posix4])
# Check for clock_gettime support
diff --git a/src/iperf.h b/src/iperf.h
index dc3c0d1df..cb821e1f7 100644
index 202d3016f..4043031b3 100644
--- a/src/iperf.h
+++ b/src/iperf.h
@@ -342,6 +342,7 @@ struct iperf_test
@@ -353,6 +353,7 @@ struct iperf_test
int repeating_payload; /* --repeating-payload */
int timestamps; /* --timestamps */
char *timestamp_format;
@ -51,12 +71,12 @@ index dc3c0d1df..cb821e1f7 100644
char *json_output_string; /* rendered JSON output if json_output is set */
/* Select related parameters */
diff --git a/src/iperf3.1 b/src/iperf3.1
index 2efd53dea..ebc603408 100644
index f8eff48d2..9e425cabc 100644
--- a/src/iperf3.1
+++ b/src/iperf3.1
@@ -193,6 +193,10 @@ parameter is specified in ms, and defaults to the system settings.
This functionality depends on the TCP_USER_TIMEOUT socket option, and
will not work on systems that do not support it.
@@ -202,6 +202,10 @@ iperf-3.17, OAEP padding is used, however this is a breaking change
that is not compatible with older iperf3 versions. Use this option to
preserve the less secure, but more compatible, behavior.
.TP
+.BR -m ", " --mptcp " "
+use mptcp variant for the current protocol. This only applies to
@ -66,33 +86,33 @@ index 2efd53dea..ebc603408 100644
emit debugging output.
Primarily (perhaps exclusively) of use to developers.
diff --git a/src/iperf_api.c b/src/iperf_api.c
index 1dcfaabf5..f7f1fbfb8 100644
index fa06dc830..419b48657 100644
--- a/src/iperf_api.c
+++ b/src/iperf_api.c
@@ -1144,6 +1144,9 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
@@ -1149,6 +1149,9 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
{"idle-timeout", required_argument, NULL, OPT_IDLE_TIMEOUT},
{"rcv-timeout", required_argument, NULL, OPT_RCV_TIMEOUT},
{"snd-timeout", required_argument, NULL, OPT_SND_TIMEOUT},
+#if defined(linux)
+#if defined(HAVE_IPPROTO_MPTCP)
+ {"mptcp", no_argument, NULL, 'm'},
+#endif
{"debug", optional_argument, NULL, 'd'},
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}
@@ -1169,7 +1172,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
@@ -1174,7 +1177,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
FILE *ptr_file;
#endif /* HAVE_SSL */
- while ((flag = getopt_long(argc, argv, "p:f:i:D1VJvsc:ub:t:n:k:l:P:Rw:B:M:N46S:L:ZO:F:A:T:C:dI:hX:", longopts, NULL)) != -1) {
+ while ((flag = getopt_long(argc, argv, "p:f:i:D1VJvsc:ub:t:n:k:l:P:Rw:B:mM:N46S:L:ZO:F:A:T:C:dI:hX:", longopts, NULL)) != -1) {
+ while ((flag = getopt_long(argc, argv, "p:f:i:D1VJvsc:ub:t:n:k:l:P:Rw:B:M:N46S:L:ZO:F:A:T:C:dI:mhX:", longopts, NULL)) != -1) {
switch (flag) {
case 'p':
portno = atoi(optarg);
@@ -1639,6 +1642,12 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
@@ -1647,6 +1650,12 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
test->settings->connect_timeout = unit_atoi(optarg);
client_flag = 1;
break;
+#if defined(linux)
+#if defined(HAVE_IPPROTO_MPTCP)
+ case 'm':
+ set_protocol(test, Ptcp);
+ test->mptcp = 1;
@ -101,58 +121,47 @@ index 1dcfaabf5..f7f1fbfb8 100644
case 'h':
usage_long(stdout);
exit(0);
@@ -2216,6 +2225,10 @@ send_parameters(struct iperf_test *test)
@@ -2259,6 +2268,10 @@ send_parameters(struct iperf_test *test)
cJSON_AddTrueToObject(j, "reverse");
if (test->bidirectional)
cJSON_AddTrueToObject(j, "bidirectional");
+#if defined(linux)
+#if defined(HAVE_IPPROTO_MPTCP)
+ if (test->mptcp)
+ cJSON_AddTrueToObject(j, "mptcp");
+#endif
if (test->settings->socket_bufsize)
cJSON_AddNumberToObject(j, "window", test->settings->socket_bufsize);
if (test->settings->blksize)
@@ -2332,6 +2345,10 @@ get_parameters(struct iperf_test *test)
@@ -2375,6 +2388,10 @@ get_parameters(struct iperf_test *test)
iperf_set_test_reverse(test, 1);
if ((j_p = cJSON_GetObjectItem(j, "bidirectional")) != NULL)
if ((j_p = iperf_cJSON_GetObjectItemType(j, "bidirectional", cJSON_True)) != NULL)
iperf_set_test_bidirectional(test, 1);
+#if defined(linux)
+ if ((j_p = cJSON_GetObjectItem(j, "mptcp")) != NULL)
+#if defined(HAVE_IPPROTO_MPTCP)
+ if ((j_p = iperf_cJSON_GetObjectItemType(j, "mptcp", cJSON_True)) != NULL)
+ test->mptcp = 1;
+#endif
if ((j_p = cJSON_GetObjectItem(j, "window")) != NULL)
if ((j_p = iperf_cJSON_GetObjectItemType(j, "window", cJSON_Number)) != NULL)
test->settings->socket_bufsize = j_p->valueint;
if ((j_p = cJSON_GetObjectItem(j, "len")) != NULL)
if ((j_p = iperf_cJSON_GetObjectItemType(j, "len", cJSON_Number)) != NULL)
diff --git a/src/iperf_locale.c b/src/iperf_locale.c
index ae0f63a41..d454af4f0 100644
index 32883da84..f1d89e298 100644
--- a/src/iperf_locale.c
+++ b/src/iperf_locale.c
@@ -128,6 +128,9 @@ const char usage_longstr[] = "Usage: iperf3 [-s|-c host] [options]\n"
" --snd-timeout # timeout for unacknowledged TCP data\n"
" (in ms, default is system settings)\n"
#endif /* HAVE_TCP_USER_TIMEOUT */
+#if defined(linux)
+#if defined(HAVE_IPPROTO_MPTCP)
+ " -m, --mptcp use MPTCP rather than plain TCP\n"
+#endif
" -d, --debug[=#] emit debugging output\n"
" (optional optional \"=\" and debug level: 1-4. Default is 4 - all messages)\n"
" -v, --version show version information and quit\n"
diff --git a/src/iperf_tcp.c b/src/iperf_tcp.c
index 184a1955e..a10322b75 100644
index 481c09dc8..2c10d7df5 100644
--- a/src/iperf_tcp.c
+++ b/src/iperf_tcp.c
@@ -44,6 +44,10 @@
#include "net.h"
#include "cjson.h"
+#ifndef IPPROTO_MPTCP
+#define IPPROTO_MPTCP 262
+#endif
+
#if defined(HAVE_FLOWLABEL)
#include "flowlabel.h"
#endif /* HAVE_FLOWLABEL */
@@ -182,9 +186,10 @@ iperf_tcp_listen(struct iperf_test *test)
@@ -184,9 +184,10 @@ iperf_tcp_listen(struct iperf_test *test)
*
* It's not clear whether this is a requirement or a convenience.
*/
@ -164,12 +173,12 @@ index 184a1955e..a10322b75 100644
FD_CLR(s, &test->read_set);
close(s);
@@ -210,7 +215,12 @@ iperf_tcp_listen(struct iperf_test *test)
@@ -212,7 +213,12 @@ iperf_tcp_listen(struct iperf_test *test)
return -1;
}
- if ((s = socket(res->ai_family, SOCK_STREAM, 0)) < 0) {
+#if defined(linux)
+#if defined(HAVE_IPPROTO_MPTCP)
+ if (test->mptcp)
+ proto = IPPROTO_MPTCP;
+#endif
@ -178,13 +187,13 @@ index 184a1955e..a10322b75 100644
freeaddrinfo(res);
i_errno = IESTREAMLISTEN;
return -1;
@@ -375,8 +385,14 @@ iperf_tcp_connect(struct iperf_test *test)
@@ -380,8 +386,14 @@ iperf_tcp_connect(struct iperf_test *test)
socklen_t optlen;
int saved_errno;
int rcvbuf_actual, sndbuf_actual;
+ int proto = 0;
+
+#if defined(linux)
+#if defined(HAVE_IPPROTO_MPTCP)
+ if (test->mptcp)
+ proto = IPPROTO_MPTCP;
+#endif
@ -195,7 +204,7 @@ index 184a1955e..a10322b75 100644
i_errno = IESTREAMCONNECT;
return -1;
diff --git a/src/net.c b/src/net.c
index c82caff1b..849e919f2 100644
index b693ea7fb..febf20885 100644
--- a/src/net.c
+++ b/src/net.c
@@ -124,7 +124,7 @@ timeout_connect(int s, const struct sockaddr *name, socklen_t namelen,
@ -243,7 +252,7 @@ index c82caff1b..849e919f2 100644
return -1;
}
diff --git a/src/net.h b/src/net.h
index f0e1b4f98..1f5cc4d34 100644
index 859c52cef..fb78d289b 100644
--- a/src/net.h
+++ b/src/net.h
@@ -28,7 +28,7 @@

View file

@ -0,0 +1,552 @@
From 197d8ba733f0502985abb5b0a22bf9f71c2596a7 Mon Sep 17 00:00:00 2001
From: David Bar-On <david.cdb004@gmail.com>
Date: Mon, 25 Mar 2024 22:11:49 +0200
Subject: [PATCH] Add SOCKS5 Proxy support for TCP
---
src/iperf.h | 8 ++
src/iperf_api.c | 250 ++++++++++++++++++++++++++++++++++++++++-
src/iperf_api.h | 13 ++-
src/iperf_client_api.c | 27 ++++-
src/iperf_error.c | 10 ++
src/iperf_locale.c | 2 +
src/iperf_tcp.c | 22 +++-
7 files changed, 323 insertions(+), 9 deletions(-)
diff --git a/src/iperf.h b/src/iperf.h
index dc3c0d1df..9823dc180 100644
--- a/src/iperf.h
+++ b/src/iperf.h
@@ -343,6 +343,14 @@ struct iperf_test
int timestamps; /* --timestamps */
char *timestamp_format;
+ char *socks5_host; /* --socks5 option */
+ uint16_t socks5_port; /* --socks5 option optional value */
+ char *socks5_username; /* --socks5 option optional value */
+ char *socks5_password; /* --socks5 option optional value */
+ char socks5_bind_atyp; /* from socks5 CONNECT response ATYP */
+ char *socks5_bind_host; /* from socks5 CONNECT response BIND.ADDR*/
+ uint16_t socks5_bind_port; /* from socks5 CONNECT response BIND.PORT */
+
char *json_output_string; /* rendered JSON output if json_output is set */
/* Select related parameters */
int max_fd;
diff --git a/src/iperf_api.c b/src/iperf_api.c
index 4765d4e97..ca47f708d 100644
--- a/src/iperf_api.c
+++ b/src/iperf_api.c
@@ -115,7 +115,7 @@ usage()
void
usage_long(FILE *f)
{
- fprintf(f, usage_longstr, DEFAULT_NO_MSG_RCVD_TIMEOUT, UDP_RATE / (1024*1024), DEFAULT_PACING_TIMER, DURATION, DEFAULT_TCP_BLKSIZE / 1024, DEFAULT_UDP_BLKSIZE);
+ fprintf(f, usage_longstr, DEFAULT_NO_MSG_RCVD_TIMEOUT, UDP_RATE / (1024*1024), DEFAULT_PACING_TIMER, DURATION, DEFAULT_TCP_BLKSIZE / 1024, DEFAULT_UDP_BLKSIZE, SOCKS5_DEFAULT_PORT);
}
@@ -1100,6 +1100,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
{"version6", no_argument, NULL, '6'},
{"tos", required_argument, NULL, 'S'},
{"dscp", required_argument, NULL, OPT_DSCP},
+ {"socks5", required_argument, NULL, OPT_SOCKS5},
{"extra-data", required_argument, NULL, OPT_EXTRA_DATA},
#if defined(HAVE_FLOWLABEL)
{"flowlabel", required_argument, NULL, 'L'},
@@ -1157,7 +1158,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
char* comma;
#endif /* HAVE_CPU_AFFINITY */
char* slash;
- char *p, *p1;
+ char *p, *p1, *p2;
struct xbind_entry *xbe;
double farg;
int rcv_timeout_in = 0;
@@ -1433,6 +1434,47 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
}
client_flag = 1;
break;
+ case OPT_SOCKS5: // Format: "[username:password@]<host addr/fqdn>[:port]"
+ if (strlen(optarg) <= 0) {
+ i_errno = IESOCKS5HOST;
+ return -1;
+ }
+ p1 = strtok(optarg, "@"); // p1 -> user:password
+ if (p1 == NULL) {
+ i_errno = IESOCKS5HOST;
+ return -1;
+ }
+ p = strtok(NULL, "@"); // p -> host[:port]
+ if (p == NULL) {
+ p = p1;
+ p1 = NULL;
+ }
+ p2 = strtok(p, ":"); // parse host[:port]
+ if (strlen(p2) <= 0) {
+ i_errno = IESOCKS5HOST;
+ return -1;
+ }
+ test->socks5_host = strdup(p2);
+ p2 = strtok(NULL, ":");
+ if (p2 && strlen(p2) > 0) {
+ test->socks5_port = atoi(p2);
+ }
+ if (p1) { // parse user:password
+ p2 = strtok(p1, ":");
+ if (strlen(p2) <= 0 || strlen(p2) > 255) {
+ i_errno = IESOCKS5HOST;
+ return -1;
+ }
+ test->socks5_username = strdup(p2);
+ p2 = strtok(NULL, ":");
+ if (!p2 || strlen(p2) <= 0 || strlen(p2) > 255) {
+ i_errno = IESOCKS5HOST;
+ return -1;
+ }
+ test->socks5_password = strdup(p2);
+ }
+ client_flag = 1;
+ break;
case OPT_EXTRA_DATA:
test->extra_data = strdup(optarg);
client_flag = 1;
@@ -1740,6 +1782,12 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
return -1;
}
+ // SOCKS5 Proxy is supported only for TCP
+ if(test->role == 'c' && test->socks5_host && test->protocol->id != Ptcp) {
+ i_errno = IESOCKS5RTCPONLY;
+ return -1;
+ }
+
if (blksize == 0) {
if (test->protocol->id == Pudp)
blksize = 0; /* try to dynamically determine from MSS */
@@ -2943,6 +2991,12 @@ iperf_defaults(struct iperf_test *testp)
testp->stats_interval = testp->reporter_interval = 1;
testp->num_streams = 1;
+ testp->socks5_host = NULL;
+ testp->socks5_port = SOCKS5_DEFAULT_PORT;
+ testp->socks5_username = NULL;
+ testp->socks5_password = NULL;
+ testp->socks5_bind_host = NULL;
+
testp->settings->domain = AF_UNSPEC;
testp->settings->unit_format = 'a';
testp->settings->socket_bufsize = 0; /* use autotuning */
@@ -3100,6 +3154,14 @@ iperf_free_test(struct iperf_test *test)
free(test->remote_congestion_used);
if (test->timestamp_format)
free(test->timestamp_format);
+ if (test->socks5_host)
+ free(test->socks5_host);
+ if (test->socks5_username)
+ free(test->socks5_username);
+ if (test->socks5_password)
+ free(test->socks5_password);
+ if (test->socks5_bind_host)
+ free(test->socks5_bind_host);
if (test->omit_timer != NULL)
tmr_cancel(test->omit_timer);
if (test->timer != NULL)
@@ -3289,6 +3351,23 @@ iperf_reset_test(struct iperf_test *test)
free(test->extra_data);
test->extra_data = NULL;
}
+ if (test->socks5_host) {
+ free(test->socks5_host);
+ test->socks5_host = NULL;
+ }
+ test->socks5_port = SOCKS5_DEFAULT_PORT;
+ if (test->socks5_username) {
+ free(test->socks5_username);
+ test->socks5_username = NULL;
+ }
+ if (test->socks5_password) {
+ free(test->socks5_password);
+ test->socks5_password = NULL;
+ }
+ if (test->socks5_bind_host) {
+ free(test->socks5_bind_host);
+ test->socks5_bind_host = NULL;
+ }
/* Free output line buffers, if any (on the server only) */
struct iperf_textline *t;
@@ -4614,6 +4693,173 @@ iperf_add_stream(struct iperf_test *test, struct iperf_stream *sp)
}
}
+/**************************************************************************/
+
+/* iperf_socks5_handshake
+ *
+ * Handshake with a SOCKS5 Proxy per RFC1928, RFC1929
+ */
+int
+iperf_socks5_handshake(struct iperf_test *test, int s) {
+ char req[1024];
+ char res[1024];
+ char selected_mthod;
+ char *p, *p1;
+ size_t len;
+ int ret;
+ uint16_t net_order_short;
+
+ // Send method selection request [RFC1928]
+ p = req;
+ *p++ = 5; // VERSION
+ if (test->socks5_username) // Number of METHODs supported
+ *p++ = 2;
+ else
+ *p++ = 1;
+ *p++ = 0; // NO AUTHENTICATION REQUIRED
+ if (test->socks5_username) *p++ = 2; // USERNAME/PASSWORD
+ if (Nwrite(s, req, p - req, Ptcp) < 0) {
+ i_errno = IESOCKS5HANDSHAKE;
+ iperf_err(test, "Writing SOCKS5 auth methods message failed\n");
+ return -1;
+ }
+
+ // Receive selected method
+ if (Nread(s, res, 2, Ptcp) != 2) {
+ i_errno = IESOCKS5HANDSHAKE;
+ iperf_err(test, "Reading selected SOCKS5 method message failed\n");
+ return -1;
+ }
+
+ selected_mthod = res[1];
+ if (res[0] != 5 || (selected_mthod != 0 && selected_mthod != 2)) {
+ i_errno = IESOCKS5HANDSHAKE;
+ iperf_err(test, "Ilegal SOCKS5 method selection response: version=%d, auth method=%d\n", res[0], selected_mthod);
+ return -1;
+ }
+ if (test->debug) {
+ iperf_printf(test, "SOCKS5 server selected authentication method %d\n", selected_mthod);
+ }
+
+ // Send Username/Password request and receive the auth response [RFC1929]
+ if (selected_mthod == 2) {
+ p = req;
+ *p++ = 1; // VERSION
+ len = strlen(test->socks5_username);
+ *p++ = len;
+ memcpy(p, test->socks5_username, len); // USERNAME
+ p += len;
+ len = strlen(test->socks5_password);
+ *p++ = len;
+ memcpy(p, test->socks5_password, len); // PASSWORD
+ p += len;
+
+ if (Nwrite(s, req, p - req, Ptcp) < 0) {
+ i_errno = IESOCKS5HANDSHAKE;
+ iperf_err(test, "Writing SOCKS5 Username/Password request message failed\n");
+ return -1;
+ }
+
+ if ((ret = Nread(s, res, 2, Ptcp)) != 2) {
+ i_errno = IESOCKS5HANDSHAKE;
+ iperf_err(test, "Reading SOCKS5 Username/Password response failed; Returned %d\n", ret);
+ return -1;
+ }
+ if (res[1] != 0) {
+ i_errno = IESOCKS5HANDSHAKE;
+ iperf_err(test, "SOCKS5 Username/Password failed with error %d\n", res[1]);
+ return -1;
+ }
+ }
+
+ // Send CONNECT request [RFC1928]
+ p = req;
+ *p++ = 5; // VERSION
+ *p++ = 1; // CMD = CONNECT
+ *p++ = 0; // RESERVED
+ *p++ = 3; // ATYPE = DOMAINNAME:
+ len = strlen(test->server_hostname);
+ if (len > 255) {
+ i_errno = IESOCKS5HANDSHAKE;
+ iperf_err(test, "iperf3 host option length is limited to 255 chars when SOCKS5 is used\n");
+ return -1;
+ }
+ *p++ = len;
+ memcpy(p, test->server_hostname, len); // ADDR
+ p += len;
+ net_order_short = htons(test->server_port);
+ p1 = (char *)&net_order_short;
+ *p++ = *p1++; // PORT
+ *p++ = *p1;
+ if (Nwrite(s, req, p - req, Ptcp) < 0) {
+ i_errno = IESOCKS5HANDSHAKE;
+ iperf_err(test, "Writing SOCKS5 CONNECT message failed\n");
+ return -1;
+ }
+
+ // Read CONNECT response [RFC1928]
+ if ((ret = Nread(s, res, 4, Ptcp)) != 4) {
+ i_errno = IESOCKS5HANDSHAKE;
+ iperf_err(test, "Reading SOCKS5 CONNECT response failed; Returned %d\n", ret);
+ return -1;
+ }
+
+ if (res[0] != 5 || res[1] != 0 || res[2] != 0) {
+ i_errno = IESOCKS5HANDSHAKE;
+ iperf_err(test, "SOCKS5 CONNECT failed with error %d\n", res[1]);
+ return -1;
+ }
+
+ // Get BND.ADDR length
+ test->socks5_bind_atyp = res[3]; // ATYP
+ switch (test->socks5_bind_atyp) {
+ case 1: // IP V4 address
+ len = 4;
+ break;
+ case 3: // DOMAINNAME:
+ if ((ret = read(s, res, 1)) != 1) {
+ i_errno = IESOCKS5HANDSHAKE;
+ iperf_err(test, "Failed to read SOCKS5 CONNECT response BND.ADDR length; Returned %d\n", ret);
+ return -1;
+ }
+ len = (unsigned char)res[0];
+ break;
+ case 4: // IP V6 address
+ len = 16;
+ break;
+ default:
+ i_errno = IESOCKS5HANDSHAKE;
+ iperf_err(test, "Illegal SOCKS5 CONNECT response ATYP %d\n", res[3]);
+ return -1;
+ }
+ // Read BND.ADDR
+ if ((ret = Nread(s, res, len, Ptcp)) != len) {
+ i_errno = IESOCKS5HANDSHAKE;
+ iperf_err(test, "Failed to read SOCKS5 detailes BND.ADDR; Returned %d\n", ret);
+ return -1;
+ }
+ res[len] = '\0';
+ test->socks5_bind_host = strdup(res);
+ // Read BND.PORT
+ if ((ret = Nread(s, res, 2, Ptcp)) != 2) {
+ i_errno = IESOCKS5HANDSHAKE;
+ iperf_err(test, "Failed to read SOCKS5 detailes BND.PORT; Returned %d\n", ret);
+ return -1;
+ }
+ p1 = (char *)&net_order_short;
+ *p1++ = res[0];
+ *p1 = res[1];
+ test->socks5_bind_port = ntohs(net_order_short);
+ if (test->debug) {
+ iperf_printf(test, "SOCKS5 server BIND ADDR type=%d, PORT=%d\n", test->socks5_bind_atyp, test->socks5_bind_port);
+ }
+
+ return 0;
+}
+
+/**************************************************************************/
+
+
/* This pair of routines gets inserted into the snd/rcv function pointers
** when there's a -F flag. They handle the file stuff and call the real
** snd/rcv functions, which have been saved in snd2/rcv2.
diff --git a/src/iperf_api.h b/src/iperf_api.h
index d2bbdfe96..01d63bf5e 100644
--- a/src/iperf_api.h
+++ b/src/iperf_api.h
@@ -68,6 +68,7 @@ typedef atomic_uint_fast64_t atomic_iperf_size_t;
#define DEFAULT_PACING_TIMER 1000
#define DEFAULT_NO_MSG_RCVD_TIMEOUT 120000
#define MIN_NO_MSG_RCVD_TIMEOUT 100
+#define SOCKS5_DEFAULT_PORT 1080
#define WARN_STR_LEN 128
@@ -100,7 +101,8 @@ typedef atomic_uint_fast64_t atomic_iperf_size_t;
#define OPT_RCV_TIMEOUT 27
#define OPT_JSON_STREAM 28
#define OPT_SND_TIMEOUT 29
#define OPT_USE_PKCS1_PADDING 30
+#define OPT_SOCKS5 31
/* states */
#define TEST_START 1
@@ -308,6 +310,12 @@ void iperf_free_stream(struct iperf_stream * sp);
*/
int iperf_common_sockopts(struct iperf_test *, int s);
+/**
+ * iperf_socks5_handshake - handshake with a SOCKS5 Proxy per RFC1928, RFC1929
+ *
+ */
+int iperf_socks5_handshake(struct iperf_test *test, int s);
+
int has_tcpinfo(void);
int has_tcpinfo_retransmits(void);
void save_tcpinfo(struct iperf_stream *sp, struct iperf_interval_results *irp);
@@ -419,6 +427,8 @@ enum {
IESNDTIMEOUT = 33, // Illegal message send timeout
IEUDPFILETRANSFER = 34, // Cannot transfer file using UDP
IESERVERAUTHUSERS = 35, // Cannot access authorized users file
+ IESOCKS5HOST = 36, // Illegal SOCKS5 host / creadentials
+ IESOCKS5RTCPONLY = 37, // SOCKS5 Proxy is supported only for TCP
/* Test errors */
IENEWTEST = 100, // Unable to create a new test (check perror)
IEINITTEST = 101, // Test initialization failed (check perror)
@@ -473,8 +483,9 @@ enum {
IEPTHREADCANCEL=151, // Unable to cancel thread (check perror)
IEPTHREADJOIN=152, // Unable to join thread (check perror)
IEPTHREADATTRINIT=153, // Unable to initialize thread attribute (check perror)
IEPTHREADATTRDESTROY=154, // Unable to destroy thread attribute (check perror)
IEPTHREADSIGMASK=155, // Unable to initialize sub thread signal mask (check perror)
+ IESOCKS5HANDSHAKE = 156, // SOCKS5 Handshake with the server failed
/* Stream errors */
IECREATESTREAM = 200, // Unable to create a new stream (check herror/perror)
IEINITSTREAM = 201, // Unable to initialize stream (check herror/perror)
diff --git a/src/iperf_client_api.c b/src/iperf_client_api.c
index 7ad4c939b..670e3521d 100644
--- a/src/iperf_client_api.c
+++ b/src/iperf_client_api.c
@@ -385,6 +385,8 @@ iperf_connect(struct iperf_test *test)
{
int opt;
socklen_t len;
+ const char *connect_server;
+ int connect_port;
if (NULL == test)
{
@@ -397,12 +399,20 @@ iperf_connect(struct iperf_test *test)
make_cookie(test->cookie);
/* Create and connect the control channel */
- if (test->ctrl_sck < 0)
- // Create the control channel using an ephemeral port
- test->ctrl_sck = netdial(test->settings->domain, Ptcp, test->bind_address, test->bind_dev, 0, test->server_hostname, test->server_port, test->settings->connect_timeout);
if (test->ctrl_sck < 0) {
- i_errno = IECONNECT;
- return -1;
+ if (test->socks5_host) {
+ connect_server = test->socks5_host;
+ connect_port = test->socks5_port;
+ } else {
+ connect_server = test->server_hostname;
+ connect_port = test->server_port;
+ }
+ // Create the control channel using an ephemeral port
+ test->ctrl_sck = netdial(test->settings->domain, Ptcp, test->bind_address, test->bind_dev, 0, connect_server, connect_port, test->settings->connect_timeout);
+ if (test->ctrl_sck < 0) {
+ i_errno = IECONNECT;
+ return -1;
+ }
}
// set TCP_NODELAY for lower latency on control messages
@@ -421,6 +431,13 @@ iperf_connect(struct iperf_test *test)
}
#endif /* HAVE_TCP_USER_TIMEOUT */
+ /* socks5 proxy handshake */
+ if (test->socks5_host) {
+ if (0 != iperf_socks5_handshake(test, test->ctrl_sck)) {
+ return -1;
+ }
+ }
+
if (Nwrite(test->ctrl_sck, test->cookie, COOKIE_SIZE, Ptcp) < 0) {
i_errno = IESENDCOOKIE;
return -1;
diff --git a/src/iperf_error.c b/src/iperf_error.c
index 6426554cf..a0bbb6844 100644
--- a/src/iperf_error.c
+++ b/src/iperf_error.c
@@ -216,6 +216,9 @@ iperf_strerror(int int_errno)
case IEUNIMP:
snprintf(errstr, len, "an option you are trying to set is not implemented yet");
break;
+ case IESOCKS5HOST:
+ snprintf(errstr, len, "ilegal SOCKS5 host / creadentials");
+ break;
case IEFILE:
snprintf(errstr, len, "unable to open -F file");
perr = 1;
@@ -375,6 +378,9 @@ iperf_strerror(int int_errno)
case IEUDPFILETRANSFER:
snprintf(errstr, len, "cannot transfer file using UDP");
break;
+ case IESOCKS5RTCPONLY:
+ snprintf(errstr, len, "SOCKS5 Proxy is supported only for TCP");
+ break;
case IERVRSONLYRCVTIMEOUT:
snprintf(errstr, len, "client receive timeout is valid only in receiving mode");
perr = 1;
@@ -507,6 +513,10 @@ iperf_strerror(int int_errno)
snprintf(errstr, len, "unable to destroy thread attributes");
perr = 1;
break;
+ case IESOCKS5HANDSHAKE:
+ snprintf(errstr, len, "socks5 Handshake with the server failed");
+ perr = 1;
+ break;
default:
snprintf(errstr, len, "int_errno=%d", int_errno);
perr = 1;
diff --git a/src/iperf_locale.c b/src/iperf_locale.c
index ae0f63a41..c8b9a71d1 100644
--- a/src/iperf_locale.c
+++ b/src/iperf_locale.c
@@ -194,6 +194,8 @@ const char usage_longstr[] = "Usage: iperf3 [-s|-c host] [options]\n"
" --dscp N or --dscp val set the IP dscp value, either 0-63 or symbolic.\n"
" Numeric values can be specified in decimal,\n"
" octal and hex (see --tos above).\n"
+ " --socks5 [user:password@]<proxy-host>[:port] use SOCKS5 Proxy for TCP connections,\n"
+ " using no auth or user:password. Default Proxy port is %d \n"
#if defined(HAVE_FLOWLABEL)
" -L, --flowlabel N set the IPv6 flow label (only supported on Linux)\n"
#endif /* HAVE_FLOWLABEL */
diff --git a/src/iperf_tcp.c b/src/iperf_tcp.c
index 184a1955e..515913581 100644
--- a/src/iperf_tcp.c
+++ b/src/iperf_tcp.c
@@ -375,14 +375,24 @@ iperf_tcp_connect(struct iperf_test *test)
socklen_t optlen;
int saved_errno;
int rcvbuf_actual, sndbuf_actual;
int proto = 0;
+ const char *connect_server;
+ int connect_port;
#if defined(HAVE_IPPROTO_MPTCP)
if (test->mptcp)
proto = IPPROTO_MPTCP;
#endif
- s = create_socket(test->settings->domain, SOCK_STREAM, proto, test->bind_address, test->bind_dev, test->bind_port, test->server_hostname, test->server_port, &server_res);
+ if (test->socks5_host) {
+ connect_server = test->socks5_host;
+ connect_port = test->socks5_port;
+ } else {
+ connect_server = test->server_hostname;
+ connect_port = test->server_port;
+ }
+
+ s = create_socket(test->settings->domain, SOCK_STREAM, proto, test->bind_address, test->bind_dev, test->bind_port, connect_server, connect_port, &server_res);
if (s < 0) {
i_errno = IESTREAMCONNECT;
return -1;
@@ -571,6 +581,16 @@ iperf_tcp_connect(struct iperf_test *test)
freeaddrinfo(server_res);
+ /* socks5 proxy handshake */
+ if (test->socks5_host) {
+ if (0 != iperf_socks5_handshake(test, s)) {
+ saved_errno = errno;
+ close(s);
+ errno = saved_errno;
+ return -1;
+ }
+ }
+
/* Send cookie for verification */
if (Nwrite(s, test->cookie, COOKIE_SIZE, Ptcp) < 0) {
saved_errno = errno;

View file

@ -3,6 +3,7 @@
# Update the MP-TCP flags without the pached iproute2
#
# Author: Mario Krueger <openwrt at xedp3x.de>
# Ycarus (Yannick Chabanois) for OpenMPTCProuter <contact@openmptcprouter.com>
# Released under GPL 3 or later
if [ -d "/proc/sys/net/mptcp" ]; then
@ -145,6 +146,7 @@ else
if [ -n "$endpoint" ]; then
ID=$(echo "${endpoint}" | sort | grep "dev $DEVICE " | awk '{print $3}')
IFF=$(echo "${endpoint}" | sort | grep -m 1 -E "dev $DEVICE " | awk '{print $4; exit}')
IFF2=$(echo "${endpoint}" | sort | grep -m 1 -E "dev $DEVICE " | awk '{print $5; exit}')
fi
if [ -n "$TYPE" ]; then
#IP=$(ip a show $DEVICE | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p')
@ -196,16 +198,20 @@ else
done
}
for i in $IP; do
ip mptcp endpoint add $i dev $DEVICE backup fullmesh
ip mptcp endpoint add $i dev $DEVICE subflow backup fullmesh
done
exit 0;;
"")
case "$IFF" in
"") echo $DEVICE is deactivated;;
"subflow") echo $DEVICE is in default mode;;
"backup") echo $DEVICE is in backup mode;;
"subflow")
case "$IFF2" in
"backup") echo $DEVICE is in backup mode;;
"fullmesh") echo $DEVICE is in default mode;;
"") echo $DEVICE is in subflow mode;;
esac
;;
"signal") echo $DEVICE is in signal mode;;
"fullmesh") echo $DEVICE is in fullmesh mode;;
*) echo "$DEVICE Unkown state!" && exit 1;;
esac
exit 0;;

View file

@ -1,5 +1,5 @@
#
# Copyright (C) 2020-2024 Ycarus (Yannick Chabanois) <ycarus@zugaina.org> for OpenMPTCProuter project
# Copyright (C) 2020-2025 Ycarus (Yannick Chabanois) <ycarus@zugaina.org> for OpenMPTCProuter project
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=mptcpd
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/multipath-tcp/mptcpd.git
PKG_SOURCE_VERSION:=0c36dbadb56586ad51b7945e3434c87c7f1b16f4
PKG_SOURCE_VERSION:=68fd9a156669ca7029a101f32282706df069cb4f
PKG_VERSION:=0.13
PKG_RELEASE:=1
PKG_MAINTAINER:=Ycarus (Yannick Chabanois) <ycarus@zugaina.org>

View file

@ -1,53 +0,0 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=netifd
PKG_RELEASE:=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=$(PROJECT_GIT)/project/netifd.git
#PKG_SOURCE_DATE:=2023-11-20
#PKG_SOURCE_VERSION:=f3e06e81b347bbdec1c6c71603328b6e442728d4
#PKG_MIRROR_HASH:=f16dd61aede5597fd7b5ee8e7752a916494281bc981b35c16e788ddb7409584a
PKG_SOURCE_DATE:=2023-11-14
PKG_SOURCE_VERSION:=8587c074f1eb2064c42adb0a6aa5073f695ab89d
PKG_MIRROR_HASH:=f5ceb771badd7a23cceb53537299580d4b483e2b3ec5de09b9c3c54692893dd9
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
PKG_LICENSE:=GPL-2.0
PKG_LICENSE_FILES:=
PKG_BUILD_FLAGS:=lto
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk
define Package/netifd
SECTION:=base
CATEGORY:=Base system
# DEPENDS:=+libuci +libnl-tiny +libubus +ubus +ubusd +jshn +libubox +libudebug
DEPENDS:=+libuci +libnl-tiny +libubus +ubus +ubusd +jshn +libubox
TITLE:=OpenWrt Network Interface Configuration Daemon
endef
define Package/netifd/conffiles
/etc/udhcpc.user
/etc/udhcpc.user.d/
endef
TARGET_CFLAGS += \
-I$(STAGING_DIR)/usr/include/libnl-tiny \
-I$(STAGING_DIR)/usr/include
CMAKE_OPTIONS += \
-DLIBNL_LIBS=-lnl-tiny \
-DDEBUG=1
define Package/netifd/install
$(INSTALL_DIR) $(1)/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/netifd $(1)/sbin/
$(CP) ./files/* $(1)/
$(INSTALL_DIR) $(1)/etc/udhcpc.user.d/
$(CP) $(PKG_BUILD_DIR)/scripts/* $(1)/lib/netifd/
endef
$(eval $(call BuildPackage,netifd))

View file

@ -1,6 +0,0 @@
[ ifup = "$ACTION" ] && {
uci_toggle_state network "$INTERFACE" up 1
[ -n "$DEVICE" ] && {
uci_toggle_state network "$INTERFACE" ifname "$DEVICE"
}
}

View file

@ -1,144 +0,0 @@
#!/bin/sh /etc/rc.common
START=20
STOP=90
USE_PROCD=1
init_switch() {
setup_switch() { return 0; }
include /lib/network
setup_switch
}
start_service() {
init_switch
procd_open_instance
procd_set_param command /sbin/netifd
procd_set_param respawn
procd_set_param watch network.interface
[ -e /proc/sys/kernel/core_pattern ] && {
procd_set_param limits core="unlimited"
}
procd_close_instance
}
reload_service() {
local rv=0
init_switch
ubus call network reload || rv=1
/sbin/wifi reload_legacy
return $rv
}
stop_service() {
/sbin/wifi down
ifdown -a
sleep 1
}
validate_atm_bridge_section()
{
uci_validate_section network "atm-bridge" "${1}" \
'unit:uinteger:0' \
'vci:range(32, 65535):35' \
'vpi:range(0, 255):8' \
'atmdev:uinteger:0' \
'encaps:or("llc", "vc"):llc' \
'payload:or("bridged", "routed"):bridged'
}
validate_route_section()
{
uci_validate_section network route "${1}" \
'interface:string' \
'target:cidr4' \
'netmask:netmask4' \
'gateway:ip4addr' \
'metric:uinteger' \
'mtu:uinteger' \
'table:or(range(0,65535),string)'
}
validate_route6_section()
{
uci_validate_section network route6 "${1}" \
'interface:string' \
'target:cidr6' \
'gateway:ip6addr' \
'metric:uinteger' \
'mtu:uinteger' \
'table:or(range(0,65535),string)'
}
validate_rule_section()
{
uci_validate_section network rule "${1}" \
'in:string' \
'out:string' \
'src:cidr4' \
'dest:cidr4' \
'tos:range(0,31)' \
'mark:string' \
'invert:bool' \
'lookup:or(range(0,65535),string)' \
'goto:range(0,65535)' \
'action:or("prohibit", "unreachable", "blackhole", "throw")'
}
validate_rule6_section()
{
uci_validate_section network rule6 "${1}" \
'in:string' \
'out:string' \
'src:cidr6' \
'dest:cidr6' \
'tos:range(0,31)' \
'mark:string' \
'invert:bool' \
'lookup:or(range(0,65535),string)' \
'goto:range(0,65535)' \
'action:or("prohibit", "unreachable", "blackhole", "throw")'
}
validate_switch_section()
{
uci_validate_section network switch "${1}" \
'name:string' \
'enable:bool' \
'enable_vlan:bool' \
'reset:bool' \
'ar8xxx_mib_poll_interval:uinteger' \
'ar8xxx_mib_type:range(0,1)'
}
validate_switch_vlan()
{
uci_validate_section network switch_vlan "${1}" \
'device:string' \
'vlan:uinteger' \
'ports:list(ports)'
}
service_triggers()
{
procd_add_reload_trigger network wireless
procd_open_validate
validate_atm_bridge_section
validate_route_section
[ -e /proc/sys/net/ipv6 ] && validate_route6_section
validate_rule_section
[ -e /proc/sys/net/ipv6 ] && validate_rule6_section
validate_switch_section
validate_switch_vlan
procd_close_validate
}
shutdown() {
ifdown -a
sleep 1
}

View file

@ -1,18 +0,0 @@
#!/bin/sh /etc/rc.common
START=25
USE_PROCD=1
start_service() {
reload_service
}
service_triggers() {
procd_add_reload_trigger "network"
procd_add_reload_trigger "firewall"
procd_add_raw_trigger "interface.*" 1000 /etc/init.d/packet_steering reload
}
reload_service() {
/usr/libexec/network/packet-steering.sh
}

View file

@ -1,23 +0,0 @@
. /lib/functions.sh
migrate_release() {
local config="$1"
local proto
local release
config_get proto "$config" proto
config_get release "$config" release
[ "$proto" = "dhcp" ] && [ -n "$release" ] && {
norelease="$((!$release))"
uci_set network "$config" norelease "$norelease"
uci_remove network "$config" release
}
}
config_load network
config_foreach migrate_release interface
uci commit network
exit 0

View file

@ -1 +0,0 @@
# This script is sourced by udhcpc's dhcp.script at every DHCP event.

View file

@ -1,122 +0,0 @@
#!/bin/sh
[ -z "$1" ] && echo "Error: should be run by udhcpc" && exit 1
. /lib/functions.sh
. /lib/netifd/netifd-proto.sh
set_classless_routes() {
local max=128
while [ -n "$1" -a -n "$2" -a $max -gt 0 ]; do
proto_add_ipv4_route "${1%%/*}" "${1##*/}" "$2" "$ip"
max=$(($max-1))
shift 2
done
}
setup_interface() {
proto_init_update "*" 1
proto_add_ipv4_address "$ip" "${subnet:-255.255.255.0}"
# TODO: apply $broadcast
local ip_net
local ip_net IP PREFIX NETWORK NETMASK BROADCAST
ipcalc "$ip/$mask" && ip_net="$NETWORK"
local i
for i in $router; do
local gw_net
ipcalc "$i/$mask" && gw_net="$NETWORK"
[ "$ip_net" != "$gw_net" ] && proto_add_ipv4_route "$i" 32 "" "$ip"
#[ "$DEFAULTROUTE" = 0 ] || proto_add_ipv4_route 0.0.0.0 0 "$i" "$ip"
proto_add_ipv4_route 0.0.0.0 0 "$i" "$ip"
local r
for r in $CUSTOMROUTES; do
proto_add_ipv4_route "${r%%/*}" "${r##*/}" "$i" "$ip"
done
done
# CIDR STATIC ROUTES (rfc3442)
[ -n "$staticroutes" ] && set_classless_routes $staticroutes
[ -n "$msstaticroutes" ] && set_classless_routes $msstaticroutes
for i in $dns; do
proto_add_dns_server "$i"
done
for i in $domain; do
proto_add_dns_search "$i"
done
# TODO: Deprecate timesvr in favor of timesrv
if [ -n "$timesvr" -a -z "$timesrv" ]; then
timesrv="$timesvr"
echo "Environment variable 'timesvr' will be deprecated; use 'timesrv' instead."
fi
proto_add_data
[ -n "$ZONE" ] && json_add_string zone "$ZONE"
[ -n "$ntpsrv" ] && json_add_string ntpserver "$ntpsrv"
[ -n "$timesrv" ] && json_add_string timeserver "$timesrv"
[ -n "$hostname" ] && json_add_string hostname "$hostname"
[ -n "$message" ] && json_add_string message "$message"
[ -n "$timezone" ] && json_add_int timezone "$timezone"
[ -n "$lease" ] && json_add_int leasetime "$lease"
[ -n "$serverid" ] && json_add_string dhcpserver "$serverid"
proto_close_data
proto_send_update "$INTERFACE"
if [ "$IFACE6RD" != 0 -a -n "$ip6rd" ]; then
local v4mask="${ip6rd%% *}"
ip6rd="${ip6rd#* }"
local ip6rdprefixlen="${ip6rd%% *}"
ip6rd="${ip6rd#* }"
local ip6rdprefix="${ip6rd%% *}"
ip6rd="${ip6rd#* }"
local ip6rdbr="${ip6rd%% *}"
[ -n "$ZONE" ] || ZONE=$(fw3 -q network $INTERFACE 2>/dev/null)
[ -z "$IFACE6RD" -o "$IFACE6RD" = 1 ] && IFACE6RD=${INTERFACE}_6
json_init
json_add_string name "$IFACE6RD"
json_add_string ifname "@$INTERFACE"
json_add_string proto "6rd"
json_add_string peeraddr "$ip6rdbr"
json_add_int ip4prefixlen "$v4mask"
json_add_string ip6prefix "$ip6rdprefix"
json_add_int ip6prefixlen "$ip6rdprefixlen"
json_add_string tunlink "$INTERFACE"
[ -n "$IFACE6RD_DELEGATE" ] && json_add_boolean delegate "$IFACE6RD_DELEGATE"
[ -n "$ZONE6RD" ] || ZONE6RD=$ZONE
[ -n "$ZONE6RD" ] && json_add_string zone "$ZONE6RD"
[ -n "$MTU6RD" ] && json_add_string mtu "$MTU6RD"
json_close_object
ubus call network add_dynamic "$(json_dump)"
fi
}
deconfig_interface() {
proto_init_update "*" 0
proto_send_update "$INTERFACE"
}
case "$1" in
deconfig)
deconfig_interface
;;
renew|bound)
setup_interface
;;
esac
# user rules
[ -f /etc/udhcpc.user ] && . /etc/udhcpc.user "$@"
for f in /etc/udhcpc.user.d/*; do
[ -f "$f" ] && (. "$f" "$@")
done
exit 0

View file

@ -1,89 +0,0 @@
#!/bin/sh
[ -x /sbin/udhcpc ] || exit 0
. /lib/functions.sh
. ../netifd-proto.sh
init_proto "$@"
proto_dhcp_init_config() {
renew_handler=1
proto_config_add_string 'ipaddr:ipaddr'
proto_config_add_string 'hostname:hostname'
proto_config_add_string clientid
proto_config_add_string vendorid
proto_config_add_boolean 'broadcast:bool'
proto_config_add_boolean 'norelease:bool'
proto_config_add_string 'reqopts:list(string)'
proto_config_add_boolean 'defaultreqopts:bool'
proto_config_add_string iface6rd
proto_config_add_array 'sendopts:list(string)'
proto_config_add_boolean delegate
proto_config_add_string zone6rd
proto_config_add_string zone
proto_config_add_string mtu6rd
proto_config_add_string customroutes
proto_config_add_boolean classlessroute
}
proto_dhcp_add_sendopts() {
[ -n "$1" ] && append "$3" "-x $1"
}
proto_dhcp_setup() {
local config="$1"
local iface="$2"
local ipaddr hostname clientid vendorid broadcast norelease reqopts defaultreqopts iface6rd sendopts delegate zone6rd zone mtu6rd customroutes classlessroute defaultroute
json_get_vars ipaddr hostname clientid vendorid broadcast norelease reqopts defaultreqopts iface6rd delegate zone6rd zone mtu6rd customroutes classlessroute defaultroute
local opt dhcpopts
for opt in $reqopts; do
append dhcpopts "-O $opt"
done
json_for_each_item proto_dhcp_add_sendopts sendopts dhcpopts
[ -z "$hostname" ] && hostname="$(cat /proc/sys/kernel/hostname)"
[ "$hostname" = "*" ] && hostname=
[ "$defaultreqopts" = 0 ] && defaultreqopts="-o" || defaultreqopts=
[ "$broadcast" = 1 ] && broadcast="-B" || broadcast=
[ "$norelease" = 1 ] && norelease="" || norelease="-R"
[ -n "$clientid" ] && clientid="-x 0x3d:${clientid//:/}" || clientid="-C"
[ -n "$iface6rd" ] && proto_export "IFACE6RD=$iface6rd"
[ "$iface6rd" != 0 -a -f /lib/netifd/proto/6rd.sh ] && append dhcpopts "-O 212"
[ -n "$zone6rd" ] && proto_export "ZONE6RD=$zone6rd"
[ -n "$zone" ] && proto_export "ZONE=$zone"
[ -n "$mtu6rd" ] && proto_export "MTU6RD=$mtu6rd"
[ -n "$customroutes" ] && proto_export "CUSTOMROUTES=$customroutes"
[ -n "$defaultroute" ] && proto_export "DEFAULTROUTE=$defaultroute"
[ "$delegate" = "0" ] && proto_export "IFACE6RD_DELEGATE=0"
# Request classless route option (see RFC 3442) by default
[ "$classlessroute" = "0" ] || append dhcpopts "-O 121"
proto_export "INTERFACE=$config"
proto_run_command "$config" udhcpc \
-p /var/run/udhcpc-$iface.pid \
-s /lib/netifd/dhcp.script \
-f -t 0 -i "$iface" \
${ipaddr:+-r ${ipaddr/\/*/}} \
${hostname:+-x "hostname:$hostname"} \
${vendorid:+-V "$vendorid"} \
$clientid $defaultreqopts $broadcast $norelease $dhcpopts
}
proto_dhcp_renew() {
local interface="$1"
# SIGUSR1 forces udhcpc to renew its lease
local sigusr1="$(kill -l SIGUSR1)"
[ -n "$sigusr1" ] && proto_kill_command "$interface" $sigusr1
}
proto_dhcp_teardown() {
local interface="$1"
proto_kill_command "$interface"
}
add_protocol dhcp

View file

@ -1,76 +0,0 @@
#!/bin/sh
# Copyright (C) 2011 OpenWrt.org
. /usr/share/libubox/jshn.sh
find_config() {
local device="$1"
local ifdev ifl3dev ifobj
for ifobj in $(ubus list network.interface.\*); do
interface="${ifobj##network.interface.}"
(
json_load "$(ifstatus $interface)"
json_get_var ifdev device
json_get_var ifl3dev l3_device
if [ "$device" = "$ifdev" ] || [ "$device" = "$ifl3dev" ]; then
echo "$interface"
exit 0
else
exit 1
fi
) && return
done
}
unbridge() {
return
}
ubus_call() {
json_init
local _data="$(ubus -S call "$1" "$2")"
[ -z "$_data" ] && return 1
json_load "$_data"
return 0
}
fixup_interface() {
local config="$1"
local ifname type device l3dev
config_get type "$config" type
config_get ifname "$config" ifname
[ "bridge" = "$type" ] && ifname="br-$config"
ubus_call "network.interface.$config" status || return 0
json_get_var l3dev l3_device
[ -n "$l3dev" ] && ifname="$l3dev"
json_init
config_set "$config" ifname "$ifname"
}
scan_interfaces() {
config_load network
config_foreach fixup_interface interface
}
prepare_interface_bridge() {
local config="$1"
[ -n "$config" ] || return 0
ubus call network.interface."$config" prepare
}
setup_interface() {
local iface="$1"
local config="$2"
[ -n "$config" ] || return 0
ubus call network.interface."$config" add_device "{ \"name\": \"$iface\" }"
}
do_sysctl() {
[ -n "$2" ] && \
sysctl -n -e -w "$1=$2" >/dev/null || \
sysctl -n -e "$1"
}

View file

@ -1,12 +0,0 @@
#!/bin/sh
. /usr/share/libubox/jshn.sh
DEVICE="$1"
[ -n "$DEVICE" ] || {
echo "Usage: $0 <device>"
exit 1
}
json_init
json_add_string name "$DEVICE"
ubus call network.device status "$(json_dump)"

View file

@ -1 +0,0 @@
ifup

View file

@ -1,13 +0,0 @@
#!/bin/sh
INTERFACE="$1"
[ -n "$INTERFACE" ] || {
echo "Usage: $0 <interface>"
exit 1
}
ubus -S list "network.interface.$INTERFACE" >/dev/null || {
echo "Interface $INTERFACE not found"
exit 1
}
ubus call network.interface status "{ \"interface\" : \"$INTERFACE\" }"

View file

@ -1,77 +0,0 @@
#!/bin/sh
ifup_all=
setup_wifi=
if_call() {
local interface="$1"
for mode in $modes; do
ubus call network.interface $mode "{ \"interface\" : \"$interface\" }"
done
}
case "$0" in
*ifdown) modes=down;;
*ifup)
modes="down up"
setup_wifi=1
;;
*) echo "Invalid command: $0";;
esac
while :; do
case "$1" in
-a)
ifup_all=1
shift
;;
-w)
setup_wifi=
shift
;;
*)
break
;;
esac
done
[ "$modes" = "down up" ] && ubus call network reload
if [ -n "$ifup_all" ]; then
for interface in $(ubus -S list 'network.interface.*'); do
if_call "${interface##network.interface.}"
done
[ -n "$setup_wifi" ] && /sbin/wifi up
exit
else
ubus -S list "network.interface.$1" > /dev/null || {
echo "Interface $1 not found"
exit
}
if_call "$1"
fi
if [ -n "$setup_wifi" ] && grep -sq config /etc/config/wireless; then
. /lib/functions.sh
find_related_radios() {
local wdev wnet
config_get wdev "$1" device
config_get wnet "$1" network
if [ -n "$wdev" ]; then
for wnet in $wnet; do
if [ "$wnet" = "$network" ]; then
append radio_devs "$wdev" "$N"
fi
done
fi
}
network="$1"
config_load wireless
config_foreach find_related_radios wifi-iface
for dev in $(echo "$radio_devs" | sort -u); do
/sbin/wifi up "$dev"
done
fi

View file

@ -1,70 +0,0 @@
#!/bin/sh
NPROCS="$(grep -c "^processor.*:" /proc/cpuinfo)"
[ "$NPROCS" -gt 1 ] || exit
PROC_MASK="$(( (1 << $NPROCS) - 1 ))"
find_irq_cpu() {
local dev="$1"
local match="$(grep -m 1 "$dev\$" /proc/interrupts)"
local cpu=0
[ -n "$match" ] && {
set -- $match
shift
for cur in $(seq 1 $NPROCS); do
[ "$1" -gt 0 ] && {
cpu=$(($cur - 1))
break
}
shift
done
}
echo "$cpu"
}
set_hex_val() {
local file="$1"
local val="$2"
val="$(printf %x "$val")"
[ -n "$DEBUG" ] && echo "$file = $val"
echo "$val" > "$file"
}
packet_steering="$(uci get "network.@globals[0].packet_steering")"
[ "$packet_steering" != 1 ] && exit 0
exec 512>/var/lock/smp_tune.lock
flock 512 || exit 1
[ -e "/usr/libexec/platform/packet-steering.sh" ] && {
/usr/libexec/platform/packet-steering.sh
exit 0
}
for dev in /sys/class/net/*; do
[ -d "$dev" ] || continue
# ignore virtual interfaces
[ -n "$(ls "${dev}/" | grep '^lower_')" ] && continue
[ -d "${dev}/device" ] || continue
device="$(readlink "${dev}/device")"
device="$(basename "$device")"
irq_cpu="$(find_irq_cpu "$device")"
irq_cpu_mask="$((1 << $irq_cpu))"
for q in ${dev}/queues/tx-*; do
set_hex_val "$q/xps_cpus" "$PROC_MASK"
done
# ignore dsa slave ports for RPS
subsys="$(readlink "${dev}/device/subsystem")"
subsys="$(basename "$subsys")"
[ "$subsys" = "mdio_bus" ] && continue
for q in ${dev}/queues/rx-*; do
set_hex_val "$q/rps_cpus" "$PROC_MASK"
done
done

View file

@ -1,57 +0,0 @@
#!/bin/sh
[ -z "$1" ] && echo "Error: should be run by udhcpc" && exit 1
set_classless_routes() {
local max=128
local type
while [ -n "$1" -a -n "$2" -a $max -gt 0 ]; do
[ ${1##*/} -eq 32 ] && type=host || type=net
echo "udhcpc: adding route for $type $1 via $2"
route add -$type "$1" gw "$2" dev "$interface"
max=$(($max-1))
shift 2
done
}
setup_interface() {
echo "udhcpc: ip addr add $ip/${subnet:-255.255.255.0} broadcast ${broadcast:-+} dev $interface"
ip addr add $ip/${subnet:-255.255.255.0} broadcast ${broadcast:-+} dev $interface
[ -n "$router" ] && [ "$router" != "0.0.0.0" ] && [ "$router" != "255.255.255.255" ] && {
echo "udhcpc: setting default routers: $router"
local valid_gw=""
for i in $router ; do
route add default gw $i dev $interface
valid_gw="${valid_gw:+$valid_gw|}$i"
done
eval $(route -n | awk '
/^0.0.0.0\W{9}('$valid_gw')\W/ {next}
/^0.0.0.0/ {print "route del -net "$1" gw "$2";"}
')
}
# CIDR STATIC ROUTES (rfc3442)
[ -n "$staticroutes" ] && set_classless_routes $staticroutes
[ -n "$msstaticroutes" ] && set_classless_routes $msstaticroutes
}
applied=
case "$1" in
deconfig)
ip -4 addr flush dev "$interface"
;;
renew)
setup_interface update
;;
bound)
setup_interface ifup
;;
esac
# user rules
[ -f /etc/udhcpc.user ] && . /etc/udhcpc.user
exit 0

View file

@ -1,12 +0,0 @@
--- a/system-linux.c 2023-11-24 16:49:37.715537192 +0100
+++ b/system-linux.c 2023-11-24 16:50:23.002742488 +0100
@@ -53,6 +53,9 @@
#ifndef RTN_FAILED_POLICY
#define RTN_FAILED_POLICY 12
#endif
+#ifndef RTN_POLICY_FAILED
+#define RTN_POLICY_FAILED 12
+#endif
#ifndef IFA_F_NOPREFIXROUTE
#define IFA_F_NOPREFIXROUTE 0x200

View file

@ -97,6 +97,11 @@ if [ "$(pgrep rpcd)" = "" ] && [ -f /etc/init.d/rpcd ]; then
/etc/init.d/rpcd restart >/dev/null 2>&1
sleep 5
fi
if [ "$(pgrep dbus)" = "" ] && [ -f /etc/init.d/dbus ]; then
_log "Can't find dbus, restart it..."
/etc/init.d/dbus restart >/dev/null 2>&1
sleep 5
fi
if [ "$(pgrep uhttpd)" = "" ] && [ -f /etc/init.d/uhttpd ]; then
_log "Can't find uhttpd, restart it..."
@ -193,7 +198,7 @@ multipath_fix() {
config_get multipath "$1" multipath
[ "$multipath" != "off" ] && return
config_get device "$1" device
{ "$(echo $device | grep '@')" ] && return
[ "$(echo $device | grep '@')" ] && return
interface="$(ifstatus $1 | jsonfilter -q -e '@.l3_device' | tr -d '\n')"
[ -n "$interface" ] && [ -z "$(multipath $interface | grep deactivated)" ] && {
_log "Fix Multipath status on $1 ($interface)"
@ -239,7 +244,7 @@ if [ -n "$(logread | tail -n 2 | grep 'Ring expansion failed')" ]; then
echo 1 > /sys/bus/pci/rescan
fi
if [ -f /etc/init.d/omr-bypass ] && (([ -e /usr/sbin/iptables-nft-save ] && [ "$(iptables-nft-save 2>/dev/null | grep omr-bypass)" = "" ]) || [ "$(iptables-save 2>/dev/null | grep omr-bypass)" = "" ]) && [ "$(pgrep -f omr-bypass)" = "" ]; then
if [ -f /etc/init.d/omr-bypass ] && [ -z "$(pgrep -f omr-bypass)" ] && (([ -e /usr/sbin/iptables-nft-save ] && [ "$(iptables-nft-save 2>/dev/null | grep omr-bypass)" = "" ]) || [ "$(iptables-save 2>/dev/null | grep omr-bypass)" = "" ]); then
_log "Can't find omr-bypass rules, restart omr-bypass..."
/etc/init.d/omr-bypass start >/dev/null 2>&1
sleep 5

View file

@ -10,7 +10,8 @@ PORTS=$(uci -q get iperf.$SERVER.ports | sed 's/,/ /g')
PORT="${PORTS%% *}"
echo $KEY | base64 -d > /tmp/iperf.pem
if [ -n "$PASSWORD" ] && [ -n "$USER" ] && [ -n "$KEY" ]; then
IPERF3_PASSWORD=$PASSWORD iperf3 --username $USER --rsa-public-key-path /tmp/iperf.pem --use-pkcs1-padding -c $HOST -p $PORT ${@}
#IPERF3_PASSWORD=$PASSWORD iperf3 --username $USER --rsa-public-key-path /tmp/iperf.pem --use-pkcs1-padding -c $HOST -p $PORT ${@}
IPERF3_PASSWORD=$PASSWORD iperf3 --username $USER --rsa-public-key-path /tmp/iperf.pem -c $HOST -p $PORT ${@}
else
iperf3 -c $HOST -p $PORT ${@}
fi

View file

@ -21,6 +21,7 @@ start_service()
if [ -z "$(grep '\toverlay' /etc/backup/installed_packages.txt | cut -f1 | xargs -r opkg -V0 install)" ]; then
rm /etc/backup/installed_packages.txt
fi
fi
fi
}

View file

@ -160,7 +160,7 @@ if [ "$(uci -q get firewall.ttl)" = "" ]; then
commit firewall
EOF
fi
if [ "$(uci -q get firewall.upnp)" = "" ]; then
if [ "$(uci -q get firewall.upnp)" = "" ] && [ -e /etc/init.d/miniupnpd ]; then
uci -q batch <<-EOF >/dev/null
set firewall.upnp=include
set firewall.upnp.path='/etc/firewall.upnp'