git: e36bb86195fa - main - net/hostapd210: Clone net/hostapd to net/hostapd210

From: Cy Schubert <cy_at_FreeBSD.org>
Date: Sun, 21 Jul 2024 13:06:49 UTC
The branch main has been updated by cy:

URL: https://cgit.FreeBSD.org/ports/commit/?id=e36bb86195fa15fc33869a99cc23e4a37590db5d

commit e36bb86195fa15fc33869a99cc23e4a37590db5d
Author:     Cy Schubert <cy@FreeBSD.org>
AuthorDate: 2024-07-21 13:00:58 +0000
Commit:     Cy Schubert <cy@FreeBSD.org>
CommitDate: 2024-07-21 13:06:29 +0000

    net/hostapd210: Clone net/hostapd to net/hostapd210
    
    We clone net/hostapd to net/hostapd210 in preparation for the
    hostapd update to 2.11. In case anyone is having issues with it
    they can fall back to net/hostapd210.
---
 net/Makefile                                       |   1 +
 net/hostapd210/Makefile                            |  41 +++
 net/hostapd210/distinfo                            |   3 +
 net/hostapd210/files/config                        | 316 +++++++++++++++++++++
 net/hostapd210/files/hostapd.in                    |  39 +++
 net/hostapd210/files/patch-src_ap_hostapd.c        |  31 ++
 net/hostapd210/files/patch-src_common_dhcp.h       |  25 ++
 .../files/patch-src_drivers_driver__bsd.c          | 281 ++++++++++++++++++
 .../patch-src_l2__packet_l2__packet__freebsd.c     |  74 +++++
 net/hostapd210/files/patch-src_utils_os__unix.c    |  15 +
 net/hostapd210/files/patch-src_wps_wps__upnp.c     |  12 +
 net/hostapd210/pkg-descr                           |  10 +
 net/hostapd210/pkg-message                         |  10 +
 13 files changed, 858 insertions(+)

diff --git a/net/Makefile b/net/Makefile
index 36bf0f8ec4eb..effe35ad890c 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -248,6 +248,7 @@
     SUBDIR += honeyd
     SUBDIR += hostapd
     SUBDIR += hostapd-devel
+    SUBDIR += hostapd210
     SUBDIR += hostapd29
     SUBDIR += hping3
     SUBDIR += hsflowd
