aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.inc12
-rw-r--r--RELNOTES12
-rw-r--r--UPDATING8
-rw-r--r--contrib/mandoc/roff_term.c5
-rw-r--r--etc/mail/Makefile4
-rw-r--r--kerberos5/lib/libroken/fbsd_ossl_provider_load.c7
-rw-r--r--lib/libc/tests/stdtime/Makefile4
-rw-r--r--lib/libc/tests/stdtime/detect_tz_changes_test.c53
-rw-r--r--lib/libsysdecode/Makefile2
-rw-r--r--lib/libsysdecode/sysdecode.32
-rw-r--r--lib/libsysdecode/sysdecode_abi_to_freebsd_errno.32
-rw-r--r--lib/libsysdecode/sysdecode_syscallname.3 (renamed from lib/libsysdecode/sysdecode_syscallnames.3)6
-rw-r--r--sbin/ipfw/Makefile3
-rw-r--r--sbin/ipfw/nptv6.c49
-rw-r--r--sbin/ipfw/tests/Makefile1
-rw-r--r--sbin/ipfw/tests/ipfw_test.sh107
-rwxr-xr-xsecure/caroot/MAca-bundle.pl305
-rw-r--r--secure/caroot/Makefile3
-rwxr-xr-xsecure/caroot/ca-extract.pl253
-rw-r--r--secure/caroot/trusted/Makefile6
-rw-r--r--secure/caroot/untrusted/Makefile5
-rw-r--r--share/man/man4/puc.42
-rw-r--r--share/man/man7/simd.743
-rw-r--r--sys/compat/linuxkpi/common/include/acpi/acpi.h2
-rw-r--r--sys/compat/linuxkpi/common/include/linux/netdevice.h9
-rw-r--r--sys/compat/linuxkpi/common/include/net/mac80211.h3
-rw-r--r--sys/compat/linuxkpi/common/src/linux_80211.c206
-rw-r--r--sys/compat/linuxkpi/common/src/linux_80211.h18
-rw-r--r--sys/conf/files.x861
-rw-r--r--sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c3
-rw-r--r--sys/dev/amdgpio/amdgpio.c136
-rw-r--r--sys/dev/amdgpio/amdgpio.h9
-rw-r--r--sys/dev/hpt27xx/hptintf.h6
-rw-r--r--sys/dev/ichwd/i6300esbwd.c245
-rw-r--r--sys/dev/ichwd/i6300esbwd.h46
-rw-r--r--sys/dev/ichwd/ichwd.c2
-rw-r--r--sys/dev/ichwd/ichwd.h3
-rw-r--r--sys/dev/puc/pucdata.c43
-rw-r--r--sys/dev/uart/uart_bus_pci.c2
-rw-r--r--sys/modules/ichwd/Makefile2
-rw-r--r--sys/net/if.c37
-rw-r--r--sys/net/if_var.h1
-rw-r--r--sys/netgraph/ng_nat.c95
-rw-r--r--sys/netinet/ip_output.c13
-rw-r--r--sys/netinet/ip_var.h1
-rw-r--r--sys/netinet/tcp_hpts.c2
-rw-r--r--sys/netinet/tcp_stacks/bbr.c2
-rw-r--r--sys/netinet/tcp_stacks/rack.c2
-rw-r--r--sys/netinet/tcp_stacks/rack_bbr_common.c2
-rw-r--r--sys/netinet/tcp_stacks/rack_pcm.c2
-rw-r--r--sys/netinet/tcp_stacks/tailq_hash.c2
-rw-r--r--sys/netlink/route/iface_drivers.c33
-rw-r--r--usr.sbin/mountd/exports.515
53 files changed, 1283 insertions, 544 deletions
diff --git a/Makefile.inc1 b/Makefile.inc1
index d899f994a40d..c6cbc411be80 100644
--- a/Makefile.inc1
+++ b/Makefile.inc1
@@ -3712,7 +3712,7 @@ check-old-libs: .PHONY
list-old-dirs: .PHONY
@cd ${.CURDIR}; \
${MAKE} -f ${.CURDIR}/Makefile.inc1 ${.MAKEFLAGS} ${.TARGET} \
- -V OLD_DIRS | sed -E 's/[[:space:]]+/\n/g' | sort -r
+ -V "OLD_DIRS:ts\n" | sort -r
delete-old-dirs: .PHONY
@echo ">>> Removing old directories"
diff --git a/RELNOTES b/RELNOTES
index 3aec631bc15e..62732cc9dff3 100644
--- a/RELNOTES
+++ b/RELNOTES
@@ -10,6 +10,18 @@ newline. Entries should be separated by a newline.
Changes to this file should not be MFCed.
+2b74ff5fceb6:
+ Introduced support for watchdog timer in Intel 6300ESB I/O controller
+ hub via the i6300esbwd driver, now included in ichwd.ko.
+ This driver is intended primarily for QEMU users, where it serves as
+ the default and only watchdog timer for x86 virtual machines.
+
+3068d706eabe:
+ Lua updated to 5.4.8, which is minor bug fixes from 5.4.7.
+
+b45a181a74c8:
+ Awk updates to August 04, 2025 version, with minor bug fixes.
+
dc5ba6b8b4f0:
The WITHOUT_GSSAPI src.conf(5) option has been removed. The GSSAPI
libraries are now always built unless WITHOUT_KERBEROS is set.
diff --git a/UPDATING b/UPDATING
index ddb2e7603b2a..8a0930b20123 100644
--- a/UPDATING
+++ b/UPDATING
@@ -74,10 +74,16 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 15.x IS SLOW:
require libmilter, you can now remove it.
20250815:
+ The [gs]etgroups(2)syscalls have changed. To maintain backwards
+ compatibility with existing programs, you need COMPAT_FREEBSD14 in
+ your kernel config until all applications which use this are
+ rebuild/reinstalled.
+
+20250815:
jemalloc 5.3.0 has been committed to the tree.
20250815:
- The removal of Secure RPC DES authentication notced in 20250810
+ The removal of Secure RPC DES authentication noted in 20250810
has been reverted. (However, it is still non-functional.)
20250813:
diff --git a/contrib/mandoc/roff_term.c b/contrib/mandoc/roff_term.c
index 8f95aa920790..85d2caeb2749 100644
--- a/contrib/mandoc/roff_term.c
+++ b/contrib/mandoc/roff_term.c
@@ -165,6 +165,7 @@ roff_term_pre_po(ROFF_TERM_ARGS)
static int polast; /* Previously requested. */
static int po; /* Currently requested. */
static int pouse; /* Currently used. */
+ int pomin; /* Minimum to be used. */
int pomax; /* Maximum to be used. */
int ponew; /* Newly requested. */
@@ -186,9 +187,9 @@ roff_term_pre_po(ROFF_TERM_ARGS)
po = ponew;
/* Truncate to the range [-offset, 60], remember, and apply it. */
+ pomin = -p->tcol->offset;
pomax = term_len(p, 60);
- pouse = po >= pomax ? pomax :
- po < -(int)p->tcol->offset ? -p->tcol->offset : po;
+ pouse = po > pomax ? pomax : po < pomin ? pomin : po;
p->tcol->offset += pouse;
}
diff --git a/etc/mail/Makefile b/etc/mail/Makefile
index 784023d6f9c0..9b03047102ea 100644
--- a/etc/mail/Makefile
+++ b/etc/mail/Makefile
@@ -241,5 +241,7 @@ restart restart-mta restart-mspq:
.include "Makefile.local"
.endif
-# For the definition of $SHAREMODE
+# For the definition of $SHAREMODE. Define _WITHOUT_SRCCONF to prevent this
+# including <bsd.compiler.mk>, which requires clang.
+_WITHOUT_SRCCONF=yes
.include <bsd.own.mk>
diff --git a/kerberos5/lib/libroken/fbsd_ossl_provider_load.c b/kerberos5/lib/libroken/fbsd_ossl_provider_load.c
index 2328041bc166..b8812f207af8 100644
--- a/kerberos5/lib/libroken/fbsd_ossl_provider_load.c
+++ b/kerberos5/lib/libroken/fbsd_ossl_provider_load.c
@@ -5,10 +5,9 @@
#include <openssl/provider.h>
#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
-#define CRYPTO_LIBRARY "/lib/libcrypto.so.30"
+#define CRYPTO_LIBRARY "/lib/libcrypto.so.35"
static void fbsd_ossl_provider_unload(void);
static void print_dlerror(char *);
-static OSSL_PROVIDER *legacy;
static OSSL_PROVIDER *deflt;
static int providers_loaded = 0;
static OSSL_PROVIDER * (*ossl_provider_load)(OSSL_LIB_CTX *, const char*) = NULL;
@@ -25,7 +24,6 @@ fbsd_ossl_provider_unload(void)
}
}
if (providers_loaded == 1) {
- (*ossl_provider_unload)(legacy);
(*ossl_provider_unload)(deflt);
providers_loaded = 0;
}
@@ -61,10 +59,7 @@ fbsd_ossl_provider_load(void)
}
if (providers_loaded == 0) {
- if ((legacy = (*ossl_provider_load)(NULL, "legacy")) == NULL)
- return (EINVAL);
if ((deflt = (*ossl_provider_load)(NULL, "default")) == NULL) {
- (*ossl_provider_unload)(legacy);
return (EINVAL);
}
if (atexit(fbsd_ossl_provider_unload)) {
diff --git a/lib/libc/tests/stdtime/Makefile b/lib/libc/tests/stdtime/Makefile
index adb883cc5b9a..6b9068e1641b 100644
--- a/lib/libc/tests/stdtime/Makefile
+++ b/lib/libc/tests/stdtime/Makefile
@@ -1,8 +1,10 @@
.include <src.opts.mk>
ATF_TESTS_C+= strptime_test
-.if ${MK_DETECT_TZ_CHANGES} != "no"
ATF_TESTS_C+= detect_tz_changes_test
+
+.if ${MK_DETECT_TZ_CHANGES} != "no"
+CFLAGS.detect_tz_changes_test+= -DDETECT_TZ_CHANGES
.endif
TESTSDIR:= ${TESTSBASE}/${RELDIR:C/libc\/tests/libc/}
diff --git a/lib/libc/tests/stdtime/detect_tz_changes_test.c b/lib/libc/tests/stdtime/detect_tz_changes_test.c
index 75f55bdede04..e3fdcc0baef7 100644
--- a/lib/libc/tests/stdtime/detect_tz_changes_test.c
+++ b/lib/libc/tests/stdtime/detect_tz_changes_test.c
@@ -4,6 +4,8 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
+#include <sys/param.h>
+#include <sys/conf.h>
#include <sys/stat.h>
#include <sys/wait.h>
@@ -41,6 +43,8 @@ static const struct tzcase {
};
static const time_t then = 1751328000; /* 2025-07-01 00:00:00 UTC */
+
+#ifdef DETECT_TZ_CHANGES
static const char *tz_change_interval_sym = "__tz_change_interval";
static int *tz_change_interval_p;
static const int tz_change_interval = 3;
@@ -272,6 +276,21 @@ ATF_TC_BODY(detect_tz_changes, tc)
ATF_REQUIRE(WIFEXITED(status));
ATF_REQUIRE_EQ(0, WEXITSTATUS(status));
}
+#endif /* DETECT_TZ_CHANGES */
+
+static void
+test_tz_env(const char *tzval, const char *expect)
+{
+ char buf[128];
+ struct tm *tm;
+ size_t len;
+
+ setenv("TZ", tzval, 1);
+ ATF_REQUIRE((tm = localtime(&then)) != NULL);
+ len = strftime(buf, sizeof(buf), "%z (%Z)", tm);
+ ATF_REQUIRE(len > 0);
+ ATF_CHECK_STREQ(expect, buf);
+}
ATF_TC(tz_env);
ATF_TC_HEAD(tz_env, tc)
@@ -280,25 +299,37 @@ ATF_TC_HEAD(tz_env, tc)
}
ATF_TC_BODY(tz_env, tc)
{
- char buf[128];
- const struct tzcase *tzcase = NULL;
- struct tm *tm;
- size_t len;
+ const struct tzcase *tzcase;
- for (tzcase = tzcases; tzcase->tzfn != NULL; tzcase++) {
- setenv("TZ", tzcase->tzfn, 1);
- ATF_REQUIRE((tm = localtime(&then)) != NULL);
- len = strftime(buf, sizeof(buf), "%z (%Z)", tm);
- ATF_REQUIRE(len > 0);
- ATF_REQUIRE_STREQ(tzcase->expect, buf);
- }
+ for (tzcase = tzcases; tzcase->tzfn != NULL; tzcase++)
+ test_tz_env(tzcase->tzfn, tzcase->expect);
+}
+
+ATF_TC(tz_env_setugid);
+ATF_TC_HEAD(tz_env_setugid, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test TZ environment variable "
+ "in setugid process");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+ATF_TC_BODY(tz_env_setugid, tc)
+{
+ const struct tzcase *tzcase;
+
+ ATF_REQUIRE_EQ(0, seteuid(UID_NOBODY));
+ ATF_REQUIRE(issetugid());
+ for (tzcase = tzcases; tzcase->tzfn != NULL; tzcase++)
+ test_tz_env(tzcase->tzfn, tzcase->expect);
}
ATF_TP_ADD_TCS(tp)
{
+#ifdef DETECT_TZ_CHANGES
debugging = !getenv("__RUNNING_INSIDE_ATF_RUN") &&
isatty(STDERR_FILENO);
ATF_TP_ADD_TC(tp, detect_tz_changes);
+#endif /* DETECT_TZ_CHANGES */
ATF_TP_ADD_TC(tp, tz_env);
+ ATF_TP_ADD_TC(tp, tz_env_setugid);
return (atf_no_error());
}
diff --git a/lib/libsysdecode/Makefile b/lib/libsysdecode/Makefile
index ca020552a6e9..11f45355b8e2 100644
--- a/lib/libsysdecode/Makefile
+++ b/lib/libsysdecode/Makefile
@@ -27,7 +27,7 @@ MAN= sysdecode.3 \
sysdecode_sigcode.3 \
sysdecode_sockopt_name.3 \
sysdecode_socket_protocol.3 \
- sysdecode_syscallnames.3 \
+ sysdecode_syscallname.3 \
sysdecode_utrace.3
MLINKS= sysdecode_abi_to_freebsd_errno.3 sysdecode_freebsd_to_abi_errno.3
MLINKS+=sysdecode_enum.3 sysdecode_acltype.3 \
diff --git a/lib/libsysdecode/sysdecode.3 b/lib/libsysdecode/sysdecode.3
index 0aa4155c004b..32f7fad4e6c5 100644
--- a/lib/libsysdecode/sysdecode.3
+++ b/lib/libsysdecode/sysdecode.3
@@ -73,7 +73,7 @@ A placeholder for use when the ABI is not known.
.Xr sysdecode_sigcode 3 ,
.Xr sysdecode_socket_protocol 3 ,
.Xr sysdecode_sockopt_name 3 ,
-.Xr sysdecode_syscallnames 3 ,
+.Xr sysdecode_syscallname 3 ,
.Xr sysdecode_utrace 3
.Sh HISTORY
The
diff --git a/lib/libsysdecode/sysdecode_abi_to_freebsd_errno.3 b/lib/libsysdecode/sysdecode_abi_to_freebsd_errno.3
index 8f710d1e3756..51955f062393 100644
--- a/lib/libsysdecode/sysdecode_abi_to_freebsd_errno.3
+++ b/lib/libsysdecode/sysdecode_abi_to_freebsd_errno.3
@@ -89,4 +89,4 @@ see
.Xr sysdecode 3 .
.Sh SEE ALSO
.Xr sysdecode 3 ,
-.Xr sysdecode_syscallnames 3
+.Xr sysdecode_syscallname 3
diff --git a/lib/libsysdecode/sysdecode_syscallnames.3 b/lib/libsysdecode/sysdecode_syscallname.3
index 610cbc9b2115..8ba88fd3c43e 100644
--- a/lib/libsysdecode/sysdecode_syscallnames.3
+++ b/lib/libsysdecode/sysdecode_syscallname.3
@@ -23,17 +23,17 @@
.\" SUCH DAMAGE.
.\"
.Dd October 17, 2016
-.Dt sysdecode_syscallnames 3
+.Dt sysdecode_syscallname 3
.Os
.Sh NAME
-.Nm sysdecode_syscallnames
+.Nm sysdecode_syscallname
.Nd lookup name of system calls
.Sh LIBRARY
.Lb libsysdecode
.Sh SYNOPSIS
.In sysdecode.h
.Ft const char *
-.Fn sysdecode_syscallnames "enum sysdecode_abi abi" "unsigned int code"
+.Fn sysdecode_syscallname "enum sysdecode_abi abi" "unsigned int code"
.Sh DESCRIPTION
This function returns a pointer to the name of a system call identified by
.Fa code
diff --git a/sbin/ipfw/Makefile b/sbin/ipfw/Makefile
index bfbe70130de7..418c0f613741 100644
--- a/sbin/ipfw/Makefile
+++ b/sbin/ipfw/Makefile
@@ -17,6 +17,9 @@ CFLAGS+=-DPF
LIBADD= jail util
MAN= ipfw.8
+HAS_TESTS=
+SUBDIR.${MK_TESTS}= tests
+
.include <bsd.prog.mk>
CWARNFLAGS+= -Wno-cast-align
diff --git a/sbin/ipfw/nptv6.c b/sbin/ipfw/nptv6.c
index 83bf4c768fd9..eee6109a3d9e 100644
--- a/sbin/ipfw/nptv6.c
+++ b/sbin/ipfw/nptv6.c
@@ -153,10 +153,10 @@ static struct _s_x nptv6newcmds[] = {
{ NULL, 0 }
};
-
static void
nptv6_parse_prefix(const char *arg, struct in6_addr *prefix, int *len)
{
+ long plen;
char *p, *l;
p = strdup(arg);
@@ -167,13 +167,15 @@ nptv6_parse_prefix(const char *arg, struct in6_addr *prefix, int *len)
if (inet_pton(AF_INET6, p, prefix) != 1)
errx(EX_USAGE, "Bad prefix: %s", p);
if (l != NULL) {
- *len = (int)strtol(l, &l, 10);
- if (*l != '\0' || *len <= 0 || *len > 64)
+ plen = strtol(l, &l, 10);
+ if (*l != '\0' || plen < 8 || plen > 64)
errx(EX_USAGE, "Bad prefix length: %s", arg);
+ *len = plen;
} else
*len = 0;
free(p);
}
+
/*
* Creates new nptv6 instance
* ipfw nptv6 <NAME> create int_prefix <prefix> ext_prefix <prefix>
@@ -189,10 +191,10 @@ nptv6_create(const char *name, uint8_t set, int ac, char *av[])
struct in6_addr mask;
ipfw_nptv6_cfg *cfg;
ipfw_obj_lheader *olh;
- int tcmd, flags, plen;
+ int tcmd, flags, iplen, eplen, pplen;
char *p;
- plen = 0;
+ iplen = eplen = pplen = 0;
memset(buf, 0, sizeof(buf));
olh = (ipfw_obj_lheader *)buf;
cfg = (ipfw_nptv6_cfg *)(olh + 1);
@@ -205,10 +207,8 @@ nptv6_create(const char *name, uint8_t set, int ac, char *av[])
switch (tcmd) {
case TOK_INTPREFIX:
NEED1("IPv6 prefix required");
- nptv6_parse_prefix(*av, &cfg->internal, &plen);
+ nptv6_parse_prefix(*av, &cfg->internal, &iplen);
flags |= NPTV6_HAS_INTPREFIX;
- if (plen > 0)
- goto check_prefix;
ac--; av++;
break;
case TOK_EXTPREFIX:
@@ -216,10 +216,8 @@ nptv6_create(const char *name, uint8_t set, int ac, char *av[])
errx(EX_USAGE,
"Only one ext_prefix or ext_if allowed");
NEED1("IPv6 prefix required");
- nptv6_parse_prefix(*av, &cfg->external, &plen);
+ nptv6_parse_prefix(*av, &cfg->external, &eplen);
flags |= NPTV6_HAS_EXTPREFIX;
- if (plen > 0)
- goto check_prefix;
ac--; av++;
break;
case TOK_EXTIF:
@@ -236,24 +234,29 @@ nptv6_create(const char *name, uint8_t set, int ac, char *av[])
break;
case TOK_PREFIXLEN:
NEED1("IPv6 prefix length required");
- plen = strtol(*av, &p, 10);
-check_prefix:
- if (*p != '\0' || plen < 8 || plen > 64)
+ pplen = strtol(*av, &p, 10);
+ if (*p != '\0' || pplen < 8 || pplen > 64)
errx(EX_USAGE, "wrong prefix length: %s", *av);
- /* RFC 6296 Sec. 3.1 */
- if (cfg->plen > 0 && cfg->plen != plen) {
- warnx("Prefix length mismatch (%d vs %d). "
- "It was extended up to %d",
- cfg->plen, plen, MAX(plen, cfg->plen));
- plen = MAX(plen, cfg->plen);
- }
- cfg->plen = plen;
- flags |= NPTV6_HAS_PREFIXLEN;
ac--; av++;
break;
}
}
+ /* RFC 6296 Sec. 3.1 */
+ if (pplen != 0) {
+ if ((eplen != 0 && eplen != pplen) ||
+ (iplen != 0 && iplen != pplen))
+ errx(EX_USAGE, "prefix length mismatch");
+ cfg->plen = pplen;
+ flags |= NPTV6_HAS_PREFIXLEN;
+ } else if (eplen != 0 || iplen != 0) {
+ if (eplen != 0 && iplen != 0 && eplen != iplen)
+ errx(EX_USAGE, "prefix length mismatch");
+ warnx("use prefixlen instead");
+ cfg->plen = eplen ? eplen : iplen;
+ flags |= NPTV6_HAS_PREFIXLEN;
+ }
+
/* Check validness */
if ((flags & NPTV6_HAS_INTPREFIX) != NPTV6_HAS_INTPREFIX)
errx(EX_USAGE, "int_prefix required");
diff --git a/sbin/ipfw/tests/Makefile b/sbin/ipfw/tests/Makefile
index 987410f5d710..e2d4dab2729a 100644
--- a/sbin/ipfw/tests/Makefile
+++ b/sbin/ipfw/tests/Makefile
@@ -1,5 +1,6 @@
PACKAGE= tests
ATF_TESTS_PYTEST+= test_add_rule.py
+ATF_TESTS_SH+= ipfw_test
.include <bsd.test.mk>
diff --git a/sbin/ipfw/tests/ipfw_test.sh b/sbin/ipfw/tests/ipfw_test.sh
new file mode 100644
index 000000000000..c7993c430a3d
--- /dev/null
+++ b/sbin/ipfw/tests/ipfw_test.sh
@@ -0,0 +1,107 @@
+#
+# Copyright (c) 2025 Dag-Erling Smørgrav <des@FreeBSD.org>
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+. $(atf_get_srcdir)/../../sys/common/vnet.subr
+
+atf_test_case nptv6 cleanup
+nptv6_head()
+{
+ atf_set "descr" "Test creation of NPTv6 rules"
+ atf_set "require.user" "root"
+ atf_set "require.kmods" "ipfw_nptv6"
+}
+nptv6_body()
+{
+ vnet_init
+ local jail=ipfw_$(atf_get ident)
+ local epair=$(vnet_mkepair)
+ vnet_mkjail ${jail} ${epair}a
+
+ local rule="xyzzy"
+ local int="2001:db8:1::"
+ local ext="2001:db8:2::"
+
+ atf_check jexec ${jail} \
+ ifconfig "${epair}"a inet6 ${ext}1/64 up
+
+ # This is how it's supposed to be used
+ atf_check jexec ${jail} ipfw nptv6 ${rule} create \
+ int_prefix ${int} ext_prefix ${ext} prefixlen 64
+ atf_check -o inline:\
+"nptv6 $rule int_prefix $int ext_prefix $ext prefixlen 64\n" \
+ jexec ${jail} ipfw nptv6 all list
+ atf_check jexec ${jail} ipfw nptv6 all destroy
+
+ # Specify external interface rather than network
+ atf_check jexec ${jail} ipfw nptv6 ${rule} create \
+ int_prefix ${int} ext_if ${epair}a prefixlen 64
+ atf_check -o inline:\
+"nptv6 $rule int_prefix $int ext_if ${epair}a prefixlen 64\n" \
+ jexec ${jail} ipfw nptv6 all list
+ atf_check jexec ${jail} ipfw nptv6 all destroy
+
+ # This should also work
+ atf_check jexec ${jail} ipfw nptv6 ${rule} create \
+ int_prefix ${int}/64 ext_prefix ${ext}/64 prefixlen 64
+ atf_check -o inline:\
+"nptv6 $rule int_prefix $int ext_prefix $ext prefixlen 64\n" \
+ jexec ${jail} ipfw nptv6 all list
+ atf_check jexec ${jail} ipfw nptv6 all destroy
+
+ # This should also work, although it's not encouraged
+ atf_check -e match:"use prefixlen instead" \
+ jexec ${jail} ipfw nptv6 ${rule} create \
+ int_prefix ${int}/64 ext_prefix ${ext}/64
+ atf_check -o inline:\
+"nptv6 $rule int_prefix $int ext_prefix $ext prefixlen 64\n" \
+ jexec ${jail} ipfw nptv6 all list
+ atf_check jexec ${jail} ipfw nptv6 all destroy
+
+ # These should all fail
+ atf_check -s not-exit:0 -e match:"one ext_prefix or ext_if" \
+ jexec ${jail} ipfw nptv6 ${rule} create \
+ int_prefix ${int} ext_prefix ${ext} ext_if ${epair}a
+ atf_check -o empty jexec ${jail} ipfw nptv6 all list
+
+ atf_check -s not-exit:0 -e match:"one ext_prefix or ext_if" \
+ jexec ${jail} ipfw nptv6 ${rule} create \
+ int_prefix ${int} ext_if ${epair}a ext_prefix ${ext}
+ atf_check -o empty jexec ${jail} ipfw nptv6 all list
+
+ atf_check -s not-exit:0 -e match:"prefix length mismatch" \
+ jexec ${jail} ipfw nptv6 ${rule} create \
+ int_prefix ${int}/48 ext_prefix ${ext}/64
+ atf_check -o empty jexec ${jail} ipfw nptv6 all list
+
+ atf_check -s not-exit:0 -e match:"prefix length mismatch" \
+ jexec ${jail} ipfw nptv6 ${rule} create \
+ int_prefix ${int}/64 ext_prefix ${ext}/64 prefixlen 48
+ atf_check -o empty jexec ${jail} ipfw nptv6 all list
+
+ atf_check -s not-exit:0 -e match:"prefix length mismatch" \
+ jexec ${jail} ipfw nptv6 ${rule} create \
+ int_prefix ${int}/64 ext_prefix ${ext} prefixlen 48
+ atf_check -o empty jexec ${jail} ipfw nptv6 all list
+
+ atf_check -s not-exit:0 -e match:"prefix length mismatch" \
+ jexec ${jail} ipfw nptv6 ${rule} create \
+ int_prefix ${int} ext_prefix ${ext}/64 prefixlen 48
+ atf_check -o empty jexec ${jail} ipfw nptv6 all list
+
+ atf_check -s not-exit:0 -e match:"prefix length mismatch" \
+ jexec ${jail} ipfw nptv6 ${rule} create \
+ int_prefix ${int}/64 ext_if ${epair}a prefixlen 48
+ atf_check -o empty jexec ${jail} ipfw nptv6 all list
+}
+nptv6_cleanup()
+{
+ vnet_cleanup
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case nptv6
+}
diff --git a/secure/caroot/MAca-bundle.pl b/secure/caroot/MAca-bundle.pl
deleted file mode 100755
index 58cfe1cbf6fa..000000000000
--- a/secure/caroot/MAca-bundle.pl
+++ /dev/null
@@ -1,305 +0,0 @@
-#!/usr/bin/env perl
-##
-## MAca-bundle.pl -- Regenerate ca-root-nss.crt from the Mozilla certdata.txt
-##
-## Rewritten in September 2011 by Matthias Andree to heed untrust
-##
-
-## Copyright (c) 2011, 2013 Matthias Andree <mandree@FreeBSD.org>
-## All rights reserved.
-## Copyright (c) 2018, Allan Jude <allanjude@FreeBSD.org>
-##
-## Redistribution and use in source and binary forms, with or without
-## modification, are permitted provided that the following conditions are
-## met:
-##
-## * Redistributions of source code must retain the above copyright
-## notice, this list of conditions and the following disclaimer.
-##
-## * Redistributions in binary form must reproduce the above copyright
-## notice, this list of conditions and the following disclaimer in the
-## documentation and/or other materials provided with the distribution.
-##
-## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-## FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-## COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-## INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-## BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-## LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-## CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-## LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-## ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-## POSSIBILITY OF SUCH DAMAGE.
-
-use strict;
-use Carp;
-use MIME::Base64;
-use Getopt::Long;
-use Time::Local qw( timegm_posix );
-use POSIX qw( strftime );
-
-my $generated = '@' . 'generated';
-my $inputfh = *STDIN;
-my $debug = 0;
-my $infile;
-my $outputdir;
-my %labels;
-my %certs;
-my %trusts;
-
-$debug++
- if defined $ENV{'WITH_DEBUG'}
- and $ENV{'WITH_DEBUG'} !~ m/(?i)^(no|0|false|)$/;
-
-GetOptions (
- "debug+" => \$debug,
- "infile:s" => \$infile,
- "outputdir:s" => \$outputdir)
- or die("Error in command line arguments\n$0 [-d] [-i input-file] [-o output-dir]\n");
-
-if ($infile) {
- open($inputfh, "<", $infile) or die "Failed to open $infile";
-}
-
-sub print_header($$)
-{
- my $dstfile = shift;
- my $label = shift;
-
- if ($outputdir) {
- print $dstfile <<EOFH;
-##
-## $label
-##
-## This is a single X.509 certificate for a public Certificate
-## Authority (CA). It was automatically extracted from Mozilla's
-## root CA list (the file `certdata.txt' in security/nss).
-##
-## It contains a certificate trusted for server authentication.
-##
-## Extracted from nss
-##
-## $generated
-##
-EOFH
- } else {
- print $dstfile <<EOH;
-##
-## ca-root-nss.crt -- Bundle of CA Root Certificates
-##
-## This is a bundle of X.509 certificates of public Certificate
-## Authorities (CA). These were automatically extracted from Mozilla's
-## root CA list (the file `certdata.txt').
-##
-## It contains certificates trusted for server authentication.
-##
-## Extracted from nss
-##
-## $generated
-##
-EOH
- }
-}
-
-sub printcert($$$)
-{
- my ($fh, $label, $certdata) = @_;
- return unless $certdata;
- open(OUT, "|openssl x509 -text -inform DER -fingerprint")
- or die "could not pipe to openssl x509";
- print OUT $certdata;
- close(OUT) or die "openssl x509 failed with exit code $?";
-}
-
-# converts a datastream that is to be \177-style octal constants
-# from <> to a (binary) string and returns it
-sub graboct($)
-{
- my $ifh = shift;
- my $data;
-
- while (<$ifh>) {
- last if /^END/;
- my (undef,@oct) = split /\\/;
- my @bin = map(chr(oct), @oct);
- $data .= join('', @bin);
- }
-
- return $data;
-}
-
-sub grabcert($)
-{
- my $ifh = shift;
- my $certdata;
- my $cka_label = '';
- my $serial = 0;
- my $distrust = 0;
-
- while (<$ifh>) {
- chomp;
- last if ($_ eq '');
-
- if (/^CKA_LABEL UTF8 "([^"]+)"/) {
- $cka_label = $1;
- }
-
- if (/^CKA_VALUE MULTILINE_OCTAL/) {
- $certdata = graboct($ifh);
- }
-
- if (/^CKA_SERIAL_NUMBER MULTILINE_OCTAL/) {
- $serial = graboct($ifh);
- }
-
- if (/^CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL/)
- {
- my $distrust_after = graboct($ifh);
- my ($year, $mon, $mday, $hour, $min, $sec) = unpack "A2A2A2A2A2A2", $distrust_after;
- $distrust_after = timegm_posix( $sec, $min, $hour, $mday, $mon - 1, $year + 100);
- my $time_now = time;
- # When a CA is distrusted before its NotAfter date, issued certificates
- # are valid for a maximum of 398 days after that date.
- if ($time_now >= $distrust_after + 398 * 24 * 60 * 60) { $distrust = 1; }
- if ($debug) {
- printf STDERR "line $.: $cka_label ser #%d: distrust 398 days after %s, now: %s -> distrust $distrust\n", $serial,
- strftime("%FT%TZ", gmtime($distrust_after)), strftime("%FT%TZ", gmtime($time_now));
- }
- if ($distrust) {
- return undef;
- }
- }
- }
- return ($serial, $cka_label, $certdata);
-}
-
-sub grabtrust($) {
- my $ifh = shift;
- my $cka_label;
- my $serial;
- my $maytrust = 0;
- my $distrust = 0;
-
- while (<$ifh>) {
- chomp;
- last if ($_ eq '');
-
- if (/^CKA_LABEL UTF8 "([^"]+)"/) {
- $cka_label = $1;
- }
-
- if (/^CKA_SERIAL_NUMBER MULTILINE_OCTAL/) {
- $serial = graboct($ifh);
- }
-
- if (/^CKA_TRUST_SERVER_AUTH CK_TRUST (\S+)$/)
- {
- if ($1 eq 'CKT_NSS_NOT_TRUSTED') {
- $distrust = 1;
- } elsif ($1 eq 'CKT_NSS_TRUSTED_DELEGATOR') {
- $maytrust = 1;
- } elsif ($1 ne 'CKT_NSS_MUST_VERIFY_TRUST') {
- confess "Unknown trust setting on line $.:\n"
- . "$_\n"
- . "Script must be updated:";
- }
- }
- }
-
- if (!$maytrust && !$distrust && $debug) {
- print STDERR "line $.: no explicit trust/distrust found for $cka_label\n";
- }
-
- my $trust = ($maytrust and not $distrust);
- return ($serial, $cka_label, $trust);
-}
-
-if (!$outputdir) {
- print_header(*STDOUT, "");
-}
-
-my $untrusted = 0;
-
-while (<$inputfh>) {
- if (/^CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE/) {
- my ($serial, $label, $certdata) = grabcert($inputfh);
- if (defined $certs{$label."\0".$serial}) {
- warn "Certificate $label duplicated!\n";
- }
- if (defined $certdata) {
- $certs{$label."\0".$serial} = $certdata;
- # We store the label in a separate hash because truncating the key
- # with \0 was causing garbage data after the end of the text.
- $labels{$label."\0".$serial} = $label;
- } else { # $certdata undefined? distrust_after in effect
- $untrusted ++;
- }
- } elsif (/^CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST/) {
- my ($serial, $label, $trust) = grabtrust($inputfh);
- if (defined $trusts{$label."\0".$serial}) {
- warn "Trust for $label duplicated!\n";
- }
- $trusts{$label."\0".$serial} = $trust;
- $labels{$label."\0".$serial} = $label;
- } elsif (/^CVS_ID.*Revision: ([^ ]*).*/) {
- print "## Source: \"certdata.txt\" CVS revision $1\n##\n\n";
- }
-}
-
-sub label_to_filename(@) {
- my @res = @_;
- map { s/\0.*//; s/[^[:alnum:]\-]/_/g; $_ = "$_.pem"; } @res;
- return wantarray ? @res : $res[0];
-}
-
-# weed out untrusted certificates
-foreach my $it (keys %trusts) {
- if (!$trusts{$it}) {
- if (!exists($certs{$it})) {
- warn "Found trust for nonexistent certificate $labels{$it}\n" if $debug;
- } else {
- delete $certs{$it};
- warn "Skipping untrusted $labels{$it}\n" if $debug;
- $untrusted++;
- }
- }
-}
-
-if (!$outputdir) {
- print "## Untrusted certificates omitted from this bundle: $untrusted\n\n";
-}
-print STDERR "## Untrusted certificates omitted from this bundle: $untrusted\n";
-
-my $certcount = 0;
-foreach my $it (sort {uc($a) cmp uc($b)} keys %certs) {
- my $fh = *STDOUT;
- my $filename;
- if (!exists($trusts{$it})) {
- die "Found certificate without trust block,\naborting";
- }
- if ($outputdir) {
- $filename = label_to_filename($labels{$it});
- open($fh, ">", "$outputdir/$filename") or die "Failed to open certificate $filename";
- print_header($fh, $labels{$it});
- }
- printcert($fh, $labels{$it}, $certs{$it});
- if ($outputdir) {
- close($fh) or die "Unable to close: $filename";
- } else {
- print $fh "\n\n\n";
- }
- $certcount++;
- print STDERR "Trusting $certcount: $labels{$it}\n" if $debug;
-}
-
-if ($certcount < 25) {
- die "Certificate count of $certcount is implausibly low.\nAbort";
-}
-
-if (!$outputdir) {
- print "## Number of certificates: $certcount\n";
- print "## End of file.\n";
-}
-print STDERR "## Number of certificates: $certcount\n";
diff --git a/secure/caroot/Makefile b/secure/caroot/Makefile
index ace802a906a3..e0ef4623b498 100644
--- a/secure/caroot/Makefile
+++ b/secure/caroot/Makefile
@@ -13,4 +13,5 @@ cleancerts: .PHONY
@${MAKE} -C ${.CURDIR}/trusted ${.TARGET}
updatecerts: .PHONY cleancerts fetchcerts
- perl ${.CURDIR}/MAca-bundle.pl -i certdata.txt -o ${.CURDIR}/trusted
+ perl ${.CURDIR}/ca-extract.pl -i certdata.txt \
+ -t ${.CURDIR}/trusted -u ${.CURDIR}/untrusted
diff --git a/secure/caroot/ca-extract.pl b/secure/caroot/ca-extract.pl
new file mode 100755
index 000000000000..75f8352e384e
--- /dev/null
+++ b/secure/caroot/ca-extract.pl
@@ -0,0 +1,253 @@
+#!/usr/bin/env perl
+#-
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2011, 2013 Matthias Andree <mandree@FreeBSD.org>
+# Copyright (c) 2018 Allan Jude <allanjude@FreeBSD.org>
+# Copyright (c) 2025 Dag-Erling Smørgrav <des@FreeBSD.org>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#
+# ca-extract.pl -- Extract trusted and untrusted certificates from
+# Mozilla's certdata.txt.
+#
+# Rewritten in September 2011 by Matthias Andree to heed untrust
+#
+
+use strict;
+use warnings;
+use Carp;
+use MIME::Base64;
+use Getopt::Long;
+use Time::Local qw( timegm_posix );
+use POSIX qw( strftime );
+
+my $generated = '@' . 'generated';
+my $inputfh = *STDIN;
+my $debug = 0;
+my $infile;
+my $trustdir = "trusted";
+my $untrustdir = "untrusted";
+my %labels;
+my %certs;
+my %trusts;
+my %expires;
+
+$debug++
+ if defined $ENV{'WITH_DEBUG'}
+ and $ENV{'WITH_DEBUG'} !~ m/(?i)^(no|0|false|)$/;
+
+GetOptions (
+ "debug+" => \$debug,
+ "infile:s" => \$infile,
+ "trustdir:s" => \$trustdir,
+ "untrustdir:s" => \$untrustdir)
+ or die("Error in command line arguments\n$0 [-d] [-i input-file] [-t trust-dir] [-u untrust-dir]\n");
+
+if ($infile) {
+ open($inputfh, "<", $infile) or die "Failed to open $infile";
+}
+
+sub print_header($$)
+{
+ my $dstfile = shift;
+ my $label = shift;
+
+ print $dstfile <<EOFH;
+##
+## $label
+##
+## This is a single X.509 certificate for a public Certificate
+## Authority (CA). It was automatically extracted from Mozilla's
+## root CA list (the file `certdata.txt' in security/nss).
+##
+## $generated
+##
+EOFH
+}
+
+sub printcert($$$)
+{
+ my ($fh, $label, $certdata) = @_;
+ return unless $certdata;
+ open(OUT, "|-", qw(openssl x509 -text -inform DER -fingerprint))
+ or die "could not pipe to openssl x509";
+ print OUT $certdata;
+ close(OUT) or die "openssl x509 failed with exit code $?";
+}
+
+# converts a datastream that is to be \177-style octal constants
+# from <> to a (binary) string and returns it
+sub graboct($)
+{
+ my $ifh = shift;
+ my $data = "";
+
+ while (<$ifh>) {
+ last if /^END/;
+ $data .= join('', map { chr(oct($_)) } m/\\([0-7]{3})/g);
+ }
+
+ return $data;
+}
+
+sub grabcert($)
+{
+ my $ifh = shift;
+ my $certdata;
+ my $cka_label = '';
+ my $serial = 0;
+ my $distrust = 0;
+
+ while (<$ifh>) {
+ chomp;
+ last if ($_ eq '');
+
+ if (/^CKA_LABEL UTF8 "([^"]+)"/) {
+ $cka_label = $1;
+ }
+
+ if (/^CKA_VALUE MULTILINE_OCTAL/) {
+ $certdata = graboct($ifh);
+ }
+
+ if (/^CKA_SERIAL_NUMBER MULTILINE_OCTAL/) {
+ $serial = graboct($ifh);
+ }
+
+ if (/^CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL/)
+ {
+ my $distrust_after = graboct($ifh);
+ my ($year, $mon, $mday, $hour, $min, $sec) = unpack "A2A2A2A2A2A2", $distrust_after;
+ $distrust_after = timegm_posix($sec, $min, $hour, $mday, $mon - 1, $year + 100);
+ $expires{$cka_label."\0".$serial} = $distrust_after;
+ }
+ }
+ return ($serial, $cka_label, $certdata);
+}
+
+sub grabtrust($) {
+ my $ifh = shift;
+ my $cka_label;
+ my $serial;
+ my $maytrust = 0;
+ my $distrust = 0;
+
+ while (<$ifh>) {
+ chomp;
+ last if ($_ eq '');
+
+ if (/^CKA_LABEL UTF8 "([^"]+)"/) {
+ $cka_label = $1;
+ }
+
+ if (/^CKA_SERIAL_NUMBER MULTILINE_OCTAL/) {
+ $serial = graboct($ifh);
+ }
+
+ if (/^CKA_TRUST_SERVER_AUTH CK_TRUST (\S+)$/) {
+ if ($1 eq 'CKT_NSS_NOT_TRUSTED') {
+ $distrust = 1;
+ } elsif ($1 eq 'CKT_NSS_TRUSTED_DELEGATOR') {
+ $maytrust = 1;
+ } elsif ($1 ne 'CKT_NSS_MUST_VERIFY_TRUST') {
+ confess "Unknown trust setting on line $.:\n"
+ . "$_\n"
+ . "Script must be updated:";
+ }
+ }
+ }
+
+ if (!$maytrust && !$distrust && $debug) {
+ print STDERR "line $.: no explicit trust/distrust found for $cka_label\n";
+ }
+
+ my $trust = ($maytrust and not $distrust);
+ return ($serial, $cka_label, $trust);
+}
+
+while (<$inputfh>) {
+ if (/^CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE/) {
+ my ($serial, $label, $certdata) = grabcert($inputfh);
+ if (defined $certs{$label."\0".$serial}) {
+ warn "Certificate $label duplicated!\n";
+ }
+ if (defined $certdata) {
+ $certs{$label."\0".$serial} = $certdata;
+ # We store the label in a separate hash because truncating the key
+ # with \0 was causing garbage data after the end of the text.
+ $labels{$label."\0".$serial} = $label;
+ }
+ } elsif (/^CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST/) {
+ my ($serial, $label, $trust) = grabtrust($inputfh);
+ if (defined $trusts{$label."\0".$serial}) {
+ warn "Trust for $label duplicated!\n";
+ }
+ $trusts{$label."\0".$serial} = $trust;
+ $labels{$label."\0".$serial} = $label;
+ } elsif (/^CVS_ID.*Revision: ([^ ]*).*/) {
+ print "## Source: \"certdata.txt\" CVS revision $1\n##\n\n";
+ }
+}
+
+sub label_to_filename(@) {
+ my @res = @_;
+ map { s/\0.*//; s/[^[:alnum:]\-]/_/g; $_ = "$_.pem"; } @res;
+ return wantarray ? @res : $res[0];
+}
+
+my $untrusted = 0;
+my $trusted = 0;
+my $now = time;
+
+foreach my $it (sort {uc($a) cmp uc($b)} keys %certs) {
+ my $fh = *STDOUT;
+ my $outputdir;
+ my $filename;
+ if (exists($expires{$it}) &&
+ $now >= $expires{$it} + 398 * 24 * 60 * 60) {
+ print(STDERR "## Expired: $labels{$it}\n");
+ $outputdir = $untrustdir;
+ $untrusted++;
+ } elsif (!$trusts{$it}) {
+ print(STDERR "## Untrusted: $labels{$it}\n");
+ $outputdir = $untrustdir;
+ $untrusted++;
+ } else {
+ print(STDERR "## Trusted: $labels{$it}\n");
+ $outputdir = $trustdir;
+ $trusted++;
+ }
+ $filename = label_to_filename($labels{$it});
+ open($fh, ">", "$outputdir/$filename") or die "Failed to open certificate $outputdir/$filename";
+ print_header($fh, $labels{$it});
+ printcert($fh, $labels{$it}, $certs{$it});
+ if ($outputdir) {
+ close($fh) or die "Unable to close: $filename";
+ } else {
+ print $fh "\n\n\n";
+ }
+}
+
+printf STDERR "## Trusted certificates: %4d\n", $trusted;
+printf STDERR "## Untrusted certificates: %4d\n", $untrusted;
diff --git a/secure/caroot/trusted/Makefile b/secure/caroot/trusted/Makefile
index b2fe43fcb802..a47e781262b8 100644
--- a/secure/caroot/trusted/Makefile
+++ b/secure/caroot/trusted/Makefile
@@ -1,10 +1,10 @@
BINDIR= /usr/share/certs/trusted
-TRUSTED_CERTS!= echo ${.CURDIR}/*.pem 2> /dev/null || true
+TRUSTED_CERTS!= (cd ${.CURDIR} && echo *.pem)
FILES+= ${TRUSTED_CERTS}
-cleancerts:
- @[ -z "${TRUSTED_CERTS}" ] || rm ${TRUSTED_CERTS}
+cleancerts: .PHONY
+ @(cd ${.CURDIR} && rm -f ${TRUSTED_CERTS})
.include <bsd.prog.mk>
diff --git a/secure/caroot/untrusted/Makefile b/secure/caroot/untrusted/Makefile
index 19d7359ddcb9..45df0a55ebd9 100644
--- a/secure/caroot/untrusted/Makefile
+++ b/secure/caroot/untrusted/Makefile
@@ -1,7 +1,10 @@
BINDIR= /usr/share/certs/untrusted
-UNTRUSTED_CERTS!= echo ${.CURDIR}/*.pem 2> /dev/null || true
+UNTRUSTED_CERTS!= (cd ${.CURDIR} && echo *.pem)
FILES+= ${UNTRUSTED_CERTS}
+cleancerts: .PHONY
+ @(cd ${.CURDIR} && rm -f ${UNTRUSTED_CERTS})
+
.include <bsd.prog.mk>
diff --git a/share/man/man4/puc.4 b/share/man/man4/puc.4
index a29376d3f2d5..624c215027af 100644
--- a/share/man/man4/puc.4
+++ b/share/man/man4/puc.4
@@ -257,6 +257,8 @@ Sunix SER5xxxx 8/4/2 port serial
.It
Syba Tech Ltd PCI-4S2P-550-ECP
.It
+Systembase SB16C1054/8 4/8 port serial
+.It
Titan PCI-800H/PCI-200H
.It
VScom:
diff --git a/share/man/man7/simd.7 b/share/man/man7/simd.7
index 2c3ed3de411e..d5092348d9b3 100644
--- a/share/man/man7/simd.7
+++ b/share/man/man7/simd.7
@@ -24,7 +24,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE
.
-.Dd July 29, 2025
+.Dd November 18, 2024
.Dt SIMD 7
.Os
.Sh NAME
@@ -50,43 +50,48 @@ can be used to override this mechanism.
.Pp
Enhanced functions are present for the following architectures:
.Bl -column FUNCTION_________ aarch64_ arm_ amd64_ i386_ ppc64_ -offset indent
-.It Em FUNCTION Ta Em AARCH64 Ta Em ARM Ta Em AMD64 Ta Em PPC64
-.It bcmp Ta A Ta Ta S1
-.It bcopy Ta A Ta S Ta S Ta SV
-.It bzero Ta A Ta S Ta S
-.It div Ta Ta Ta S
+.It Em FUNCTION Ta Em AARCH64 Ta Em ARM Ta Em AMD64 Ta Em I386 Ta Em PPC64
+.It bcmp Ta A Ta Ta S1 Ta S
+.It bcopy Ta A Ta S Ta S Ta S Ta SV
+.It bzero Ta A Ta S Ta S Ta S
+.It div Ta Ta Ta S Ta S
.It index Ta A Ta Ta S1
-.It ldiv Ta Ta Ta S
+.It ldiv Ta Ta Ta S Ta S
.It lldiv Ta Ta Ta S
.It memchr Ta A Ta Ta S1
-.It memcmp Ta A Ta S Ta S1
+.It memcmp Ta A Ta S Ta S1 Ta S
.It memccpy Ta A Ta Ta S1
-.It memcpy Ta A Ta S Ta S Ta SV
-.It memmove Ta A Ta S Ta S Ta SV
+.It memcpy Ta A Ta S Ta S Ta S Ta SV
+.It memmove Ta A Ta S Ta S Ta S Ta SV
.It memrchr Ta A Ta Ta S1
-.It memset Ta A Ta S Ta S
-.It rindex Ta A Ta Ta S1
+.It memset Ta A Ta S Ta S Ta S
+.It rindex Ta A Ta Ta S1 Ta S
.It stpcpy Ta A Ta Ta S1
.It stpncpy Ta Ta Ta S1
-.It strcat Ta A Ta Ta S1
-.It strchr Ta A Ta Ta S1
+.It strcat Ta A Ta Ta S1 Ta S
+.It strchr Ta A Ta Ta S1 Ta S
.It strchrnul Ta A Ta Ta S1
-.It strcmp Ta A Ta S Ta S1
-.It strcpy Ta A Ta Ta S1 Ta S2
+.It strcmp Ta A Ta S Ta S1 Ta S
+.It strcpy Ta A Ta Ta S1 Ta S Ta S2
.It strcspn Ta S Ta Ta S2
.It strlcat Ta A Ta Ta S1
.It strlcpy Ta A Ta Ta S1
.It strlen Ta A Ta S Ta S1
.It strncat Ta A Ta Ta S1
-.It strncmp Ta A Ta S Ta S1
-.It strncpy Ta Ta Ta S1 Ta S2
+.It strncmp Ta A Ta S Ta S1 Ta S
+.It strncpy Ta Ta Ta S1 Ta Ta S2
.It strnlen Ta A Ta Ta S1
-.It strrchr Ta A Ta Ta S1
+.It strrchr Ta A Ta Ta S1 Ta S
.It strpbrk Ta S Ta Ta S2
.It strsep Ta S Ta Ta S2
.It strspn Ta S Ta Ta S2
+.It swab Ta Ta Ta Ta S
.It timingsafe_bcmp Ta A Ta Ta S1
.It timingsafe_memcmp Ta S Ta Ta S
+.It wcschr Ta Ta Ta Ta S
+.It wcscmp Ta Ta Ta Ta S
+.It wcslen Ta Ta Ta Ta S
+.It wmemchr Ta Ta Ta Ta S
.El
.Pp
.Sy S Ns :\ scalar (non-SIMD),
diff --git a/sys/compat/linuxkpi/common/include/acpi/acpi.h b/sys/compat/linuxkpi/common/include/acpi/acpi.h
index 1e398d05ba20..016c7ede0f6e 100644
--- a/sys/compat/linuxkpi/common/include/acpi/acpi.h
+++ b/sys/compat/linuxkpi/common/include/acpi/acpi.h
@@ -37,7 +37,7 @@
/*
* LINUXKPI_WANT_LINUX_ACPI is a temporary workaround to allow drm-kmod
* to update all needed branches without breaking builds.
- * Once that happened and checks are implemented based on __FreeBSD_verison
+ * Once that happened and checks are implemented based on __FreeBSD_version
* we will remove these conditions again.
*/
diff --git a/sys/compat/linuxkpi/common/include/linux/netdevice.h b/sys/compat/linuxkpi/common/include/linux/netdevice.h
index cd7d23077a62..3b808a4a1749 100644
--- a/sys/compat/linuxkpi/common/include/linux/netdevice.h
+++ b/sys/compat/linuxkpi/common/include/linux/netdevice.h
@@ -4,7 +4,7 @@
* Copyright (c) 2010 Panasas, Inc.
* Copyright (c) 2013-2019 Mellanox Technologies, Ltd.
* All rights reserved.
- * Copyright (c) 2020-2021 The FreeBSD Foundation
+ * Copyright (c) 2020-2025 The FreeBSD Foundation
* Copyright (c) 2020-2022 Bjoern A. Zeeb
*
* Portions of this software were developed by Björn Zeeb
@@ -302,6 +302,13 @@ netdev_rss_key_fill(uint32_t *buf, size_t len)
get_random_bytes(buf, len);
}
+static inline void
+__hw_addr_init(struct netdev_hw_addr_list *list)
+{
+ list->count = 0;
+ INIT_LIST_HEAD(&list->addr_list);
+}
+
static inline int
netdev_hw_addr_list_count(struct netdev_hw_addr_list *list)
{
diff --git a/sys/compat/linuxkpi/common/include/net/mac80211.h b/sys/compat/linuxkpi/common/include/net/mac80211.h
index 19f7bcff29dc..0106e6648bd4 100644
--- a/sys/compat/linuxkpi/common/include/net/mac80211.h
+++ b/sys/compat/linuxkpi/common/include/net/mac80211.h
@@ -87,6 +87,9 @@ enum mcast_filter_flags {
FIF_PSPOLL = BIT(5),
FIF_CONTROL = BIT(6),
FIF_MCAST_ACTION = BIT(7),
+
+ /* Must stay last. */
+ FIF_FLAGS_MASK = BIT(8)-1,
};
enum ieee80211_bss_changed {
diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c
index 500c1c1d52eb..e248588dd275 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -1179,7 +1179,7 @@ lkpi_find_lkpi80211_chan(struct lkpi_hw *lhw,
channels = hw->wiphy->bands[band]->channels;
for (i = 0; i < nchans; i++) {
- if (channels[i].hw_value == c->ic_ieee)
+ if (channels[i].center_freq == c->ic_freq)
return (&channels[i]);
}
@@ -1717,6 +1717,24 @@ lkpi_iv_key_update_end(struct ieee80211vap *vap)
}
#endif
+static void
+lkpi_cleanup_mcast_list_locked(struct lkpi_hw *lhw)
+{
+ struct list_head *le, *next;
+ struct netdev_hw_addr *addr;
+
+ if (lhw->mc_list.count != 0) {
+ list_for_each_safe(le, next, &lhw->mc_list.addr_list) {
+ addr = list_entry(le, struct netdev_hw_addr, addr_list);
+ list_del(le);
+ lhw->mc_list.count--;
+ free(addr, M_LKPI80211);
+ }
+ }
+ KASSERT(lhw->mc_list.count == 0, ("%s: mc_list %p count %d != 0\n",
+ __func__, &lhw->mc_list, lhw->mc_list.count));
+}
+
static u_int
lkpi_ic_update_mcast_copy(void *arg, struct sockaddr_dl *sdl, u_int cnt)
{
@@ -1753,16 +1771,13 @@ lkpi_ic_update_mcast_copy(void *arg, struct sockaddr_dl *sdl, u_int cnt)
}
static void
-lkpi_update_mcast_filter(struct ieee80211com *ic, bool force)
+lkpi_update_mcast_filter(struct ieee80211com *ic)
{
struct lkpi_hw *lhw;
struct ieee80211_hw *hw;
- struct netdev_hw_addr_list mc_list;
- struct list_head *le, *next;
- struct netdev_hw_addr *addr;
- struct ieee80211vap *vap;
u64 mc;
- unsigned int changed_flags, total_flags;
+ unsigned int changed_flags, flags;
+ bool scanning;
lhw = ic->ic_softc;
@@ -1770,44 +1785,32 @@ lkpi_update_mcast_filter(struct ieee80211com *ic, bool force)
lhw->ops->configure_filter == NULL)
return;
- if (!lhw->update_mc && !force)
- return;
+ LKPI_80211_LHW_SCAN_LOCK(lhw);
+ scanning = (lhw->scan_flags & LKPI_LHW_SCAN_RUNNING) != 0;
+ LKPI_80211_LHW_SCAN_UNLOCK(lhw);
- changed_flags = total_flags = 0;
- mc_list.count = 0;
- INIT_LIST_HEAD(&mc_list.addr_list);
- if (ic->ic_allmulti == 0) {
- TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
- if_foreach_llmaddr(vap->iv_ifp,
- lkpi_ic_update_mcast_copy, &mc_list);
- } else {
- changed_flags |= FIF_ALLMULTI;
- }
+ LKPI_80211_LHW_MC_LOCK(lhw);
+
+ flags = 0;
+ if (scanning)
+ flags |= FIF_BCN_PRBRESP_PROMISC;
+ if (lhw->mc_all_multi)
+ flags |= FIF_ALLMULTI;
hw = LHW_TO_HW(lhw);
- mc = lkpi_80211_mo_prepare_multicast(hw, &mc_list);
- /*
- * XXX-BZ make sure to get this sorted what is a change,
- * what gets all set; what was already set?
- */
- total_flags = changed_flags;
- lkpi_80211_mo_configure_filter(hw, changed_flags, &total_flags, mc);
+ mc = lkpi_80211_mo_prepare_multicast(hw, &lhw->mc_list);
+
+ changed_flags = (lhw->mc_flags ^ flags) & FIF_FLAGS_MASK;
+ lkpi_80211_mo_configure_filter(hw, changed_flags, &flags, mc);
+ lhw->mc_flags = flags;
#ifdef LINUXKPI_DEBUG_80211
if (linuxkpi_debug_80211 & D80211_TRACE)
- printf("%s: changed_flags %#06x count %d total_flags %#010x\n",
- __func__, changed_flags, mc_list.count, total_flags);
+ printf("%s: changed_flags %#06x count %d mc_flags %#010x\n",
+ __func__, changed_flags, lhw->mc_list.count, lhw->mc_flags);
#endif
- if (mc_list.count != 0) {
- list_for_each_safe(le, next, &mc_list.addr_list) {
- addr = list_entry(le, struct netdev_hw_addr, addr_list);
- free(addr, M_LKPI80211);
- mc_list.count--;
- }
- }
- KASSERT(mc_list.count == 0, ("%s: mc_list %p count %d != 0\n",
- __func__, &mc_list, mc_list.count));
+ LKPI_80211_LHW_MC_UNLOCK(lhw);
}
static enum ieee80211_bss_changed
@@ -1926,19 +1929,19 @@ lkpi_disassoc(struct ieee80211_sta *sta, struct ieee80211_vif *vif,
struct lkpi_hw *lhw)
{
enum ieee80211_bss_changed changed;
+ struct lkpi_vif *lvif;
changed = 0;
sta->aid = 0;
if (vif->cfg.assoc) {
- lhw->update_mc = true;
- lkpi_update_mcast_filter(lhw->ic, true);
-
vif->cfg.assoc = false;
vif->cfg.aid = 0;
changed |= BSS_CHANGED_ASSOC;
IMPROVE();
+ lkpi_update_mcast_filter(lhw->ic);
+
/*
* Executing the bss_info_changed(BSS_CHANGED_ASSOC) with
* assoc = false right away here will remove the sta from
@@ -1949,6 +1952,9 @@ lkpi_disassoc(struct ieee80211_sta *sta, struct ieee80211_vif *vif,
* bss_info_changed() update.
* See lkpi_sta_run_to_init() for more detailed comment.
*/
+
+ lvif = VIF_TO_LVIF(vif);
+ lvif->beacons = 0;
}
return (changed);
@@ -2219,6 +2225,7 @@ lkpi_sta_scan_to_auth(struct ieee80211vap *vap, enum ieee80211_state nstate, int
/* vif->bss_conf.basic_rates ? Where exactly? */
+ lvif->beacons = 0;
/* Should almost assert it is this. */
vif->cfg.assoc = false;
vif->cfg.aid = 0;
@@ -2408,6 +2415,7 @@ lkpi_sta_auth_to_scan(struct ieee80211vap *vap, enum ieee80211_state nstate, int
struct lkpi_sta *lsta;
struct ieee80211_sta *sta;
struct ieee80211_prep_tx_info prep_tx_info;
+ enum ieee80211_bss_changed bss_changed;
int error;
lhw = vap->iv_ic->ic_softc;
@@ -2479,6 +2487,11 @@ lkpi_sta_auth_to_scan(struct ieee80211vap *vap, enum ieee80211_state nstate, int
lsta->added_to_drv = false; /* mo manages. */
#endif
+ bss_changed = 0;
+ vif->bss_conf.dtim_period = 0; /* go back to 0. */
+ bss_changed |= BSS_CHANGED_BEACON_INFO;
+ lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, bss_changed);
+
lkpi_lsta_dump(lsta, ni, __func__, __LINE__);
LKPI_80211_LVIF_LOCK(lvif);
@@ -2807,6 +2820,8 @@ _lkpi_sta_assoc_to_down(struct ieee80211vap *vap, enum ieee80211_state nstate, i
vif->cfg.ssid_len = 0;
memset(vif->cfg.ssid, '\0', sizeof(vif->cfg.ssid));
bss_changed |= BSS_CHANGED_BSSID;
+ vif->bss_conf.dtim_period = 0; /* go back to 0. */
+ bss_changed |= BSS_CHANGED_BEACON_INFO;
lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, bss_changed);
LKPI_80211_LVIF_LOCK(lvif);
@@ -2939,6 +2954,7 @@ lkpi_sta_assoc_to_run(struct ieee80211vap *vap, enum ieee80211_state nstate, int
bss_changed |= lkpi_wme_update(lhw, vap, true);
#endif
if (!vif->cfg.assoc || vif->cfg.aid != IEEE80211_NODE_AID(ni)) {
+ lvif->beacons = 0;
vif->cfg.assoc = true;
vif->cfg.aid = IEEE80211_NODE_AID(ni);
bss_changed |= BSS_CHANGED_ASSOC;
@@ -2987,9 +3003,6 @@ lkpi_sta_assoc_to_run(struct ieee80211vap *vap, enum ieee80211_state nstate, int
* - set_key (?)
* - ipv6_addr_change (?)
*/
- /* Prepare_multicast && configure_filter. */
- lhw->update_mc = true;
- lkpi_update_mcast_filter(vap->iv_ic, true);
if (!ieee80211_node_is_authorized(ni)) {
IMPROVE("net80211 does not consider node authorized");
@@ -3028,6 +3041,9 @@ lkpi_sta_assoc_to_run(struct ieee80211vap *vap, enum ieee80211_state nstate, int
bss_changed |= lkpi_update_dtim_tsf(vif, ni, vap, __func__, __LINE__);
lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, bss_changed);
+ /* Prepare_multicast && configure_filter. */
+ lkpi_update_mcast_filter(vap->iv_ic);
+
out:
wiphy_unlock(hw->wiphy);
IEEE80211_LOCK(vap->iv_ic);
@@ -3408,6 +3424,8 @@ lkpi_sta_run_to_init(struct ieee80211vap *vap, enum ieee80211_state nstate, int
vif->bss_conf.use_short_preamble = false;
vif->bss_conf.qos = false;
/* XXX BSS_CHANGED_???? */
+ vif->bss_conf.dtim_period = 0; /* go back to 0. */
+ bss_changed |= BSS_CHANGED_BEACON_INFO;
lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, bss_changed);
LKPI_80211_LVIF_LOCK(lvif);
@@ -3710,6 +3728,42 @@ lkpi_ic_wme_update(struct ieee80211com *ic)
return (0); /* unused */
}
+static void
+lkpi_iv_sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
+ int subtype, const struct ieee80211_rx_stats *rxs, int rssi, int nf)
+{
+ struct lkpi_hw *lhw;
+ struct ieee80211_hw *hw;
+ struct lkpi_vif *lvif;
+ struct ieee80211_vif *vif;
+ enum ieee80211_bss_changed bss_changed;
+
+ lvif = VAP_TO_LVIF(ni->ni_vap);
+
+ lvif->iv_recv_mgmt(ni, m0, subtype, rxs, rssi, nf);
+
+ switch (subtype) {
+ case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
+ break;
+ case IEEE80211_FC0_SUBTYPE_BEACON:
+ lvif->beacons++;
+ break;
+ default:
+ return;
+ }
+
+ vif = LVIF_TO_VIF(lvif);
+ lhw = ni->ni_ic->ic_softc;
+ hw = LHW_TO_HW(lhw);
+
+ /*
+ * If this direct call to mo_bss_info_changed will not work due to
+ * locking, see if queue_work() is fast enough.
+ */
+ bss_changed = lkpi_update_dtim_tsf(vif, ni, ni->ni_vap, __func__, __LINE__);
+ lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, bss_changed);
+}
+
/*
* Change link-layer address on the vif (if the vap is not started/"UP").
* This can happen if a user changes 'ether' using ifconfig.
@@ -3892,7 +3946,7 @@ lkpi_ic_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ],
lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, changed);
/* Force MC init. */
- lkpi_update_mcast_filter(ic, true);
+ lkpi_update_mcast_filter(ic);
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
@@ -3905,6 +3959,8 @@ lkpi_ic_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ],
vap->iv_newstate = lkpi_iv_newstate;
lvif->iv_update_bss = vap->iv_update_bss;
vap->iv_update_bss = lkpi_iv_update_bss;
+ lvif->iv_recv_mgmt = vap->iv_recv_mgmt;
+ vap->iv_recv_mgmt = lkpi_iv_sta_recv_mgmt;
#ifdef LKPI_80211_HW_CRYPTO
/* Key management. */
@@ -4027,8 +4083,30 @@ lkpi_ic_vap_delete(struct ieee80211vap *vap)
static void
lkpi_ic_update_mcast(struct ieee80211com *ic)
{
+ struct ieee80211vap *vap;
+ struct lkpi_hw *lhw;
+
+ lhw = ic->ic_softc;
+ if (lhw->ops->prepare_multicast == NULL ||
+ lhw->ops->configure_filter == NULL)
+ return;
+
+ LKPI_80211_LHW_MC_LOCK(lhw);
+ /* Cleanup anything on the current list. */
+ lkpi_cleanup_mcast_list_locked(lhw);
- lkpi_update_mcast_filter(ic, false);
+ /* Build up the new list (or allmulti). */
+ if (ic->ic_allmulti == 0) {
+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
+ if_foreach_llmaddr(vap->iv_ifp,
+ lkpi_ic_update_mcast_copy, &lhw->mc_list);
+ lhw->mc_all_multi = false;
+ } else {
+ lhw->mc_all_multi = true;
+ }
+ LKPI_80211_LHW_MC_UNLOCK(lhw);
+
+ lkpi_update_mcast_filter(ic);
TRACEOK();
}
@@ -4264,6 +4342,8 @@ sw_scan:
if (vap->iv_state == IEEE80211_S_SCAN)
lkpi_hw_conf_idle(hw, false);
+ lkpi_update_mcast_filter(ic);
+
lkpi_80211_mo_sw_scan_start(hw, vif, vif->addr);
/* net80211::scan_start() handled PS for us. */
IMPROVE();
@@ -4371,7 +4451,6 @@ sw_scan:
struct ieee80211_channel *c;
c = ss->ss_chans[ss->ss_next + i];
- lc->hw_value = c->ic_ieee;
lc->center_freq = c->ic_freq; /* XXX */
/* lc->flags */
lc->band = lkpi_net80211_chan_to_nl80211_band(c);
@@ -4400,7 +4479,6 @@ sw_scan:
}
}
#endif
-
hw_req->req.n_ssids = ssid_count;
if (hw_req->req.n_ssids > 0) {
ssids = (struct cfg80211_ssid *)lc;
@@ -4447,6 +4525,8 @@ sw_scan:
return;
}
+ lkpi_update_mcast_filter(ic);
+
error = lkpi_80211_mo_hw_scan(hw, vif, hw_req);
if (error != 0) {
ieee80211_cancel_scan(vap);
@@ -4472,6 +4552,7 @@ sw_scan:
lhw->scan_flags &= ~LKPI_LHW_SCAN_RUNNING;
}
LKPI_80211_LHW_SCAN_UNLOCK(lhw);
+ lkpi_update_mcast_filter(ic);
/*
* XXX-SIGH magic number.
@@ -5839,8 +5920,9 @@ lkpi_ic_getradiocaps(struct ieee80211com *ic, int maxchan,
cflags &= ~NET80211_CBW_FLAG_HT40;
error = ieee80211_add_channel_cbw(c, maxchan, n,
- channels[i].hw_value, channels[i].center_freq,
- channels[i].max_power,
+ ieee80211_mhz2ieee(channels[i].center_freq,
+ lkpi_nl80211_band_to_net80211_band(channels[i].band)),
+ channels[i].center_freq, channels[i].max_power,
nflags, bands, cflags);
/* net80211::ENOBUFS: *n >= maxchans */
if (error != 0 && error != ENOBUFS)
@@ -5911,8 +5993,9 @@ lkpi_ic_getradiocaps(struct ieee80211com *ic, int maxchan,
cflags &= ~NET80211_CBW_FLAG_HT40;
error = ieee80211_add_channel_cbw(c, maxchan, n,
- channels[i].hw_value, channels[i].center_freq,
- channels[i].max_power,
+ ieee80211_mhz2ieee(channels[i].center_freq,
+ lkpi_nl80211_band_to_net80211_band(channels[i].band)),
+ channels[i].center_freq, channels[i].max_power,
nflags, bands, cflags);
/* net80211::ENOBUFS: *n >= maxchans */
if (error != 0 && error != ENOBUFS)
@@ -5960,7 +6043,9 @@ linuxkpi_ieee80211_alloc_hw(size_t priv_len, const struct ieee80211_ops *ops)
LKPI_80211_LHW_SCAN_LOCK_INIT(lhw);
LKPI_80211_LHW_TXQ_LOCK_INIT(lhw);
sx_init_flags(&lhw->lvif_sx, "lhw-lvif", SX_RECURSE | SX_DUPOK);
+ LKPI_80211_LHW_MC_LOCK_INIT(lhw);
TAILQ_INIT(&lhw->lvif_head);
+ __hw_addr_init(&lhw->mc_list);
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
lhw->txq_generation[ac] = 1;
TAILQ_INIT(&lhw->scheduled_txqs[ac]);
@@ -6057,10 +6142,15 @@ linuxkpi_ieee80211_iffree(struct ieee80211_hw *hw)
}
}
+ LKPI_80211_LHW_MC_LOCK(lhw);
+ lkpi_cleanup_mcast_list_locked(lhw);
+ LKPI_80211_LHW_MC_UNLOCK(lhw);
+
/* Cleanup more of lhw here or in wiphy_free()? */
LKPI_80211_LHW_TXQ_LOCK_DESTROY(lhw);
LKPI_80211_LHW_SCAN_LOCK_DESTROY(lhw);
sx_destroy(&lhw->lvif_sx);
+ LKPI_80211_LHW_MC_LOCK_DESTROY(lhw)
IMPROVE();
}
@@ -7865,8 +7955,11 @@ linuxkpi_ieee80211_connection_loss(struct ieee80211_vif *vif)
nstate = IEEE80211_S_INIT;
arg = 0; /* Not a valid reason. */
- ic_printf(vap->iv_ic, "%s: vif %p vap %p state %s\n", __func__,
- vif, vap, ieee80211_state_name[vap->iv_state]);
+ ic_printf(vap->iv_ic, "%s: vif %p vap %p state %s (synched %d, assoc %d "
+ "beacons %d dtim_period %d)\n", __func__, vif, vap,
+ ieee80211_state_name[vap->iv_state],
+ lvif->lvif_bss_synched, vif->cfg.assoc, lvif->beacons,
+ vif->bss_conf.dtim_period);
ieee80211_new_state(vap, nstate, arg);
}
@@ -7879,8 +7972,11 @@ linuxkpi_ieee80211_beacon_loss(struct ieee80211_vif *vif)
lvif = VIF_TO_LVIF(vif);
vap = LVIF_TO_VAP(lvif);
- ic_printf(vap->iv_ic, "%s: vif %p vap %p state %s\n", __func__,
- vif, vap, ieee80211_state_name[vap->iv_state]);
+ ic_printf(vap->iv_ic, "%s: vif %p vap %p state %s (synched %d, assoc %d "
+ "beacons %d dtim_period %d)\n", __func__, vif, vap,
+ ieee80211_state_name[vap->iv_state],
+ lvif->lvif_bss_synched, vif->cfg.assoc, lvif->beacons,
+ vif->bss_conf.dtim_period);
ieee80211_beacon_miss(vap->iv_ic);
}
diff --git a/sys/compat/linuxkpi/common/src/linux_80211.h b/sys/compat/linuxkpi/common/src/linux_80211.h
index 89afec1235bd..eaf6d804af4c 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.h
+++ b/sys/compat/linuxkpi/common/src/linux_80211.h
@@ -187,6 +187,11 @@ struct lkpi_vif {
enum ieee80211_state, int);
struct ieee80211_node * (*iv_update_bss)(struct ieee80211vap *,
struct ieee80211_node *);
+ void (*iv_recv_mgmt)(struct ieee80211_node *,
+ struct mbuf *, int,
+ const struct ieee80211_rx_stats *,
+ int, int);
+
struct list_head lsta_list;
struct lkpi_sta *lvif_bss;
@@ -194,6 +199,7 @@ struct lkpi_vif {
struct ieee80211_node *key_update_iv_bss;
int ic_unlocked; /* Count of ic unlocks pending (*mo_set_key) */
int nt_unlocked; /* Count of nt unlocks pending (*mo_set_key) */
+ int beacons; /* # of beacons since assoc */
bool lvif_bss_synched;
bool added_to_drv; /* Driver knows; i.e. we called add_interface(). */
@@ -223,6 +229,9 @@ struct lkpi_hw { /* name it mac80211_sc? */
struct sx lvif_sx;
struct list_head lchanctx_list;
+ struct netdev_hw_addr_list mc_list;
+ unsigned int mc_flags;
+ struct sx mc_sx;
struct mtx txq_mtx;
uint32_t txq_generation[IEEE80211_NUM_ACS];
@@ -279,7 +288,7 @@ struct lkpi_hw { /* name it mac80211_sc? */
int max_rates; /* Maximum number of bitrates supported in any channel. */
int scan_ie_len; /* Length of common per-band scan IEs. */
- bool update_mc;
+ bool mc_all_multi;
bool update_wme;
bool rxq_stopped;
@@ -369,6 +378,13 @@ struct lkpi_wiphy {
#define LKPI_80211_LHW_LVIF_LOCK(_lhw) sx_xlock(&(_lhw)->lvif_sx)
#define LKPI_80211_LHW_LVIF_UNLOCK(_lhw) sx_xunlock(&(_lhw)->lvif_sx)
+#define LKPI_80211_LHW_MC_LOCK_INIT(_lhw) \
+ sx_init_flags(&lhw->mc_sx, "lhw-mc", 0);
+#define LKPI_80211_LHW_MC_LOCK_DESTROY(_lhw) \
+ sx_destroy(&lhw->mc_sx);
+#define LKPI_80211_LHW_MC_LOCK(_lhw) sx_xlock(&(_lhw)->mc_sx)
+#define LKPI_80211_LHW_MC_UNLOCK(_lhw) sx_xunlock(&(_lhw)->mc_sx)
+
#define LKPI_80211_LVIF_LOCK(_lvif) mtx_lock(&(_lvif)->mtx)
#define LKPI_80211_LVIF_UNLOCK(_lvif) mtx_unlock(&(_lvif)->mtx)
diff --git a/sys/conf/files.x86 b/sys/conf/files.x86
index 9976e9cfec5d..953da7dd1284 100644
--- a/sys/conf/files.x86
+++ b/sys/conf/files.x86
@@ -146,6 +146,7 @@ dev/hyperv/vmbus/vmbus_et.c optional hyperv
dev/hyperv/vmbus/vmbus_if.m optional hyperv
dev/hyperv/vmbus/vmbus_res.c optional hyperv
dev/hyperv/vmbus/vmbus_xact.c optional hyperv
+dev/ichwd/i6300esbwd.c optional ichwd
dev/ichwd/ichwd.c optional ichwd
dev/imcsmb/imcsmb.c optional imcsmb
dev/imcsmb/imcsmb_pci.c optional imcsmb pci
diff --git a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c
index ab8981e25cb2..0150ce72f0a4 100644
--- a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c
+++ b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c
@@ -464,7 +464,8 @@ create_pagelist(char __user *buf, size_t count, unsigned short type,
(type == PAGELIST_READ ? VM_PROT_WRITE : 0 ) | VM_PROT_READ, pages, num_pages);
if (actual_pages != num_pages) {
- vm_page_unhold_pages(pages, actual_pages);
+ if (actual_pages > 0)
+ vm_page_unhold_pages(pages, actual_pages);
free(pagelist, M_VCPAGELIST);
return (-ENOMEM);
}
diff --git a/sys/dev/amdgpio/amdgpio.c b/sys/dev/amdgpio/amdgpio.c
index 2bd455c612b8..20589ff71b0b 100644
--- a/sys/dev/amdgpio/amdgpio.c
+++ b/sys/dev/amdgpio/amdgpio.c
@@ -3,6 +3,10 @@
*
* Copyright (c) 2018 Advanced Micro Devices
* All rights reserved.
+ * Copyright (c) 2025 The FreeBSD Foundation
+ *
+ * Portions of this software were developed by Aymeric Wibo
+ * <obiwac@freebsd.org> under sponsorship from the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -51,11 +55,11 @@
#include <dev/acpica/acpivar.h>
#include <dev/gpio/gpiobusvar.h>
-#include "gpio_if.h"
#include "amdgpio.h"
static struct resource_spec amdgpio_spec[] = {
- { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE },
{ -1, 0, 0 }
};
@@ -196,7 +200,7 @@ static int
amdgpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
{
struct amdgpio_softc *sc;
- uint32_t reg, val, allowed;
+ uint32_t reg, val;
sc = device_get_softc(dev);
@@ -204,18 +208,19 @@ amdgpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
if (!amdgpio_valid_pin(sc, pin))
return (EINVAL);
- allowed = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
+ if ((flags & ~AMDGPIO_DEFAULT_CAPS) != 0) {
+ device_printf(dev, "disallowed flags (0x%x) trying to be set "
+ "(allowed is 0x%x)\n", flags, AMDGPIO_DEFAULT_CAPS);
+ return (EINVAL);
+ }
- /*
- * Only directtion flag allowed
- */
- if (flags & ~allowed)
+ /* Either input or output must be selected. */
+ if ((flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) == 0)
return (EINVAL);
- /*
- * Not both directions simultaneously
- */
- if ((flags & allowed) == allowed)
+ /* Not both directions simultaneously. */
+ if ((flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) ==
+ (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT))
return (EINVAL);
/* Set the GPIO mode and state */
@@ -224,16 +229,21 @@ amdgpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
reg = AMDGPIO_PIN_REGISTER(pin);
val = amdgpio_read_4(sc, reg);
- if (flags & GPIO_PIN_INPUT) {
+ if ((flags & GPIO_PIN_INPUT) != 0)
val &= ~BIT(OUTPUT_ENABLE_OFF);
- sc->sc_gpio_pins[pin].gp_flags = GPIO_PIN_INPUT;
- } else {
+ else
val |= BIT(OUTPUT_ENABLE_OFF);
- sc->sc_gpio_pins[pin].gp_flags = GPIO_PIN_OUTPUT;
- }
+
+ val &= ~(BIT(PULL_DOWN_ENABLE_OFF) | BIT(PULL_UP_ENABLE_OFF));
+
+ if ((flags & GPIO_PIN_PULLDOWN) != 0)
+ val |= BIT(PULL_DOWN_ENABLE_OFF);
+ if ((flags & GPIO_PIN_PULLUP) != 0)
+ val |= BIT(PULL_UP_ENABLE_OFF);
amdgpio_write_4(sc, reg, val);
+ sc->sc_gpio_pins[pin].gp_flags = flags;
dprintf("pin %d flags 0x%x val 0x%x gp_flags 0x%x\n",
pin, flags, val, sc->sc_gpio_pins[pin].gp_flags);
@@ -359,11 +369,73 @@ amdgpio_probe(device_t dev)
return (rv);
}
+static void
+amdgpio_eoi_locked(struct amdgpio_softc *sc)
+{
+ uint32_t master_reg = amdgpio_read_4(sc, WAKE_INT_MASTER_REG);
+
+ AMDGPIO_ASSERT_LOCKED(sc);
+ master_reg |= EOI_MASK;
+ amdgpio_write_4(sc, WAKE_INT_MASTER_REG, master_reg);
+}
+
+static void
+amdgpio_eoi(struct amdgpio_softc *sc)
+{
+ AMDGPIO_LOCK(sc);
+ amdgpio_eoi_locked(sc);
+ AMDGPIO_UNLOCK(sc);
+}
+
+static int
+amdgpio_intr_filter(void *arg)
+{
+ struct amdgpio_softc *sc = arg;
+ int off, rv = FILTER_STRAY;
+ uint32_t reg;
+
+ /* We can lock in the filter routine as it is MTX_SPIN. */
+ AMDGPIO_LOCK(sc);
+
+ /*
+ * TODO Instead of just reading the registers of all pins, we should
+ * read WAKE_INT_STATUS_REG0/1. A bit set in here denotes a group of
+ * 4 pins where at least one has an interrupt for us. Then we can just
+ * iterate over those 4 pins.
+ *
+ * See GPIO_Interrupt_Status_Index_0 in BKDG.
+ */
+ for (size_t pin = 0; pin < AMD_GPIO_PINS_EXPOSED; pin++) {
+ off = AMDGPIO_PIN_REGISTER(pin);
+ reg = amdgpio_read_4(sc, off);
+ if ((reg & UNSERVICED_INTERRUPT_MASK) == 0)
+ continue;
+ /*
+ * Must write 1's to wake/interrupt status bits to clear them.
+ * We can do this simply by writing back to the register.
+ */
+ amdgpio_write_4(sc, off, reg);
+ }
+
+ amdgpio_eoi_locked(sc);
+ AMDGPIO_UNLOCK(sc);
+
+ rv = FILTER_HANDLED;
+ return (rv);
+}
+
+static void
+amdgpio_intr_handler(void *arg)
+{
+ /* TODO */
+}
+
static int
amdgpio_attach(device_t dev)
{
struct amdgpio_softc *sc;
- int i, pin, bank;
+ int i, pin, bank, reg;
+ uint32_t flags;
sc = device_get_softc(dev);
sc->sc_dev = dev;
@@ -386,6 +458,14 @@ amdgpio_attach(device_t dev)
sc->sc_bst = rman_get_bustag(sc->sc_res[0]);
sc->sc_bsh = rman_get_bushandle(sc->sc_res[0]);
+ /* Set up interrupt handler. */
+ if (bus_setup_intr(dev, sc->sc_res[1], INTR_TYPE_MISC | INTR_MPSAFE,
+ amdgpio_intr_filter, amdgpio_intr_handler, sc, &sc->sc_intr_handle)
+ != 0) {
+ device_printf(dev, "couldn't set up interrupt\n");
+ goto err_intr;
+ }
+
/* Initialize all possible pins to be Invalid */
for (i = 0; i < AMD_GPIO_PINS_MAX ; i++) {
snprintf(sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME,
@@ -395,7 +475,12 @@ amdgpio_attach(device_t dev)
sc->sc_gpio_pins[i].gp_flags = 0;
}
- /* Initialize only driver exposed pins with appropriate capabilities */
+ /*
+ * Initialize only driver exposed pins with appropriate capabilities.
+ *
+ * XXX Also mask and disable interrupts on all pins, since we don't
+ * support them at the moment.
+ */
for (i = 0; i < AMD_GPIO_PINS_EXPOSED ; i++) {
pin = kernzp_pins[i].pin_num;
bank = pin/AMD_GPIO_PINS_PER_BANK;
@@ -406,7 +491,14 @@ amdgpio_attach(device_t dev)
sc->sc_gpio_pins[pin].gp_flags =
amdgpio_is_pin_output(sc, pin) ?
GPIO_PIN_OUTPUT : GPIO_PIN_INPUT;
+
+ reg = AMDGPIO_PIN_REGISTER(pin);
+ flags = amdgpio_read_4(sc, reg);
+ flags &= ~(1 << INTERRUPT_ENABLE_OFF);
+ flags &= ~(1 << INTERRUPT_MASK_OFF);
+ amdgpio_write_4(sc, reg, flags);
}
+ amdgpio_eoi(sc);
sc->sc_busdev = gpiobus_add_bus(dev);
if (sc->sc_busdev == NULL) {
@@ -418,8 +510,9 @@ amdgpio_attach(device_t dev)
return (0);
err_bus:
+ bus_teardown_intr(dev, sc->sc_res[1], sc->sc_intr_handle);
+err_intr:
bus_release_resources(dev, amdgpio_spec, sc->sc_res);
-
err_rsrc:
AMDGPIO_LOCK_DESTROY(sc);
@@ -434,7 +527,8 @@ amdgpio_detach(device_t dev)
if (sc->sc_busdev)
gpiobus_detach_bus(dev);
-
+ if (sc->sc_intr_handle)
+ bus_teardown_intr(dev, sc->sc_res[1], sc->sc_intr_handle);
bus_release_resources(dev, amdgpio_spec, sc->sc_res);
AMDGPIO_LOCK_DESTROY(sc);
diff --git a/sys/dev/amdgpio/amdgpio.h b/sys/dev/amdgpio/amdgpio.h
index aca3039bfc98..3743eba23e17 100644
--- a/sys/dev/amdgpio/amdgpio.h
+++ b/sys/dev/amdgpio/amdgpio.h
@@ -50,7 +50,8 @@
AMD_GPIO_PINS_BANK1 + \
AMD_GPIO_PINS_BANK2 + \
AMD_GPIO_PINS_BANK3)
-#define AMDGPIO_DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)
+#define AMDGPIO_DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \
+ GPIO_PIN_PULLDOWN | GPIO_PIN_PULLUP)
/* Register related macros */
#define AMDGPIO_PIN_REGISTER(pin) (pin * 4)
@@ -84,6 +85,9 @@
#define INTERRUPT_STS_OFF 28
#define WAKE_STS_OFF 29
+#define UNSERVICED_INTERRUPT_MASK \
+ ((1 << INTERRUPT_STS_OFF) | (1 << WAKE_STS_OFF))
+
#define DB_TMR_OUT_MASK 0xFUL
#define DB_CNTRL_MASK 0x3UL
#define ACTIVE_LEVEL_MASK 0x3UL
@@ -316,12 +320,13 @@ struct amdgpio_softc {
int sc_npins;
int sc_ngroups;
struct mtx sc_mtx;
- struct resource *sc_res[AMD_GPIO_NUM_PIN_BANK + 1];
+ struct resource *sc_res[2];
bus_space_tag_t sc_bst;
bus_space_handle_t sc_bsh;
struct gpio_pin sc_gpio_pins[AMD_GPIO_PINS_MAX];
const struct pin_info *sc_pin_info;
const struct amd_pingroup *sc_groups;
+ void *sc_intr_handle;
};
struct amdgpio_sysctl {
diff --git a/sys/dev/hpt27xx/hptintf.h b/sys/dev/hpt27xx/hptintf.h
index 558b479ec2ee..eb8105ec5666 100644
--- a/sys/dev/hpt27xx/hptintf.h
+++ b/sys/dev/hpt27xx/hptintf.h
@@ -155,8 +155,8 @@ typedef HPT_U32 DEVICEID;
#define ARRAY_FLAG_NEED_AUTOREBUILD 0x00000080 /* auto-rebuild should start */
#define ARRAY_FLAG_VERIFYING 0x00000100 /* is being verified */
#define ARRAY_FLAG_INITIALIZING 0x00000200 /* is being initialized */
-#define ARRAY_FLAG_TRANSFORMING 0x00000400 /* tranform in progress */
-#define ARRAY_FLAG_NEEDTRANSFORM 0x00000800 /* array need tranform */
+#define ARRAY_FLAG_TRANSFORMING 0x00000400 /* transform in progress */
+#define ARRAY_FLAG_NEEDTRANSFORM 0x00000800 /* array need transform */
#define ARRAY_FLAG_NEEDINITIALIZING 0x00001000 /* the array's initialization hasn't finished*/
#define ARRAY_FLAG_BROKEN_REDUNDANT 0x00002000 /* broken but redundant (raid6) */
#define ARRAY_FLAG_RAID15PLUS 0x80000000 /* display this RAID 1 as RAID 1.5 */
@@ -2018,7 +2018,7 @@ DEVICEID hpt_create_transform_v2(DEVICEID idArray, PCREATE_ARRAY_PARAMS_V3 destI
#endif
/* hpt_step_transform
- * move a block in a tranform progress.
+ * move a block in a transform progress.
* This function is called by mid-layer, not GUI (which uses set_array_state instead).
* Version compatibility: v2.0.0.0 or later
* Parameters:
diff --git a/sys/dev/ichwd/i6300esbwd.c b/sys/dev/ichwd/i6300esbwd.c
new file mode 100644
index 000000000000..d95aeb53c3f5
--- /dev/null
+++ b/sys/dev/ichwd/i6300esbwd.c
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2025 The FreeBSD Foundation
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+/*
+ * Reference: Intel 6300ESB Controller Hub Datasheet Section 16
+ */
+
+#include <sys/param.h>
+#include <sys/eventhandler.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/sysctl.h>
+#include <sys/errno.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+#include <sys/watchdog.h>
+
+#include <dev/pci/pcireg.h>
+
+#include <dev/ichwd/ichwd.h>
+#include <dev/ichwd/i6300esbwd.h>
+
+#include <x86/pci_cfgreg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pci_private.h>
+
+struct i6300esbwd_softc {
+ device_t dev;
+ int res_id;
+ struct resource *res;
+ eventhandler_tag ev_tag;
+ bool locked;
+};
+
+static const struct i6300esbwd_pci_id {
+ uint16_t id;
+ const char *name;
+} i6300esbwd_pci_devices[] = {
+ { DEVICEID_6300ESB_2, "6300ESB Watchdog Timer" },
+};
+
+static uint16_t
+i6300esbwd_cfg_read(struct i6300esbwd_softc *sc)
+{
+ return (pci_read_config(sc->dev, WDT_CONFIG_REG, 2));
+}
+
+static void
+i6300esbwd_cfg_write(struct i6300esbwd_softc *sc, uint16_t val)
+{
+ pci_write_config(sc->dev, WDT_CONFIG_REG, val, 2);
+}
+
+static uint8_t
+i6300esbwd_lock_read(struct i6300esbwd_softc *sc)
+{
+ return (pci_read_config(sc->dev, WDT_LOCK_REG, 1));
+}
+
+static void
+i6300esbwd_lock_write(struct i6300esbwd_softc *sc, uint8_t val)
+{
+ pci_write_config(sc->dev, WDT_LOCK_REG, val, 1);
+}
+
+/*
+ * According to Intel 6300ESB I/O Controller Hub Datasheet 16.5.2,
+ * the resource should be unlocked before modifing any registers.
+ * The way to unlock is by write 0x80, 0x86 to the reload register.
+ */
+static void
+i6300esbwd_unlock_res(struct i6300esbwd_softc *sc)
+{
+ bus_write_2(sc->res, WDT_RELOAD_REG, WDT_UNLOCK_SEQ_1_VAL);
+ bus_write_2(sc->res, WDT_RELOAD_REG, WDT_UNLOCK_SEQ_2_VAL);
+}
+
+static int
+i6300esbwd_sysctl_locked(SYSCTL_HANDLER_ARGS)
+{
+ struct i6300esbwd_softc *sc = (struct i6300esbwd_softc *)arg1;
+ int error;
+ int result;
+
+ result = sc->locked;
+ error = sysctl_handle_int(oidp, &result, 0, req);
+
+ if (error || !req->newptr)
+ return (error);
+
+ if (result == 1 && !sc->locked) {
+ i6300esbwd_lock_write(sc, i6300esbwd_lock_read(sc) | WDT_LOCK);
+ sc->locked = true;
+ }
+
+ return (0);
+}
+
+static void
+i6300esbwd_event(void *arg, unsigned int cmd, int *error)
+{
+ struct i6300esbwd_softc *sc = arg;
+ uint32_t timeout;
+ uint16_t regval;
+
+ cmd &= WD_INTERVAL;
+ if (cmd != 0 &&
+ (cmd < WD_TO_1MS || (cmd - WD_TO_1MS) >= WDT_PRELOAD_BIT)) {
+ *error = EINVAL;
+ return;
+ }
+ timeout = 1 << (cmd - WD_TO_1MS);
+
+ /* reset the timer to prevent timeout a timeout is about to occur */
+ i6300esbwd_unlock_res(sc);
+ bus_write_2(sc->res, WDT_RELOAD_REG, WDT_RELOAD);
+
+ if (!cmd) {
+ /*
+ * when the lock is enabled, we are unable to overwrite LOCK
+ * register
+ */
+ if (sc->locked)
+ *error = EPERM;
+ else
+ i6300esbwd_lock_write(sc,
+ i6300esbwd_lock_read(sc) & ~WDT_ENABLE);
+ return;
+ }
+
+ i6300esbwd_unlock_res(sc);
+ bus_write_4(sc->res, WDT_PRELOAD_1_REG, timeout);
+
+ i6300esbwd_unlock_res(sc);
+ bus_write_4(sc->res, WDT_PRELOAD_2_REG, timeout);
+
+ i6300esbwd_unlock_res(sc);
+ bus_write_2(sc->res, WDT_RELOAD_REG, WDT_RELOAD);
+
+ if (!sc->locked) {
+ i6300esbwd_lock_write(sc, WDT_ENABLE);
+ regval = i6300esbwd_lock_read(sc);
+ sc->locked = regval & WDT_LOCK;
+ }
+}
+
+static int
+i6300esbwd_probe(device_t dev)
+{
+ const struct i6300esbwd_pci_id *pci_id;
+ uint16_t pci_dev_id;
+ int err = ENXIO;
+
+ if (pci_get_vendor(dev) != VENDORID_INTEL)
+ goto end;
+
+ pci_dev_id = pci_get_device(dev);
+ for (pci_id = i6300esbwd_pci_devices;
+ pci_id < i6300esbwd_pci_devices + nitems(i6300esbwd_pci_devices);
+ ++pci_id) {
+ if (pci_id->id == pci_dev_id) {
+ device_set_desc(dev, pci_id->name);
+ err = BUS_PROBE_DEFAULT;
+ break;
+ }
+ }
+
+end:
+ return (err);
+}
+
+static int
+i6300esbwd_attach(device_t dev)
+{
+ struct i6300esbwd_softc *sc = device_get_softc(dev);
+ uint16_t regval;
+
+ sc->dev = dev;
+ sc->res_id = PCIR_BAR(0);
+ sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->res_id,
+ RF_ACTIVE);
+ if (sc->res == NULL) {
+ device_printf(dev, "unable to map memory region\n");
+ return (ENXIO);
+ }
+
+ i6300esbwd_cfg_write(sc, WDT_INT_TYPE_DISABLED_VAL);
+ regval = i6300esbwd_lock_read(sc);
+ if (regval & WDT_LOCK)
+ sc->locked = true;
+ else {
+ sc->locked = false;
+ i6300esbwd_lock_write(sc, WDT_TOUT_CNF_WT_MODE);
+ }
+
+ i6300esbwd_unlock_res(sc);
+ bus_write_2(sc->res, WDT_RELOAD_REG, WDT_RELOAD | WDT_TIMEOUT);
+
+ sc->ev_tag = EVENTHANDLER_REGISTER(watchdog_list, i6300esbwd_event, sc,
+ 0);
+
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "locked",
+ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0,
+ i6300esbwd_sysctl_locked, "I",
+ "Lock the timer so that we cannot disable it");
+
+ return (0);
+}
+
+static int
+i6300esbwd_detach(device_t dev)
+{
+ struct i6300esbwd_softc *sc = device_get_softc(dev);
+
+ if (sc->ev_tag)
+ EVENTHANDLER_DEREGISTER(watchdog_list, sc->ev_tag);
+
+ if (sc->res)
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->res_id, sc->res);
+
+ return (0);
+}
+
+static device_method_t i6300esbwd_methods[] = {
+ DEVMETHOD(device_probe, i6300esbwd_probe),
+ DEVMETHOD(device_attach, i6300esbwd_attach),
+ DEVMETHOD(device_detach, i6300esbwd_detach),
+ DEVMETHOD(device_shutdown, i6300esbwd_detach),
+ DEVMETHOD_END
+};
+
+static driver_t i6300esbwd_driver = {
+ "i6300esbwd",
+ i6300esbwd_methods,
+ sizeof(struct i6300esbwd_softc),
+};
+
+DRIVER_MODULE(i6300esbwd, pci, i6300esbwd_driver, NULL, NULL);
diff --git a/sys/dev/ichwd/i6300esbwd.h b/sys/dev/ichwd/i6300esbwd.h
new file mode 100644
index 000000000000..39ed5d5a84f6
--- /dev/null
+++ b/sys/dev/ichwd/i6300esbwd.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2025 The FreeBSD Foundation
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef _I6300ESBWD_H_
+#define _I6300ESBWD_H_
+
+#define WDT_CONFIG_REG 0x60
+#define WDT_LOCK_REG 0x68
+
+#define WDT_PRELOAD_1_REG 0x00
+#define WDT_PRELOAD_2_REG 0x04
+#define WDT_INTR_REG 0x08
+#define WDT_RELOAD_REG 0x0C
+
+/* For config register */
+#define WDT_OUTPUT_EN (0x1 << 5)
+#define WDT_PRE_SEL (0x1 << 2)
+#define WDT_INT_TYPE_BITS (0x3)
+#define WDT_INT_TYPE_IRQ_VAL (0x0)
+#define WDT_INT_TYPE_RES_VAL (0x1)
+#define WDT_INT_TYPE_SMI_VAL (0x2)
+#define WDT_INT_TYPE_DISABLED_VAL (0x3)
+
+/* For lock register */
+#define WDT_TOUT_CNF_WT_MODE (0x0 << 2)
+#define WDT_TOUT_CNF_FR_MODE (0x1 << 2)
+#define WDT_ENABLE (0x02)
+#define WDT_LOCK (0x01)
+
+/* For preload 1/2 registers */
+#define WDT_PRELOAD_BIT 20
+#define WDT_PRELOAD_BITS ((0x1 << WDT_PRELOAD_BIT) - 1)
+
+/* For interrupt register */
+#define WDT_INTR_ACT (0x01 << 0)
+
+/* For reload register */
+#define WDT_TIMEOUT (0x01 << 9)
+#define WDT_RELOAD (0x01 << 8)
+#define WDT_UNLOCK_SEQ_1_VAL 0x80
+#define WDT_UNLOCK_SEQ_2_VAL 0x86
+
+#endif /* _I6300ESBWD_H_ */
diff --git a/sys/dev/ichwd/ichwd.c b/sys/dev/ichwd/ichwd.c
index cade2cc4fb45..5481553cc175 100644
--- a/sys/dev/ichwd/ichwd.c
+++ b/sys/dev/ichwd/ichwd.c
@@ -90,7 +90,7 @@ static struct ichwd_device ichwd_devices[] = {
{ DEVICEID_82801E, "Intel 82801E watchdog timer", 5, 1 },
{ DEVICEID_82801EB, "Intel 82801EB watchdog timer", 5, 1 },
{ DEVICEID_82801EBR, "Intel 82801EB/ER watchdog timer", 5, 1 },
- { DEVICEID_6300ESB, "Intel 6300ESB watchdog timer", 5, 1 },
+ { DEVICEID_6300ESB_1, "Intel 6300ESB watchdog timer", 5, 1 },
{ DEVICEID_82801FBR, "Intel 82801FB/FR watchdog timer", 6, 2 },
{ DEVICEID_ICH6M, "Intel ICH6M watchdog timer", 6, 2 },
{ DEVICEID_ICH6W, "Intel ICH6W watchdog timer", 6, 2 },
diff --git a/sys/dev/ichwd/ichwd.h b/sys/dev/ichwd/ichwd.h
index 90fda08b74c1..72d0ca1cd6aa 100644
--- a/sys/dev/ichwd/ichwd.h
+++ b/sys/dev/ichwd/ichwd.h
@@ -151,7 +151,8 @@ struct ichwd_softc {
#define DEVICEID_82801E 0x2450
#define DEVICEID_82801EB 0x24dc
#define DEVICEID_82801EBR 0x24d0
-#define DEVICEID_6300ESB 0x25a1
+#define DEVICEID_6300ESB_1 0x25a1
+#define DEVICEID_6300ESB_2 0x25ab
#define DEVICEID_82801FBR 0x2640
#define DEVICEID_ICH6M 0x2641
#define DEVICEID_ICH6W 0x2642
diff --git a/sys/dev/puc/pucdata.c b/sys/dev/puc/pucdata.c
index e911a407cca9..436af76001da 100644
--- a/sys/dev/puc/pucdata.c
+++ b/sys/dev/puc/pucdata.c
@@ -64,6 +64,7 @@ static puc_config_f puc_config_quatech;
static puc_config_f puc_config_syba;
static puc_config_f puc_config_siig;
static puc_config_f puc_config_sunix;
+static puc_config_f puc_config_systembase;
static puc_config_f puc_config_timedia;
static puc_config_f puc_config_titan;
@@ -1705,6 +1706,23 @@ const struct puc_cfg puc_pci_devices[] = {
PUC_PORT_4S, 0x10, 0, 8,
.config_function = puc_config_icbook
},
+
+ /*
+ * Systembase cards using SB16C1050 UARTs:
+ */
+ { 0x14a1, 0x0008, 0x14a1, 0x0008,
+ "Systembase SB16C1058",
+ DEFAULT_RCLK * 8,
+ PUC_PORT_8S, 0x10, 0, 8,
+ .config_function = puc_config_systembase,
+ },
+ { 0x14a1, 0x0004, 0x14a1, 0x0004,
+ "Systembase SB16C1054",
+ DEFAULT_RCLK * 8,
+ PUC_PORT_4S, 0x10, 0, 8,
+ .config_function = puc_config_systembase,
+ },
+
{ 0xffff, 0, 0xffff, 0, NULL, 0 }
};
@@ -2294,3 +2312,28 @@ puc_config_titan(struct puc_softc *sc __unused, enum puc_cfg_cmd cmd,
}
return (ENXIO);
}
+
+static int
+puc_config_systembase(struct puc_softc *sc __unused,
+ enum puc_cfg_cmd cmd, int port, intptr_t *res)
+{
+ struct puc_bar *bar;
+
+ switch (cmd) {
+ case PUC_CFG_SETUP:
+ bar = puc_get_bar(sc, 0x14);
+ if (bar == NULL)
+ return (ENXIO);
+
+ /*
+ * The Systembase SB16C1058 (and probably other devices
+ * based on the SB16C1050 UART core) require poking a
+ * register in the *other* RID to turn on interrupts.
+ */
+ bus_write_1(bar->b_res, /* OPT_IMRREG0 */ 0xc, 0xff);
+ return (0);
+ default:
+ break;
+ }
+ return (ENXIO);
+}
diff --git a/sys/dev/uart/uart_bus_pci.c b/sys/dev/uart/uart_bus_pci.c
index 14ac213066b8..22af8ee8663c 100644
--- a/sys/dev/uart/uart_bus_pci.c
+++ b/sys/dev/uart/uart_bus_pci.c
@@ -141,6 +141,8 @@ static const struct pci_id pci_ns8250_ids[] = {
0x10, 16384000 },
{ 0x1415, 0xc120, 0xffff, 0, "Oxford Semiconductor OXPCIe952 PCIe 16950 UART",
0x10 },
+{ 0x14a1, 0x0008, 0x14a1, 0x0008, "Systembase SB16C1058",
+ 0x10, 8 * DEFAULT_RCLK, },
{ 0x14e4, 0x160a, 0xffff, 0, "Broadcom TruManage UART", 0x10,
128 * DEFAULT_RCLK, 2},
{ 0x14e4, 0x4344, 0xffff, 0, "Sony Ericsson GC89 PC Card", 0x10},
diff --git a/sys/modules/ichwd/Makefile b/sys/modules/ichwd/Makefile
index 3c3bbc37eff5..27b4c38437ff 100644
--- a/sys/modules/ichwd/Makefile
+++ b/sys/modules/ichwd/Makefile
@@ -1,6 +1,6 @@
.PATH: ${SRCTOP}/sys/dev/ichwd
KMOD= ichwd
-SRCS= ichwd.c device_if.h bus_if.h pci_if.h isa_if.h
+SRCS= i6300esbwd.c ichwd.c device_if.h bus_if.h pci_if.h isa_if.h
.include <bsd.kmod.mk>
diff --git a/sys/net/if.c b/sys/net/if.c
index 79c883fd4a0a..202be4794f6e 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -2589,16 +2589,7 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
* flip. They require special handling because in-kernel
* consumers may indepdently toggle them.
*/
- if ((ifp->if_flags ^ new_flags) & IFF_PPROMISC) {
- if (new_flags & IFF_PPROMISC)
- ifp->if_flags |= IFF_PROMISC;
- else if (ifp->if_pcount == 0)
- ifp->if_flags &= ~IFF_PROMISC;
- if (log_promisc_mode_change)
- if_printf(ifp, "permanently promiscuous mode %s\n",
- ((new_flags & IFF_PPROMISC) ?
- "enabled" : "disabled"));
- }
+ if_setppromisc(ifp, new_flags & IFF_PPROMISC);
if ((ifp->if_flags ^ new_flags) & IFF_PALLMULTI) {
if (new_flags & IFF_PALLMULTI)
ifp->if_flags |= IFF_ALLMULTI;
@@ -4456,6 +4447,32 @@ if_getmtu_family(const if_t ifp, int family)
return (ifp->if_mtu);
}
+void
+if_setppromisc(if_t ifp, bool ppromisc)
+{
+ int new_flags;
+
+ if (ppromisc)
+ new_flags = ifp->if_flags | IFF_PPROMISC;
+ else
+ new_flags = ifp->if_flags & ~IFF_PPROMISC;
+ if ((ifp->if_flags ^ new_flags) & IFF_PPROMISC) {
+ if (new_flags & IFF_PPROMISC)
+ new_flags |= IFF_PROMISC;
+ /*
+ * Only unset IFF_PROMISC if there are no more consumers of
+ * promiscuity, i.e. the ifp->if_pcount refcount is 0.
+ */
+ else if (ifp->if_pcount == 0)
+ new_flags &= ~IFF_PROMISC;
+ if (log_promisc_mode_change)
+ if_printf(ifp, "permanently promiscuous mode %s\n",
+ ((new_flags & IFF_PPROMISC) ?
+ "enabled" : "disabled"));
+ }
+ ifp->if_flags = new_flags;
+}
+
/*
* Methods for drivers to access interface unicast and multicast
* link level addresses. Driver shall not know 'struct ifaddr' neither
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index 08435e7bd5f6..f2df612b19c1 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -622,6 +622,7 @@ int if_setmtu(if_t ifp, int mtu);
int if_getmtu(const if_t ifp);
int if_getmtu_family(const if_t ifp, int family);
void if_notifymtu(if_t ifp);
+void if_setppromisc(const if_t ifp, bool ppromisc);
int if_setflagbits(if_t ifp, int set, int clear);
int if_setflags(if_t ifp, int flags);
int if_getflags(const if_t ifp);
diff --git a/sys/netgraph/ng_nat.c b/sys/netgraph/ng_nat.c
index defbe817becd..8b82d777caeb 100644
--- a/sys/netgraph/ng_nat.c
+++ b/sys/netgraph/ng_nat.c
@@ -818,7 +818,8 @@ ng_nat_rcvdata(hook_p hook, item_p item )
if (ip->ip_v != IPVERSION)
goto send; /* other IP version, let it pass */
- if (m->m_pkthdr.len < ipofs + ntohs(ip->ip_len))
+ uint16_t ip_len = ntohs(ip->ip_len);
+ if (m->m_pkthdr.len < (ipofs + ip_len))
goto send; /* packet too short (i.e. fragmented or broken) */
/*
@@ -852,50 +853,68 @@ ng_nat_rcvdata(hook_p hook, item_p item )
if (rval == PKT_ALIAS_RESPOND)
m->m_flags |= M_SKIP_FIREWALL;
- m->m_pkthdr.len = m->m_len = ntohs(ip->ip_len) + ipofs;
- if ((ip->ip_off & htons(IP_OFFMASK)) == 0 &&
- ip->ip_p == IPPROTO_TCP) {
- struct tcphdr *th = (struct tcphdr *)((caddr_t)ip +
- (ip->ip_hl << 2));
+ /* Re-read just in case it has been updated */
+ ip_len = ntohs(ip->ip_len);
+ int new_m_len = ip_len + ipofs;
+ if (new_m_len > (m->m_len + M_TRAILINGSPACE(m))) {
/*
- * Here is our terrible HACK.
- *
- * Sometimes LibAlias edits contents of TCP packet.
- * In this case it needs to recompute full TCP
- * checksum. However, the problem is that LibAlias
- * doesn't have any idea about checksum offloading
- * in kernel. To workaround this, we do not do
- * checksumming in LibAlias, but only mark the
- * packets with TH_RES1 in the th_x2 field. If we
- * receive a marked packet, we calculate correct
- * checksum for it aware of offloading.
- *
- * Why do I do such a terrible hack instead of
- * recalculating checksum for each packet?
- * Because the previous checksum was not checked!
- * Recalculating checksums for EVERY packet will
- * hide ALL transmission errors. Yes, marked packets
- * still suffer from this problem. But, sigh, natd(8)
- * has this problem, too.
+ * This is just a safety railguard to make sure LibAlias has not
+ * screwed the IP packet up somehow, should probably be KASSERT()
+ * at some point. Calling in_delayed_cksum() will parse IP packet
+ * again and reliably panic if there is less data than the IP
+ * header declares, there might be some other places too.
*/
+ log(LOG_ERR, "ng_nat_rcvdata: outgoing packet corrupted, "
+ "not enough data: expected %d, available (%d - %d)\n",
+ ip_len, m->m_len + (int)M_TRAILINGSPACE(m), ipofs);
+ NG_FREE_ITEM(item);
+ return (ENXIO);
+ }
+
+ m->m_pkthdr.len = m->m_len = new_m_len;
- if (tcp_get_flags(th) & TH_RES1) {
- uint16_t ip_len = ntohs(ip->ip_len);
+ if ((ip->ip_off & htons(IP_OFFMASK)) != 0 || ip->ip_p != IPPROTO_TCP)
+ goto send;
- tcp_set_flags(th, tcp_get_flags(th) & ~TH_RES1);
- th->th_sum = in_pseudo(ip->ip_src.s_addr,
- ip->ip_dst.s_addr, htons(IPPROTO_TCP +
- ip_len - (ip->ip_hl << 2)));
+ uint16_t pl_offset = ip->ip_hl << 2;
+ struct tcphdr *th = (struct tcphdr *)((caddr_t)ip + pl_offset);
- if ((m->m_pkthdr.csum_flags & CSUM_TCP) == 0) {
- m->m_pkthdr.csum_data = offsetof(struct tcphdr,
- th_sum);
- in_delayed_cksum(m);
- }
- }
- }
+ /*
+ * Here is our terrible HACK.
+ *
+ * Sometimes LibAlias edits contents of TCP packet.
+ * In this case it needs to recompute full TCP
+ * checksum. However, the problem is that LibAlias
+ * doesn't have any idea about checksum offloading
+ * in kernel. To workaround this, we do not do
+ * checksumming in LibAlias, but only mark the
+ * packets with TH_RES1 in the th_x2 field. If we
+ * receive a marked packet, we calculate correct
+ * checksum for it aware of offloading.
+ *
+ * Why do I do such a terrible hack instead of
+ * recalculating checksum for each packet?
+ * Because the previous checksum was not checked!
+ * Recalculating checksums for EVERY packet will
+ * hide ALL transmission errors. Yes, marked packets
+ * still suffer from this problem. But, sigh, natd(8)
+ * has this problem, too.
+ */
+
+ if (!(tcp_get_flags(th) & TH_RES1))
+ goto send;
+
+ tcp_set_flags(th, tcp_get_flags(th) & ~TH_RES1);
+ th->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
+ htons(IPPROTO_TCP + ip_len - pl_offset));
+
+ if ((m->m_pkthdr.csum_flags & CSUM_TCP) != 0)
+ goto send;
+
+ m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
+ in_delayed_cksum_o(m, ipofs);
send:
if (hook == priv->in)
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index ec6ba8d92015..ef08b9cfd3d6 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -1044,14 +1044,14 @@ done:
}
void
-in_delayed_cksum(struct mbuf *m)
+in_delayed_cksum_o(struct mbuf *m, uint16_t iph_offset)
{
struct ip *ip;
struct udphdr *uh;
uint16_t cklen, csum, offset;
- ip = mtod(m, struct ip *);
- offset = ip->ip_hl << 2 ;
+ ip = (struct ip *)mtodo(m, iph_offset);
+ offset = iph_offset + (ip->ip_hl << 2);
if (m->m_pkthdr.csum_flags & CSUM_UDP) {
/* if udp header is not in the first mbuf copy udplen */
@@ -1078,6 +1078,13 @@ in_delayed_cksum(struct mbuf *m)
*(u_short *)mtodo(m, offset) = csum;
}
+void
+in_delayed_cksum(struct mbuf *m)
+{
+
+ in_delayed_cksum_o(m, 0);
+}
+
/*
* IP socket option processing.
*/
diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h
index f782ebc53eb0..c113484079a3 100644
--- a/sys/netinet/ip_var.h
+++ b/sys/netinet/ip_var.h
@@ -271,6 +271,7 @@ VNET_DECLARE(struct pfil_head *, inet_local_pfil_head);
#define PFIL_INET_LOCAL_NAME "inet-local"
void in_delayed_cksum(struct mbuf *m);
+void in_delayed_cksum_o(struct mbuf *m, uint16_t o);
/* Hooks for ipfw, dummynet, divert etc. Most are declared in raw_ip.c */
/*
diff --git a/sys/netinet/tcp_hpts.c b/sys/netinet/tcp_hpts.c
index b77ebc928809..63bbe4bba11b 100644
--- a/sys/netinet/tcp_hpts.c
+++ b/sys/netinet/tcp_hpts.c
@@ -137,8 +137,6 @@
#include <netinet/in_kdtrace.h>
#include <netinet/in_pcb.h>
#include <netinet/ip.h>
-#include <netinet/ip_icmp.h> /* required for icmp_var.h */
-#include <netinet/icmp_var.h> /* for ICMP_BANDLIM */
#include <netinet/ip_var.h>
#include <netinet/ip6.h>
#include <netinet6/in6_pcb.h>
diff --git a/sys/netinet/tcp_stacks/bbr.c b/sys/netinet/tcp_stacks/bbr.c
index fed259f4d8e1..f2d7867df9b4 100644
--- a/sys/netinet/tcp_stacks/bbr.c
+++ b/sys/netinet/tcp_stacks/bbr.c
@@ -78,8 +78,6 @@
#include <netinet/in_kdtrace.h>
#include <netinet/in_pcb.h>
#include <netinet/ip.h>
-#include <netinet/ip_icmp.h> /* required for icmp_var.h */
-#include <netinet/icmp_var.h> /* for ICMP_BANDLIM */
#include <netinet/ip_var.h>
#include <netinet/ip6.h>
#include <netinet6/in6_pcb.h>
diff --git a/sys/netinet/tcp_stacks/rack.c b/sys/netinet/tcp_stacks/rack.c
index 71dd4de6baf9..11ef5ba706c5 100644
--- a/sys/netinet/tcp_stacks/rack.c
+++ b/sys/netinet/tcp_stacks/rack.c
@@ -77,8 +77,6 @@
#include <netinet/in_kdtrace.h>
#include <netinet/in_pcb.h>
#include <netinet/ip.h>
-#include <netinet/ip_icmp.h> /* required for icmp_var.h */
-#include <netinet/icmp_var.h> /* for ICMP_BANDLIM */
#include <netinet/ip_var.h>
#include <netinet/ip6.h>
#include <netinet6/in6_pcb.h>
diff --git a/sys/netinet/tcp_stacks/rack_bbr_common.c b/sys/netinet/tcp_stacks/rack_bbr_common.c
index fc12672a45f7..4a0a5fc118f6 100644
--- a/sys/netinet/tcp_stacks/rack_bbr_common.c
+++ b/sys/netinet/tcp_stacks/rack_bbr_common.c
@@ -76,8 +76,6 @@
#include <netinet/in_kdtrace.h>
#include <netinet/in_pcb.h>
#include <netinet/ip.h>
-#include <netinet/ip_icmp.h> /* required for icmp_var.h */
-#include <netinet/icmp_var.h> /* for ICMP_BANDLIM */
#include <netinet/ip_var.h>
#include <netinet/ip6.h>
#include <netinet6/in6_pcb.h>
diff --git a/sys/netinet/tcp_stacks/rack_pcm.c b/sys/netinet/tcp_stacks/rack_pcm.c
index 759bfda98357..1a51097f627c 100644
--- a/sys/netinet/tcp_stacks/rack_pcm.c
+++ b/sys/netinet/tcp_stacks/rack_pcm.c
@@ -78,8 +78,6 @@
#include <netinet/in_kdtrace.h>
#include <netinet/in_pcb.h>
#include <netinet/ip.h>
-#include <netinet/ip_icmp.h> /* required for icmp_var.h */
-#include <netinet/icmp_var.h> /* for ICMP_BANDLIM */
#include <netinet/ip_var.h>
#include <netinet/ip6.h>
#include <netinet6/in6_pcb.h>
diff --git a/sys/netinet/tcp_stacks/tailq_hash.c b/sys/netinet/tcp_stacks/tailq_hash.c
index 5ba3e7cd36c0..ff01640524b6 100644
--- a/sys/netinet/tcp_stacks/tailq_hash.c
+++ b/sys/netinet/tcp_stacks/tailq_hash.c
@@ -51,8 +51,6 @@
#include <netinet/in_kdtrace.h>
#include <netinet/in_pcb.h>
#include <netinet/ip.h>
-#include <netinet/ip_icmp.h> /* required for icmp_var.h */
-#include <netinet/icmp_var.h> /* for ICMP_BANDLIM */
#include <netinet/ip_var.h>
#include <netinet/ip6.h>
#include <netinet6/in6_pcb.h>
diff --git a/sys/netlink/route/iface_drivers.c b/sys/netlink/route/iface_drivers.c
index 21db3017df18..4f1540740ead 100644
--- a/sys/netlink/route/iface_drivers.c
+++ b/sys/netlink/route/iface_drivers.c
@@ -82,28 +82,39 @@ _nl_modify_ifp_generic(struct ifnet *ifp, struct nl_parsed_link *lattrs,
}
}
- if ((lattrs->ifi_change & IFF_UP) && (lattrs->ifi_flags & IFF_UP) == 0) {
- /* Request to down the interface */
- if_down(ifp);
+ if ((lattrs->ifi_change & IFF_UP) != 0 || lattrs->ifi_change == 0) {
+ /* Request to up or down the interface */
+ if (lattrs->ifi_flags & IFF_UP)
+ if_up(ifp);
+ else
+ if_down(ifp);
}
if (lattrs->ifla_mtu > 0) {
if (nlp_has_priv(npt->nlp, PRIV_NET_SETIFMTU)) {
struct ifreq ifr = { .ifr_mtu = lattrs->ifla_mtu };
- error = ifhwioctl(SIOCSIFMTU, ifp, (char *)&ifr, curthread);
+ error = ifhwioctl(SIOCSIFMTU, ifp, (char *)&ifr,
+ curthread);
+ if (error != 0) {
+ nlmsg_report_err_msg(npt, "Failed to set mtu");
+ return (error);
+ }
} else {
nlmsg_report_err_msg(npt, "Not enough privileges to set mtu");
return (EPERM);
}
}
- if (lattrs->ifi_change & IFF_PROMISC) {
- error = ifpromisc(ifp, lattrs->ifi_flags & IFF_PROMISC);
- if (error != 0) {
- nlmsg_report_err_msg(npt, "unable to set promisc");
- return (error);
- }
- }
+ if ((lattrs->ifi_change & IFF_PROMISC) != 0 ||
+ lattrs->ifi_change == 0)
+ /*
+ * When asking for IFF_PROMISC, set permanent flag instead
+ * (IFF_PPROMISC) as we have no way of doing promiscuity
+ * reference counting through ifpromisc(). Every call to this
+ * function either sets or unsets IFF_PROMISC, and ifi_change
+ * is usually set to 0xFFFFFFFF.
+ */
+ if_setppromisc(ifp, (lattrs->ifi_flags & IFF_PROMISC) != 0);
if (lattrs->ifla_address != NULL) {
if (nlp_has_priv(npt->nlp, PRIV_NET_SETIFMAC)) {
diff --git a/usr.sbin/mountd/exports.5 b/usr.sbin/mountd/exports.5
index a90d81c4db99..786411fbf6d8 100644
--- a/usr.sbin/mountd/exports.5
+++ b/usr.sbin/mountd/exports.5
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd December 16, 2024
+.Dd August 24, 2025
.Dt EXPORTS 5
.Os
.Sh NAME
@@ -148,6 +148,19 @@ characters.
Mount points for a file system may appear on multiple lines each with
different sets of hosts and export options.
.Pp
+Note that, for NFSv4 exporting, there must be both one or more ``V4:'' line(s)
+and one or more line(s) exporting the file systems that are to be
+exported to NFSv4 clients.
+If there are multiple ``V4:'' lines, these lines must all specify the
+same root directory path, but with different options for different
+clients.
+These line(s) do not export any file system, but simply define the
+location of the ``root'' of the NFSv4 export subtree.
+The line(s) exporting the file systems should always
+specify the pathname of the root of a server file system
+and must include at least one line exporting the file system
+which is specified as the ``root'' by the ``V4:'' line(s).
+.Pp
The second component of a line specifies how the file system is to be
exported to the host set.
The option flags specify whether the file system