diff --git a/net/hostapd210/Makefile b/net/hostapd210/Makefile
new file mode 100644
index 000000000000..59d57624431f
--- /dev/null
+++ b/net/hostapd210/Makefile
@@ -0,0 +1,41 @@
+PORTNAME=	hostapd
+PORTVERSION=	2.10
+PORTREVISION=	10
+CATEGORIES=	net
+MASTER_SITES=	https://w1.fi/releases/
+PKGNAMESUFFIX=	210
+
+MAINTAINER=	cy@FreeBSD.org
+COMMENT=	IEEE 802.11 AP, IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator
+WWW=		https://w1.fi/hostapd/
+
+LICENSE=	BSD3CLAUSE
+
+USES=		cpe gmake ssl
+CPE_VENDOR=	w1.fi
+BUILD_WRKSRC=	${WRKSRC}/hostapd
+CFLAGS+=	-I${OPENSSLINC}
+LDFLAGS+=	-L${OPENSSLLIB}
+
+PLIST_FILES=	sbin/hostapd sbin/hostapd_cli share/man/man1/hostapd_cli.1.gz \
+		share/man/man8/hostapd.8.gz
+.if !exists(/etc/rc.d/hostapd)
+USE_RC_SUBR=	hostapd
+.endif
+
+post-patch:
+	@${REINPLACE_CMD} -e 's|@$$(E) "  CC " $$<|@$$(E) "  $$(CC) " $$<|' \
+		${BUILD_WRKSRC}/Makefile
+	@${SED} -e 's|@PREFIX@|${PREFIX}|g' ${FILESDIR}/config \
+		>> ${WRKSRC}/hostapd/.config
+
+do-install:
+	${INSTALL_PROGRAM} ${WRKSRC}/hostapd/hostapd ${STAGEDIR}${PREFIX}/sbin
+	${INSTALL_PROGRAM} ${WRKSRC}/hostapd/hostapd_cli \
+		${STAGEDIR}${PREFIX}/sbin
+	${INSTALL_MAN} ${WRKSRC}/hostapd/hostapd_cli.1 \
+		${STAGEDIR}${PREFIX}/share/man/man1
+	${INSTALL_MAN} ${WRKSRC}/hostapd/hostapd.8 \
+		${STAGEDIR}${PREFIX}/share/man/man8
+
+.include <bsd.port.mk>
diff --git a/net/hostapd210/distinfo b/net/hostapd210/distinfo
new file mode 100644
index 000000000000..784e7e6d9238
--- /dev/null
+++ b/net/hostapd210/distinfo
@@ -0,0 +1,3 @@
+TIMESTAMP = 1642436112
+SHA256 (hostapd-2.10.tar.gz) = 206e7c799b678572c2e3d12030238784bc4a9f82323b0156b4c9466f1498915d
+SIZE (hostapd-2.10.tar.gz) = 2440435
diff --git a/net/hostapd210/files/config b/net/hostapd210/files/config
new file mode 100644
index 000000000000..de05f3384a1a
--- /dev/null
+++ b/net/hostapd210/files/config
@@ -0,0 +1,316 @@
+# FreeBSD hostapd build time configuration
+#
+# This file lists the configuration options that are used when building the
+# hostapd binary. All lines starting with # are ignored. Configuration option
+# lines must be commented out complete, if they are not to be included, i.e.,
+# just setting VARIABLE=n is not disabling that variable.
+#
+# This file is included in Makefile, so variables like CFLAGS and LIBS can also
+# be modified from here. In most cass, these lines should use += in order not
+# to override previous values of the variables.
+
+# Driver interface for Host AP driver
+#CONFIG_DRIVER_HOSTAP=y
+
+# Driver interface for wired authenticator
+#CONFIG_DRIVER_WIRED=y
+
+# Driver interface for madwifi driver
+#CONFIG_DRIVER_MADWIFI=y
+#CFLAGS += -I../../madwifi # change to the madwifi source directory
+
+# Driver interface for drivers using the nl80211 kernel interface
+#CONFIG_DRIVER_NL80211=y
+
+# driver_nl80211.c requires libnl. If you are compiling it yourself
+# you may need to point hostapd to your version of libnl.
+#
+#CFLAGS += -I$<path to libnl include files>
+#LIBS += -L$<path to libnl library files>
+
+# Use libnl v2.0 (or 3.0) libraries.
+#CONFIG_LIBNL20=y
+
+# Use libnl 3.2 libraries (if this is selected, CONFIG_LIBNL20 is ignored)
+#CONFIG_LIBNL32=y
+
+# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
+CONFIG_DRIVER_BSD=y
+CFLAGS += -I@PREFIX@/include
+LIBS += -L@PREFIX@/lib
+LIBS_p += -L@PREFIX@/lib
+LIBS_c += -L@PREFIX@/lib
+
+# Driver interface for no driver (e.g., RADIUS server only)
+#CONFIG_DRIVER_NONE=y
+
+# IEEE 802.11F/IAPP
+#CONFIG_IAPP=y
+
+# WPA2/IEEE 802.11i RSN pre-authentication
+CONFIG_RSN_PREAUTH=y
+
+# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS)
+#CONFIG_PEERKEY=y
+
+# IEEE 802.11w (management frame protection)
+#CONFIG_IEEE80211W=y
+
+# Integrated EAP server
+CONFIG_EAP=y
+
+# EAP-MD5 for the integrated EAP server
+CONFIG_EAP_MD5=y
+
+# EAP-TLS for the integrated EAP server
+CONFIG_EAP_TLS=y
+
+# EAP-MSCHAPv2 for the integrated EAP server
+CONFIG_EAP_MSCHAPV2=y
+
+# EAP-PEAP for the integrated EAP server
+CONFIG_EAP_PEAP=y
+
+# EAP-GTC for the integrated EAP server
+CONFIG_EAP_GTC=y
+
+# EAP-TTLS for the integrated EAP server
+CONFIG_EAP_TTLS=y
+
+# EAP-SIM for the integrated EAP server
+#CONFIG_EAP_SIM=y
+
+# EAP-AKA for the integrated EAP server
+#CONFIG_EAP_AKA=y
+
+# EAP-AKA' for the integrated EAP server
+# This requires CONFIG_EAP_AKA to be enabled, too.
+#CONFIG_EAP_AKA_PRIME=y
+
+# EAP-PAX for the integrated EAP server
+#CONFIG_EAP_PAX=y
+
+# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK)
+#CONFIG_EAP_PSK=y
+
+# EAP-pwd for the integrated EAP server (secure authentication with a password)
+#CONFIG_EAP_PWD=y
+
+# EAP-SAKE for the integrated EAP server
+#CONFIG_EAP_SAKE=y
+
+# EAP-GPSK for the integrated EAP server
+#CONFIG_EAP_GPSK=y
+# Include support for optional SHA256 cipher suite in EAP-GPSK
+#CONFIG_EAP_GPSK_SHA256=y
+
+# EAP-FAST for the integrated EAP server
+# Note: If OpenSSL is used as the TLS library, OpenSSL 1.0 or newer is needed
+# for EAP-FAST support. Older OpenSSL releases would need to be patched, e.g.,
+# with openssl-0.9.8x-tls-extensions.patch, to add the needed functions.
+#CONFIG_EAP_FAST=y
+
+# Wi-Fi Protected Setup (WPS)
+#CONFIG_WPS=y
+# Enable UPnP support for external WPS Registrars
+#CONFIG_WPS_UPNP=y
+# Enable WPS support with NFC config method
+#CONFIG_WPS_NFC=y
+
+# EAP-IKEv2
+#CONFIG_EAP_IKEV2=y
+
+# Trusted Network Connect (EAP-TNC)
+#CONFIG_EAP_TNC=y
+
+# EAP-EKE for the integrated EAP server
+#CONFIG_EAP_EKE=y
+
+# PKCS#12 (PFX) support (used to read private key and certificate file from
+# a file that usually has extension .p12 or .pfx)
+CONFIG_PKCS12=y
+
+# RADIUS authentication server. This provides access to the integrated EAP
+# server from external hosts using RADIUS.
+#CONFIG_RADIUS_SERVER=y
+
+# Build IPv6 support for RADIUS operations
+CONFIG_IPV6=y
+
+# IEEE Std 802.11r-2008 (Fast BSS Transition)
+#CONFIG_IEEE80211R=y
+
+# Use the hostapd's IEEE 802.11 authentication (ACL), but without
+# the IEEE 802.11 Management capability (e.g., madwifi or FreeBSD/net80211)
+CONFIG_DRIVER_RADIUS_ACL=y
+
+# IEEE 802.11n (High Throughput) support
+#CONFIG_IEEE80211N=y
+
+# Wireless Network Management (IEEE Std 802.11v-2011)
+# Note: This is experimental and not complete implementation.
+#CONFIG_WNM=y
+
+# IEEE 802.11ac (Very High Throughput) support
+#CONFIG_IEEE80211AC=y
+
+# Remove debugging code that is printing out debug messages to stdout.
+# This can be used to reduce the size of the hostapd considerably if debugging
+# code is not needed.
+#CONFIG_NO_STDOUT_DEBUG=y
+
+# Add support for writing debug log to a file: -f /tmp/hostapd.log
+# Disabled by default.
+#CONFIG_DEBUG_FILE=y
+
+# Add support for sending all debug messages (regardless of debug verbosity)
+# to the Linux kernel tracing facility. This helps debug the entire stack by
+# making it easy to record everything happening from the driver up into the
+# same file, e.g., using trace-cmd.
+#CONFIG_DEBUG_LINUX_TRACING=y
+
+# Remove support for RADIUS accounting
+#CONFIG_NO_ACCOUNTING=y
+
+# Remove support for RADIUS
+#CONFIG_NO_RADIUS=y
+
+# Remove support for VLANs
+#CONFIG_NO_VLAN=y
+
+# Enable support for fully dynamic VLANs. This enables hostapd to
+# automatically create bridge and VLAN interfaces if necessary.
+#CONFIG_FULL_DYNAMIC_VLAN=y
+
+# Use netlink-based kernel API for VLAN operations instead of ioctl()
+# Note: This requires libnl 3.1 or newer.
+#CONFIG_VLAN_NETLINK=y
+
+# Remove support for dumping internal state through control interface commands
+# This can be used to reduce binary size at the cost of disabling a debugging
+# option.
+#CONFIG_NO_DUMP_STATE=y
+
+# Enable tracing code for developer debugging
+# This tracks use of memory allocations and other registrations and reports
+# incorrect use with a backtrace of call (or allocation) location.
+#CONFIG_WPA_TRACE=y
+# For BSD, comment out these.
+#LIBS += -lexecinfo
+#LIBS_p += -lexecinfo
+#LIBS_c += -lexecinfo
+
+# Use libbfd to get more details for developer debugging
+# This enables use of libbfd to get more detailed symbols for the backtraces
+# generated by CONFIG_WPA_TRACE=y.
+#CONFIG_WPA_TRACE_BFD=y
+# For BSD, comment out these.
+#LIBS += -lbfd -liberty -lz
+#LIBS_p += -lbfd -liberty -lz
+#LIBS_c += -lbfd -liberty -lz
+
+# hostapd depends on strong random number generation being available from the
+# operating system. os_get_random() function is used to fetch random data when
+# needed, e.g., for key generation. On Linux and BSD systems, this works by
+# reading /dev/urandom. It should be noted that the OS entropy pool needs to be
+# properly initialized before hostapd is started. This is important especially
+# on embedded devices that do not have a hardware random number generator and
+# may by default start up with minimal entropy available for random number
+# generation.
+#
+# As a safety net, hostapd is by default trying to internally collect
+# additional entropy for generating random data to mix in with the data
+# fetched from the OS. This by itself is not considered to be very strong, but
+# it may help in cases where the system pool is not initialized properly.
+# However, it is very strongly recommended that the system pool is initialized
+# with enough entropy either by using hardware assisted random number
+# generator or by storing state over device reboots.
+#
+# hostapd can be configured to maintain its own entropy store over restarts to
+# enhance random number generation. This is not perfect, but it is much more
+# secure than using the same sequence of random numbers after every reboot.
+# This can be enabled with -e<entropy file> command line option. The specified
+# file needs to be readable and writable by hostapd.
+#
+# If the os_get_random() is known to provide strong random data (e.g., on
+# Linux/BSD, the board in question is known to have reliable source of random
+# data from /dev/urandom), the internal hostapd random pool can be disabled.
+# This will save some in binary size and CPU use. However, this should only be
+# considered for builds that are known to be used on devices that meet the
+# requirements described above.
+#CONFIG_NO_RANDOM_POOL=y
+
+# Select TLS implementation
+# openssl = OpenSSL (default)
+# gnutls = GnuTLS
+# internal = Internal TLSv1 implementation (experimental)
+# none = Empty template
+#CONFIG_TLS=openssl
+
+# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.1)
+# can be enabled to get a stronger construction of messages when block ciphers
+# are used.
+#CONFIG_TLSV11=y
+
+# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.2)
+# can be enabled to enable use of stronger crypto algorithms.
+#CONFIG_TLSV12=y
+
+# If CONFIG_TLS=internal is used, additional library and include paths are
+# needed for LibTomMath. Alternatively, an integrated, minimal version of
+# LibTomMath can be used. See beginning of libtommath.c for details on benefits
+# and drawbacks of this option.
+#CONFIG_INTERNAL_LIBTOMMATH=y
+#ifndef CONFIG_INTERNAL_LIBTOMMATH
+#LTM_PATH=/usr/src/libtommath-0.39
+#CFLAGS += -I$(LTM_PATH)
+#LIBS += -L$(LTM_PATH)
+#LIBS_p += -L$(LTM_PATH)
+#endif
+# At the cost of about 4 kB of additional binary size, the internal LibTomMath
+# can be configured to include faster routines for exptmod, sqr, and div to
+# speed up DH and RSA calculation considerably
+#CONFIG_INTERNAL_LIBTOMMATH_FAST=y
+
+# Interworking (IEEE 802.11u)
+# This can be used to enable functionality to improve interworking with
+# external networks.
+#CONFIG_INTERWORKING=y
+
+# Hotspot 2.0
+#CONFIG_HS20=y
+
+# Enable SQLite database support in hlr_auc_gw, EAP-SIM DB, and eap_user_file
+#CONFIG_SQLITE=y
+
+# Testing options
+# This can be used to enable some testing options (see also the example
+# configuration file) that are really useful only for testing clients that
+# connect to this hostapd. These options allow, for example, to drop a
+# certain percentage of probe requests or auth/(re)assoc frames.
+#
+#CONFIG_TESTING_OPTIONS=y
+
+# Automatic Channel Selection
+# This will allow hostapd to pick the channel automatically when channel is set
+# to "acs_survey" or "0". Eventually, other ACS algorithms can be added in
+# similar way.
+#
+# Automatic selection is currently only done through initialization, later on
+# we hope to do background checks to keep us moving to more ideal channels as
+# time goes by. ACS is currently only supported through the nl80211 driver and
+# your driver must have survey dump capability that is filled by the driver
+# during scanning.
+#
+# You can customize the ACS survey algorithm with the hostapd.conf variable
+# acs_num_scans.
+#
+# Supported ACS drivers:
+# * ath9k
+# * ath5k
+# * ath10k
+#
+# For more details refer to:
+# http://wireless.kernel.org/en/users/Documentation/acs
+#
+#CONFIG_ACS=y
diff --git a/net/hostapd210/files/hostapd.in b/net/hostapd210/files/hostapd.in
new file mode 100644
index 000000000000..b6e717098472
--- /dev/null
+++ b/net/hostapd210/files/hostapd.in
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+# PROVIDE: hostapd
+# REQUIRE: mountcritremote
+# KEYWORD: nojail shutdown
+
+. /etc/rc.subr
+
+name="hostapd"
+desc="Authenticator for IEEE 802.11 networks"
+#
+# This portion of this rc.script is different from base.
+case ${command} in
+/usr/sbin/hostapd)	# Assume user does not want base hostapd because
+			# user specified WITHOUT_WIRELESS in make.conf
+			# and /etc/defaults/rc.conf contains this value.
+			unset command;;
+esac
+command=${hostapd_program:-%%PREFIX%%/sbin/hostapd}
+# End of differences from base. The rest of the file should remain the same.
+
+ifn="$2"
+if [ -z "$ifn" ]; then
+	rcvar="hostapd_enable"
+	conf_file="/etc/${name}.conf"
+	pidfile="/var/run/${name}.pid"
+else
+	rcvar=
+	conf_file="/etc/${name}-${ifn}.conf"
+	pidfile="/var/run/${name}-${ifn}.pid"
+fi
+
+command_args="-P ${pidfile} -B ${conf_file}"
+required_files="${conf_file}"
+required_modules="wlan_xauth wlan_wep wlan_tkip wlan_ccmp"
+extra_commands="reload"
+
+load_rc_config ${name}
+run_rc_command "$1"
diff --git a/net/hostapd210/files/patch-src_ap_hostapd.c b/net/hostapd210/files/patch-src_ap_hostapd.c
new file mode 100644
index 000000000000..1eafe68ad485
--- /dev/null
+++ b/net/hostapd210/files/patch-src_ap_hostapd.c
@@ -0,0 +1,31 @@
+--- src/ap/hostapd.c.orig	2022-01-16 12:51:29.000000000 -0800
++++ src/ap/hostapd.c	2024-02-26 20:24:39.350068000 -0800
+@@ -1698,6 +1698,20 @@
+ {
+ 	iface->wait_channel_update = 0;
+ 
++#ifdef __FreeBSD
++	/* XXX hostapd_get_hw_features() is an inline that always returns -1
++	 * because MLME will not build under FreeBSD due to its use of
++	 * Linux definitions. Normally FreeBSD would uncondionally execute the
++	 * "Not all drivers support..." block. Instead we #ifdef out the entire
++	 * block of code instead of maintaining the fallacy that
++	 * hostapd_get_hw_features() returns anything meaninful.
++	 *
++	 * Ideally WANT_AP_MLME should be taught about FreeBSD data structures
++	 * and defintions. Instead we do this to enable channel selection in
++	 * hostapd.conf.
++	 */
++	iface->freq = iface->conf->channel;
++#else
+ 	if (hostapd_get_hw_features(iface)) {
+ 		/* Not all drivers support this yet, so continue without hw
+ 		 * feature data. */
+@@ -1744,6 +1758,7 @@
+ 		if (iface->conf->ieee80211h)
+ 			wpa_printf(MSG_DEBUG, "DFS support is enabled");
+ 	}
++#endif
+ 	return hostapd_setup_interface_complete(iface, 0);
+ 
+ fail:
diff --git a/net/hostapd210/files/patch-src_common_dhcp.h b/net/hostapd210/files/patch-src_common_dhcp.h
new file mode 100644
index 000000000000..f88d1921a380
--- /dev/null
+++ b/net/hostapd210/files/patch-src_common_dhcp.h
@@ -0,0 +1,25 @@
+--- src/common/dhcp.h.orig	2018-12-02 11:34:59.000000000 -0800
++++ src/common/dhcp.h	2018-12-06 00:01:11.429254000 -0800
+@@ -9,6 +9,22 @@
+ #ifndef DHCP_H
+ #define DHCP_H
+ 
++/*
++ * Translate Linux to FreeBSD
++ */
++#define iphdr		ip
++#define ihl		ip_hl
++#define verson		ip_v
++#define tos		ip_tos
++#define tot_len		ip_len
++#define id		ip_id
++#define frag_off	ip_off
++#define ttl		ip_ttl
++#define protocol	ip_p
++#define check		ip_sum
++#define saddr		ip_src
++#define daddr		ip_dst
++
+ #include <netinet/ip.h>
+ #if __FAVOR_BSD
+ #include <netinet/udp.h>
diff --git a/net/hostapd210/files/patch-src_drivers_driver__bsd.c b/net/hostapd210/files/patch-src_drivers_driver__bsd.c
new file mode 100644
index 000000000000..014a10354b0c
--- /dev/null
+++ b/net/hostapd210/files/patch-src_drivers_driver__bsd.c
@@ -0,0 +1,281 @@
+--- src/drivers/driver_bsd.c.orig	2022-01-16 12:51:29.000000000 -0800
++++ src/drivers/driver_bsd.c	2023-09-10 23:11:43.205866000 -0700
+@@ -14,6 +14,7 @@
+ #include "driver.h"
+ #include "eloop.h"
+ #include "common/ieee802_11_defs.h"
++#include "common/ieee802_11_common.h"
+ #include "common/wpa_common.h"
+ 
+ #include <ifaddrs.h>
+@@ -293,8 +294,9 @@
+ }
+ 
+ static int
+-bsd_get_iface_flags(struct bsd_driver_data *drv)
++bsd_ctrl_iface(void *priv, int enable)
+ {
++	struct bsd_driver_data *drv = priv;
+ 	struct ifreq ifr;
+ 
+ 	os_memset(&ifr, 0, sizeof(ifr));
+@@ -306,7 +308,34 @@
+ 		return -1;
+ 	}
+ 	drv->flags = ifr.ifr_flags;
++
++
++	if (enable) {
++		if (ifr.ifr_flags & IFF_UP)
++			goto nochange;
++		ifr.ifr_flags |= IFF_UP;
++	} else {
++		if (!(ifr.ifr_flags & IFF_UP))
++			goto nochange;
++		ifr.ifr_flags &= ~IFF_UP;
++	}
++
++	if (ioctl(drv->global->sock, SIOCSIFFLAGS, &ifr) < 0) {
++		wpa_printf(MSG_ERROR, "ioctl[SIOCSIFFLAGS]: %s",
++			   strerror(errno));
++		return -1;
++	}
++
++	wpa_printf(MSG_DEBUG, "%s: if %s (changed) enable %d IFF_UP %d ",
++	    __func__, drv->ifname, enable, ((ifr.ifr_flags & IFF_UP) != 0));
++
++	drv->flags = ifr.ifr_flags;
+ 	return 0;
++
++nochange:
++	wpa_printf(MSG_DEBUG, "%s: if %s (no change) enable %d IFF_UP %d ",
++	    __func__, drv->ifname, enable, ((ifr.ifr_flags & IFF_UP) != 0));
++	return 0;
+ }
+ 
+ static int
+@@ -525,7 +554,7 @@
+ 			   __func__);
+ 		return -1;
+ 	}
+-	return 0;
++	return bsd_ctrl_iface(priv, 1);
+ }
+ 
+ static void
+@@ -853,14 +882,18 @@
+ 		drv = bsd_get_drvindex(global, ifm->ifm_index);
+ 		if (drv == NULL)
+ 			return;
+-		if ((ifm->ifm_flags & IFF_UP) == 0 &&
+-		    (drv->flags & IFF_UP) != 0) {
++		if (((ifm->ifm_flags & IFF_UP) == 0 ||
++		    (ifm->ifm_flags & IFF_RUNNING) == 0) &&
++		    (drv->flags & IFF_UP) != 0 &&
++		    (drv->flags & IFF_RUNNING) != 0) {
+ 			wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN",
+ 				   drv->ifname);
+ 			wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED,
+ 					     NULL);
+ 		} else if ((ifm->ifm_flags & IFF_UP) != 0 &&
+-		    (drv->flags & IFF_UP) == 0) {
++		    (ifm->ifm_flags & IFF_RUNNING) != 0 &&
++		    ((drv->flags & IFF_UP) == 0 ||
++		    (drv->flags & IFF_RUNNING)  == 0)) {
+ 			wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' UP",
+ 				   drv->ifname);
+ 			wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED,
+@@ -1025,7 +1058,8 @@
+ 	if (l2_packet_get_own_addr(drv->sock_xmit, params->own_addr))
+ 		goto bad;
+ 
+-	if (bsd_get_iface_flags(drv) < 0)
++	/* mark down during setup */
++	if (bsd_ctrl_iface(drv, 0) < 0)
+ 		goto bad;
+ 
+ 	if (bsd_set_mediaopt(drv, IFM_OMASK, IFM_IEEE80211_HOSTAP) < 0) {
+@@ -1050,12 +1084,13 @@
+ {
+ 	struct bsd_driver_data *drv = priv;
+ 
++	if (drv->ifindex != 0)
++		bsd_ctrl_iface(drv, 0);
+ 	if (drv->sock_xmit != NULL)
+ 		l2_packet_deinit(drv->sock_xmit);
+ 	os_free(drv);
+ }
+ 
+-
+ static int
+ bsd_set_sta_authorized(void *priv, const u8 *addr,
+ 		       unsigned int total_flags, unsigned int flags_or,
+@@ -1197,13 +1232,41 @@
+ }
+ 
+ static int
++wpa_driver_bsd_set_rsn_wpa_ie(struct bsd_driver_data * drv,
++    struct wpa_driver_associate_params *params, const u8 *ie)
++{
++	int privacy;
++	size_t ie_len = ie[1] ? ie[1] + 2 : 0;
++
++	/* XXX error handling is wrong but unclear what to do... */
++	if (wpa_driver_bsd_set_wpa_ie(drv, ie, ie_len) < 0)
++		return -1;
++
++	privacy = !(params->pairwise_suite == WPA_CIPHER_NONE &&
++	    params->group_suite == WPA_CIPHER_NONE &&
++	    params->key_mgmt_suite == WPA_KEY_MGMT_NONE);
++	wpa_printf(MSG_DEBUG, "%s: set PRIVACY %u", __func__,
++	    privacy);
++
++	if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0)
++		return -1;
++
++	if (ie_len &&
++	    set80211param(drv, IEEE80211_IOC_WPA,
++	    ie[0] == WLAN_EID_RSN ? 2 : 1) < 0)
++		return -1;
++
++	return 0;
++}
++
++static int
+ wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params)
+ {
+ 	struct bsd_driver_data *drv = priv;
+ 	struct ieee80211req_mlme mlme;
+ 	u32 mode;
+-	int privacy;
+ 	int ret = 0;
++	const u8 *wpa_ie, *rsn_ie;
+ 
+ 	wpa_printf(MSG_DEBUG,
+ 		"%s: ssid '%.*s' wpa ie len %u pairwise %u group %u key mgmt %u"
+@@ -1220,7 +1283,10 @@
+ 		mode = 0 /* STA */;
+ 		break;
+ 	case IEEE80211_MODE_IBSS:
++#if 0
+ 		mode = IFM_IEEE80211_IBSS;
++#endif
++		mode = IFM_IEEE80211_ADHOC;
+ 		break;
+ 	case IEEE80211_MODE_AP:
+ 		mode = IFM_IEEE80211_HOSTAP;
+@@ -1249,24 +1315,33 @@
+ 		ret = -1;
+ 	if (wpa_driver_bsd_set_auth_alg(drv, params->auth_alg) < 0)
+ 		ret = -1;
+-	/* XXX error handling is wrong but unclear what to do... */
+-	if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0)
+-		return -1;
+ 
+-	privacy = !(params->pairwise_suite == WPA_CIPHER_NONE &&
+-	    params->group_suite == WPA_CIPHER_NONE &&
+-	    params->key_mgmt_suite == WPA_KEY_MGMT_NONE &&
+-	    params->wpa_ie_len == 0);
+-	wpa_printf(MSG_DEBUG, "%s: set PRIVACY %u", __func__, privacy);
++	if (params->wpa_ie_len) {
++		rsn_ie = get_ie(params->wpa_ie, params->wpa_ie_len,
++		    WLAN_EID_RSN);
++		if (rsn_ie) {
++			if (wpa_driver_bsd_set_rsn_wpa_ie(drv, params,
++			    rsn_ie) < 0)
++				return -1;
++		}
++		else {
++			wpa_ie = get_vendor_ie(params->wpa_ie,
++			    params->wpa_ie_len, WPA_IE_VENDOR_TYPE);
++			if (wpa_ie) {
++				if (wpa_driver_bsd_set_rsn_wpa_ie(drv, params,
++				    wpa_ie) < 0)
++					return -1;
++			}
++		}
++	}
+ 
+-	if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0)
++	/*
++	 * NB: interface must be marked UP for association
++	 * or scanning (ap_scan=2)
++	 */
++	if (bsd_ctrl_iface(drv, 1) < 0)
+ 		return -1;
+ 
+-	if (params->wpa_ie_len &&
+-	    set80211param(drv, IEEE80211_IOC_WPA,
+-			  params->wpa_ie[0] == WLAN_EID_RSN ? 2 : 1) < 0)
+-		return -1;
+-
+ 	os_memset(&mlme, 0, sizeof(mlme));
+ 	mlme.im_op = IEEE80211_MLME_ASSOC;
+ 	if (params->ssid != NULL)
+@@ -1309,11 +1384,8 @@
+ 	}
+ 
+ 	/* NB: interface must be marked UP to do a scan */
+-	if (!(drv->flags & IFF_UP)) {
+-		wpa_printf(MSG_DEBUG, "%s: interface is not up, cannot scan",
+-			   __func__);
++	if (bsd_ctrl_iface(drv, 1) < 0)
+ 		return -1;
+-	}
+ 
+ #ifdef IEEE80211_IOC_SCAN_MAX_SSID
+ 	os_memset(&sr, 0, sizeof(sr));
+@@ -1485,6 +1557,17 @@
+ 	if (devcaps.dc_drivercaps & IEEE80211_C_WPA2)
+ 		drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
+ 			WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
++#ifdef __FreeBSD__
++	drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 |
++	    WPA_DRIVER_CAPA_ENC_WEP104 |
++	    WPA_DRIVER_CAPA_ENC_TKIP |
++	    WPA_DRIVER_CAPA_ENC_CCMP;
++#else
++	/*
++	 * XXX
++	 * FreeBSD exports hardware cryptocaps.  These have no meaning for wpa
++	 * since net80211 performs software crypto.
++	 */
+ 
+ 	if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_WEP)
+ 		drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 |
+@@ -1493,6 +1576,7 @@
+ 		drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP;
+ 	if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_AES_CCM)
+ 		drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP;
++#endif
+ 
+ 	if (devcaps.dc_drivercaps & IEEE80211_C_HOSTAP)
+ 		drv->capa.flags |= WPA_DRIVER_FLAGS_AP;
+@@ -1545,6 +1629,8 @@
+ 		}
+ 		if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP)
+ 			return IEEE80211_M_HOSTAP;
++		if (ifmr.ifm_current & IFM_IEEE80211_IBSS)
++			return IEEE80211_M_IBSS;
+ 		if (ifmr.ifm_current & IFM_IEEE80211_MONITOR)
+ 			return IEEE80211_M_MONITOR;
+ #ifdef IEEE80211_M_MBSS
+@@ -1605,7 +1691,7 @@
+ 		drv->capa.key_mgmt_iftype[i] = drv->capa.key_mgmt;
+ 
+ 	/* Down interface during setup. */
+-	if (bsd_get_iface_flags(drv) < 0)
++	if (bsd_ctrl_iface(drv, 0) < 0)
+ 		goto fail;
+ 
+ 	/* Proven to work, lets go! */
+@@ -1628,6 +1714,9 @@
+ 
+ 	if (drv->ifindex != 0 && !drv->if_removed) {
+ 		wpa_driver_bsd_set_wpa(drv, 0);
++
++		/* NB: mark interface down */
++		bsd_ctrl_iface(drv, 0);
+ 
+ 		wpa_driver_bsd_set_wpa_internal(drv, drv->prev_wpa,
+ 						drv->prev_privacy);
diff --git a/net/hostapd210/files/patch-src_l2__packet_l2__packet__freebsd.c b/net/hostapd210/files/patch-src_l2__packet_l2__packet__freebsd.c
new file mode 100644
index 000000000000..e0aa170fa91f
--- /dev/null
+++ b/net/hostapd210/files/patch-src_l2__packet_l2__packet__freebsd.c
@@ -0,0 +1,74 @@
+--- src/l2_packet/l2_packet_freebsd.c.orig	2022-01-16 12:51:29.000000000 -0800
++++ src/l2_packet/l2_packet_freebsd.c	2023-09-11 22:21:12.054042000 -0700
+@@ -8,7 +8,10 @@
+  */
+ 
+ #include "includes.h"
+-#if defined(__APPLE__) || defined(__GLIBC__)
++#if defined(__FreeBSD__) \
++ || defined(__DragonFly__) \
++ || defined(__APPLE__) \
++ || defined(__GLIBC__)
+ #include <net/bpf.h>
+ #endif /* __APPLE__ */
+ #include <pcap.h>
+@@ -20,6 +23,7 @@
+ #include <sys/sysctl.h>
+ #endif /* __sun__ */
+ 
++#include <net/ethernet.h>
+ #include <net/if.h>
+ #include <net/if_dl.h>
+ #include <net/route.h>
+@@ -76,24 +80,33 @@
+ {
+ 	struct l2_packet_data *l2 = eloop_ctx;
+ 	pcap_t *pcap = sock_ctx;
+-	struct pcap_pkthdr hdr;
++	struct pcap_pkthdr *hdr;
+ 	const u_char *packet;
+ 	struct l2_ethhdr *ethhdr;
+ 	unsigned char *buf;
+ 	size_t len;
+ 
+-	packet = pcap_next(pcap, &hdr);
++	if (pcap_next_ex(pcap, &hdr, &packet) == -1) {
++		wpa_printf(MSG_ERROR, "Error reading packet, has device disappeared?");
++		packet = NULL;
++		eloop_terminate();
++	}
+ 
+-	if (!l2->rx_callback || !packet || hdr.caplen < sizeof(*ethhdr))
++	if (!l2->rx_callback || !packet || hdr->caplen < sizeof(*ethhdr))
+ 		return;
+ 
+ 	ethhdr = (struct l2_ethhdr *) packet;
+ 	if (l2->l2_hdr) {
+ 		buf = (unsigned char *) ethhdr;
+-		len = hdr.caplen;
++		len = hdr->caplen;
+ 	} else {
+ 		buf = (unsigned char *) (ethhdr + 1);
+-		len = hdr.caplen - sizeof(*ethhdr);
++		len = hdr->caplen - sizeof(*ethhdr);
++		/* handle 8021Q encapsulated frames */
++		if (ethhdr->h_proto == htons(ETH_P_8021Q)) {
++			buf += ETHER_VLAN_ENCAP_LEN;
++			len -= ETHER_VLAN_ENCAP_LEN;
++		}
+ 	}
+ 	l2->rx_callback(l2->rx_callback_ctx, ethhdr->h_source, buf, len);
+ }
+@@ -122,10 +135,10 @@
+ 	os_snprintf(pcap_filter, sizeof(pcap_filter),
+ 		    "not ether src " MACSTR " and "
+ 		    "( ether dst " MACSTR " or ether dst " MACSTR " ) and "
+-		    "ether proto 0x%x",
++		    "( ether proto 0x%x or ( vlan 0 and ether proto 0x%x ) )",
+ 		    MAC2STR(l2->own_addr), /* do not receive own packets */
+ 		    MAC2STR(l2->own_addr), MAC2STR(pae_group_addr),
+-		    protocol);
++		    protocol, protocol);
+ 	if (pcap_compile(l2->pcap, &pcap_fp, pcap_filter, 1, pcap_netp) < 0) {
+ 		fprintf(stderr, "pcap_compile: %s\n", pcap_geterr(l2->pcap));
+ 		return -1;
diff --git a/net/hostapd210/files/patch-src_utils_os__unix.c b/net/hostapd210/files/patch-src_utils_os__unix.c
new file mode 100644
index 000000000000..860682df6e05
--- /dev/null
+++ b/net/hostapd210/files/patch-src_utils_os__unix.c
@@ -0,0 +1,15 @@
+--- src/utils/os_unix.c.orig	2022-01-16 12:51:29.000000000 -0800
++++ src/utils/os_unix.c	2024-06-01 22:20:49.333716000 -0700
+@@ -103,10 +103,12 @@
+ 			break;
+ #endif
+ #ifdef CLOCK_MONOTONIC
++#if !(defined(CLOCK_BOOTTIME) && CLOCK_BOOTTIME == CLOCK_MONOTONIC)
+ 		case CLOCK_MONOTONIC:
+ 			clock_id = CLOCK_REALTIME;
+ 			break;
+ #endif
++#endif
+ 		case CLOCK_REALTIME:
+ 			return -1;
+ 		}
diff --git a/net/hostapd210/files/patch-src_wps_wps__upnp.c b/net/hostapd210/files/patch-src_wps_wps__upnp.c
new file mode 100644
index 000000000000..ee10b79e48aa
--- /dev/null
+++ b/net/hostapd210/files/patch-src_wps_wps__upnp.c
@@ -0,0 +1,12 @@
+--- src/wps/wps_upnp.c.orig	2021-03-16 13:50:10.000000000 -0700
++++ src/wps/wps_upnp.c	2021-03-18 12:49:19.537874000 -0700
+@@ -963,7 +963,8 @@
+ 		goto fail;
+ 	}
+ 	os_memcpy(mac, req.ifr_addr.sa_data, 6);
+-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
++#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) \
++	|| defined(__DragonFly__)
+ 	if (eth_get(net_if, mac) < 0) {
+ 		wpa_printf(MSG_ERROR, "WPS UPnP: Failed to get MAC address");
+ 		goto fail;
diff --git a/net/hostapd210/pkg-descr b/net/hostapd210/pkg-descr
new file mode 100644
index 000000000000..873d58411d7a
--- /dev/null
+++ b/net/hostapd210/pkg-descr
@@ -0,0 +1,10 @@
+hostapd is a user space daemon for access point and authentication
+servers. It implements IEEE 802.11 access point management, IEEE
+802.1X/WPA/WPA2/EAP Authenticators, RADIUS client, EAP server, and
+RADIUS authentication server. The current version supports Linux
+(Host AP, madwifi, mac80211-based drivers) and FreeBSD (net80211).
+
+Add the following to /etc/rc.conf to use the ports version instead
+of the base version:
+
+    hostapd_program="/usr/local/sbin/hostapd"
diff --git a/net/hostapd210/pkg-message b/net/hostapd210/pkg-message
new file mode 100644
index 000000000000..43d22d9a1e7d
--- /dev/null
+++ b/net/hostapd210/pkg-message
@@ -0,0 +1,10 @@
+[
+{ type: install
+  message: <<EOM
+Add the following to /etc/rc.conf to use the ports version instead
+of the base version:
+
+    hostapd_program="/usr/local/sbin/hostapd"
+EOM
+}
+]