Networking

RSS for tag

Explore the networking protocols and technologies used by the device to connect to Wi-Fi networks, Bluetooth devices, and cellular data services.

Networking Documentation

Posts under Networking subtopic

Post

Replies

Boosts

Views

Activity

Unexplained behavioural changes in BSD sockets on macos 26.6.x and 27
We have started seeing some unexplained behavioural differences in the BSD socket APIs on macos 26.6.x and macos 27. On a different front, there also seems to be some changes in the ptrace area for PT_DETACH. Historically, the release notes of macos don't include any mention of such changes. And unfortunately, prior experience of filing feedback assistant issues too hasn't been very motivating due to lack of any response on those tickets. These forums have been very helpful in trying to understand some of these changes, and I plan to raise separate topics for the issues shortly. In the past, the other useful option I have used is reading up the kernel sources published at https://opensource.apple.com/releases/. But there hasn't been any updates for macos 26.6 or macos 27. It will be very useful if macos 26.6 and 27 releases are published there. That will help expedite investigating some of these failures. BSD socket APIs in the recent releases of macos have seen several issues (feedback assistant issues have been filed). The implications of these failures is that we (in OpenJDK) have had to disable several tests on recent versions of macos which has reduced the test coverage and reliability of these very primitive networking APIs on this platform.
5
0
384
3w
WCSession.sendMessage is crashing when a reply or error handler is attached, why?
The following code should send a message from the watch to the iPhone. Unfortunately, it is crashing. I have no clue why. if WCSession.isSupported() { let session = WCSession.default if ((session.activationState == .activated) && session.isReachable) { session.sendMessage(["SimpleMessages":["start"]], replyHandler:{reply in _ = 0 }, errorHandler:nil) } } If the reply handler is set to nil, the code does not crash. Anyway, in both cases the message is correctly sent from the watch to the phone. The code itself is run on the main thread (verified). I am running watchOS 26.6 and iOS 27. Here is the crash : Stack trace
3
0
307
3w
Dual-stack UDP socket bound to port 0 can get a port already in use on 127.0.0.1 (FB25058707)
I filed FB25058707 and wanted to make sure it reaches the right people, because it causes silent datagram loss that's hard to trace. On macOS, when a dual-stack UDP socket (AF_INET6 with IPV6_V6ONLY=0) binds [::]:0, the kernel sometimes gives it a port that an AF_INET socket already has bound to 127.0.0.1. Datagrams sent to 127.0.0.1 on that port then go to the AF_INET socket, so the dual-stack socket never receives them. An explicit bind of the same socket to that port fails with EADDRINUSE; only port-0 assignment hands it out. This program binds 1000 AF_INET sockets to 127.0.0.1:0, then binds dual-stack sockets to [::]:0 and checks where a datagram to 127.0.0.1:port lands whenever the port is already held. It's loopback only and runs in a few seconds: /* * A dual-stack UDP socket (AF_INET6, IPV6_V6ONLY=0) bound to [::]:0 can be * assigned a port already bound by an AF_INET socket on 127.0.0.1. Datagrams * to 127.0.0.1:port then reach the AF_INET socket, not the dual-stack one. * Loopback only. Build: cc -O2 -o dualstack_port0 dualstack_port0.c */ #include <arpa/inet.h> #include <errno.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/resource.h> #include <sys/socket.h> #include <sys/time.h> #include <unistd.h> #define HELD 1000 #define TRIALS 2000 static int held[65536]; static void die(const char *what) { perror(what); exit(1); } static int port_of(int s) { struct sockaddr_storage ss; socklen_t len = sizeof(ss); if (getsockname(s, (struct sockaddr *)&ss, &len) != 0) die("getsockname"); if (ss.ss_family == AF_INET) return ntohs(((struct sockaddr_in *)&ss)->sin_port); return ntohs(((struct sockaddr_in6 *)&ss)->sin6_port); } static int bind_v4(in_addr_t addr) { int s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) die("socket AF_INET"); struct sockaddr_in sin = { .sin_len = sizeof(sin), .sin_family = AF_INET, .sin_addr.s_addr = addr }; if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) != 0) die("bind AF_INET"); return s; } static int bind_dual(void) { int s = socket(AF_INET6, SOCK_DGRAM, 0), off = 0; if (s < 0) die("socket AF_INET6"); if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off)) != 0) die("IPV6_V6ONLY"); struct sockaddr_in6 sin6 = { .sin6_len = sizeof(sin6), .sin6_family = AF_INET6, .sin6_addr = in6addr_any }; if (bind(s, (struct sockaddr *)&sin6, sizeof(sin6)) != 0) die("bind AF_INET6"); return s; } /* Returns 1 if s receives token within 100ms, skipping other datagrams. */ static int got(int s, const char *token) { struct timeval tv = { .tv_sec = 0, .tv_usec = 100000 }; if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) != 0) die("SO_RCVTIMEO"); char buf[64]; for (;;) { ssize_t n = recv(s, buf, sizeof(buf) - 1, 0); if (n < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) return 0; die("recv"); } buf[n] = 0; if (strcmp(buf, token) == 0) return 1; } } int main(void) { struct rlimit rl; if (getrlimit(RLIMIT_NOFILE, &rl) != 0) die("getrlimit"); rl.rlim_cur = rl.rlim_max < 4096 ? rl.rlim_max : 4096; if (setrlimit(RLIMIT_NOFILE, &rl) != 0) die("setrlimit"); memset(held, -1, sizeof(held)); for (int i = 0; i < HELD;) { int s = bind_v4(htonl(INADDR_LOOPBACK)), p = port_of(s); if (held[p] >= 0) { close(s); continue; } held[p] = s; i++; } int sender = bind_v4(htonl(INADDR_LOOPBACK)); for (int dual = 1; dual >= 0; dual--) { int collisions = 0, to_held = 0, to_wild = 0; for (int i = 0; i < TRIALS; i++) { int w = dual ? bind_dual() : bind_v4(htonl(INADDR_ANY)), p = port_of(w); if (held[p] >= 0) { collisions++; char token[32]; snprintf(token, sizeof(token), "%d-%d", dual, i); struct sockaddr_in to = { .sin_len = sizeof(to), .sin_family = AF_INET, .sin_port = htons(p), .sin_addr.s_addr = htonl(INADDR_LOOPBACK) }; if (sendto(sender, token, strlen(token), 0, (struct sockaddr *)&to, sizeof(to)) < 0) die("sendto"); to_held += got(held[p], token); to_wild += got(w, token); } close(w); } printf("%s: %d/%d wildcard binds got a port held by a 127.0.0.1 socket; the probe reached that socket %d times, the wildcard socket %d times\n", dual ? "AF_INET6 V6ONLY=0 [::]:0" : "AF_INET 0.0.0.0:0 ", collisions, TRIALS, to_held, to_wild); } return 0; } On macOS 27.0 (26A428): AF_INET6 V6ONLY=0 [::]:0: 122/2000 wildcard binds got a port held by a 127.0.0.1 socket; the probe reached that socket 122 times, the wildcard socket 0 times AF_INET 0.0.0.0:0 : 0/2000 wildcard binds got a port held by a 127.0.0.1 socket; the probe reached that socket 0 times, the wildcard socket 0 times macOS 15.8.1 x86_64 gives the same pattern, and a Go version of the test reproduces on 15.7.9 and 26.6.2 as well. FreeBSD 15.1 gives 0/2000 with a dual-stack socket. From the public XNU source (xnu-12377.121.6), in6_pcbsetport checks candidate ports with in6_pcblookup_local, which skips PCBs without INP_IPV6, while in6_pcbbind does an IPv4 PCB lookup for dual-stack wildcard binds. That would explain why an explicit bind is refused but port 0 isn't. This is the cause of the long-standing Go issue golang/go#67226, since Go's net.ListenUDP("udp", 0.0.0.0:0) creates exactly this socket, and of intermittent failures in QUIC client tests. Using an AF_INET socket for IPv4-only traffic avoids it, but there's no workaround for a socket that needs both families on one port.
2
0
316
3w
macos 27 - EDOM error from setsockopt() for SO_LINGER socket option for values greater than 32767
On macos 27, there appears to be a change in the setsockopt() implementation for the SO_LINGER option. It looks like the implementation now imposes a different maximum limit on the value that is accepted for linger. Consider the trivial attached C program. Rename it from main.c.txt to main.c. Compiling it (using clang main.c) and running it (using ./a.out), on older versions of macos (like 26.x), it returns: ----------------------- MacOS version: 26.7.1 Kernel version: Darwin Kernel Version 25.6.0: Tue Aug 18 17:49:13 PDT 2026; root:xnu-12377.161.15.700.19~2/RELEASE_ARM64_T6000 ----------------------- SUCCESS - set SO_LINGER to value 10 SUCCESS - set SO_LINGER to value 42 SUCCESS - set SO_LINGER to value 1024 SUCCESS - set SO_LINGER to value 32767 SUCCESS - set SO_LINGER to value 32768 SUCCESS - set SO_LINGER to value 65535 SUCCESS - set SO_LINGER to value 65536 SUCCESS - set SO_LINGER to value 65578 However, on macos 27, this now fails with EDOM error ("Numerical argument out of domain") for values greater than 32767: ----------------------- MacOS version: 27.0.1 Kernel version: Darwin Kernel Version 27.0.0: Tue Aug 11 21:02:16 PDT 2026; root:xnu-13432.1.9~1/RELEASE_ARM64_T8112 ----------------------- SUCCESS - set SO_LINGER to value 10 SUCCESS - set SO_LINGER to value 42 SUCCESS - set SO_LINGER to value 1024 SUCCESS - set SO_LINGER to value 32767 FAILURE - failed to set SO_LINGER to value 32768, reason: Numerical argument out of domain FAILURE - failed to set SO_LINGER to value 65535, reason: Numerical argument out of domain FAILURE - failed to set SO_LINGER to value 65536, reason: Numerical argument out of domain FAILURE - failed to set SO_LINGER to value 65578, reason: Numerical argument out of domain I'm guessing this is an intentional change, but I wanted to confirm nonetheless. Should the documentation of SO_LINGER and SO_LINGER_SEC socket options, in man setsockopt, mention the acceptable value range for them? main.c.txt
2
0
302
4w
macos 27 - unexpected/new errno from BSD socket connect() when pending connections exceed backlog
Please consider the trivial C program attached to this thread. The code creates a socket() and listen()s for connections, but (intentionally) doesn't accept() the connections. The listen() is done using a small backlog (of 1). This test then does several connect() attempts and expects that the connect() attempts will accumulate in the pending queue and once the queue exceeds the backlog limit, then as specified in man listen: The backlog parameter defines the maximum length for the queue of pending connections. If a connection request arrives with the queue full, the client may receive an error with an indication of ECONNREFUSED. then the connect() attempt will receive a ECONNREFUSED. However, in macos 27, such a connect() attempt leads to ECONNRESET (Connection reset by peer) instead of ECONNREFUSED. Is this expected? Experiments show that prior versions of macos were returning a ETIMEDOUT for such connect() attempts. If this new error is expected from connect() when the backlog limit has exceeded, should it be specified in the man listen documentation? Rename the attached main.c.txt to main.c. Compiling the attached program on macos 27, using clang main.c and then running ./a.out results in: ----------------------- MacOS version: 27.0.1 Kernel version: Darwin Kernel Version 27.0.0: Tue Aug 11 21:02:16 PDT 2026; root:xnu-13432.1.9~1/RELEASE_ARM64_T8112 ----------------------- started server at at 127.0.0.1:52753 with a backlog of 1 connect() attempt 1 - connected connect() attempt 2 - connected connect() attempt 3 - connected connect() attempt 4 - connected connect() attempt 5 - failed to connect() - Connection reset by peer <-- FAILURE: Unexpected error code, expected either ETIMEDOUT or ECONNREFUSED but got 54 connect() attempt 6 - connected connect() attempt 7 - connected connect() attempt 8 - connected connect() attempt 9 - failed to connect() - Connection reset by peer <-- FAILURE: Unexpected error code, expected either ETIMEDOUT or ECONNREFUSED but got 54 connect() attempt 10 - failed to connect() - Connection reset by peer <-- FAILURE: Unexpected error code, expected either ETIMEDOUT or ECONNREFUSED but got 54 connect() attempt 11 - failed to connect() - Connection reset by peer <-- FAILURE: Unexpected error code, expected either ETIMEDOUT or ECONNREFUSED but got 54 On a related note, it's unclear why several of the connect() attempts succeeded instead of just 1 of them succeeding. On prior versions of macos, the output of the same program is: ----------------------- MacOS version: 26.7.1 Kernel version: Darwin Kernel Version 25.6.0: Tue Aug 18 17:49:13 PDT 2026; root:xnu-12377.161.15.700.19~2/RELEASE_ARM64_T6000 ----------------------- started server at at 127.0.0.1:52451 with a backlog of 1 connect() attempt 1 - connected connect() attempt 2 - failed to connect() - Operation timed out connect() attempt 3 - failed to connect() - Operation timed out connect() attempt 4 - failed to connect() - Operation timed out connect() attempt 5 - failed to connect() - Operation timed out connect() attempt 6 - failed to connect() - Operation timed out connect() attempt 7 - failed to connect() - Operation timed out connect() attempt 8 - failed to connect() - Operation timed out connect() attempt 9 - failed to connect() - Operation timed out connect() attempt 10 - failed to connect() - Operation timed out connect() attempt 11 - failed to connect() - Operation timed out and this output is much more understandable and deterministic. main.c.txt
2
0
313
4w
TCP connection in with Wi-Fi aware framework never reaches ".ready" state
While developing our wifi-aware implementation we ran into a specific issue where TCP connections seem to never reach a "ready" state (ready to transfer data). It stays in “”preparing” state trying to connect for forever. We tried to recreate a new TCP connection every time after the connection stays in "preparing" for longer than 10 seconds. This helps to "recover" eventually, but it only happens after 1.5 - 2 minutes. Creating a completely new NetworkBrowser and NetworkListener doesn’t speed up this process. The issue occurs when the browser and listener are setting up the NAN/TCP connection, at that time if the user opens the DevicePairingView it seems that it disrupts or interferes with the connection, entering an invalid state. From what we can see it takes around 2 minutes for it to recover, presumably this is when NAN drops the connection (timeout) and creates a new one.

 STEPS TO REPRODUCE Reproduction steps:

 Open the app on 2 wifi-aware devices.
 Device 1 presses “Pair with device”. Device 2 navigates to “Receive” and presses the “”Pair with sender”.
 Complete the pairing process.

 Device 1 (Send) presses the start button.
 Device 2 (receive) presses start button, Directly after the button press, device 1 presses the “”Pair with sender” button
 Observe TCP connection never fully establishes (1.5 - 2 mins) PLATFORM AND VERSION iOS Development environment: Xcode 26.3, macOS 26.4.1 Run-time configuration: iOS 26.5 test project with a recording showing the issue: https://github.com/DeveloperNiels/WAIssue
7
0
768
4w
Out-of-band data returned by recv() and read() on socket bound to non-loopback address even when SO_OOBINLINE is disabled
I've been investigating an issue with the SO_OOBINLINE socket option. When that option is disabled, the expectation is that out-of-band data that is sent on the socket will not be available through the use of read() or recv() calls on that socket. What we have been noticing is that when the socket is bound to a non-loopback address (and the communication is happening over that non-loopback address), then even when SO_OOBINLINE is disabled for the socket, the read()/recv() calls both return the out-of-band data. The issue however isn't reproducible with loopback address, and read()/recv() both correctly exclude the out-of-band data. This issue is only noticed on macos. I have been able to reproduce on macos M1, following version, but the original report which prompted me to look into this was reported on macos x64. My M1 OS version is: sw_vers ProductName: macOS ProductVersion: 14.3.1 BuildVersion: 23D60 Attached is a reproducer (main.c.txt - rename it to main.c after downloading) that I have been able to develop which reproduces this issue on macos. When you compile and run that: ./a.out it binds to a non-loopback address by default and you should see the failure log, resembling: ... ERROR: expected: 1234512345 but received: 12345U12345 To run the same reproducer against loopback address, run it as: ./a.out loopback and that should succeed (i.e. no out-of-band data) with logs resembling: ... SUCCESS: completed successfully, expected: 1234512345, received: 1234512345 Is this a bug in the OS? I would have reported this directly through feedback assistant, but my past few open issues (since more than a year) have not even seen an acknowledgement or a reply, so I decided to check here first. main.c.txt
8
0
1.3k
4w
NEURLFilterManager.localizedDescription is ignored by System Settings -> Network -> Filters
macOS 26.6, 26.7, 27.0 and 27.2 beta 1/2. Reproduced with Apple's SimpleURLFilter sample ("Filtering traffic by URL", WWDC25 session 234), built and run as a macOS app. The sample never sets localizedDescription, so I added one line to ConfigurationModel.save(configuration:) before saveToPreferences(): sharedFilterManager.localizedDescription = "Sentinel Filter Name" The property holds the value in memory: after loadFromPreferences(), the logged LocalizedStringResource still has key: "Sentinel Filter Name". But the effective configuration the system starts the session with has no localizedDescription — the session is named after the app: name = SimpleURLFilter applicationName = SimpleURLFilter application = com.example.apple-samplecode.SimpleURLFilterTC3Q7MAJXF (the rest of the nesessionmanager dump is the urlFilter dictionary, and it has no localizedDescription key). System Settings > Network > Filters shows the filter as URLFilter, not "Sentinel Filter Name". The stored configuration (/Library/Preferences/com.apple.networkextension.plist) has no localizedDescription key either, and injecting one by hand does not survive a nesessionmanager restart. Re-saving, removing and re-creating the configuration, and rebooting the Mac do not change the displayed name. Expected: the docs describe localizedDescription as "A string containing a description of the URL filter", and WWDC25 session 234's code sample ("Configure and manage URL Filter") sets it this way (manager.localizedDescription = "Alice's URL Filter"). For comparison, a NETransparentProxyManager configuration on the same Mac persists localizedDescription as the configuration's Name in the same plist, while the URL filter configuration has no such field. Filed as FB24987420.
1
0
296
Sep ’26
iOS leaves an accessory's no-internet Wi-Fi (NEHotspotConfiguration) for a saved network mid-session
We're building an iOS and Android app that transfers files to and from a device over a Wi-Fi network the device creates. That network has no internet access. The app gets the Wi-Fi credentials from the device (over Bluetooth, or from a QR code on its screen) and joins with NEHotspotConfiguration. Android works reliably. On iOS, partway through a session the phone leaves the device's network and joins a saved network that has internet, which breaks our connection to the device. Setup: iPhone 13 Pro, iOS 26.x NEHotspotConfiguration(ssid:passphrase:isWEP: false) with joinOnce = false. With joinOnce = true, iOS usually stays on the current internet Wi-Fi and never joins the device's network. WPA2. The device is at 192.168.4.1, and its DHCP server hands out the device as router and DNS. Device traffic: NWConnection (TCP) with prohibitedInterfaceTypes = [.cellular]. Server traffic: a separate NWConnection with requiredInterfaceType = .cellular. Wi-Fi Assist is off. Example: we read an 8 MB file from the device (30 s, no problem), then post it to our server over cellular (93 s). During the post, the device connection carries only a small message every ~15 s. 28 s into the post, NWPathMonitor shows Wi-Fi drop out for 3 s, and when it returns the phone is on the our primary network. Occasionally iOS shows a prompt asking whether to stay connected without internet, but usually it switches without asking. We haven't seen it switch during the file read, while the device connection is busy. Questions: Is there a supported way to keep iOS on a device's no-internet network for a whole session? Does traffic on the Wi-Fi interface (such as an active NWConnection) affect whether iOS switches away? Would a DHCP configuration without a router or DNS server change how iOS treats the network? Is joinOnce = false right for this, or can joinOnce = true join when the phone is already on an internet-capable Wi-Fi?
1
0
533
Sep ’26
macOS content filter: supported denial guarantee across provider failure for a bounded process tree
We are designing a bounded local macOS operation with a supervisor, controller and helper. All three must be unable to cause prohibited network effects, including attributable delegated requests, before admission and until quiescence. Unrelated applications must retain their normal network access. We are seeking an API contract clarification, not reporting a reproduced OS bug. No NetworkExtension provider has been activated for this design. Our reviewed SDK is MacOSX27.0.sdk; its presence is not a runtime qualification. Please identify the supported macOS versions for your answer. The design must tolerate provider crash, termination, disconnection and unresponsiveness, and operation lease expiry/revocation. Administrative filter disablement or privileged reconfiguration is a separate unresolved threat-model case, not something we assume ordinary failure handling covers. We reviewed content-filter deployment in TN3134 and the nullable/delegated audit tokens in NEFilterFlow. We understand that NEURLFilterManager.shouldFailClosed concerns URL-filter decisions, not an established guarantee for arbitrary content-filter traffic. EndpointSecurity AUTH deadlines are also a separate mechanism. The VPN routing article documents dropping during specific transitions, but has system exceptions; TN3120 excludes using a packet tunnel as a dropping content filter. We therefore have not adopted that workaround. For macOS NEFilterDataProvider / NEFilterPacketProvider, is there a supported configuration that keeps prohibited operation traffic denied when the provider crashes, is killed, disconnects, hangs or cannot deliver a decision? Please distinguish new flows, existing/previously permitted flows, queued data, restart intervals, and configuration disable/removal. What supported admission and teardown guarantees allow releasing the first protected process only after enforcement is effective, then retaining denial through lease revocation and shutdown? An enabled configuration alone would not demonstrate that barrier. How should this guarantee cover operation-caused DNS and delegated system-service traffic, including absent/ambiguous audit tokens, without denying unrelated host traffic? If content filters cannot meet that scope, can App Sandbox without network entitlements provide the independent denial boundary for these roles, and what documented exclusions or additional constraints apply? A reference to the supported contract, or a precise statement of the requirement that needs to change, would let us select an architecture before implementing and activating a native provider. We are not requesting private APIs or an unsupported packet-tunnel filter.
3
0
267
Sep ’26
Access to MAC addresses of local network interfaces in macOS 27
Hi all, we are building a custom controller for ATDECC, which is a layer 2 protocol standardized by IEEE in 1722.1. Our controller can work on multiple network interfaces at the same time . It uses the interface's MAC address to identify, on which interface a certain AVB / ATDECC device was discovered. It then sends replies for this device only to this interface. This controller worked fine up to and including macOS 26, but when running the same code on macOS 27, we cannot get the MAC addresses for the local interfaces anymore, but we receive 02:00:00:00:00:00 for each of them. This seems to indicate that the MAC address was redacted (looks like the same MAC address, that is being returned since iOS 11 due to privacy reason). Is this a bug or is macOS going to redact the MAC addresses also in the final release? If MAC addresses are being redacted, would it help to request access to the new entitlement called com.apple.developer.networking.topology-observation? I attached a little code snippet, that returns actual MAC addresses on macOS 26, but redacted ones on macOS 27. Build with clang++ -std=c++23 -o ifprobe ifprobe.cpp and then run it with ./ifprobe. ifprobe.cpp
11
0
917
Sep ’26
URLSession fails with -1009 on physical iPhone 16 Pro Max running iOS 27 beta, works in Simulator
I’m building a SwiftUI app that fetches public JSON data using URLSession.shared. The request works correctly in the iPhone 17 Pro Max Simulator, but fails on my physical iPhone 16 Pro Max running iOS 27 beta. Endpoint: https://api.jolpi.ca/ergast/f1/2026/driverstandings.json?limit=100 Error: NSURLErrorDomain Code=-1009 “The Internet connection appears to be offline.” NWPath: unsatisfied (Denied over Wi-Fi interface) Resolved 0 endpoints in 1ms The device can access the endpoint through Safari, and the same request works in Simulator. VPN, cellular permissions, Wi-Fi changes, and ATS settings have been checked. Could this be an iOS 27 beta networking regression affecting URLSession on physical devices? Are there recommended workarounds or diagnostics?
1
0
955
Sep ’26
mDNSResponder 2881.60.4 and later fail to build
I tried to compile the latest mDNSResponder (2881.120.11) for linux and discovered that it simply doesn't build: ../mDNSShared/uds_daemon.c: In function ‘resolve_result_callback’: ../mDNSShared/uds_daemon.c:3629:46: error: ‘request_state’ has no member named ‘resolve_awdl’ 3629 | const mDNSBool is_split_awdl_query = (req->resolve_awdl && question->InterfaceID == AWDLInterfaceID); | ^~ ../mDNSShared/uds_daemon.c:3629:89: error: ‘AWDLInterfaceID’ undeclared (first use in this function); did you mean ‘mDNSInterfaceID’? 3629 | const mDNSBool is_split_awdl_query = (req->resolve_awdl && question->InterfaceID == AWDLInterfaceID); | ^~~~~~~~~~~~~~~ This line was introduced in release 2881.60.4 (Jan 5, 2026), and all of the AWDL-related changes made to uds_daemon in that version look like unfinished code: The line shown above which references a non-existent struct field and nowhere-defined identifier/constant. Two functions in uds_daemon.c define a variable mDNSBool has_split_awdl_query = mDNSfalse; which is unused apart from its (unconditionally false) value being logged. The max-size-check for struct request_state in uds_daemon.h is increased but the struct itself wasn't changed (nor does the release introduce any other changes that might indirectly change the size of the struct) This code is common to all supported targets, so that means all four mDNSResponder releases done this year fail to build on all platforms. I'm a bit astonished how this even happens and has gone unnoticed for this long. Unfortunately it's not clear how to properly report this, the github repo has no issue tracker and the feedback assistant doesn't seem to have applicable options for this.
3
0
371
Sep ’26
How to do line- and message-delimination
I'm trying to write a NWProtocolFramerImplementation class that will be channeled through a Framer wrapper. There are still some parts I need figuring out. For handleOutput(framer: message: messageLength: isComplete), what do the last two parameters do? Does isComplete refer to the end of the current conversation, or the entire connection? Why would we submit a messageLength if the data size should already be implied within message? If I parse by line breaks, is there a way to indicate if the latest line is the last of the current conversation, either input or output?
1
0
229
Sep ’26
Network Interface APIs
For important background information, read Extra-ordinary Networking before reading this. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Network Interface APIs Most developers don’t need to interact directly with network interfaces. If you do, read this post for a summary of the APIs available to you. Before you read this, read Network Interface Concepts. Interface List The standard way to get a list of interfaces and their addresses is getifaddrs. To learn more about this API, see its man page. A network interface has four fundamental attributes: A set of flags — These are packed into a CUnsignedInt. The flags bits are declared in <net/if.h>, starting with IFF_UP. An interface type — See Network Interface Type, below. An interface index — Valid indexes are greater than 0. A BSD interface name. For example, an Ethernet interface might be called en0. The interface name is shared between multiple network interfaces running over a given hardware interface. For example, IPv4 and IPv6 running over that Ethernet interface will both have the name en0. WARNING BSD interface names are not considered API. There’s no guarantee, for example, that an iPhone’s Wi-Fi interface is en0. You can map between the last two using if_indextoname and if_nametoindex. See the if_indextoname man page for details. An interface may also have address information. If present, this always includes the interface address (ifa_addr) and the network mask (ifa_netmask). In addition: Broadcast-capable interfaces (IFF_BROADCAST) have a broadcast address (ifa_broadaddr, which is an alias for ifa_dstaddr). Point-to-point interfaces (IFF_POINTOPOINT) have a destination address (ifa_dstaddr). Calling getifaddrs from Swift is a bit tricky. For an example of this, see QSocket: Interfaces. IP Address List Once you have getifaddrs working, it’s relatively easy to manipulate the results to build a list of just IP addresses, a list of IP addresses for each interface, and so on. QSocket: Interfaces has some Swift snippets that show this. Interface List Updates The interface list can change over time. Hardware interfaces can be added and removed, network interfaces come up and go down, and their addresses can change. It’s best to avoid caching information from getifaddrs. If thats unavoidable, use the kNotifySCNetworkChange Darwin notification to update your cache. For information about registering for Darwin notifications, see the notify man page (in section 3). This notification just tells you that something has changed. It’s up to you to fetch the new interface list and adjust your cache accordingly. You’ll find that this notification is sometimes posted numerous times in rapid succession. To avoid unnecessary thrashing, debounce it. While the Darwin notification API is easy to call from Swift, Swift does not import kNotifySCNetworkChange. To fix that, define that value yourself, calling a C function to get the value: var kNotifySCNetworkChange: UnsafePointer<CChar> { networkChangeNotifyKey() } Here’s what that C function looks like: extern const char * networkChangeNotifyKey(void) { return kNotifySCNetworkChange; } Network Interface Type There are two ways to think about a network interface’s type. Historically there were a wide variety of weird and wonderful types of network interfaces. The following code gets this legacy value for a specific BSD interface name: func legacyTypeForInterfaceNamed(_ name: String) -> UInt8? { var addrList: UnsafeMutablePointer<ifaddrs>? = nil let err = getifaddrs(&addrList) // In theory we could check `errno` here but, honestly, what are gonna // do with that info? guard err >= 0, let first = addrList else { return nil } defer { freeifaddrs(addrList) } return sequence(first: first, next: { $0.pointee.ifa_next }) .compactMap { addr in guard let nameC = addr.pointee.ifa_name, name == String(cString: nameC), let sa = addr.pointee.ifa_addr, sa.pointee.sa_family == AF_LINK, let data = addr.pointee.ifa_data else { return nil } return data.assumingMemoryBound(to: if_data.self).pointee.ifi_type } .first } The values are defined in <net/if_types.h>, starting with IFT_OTHER. However, this value is rarely useful because many interfaces ‘look like’ Ethernet and thus have a type of IFT_ETHER. Network framework has the concept of an interface’s functional type. This is an indication of how the interface fits into the system. There are two ways to get an interface’s functional type: If you’re using Network framework and have an NWInterface value, get the type property. If not, call ioctl with a SIOCGIFFUNCTIONALTYPE request. The return values are defined in <net/if.h>, starting with IFRTYPE_FUNCTIONAL_UNKNOWN. Swift does not import SIOCGIFFUNCTIONALTYPE, so it’s best to write this code in a C: extern uint32_t functionalTypeForInterfaceNamed(const char * name) { int fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { return IFRTYPE_FUNCTIONAL_UNKNOWN; } struct ifreq ifr = {}; strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); bool success = ioctl(fd, SIOCGIFFUNCTIONALTYPE, &ifr) >= 0; int junk = close(fd); assert(junk == 0); if ( ! success ) { return IFRTYPE_FUNCTIONAL_UNKNOWN; } return ifr.ifr_ifru.ifru_functional_type; } Finally, TN3158 Resolving Xcode 15 device connection issues documents the SIOCGIFDIRECTLINK flag as a specific way to identify the network interfaces uses by Xcode for device connection traffic. Routing Sockets macOS supports the traditional BSD routine socket interface. See the route man page for details. Note You can access some routing socket functionality via sysctl, and all of this section applies to that as well. Other Apple platforms don’t support routing sockets [1]. On macOS it’s reasonable to use a routing socket to learn about the current state of the networking stack and be notified of changes to that state. Doing this on macOS 27 and later may require you to sign your code with the com.apple.developer.networking.topology-observation entitlement. In Xcode, add the Network Topology Observation capability [2] to your target. This is a restricted entitlement, which means it must be authorised by a provisioning profile. If you’re building a command-line tool, follow the advice in Signing a daemon with a restricted entitlement. Don’t use a routing socket to change the state of the networking stack. Such activities are not supported because macOS maintains its source of truth outside of the kernel, primarily in the System Configuration infrastructure [3]. If you make changes behind the back of this infrastructure then, in the best case, they’ll simply be overwritten at some point in the future, but in the worst case you could trigger stability problems. [1] You may or may not be able to open one, based on the current sandbox setup. Even if you can, that effort is not supported because the declarations required to use the socket, most obviously rt_msghdr, are only present in the macOS SDK. And no, copying declarations from one SDK to another is not supported (-; [2] There’s no link to the docs for this capability because that hasn’t yet landed (r. 181611259). [3] See System Configuration Programming Guidelines for a general introduction this architecture. Revision History 2026-09-23 Added the Routing Sockets section. 2025-12-10 Added info about SIOCGIFDIRECTLINK. 2023-07-19 First posted.
0
0
2.7k
Sep ’26
Appropriate API for measuring device-wide network traffic on iOS
I am developing a consumer iOS app for App Store distribution and would like to confirm the appropriate public API for the following use case. The app needs to measure the amount of network traffic passing through the device over short time intervals, for example once per second or more frequently. The app does not need to inspect packet contents, block or filter traffic, or provide a remote VPN service. It also should not generate dedicated network traffic solely for speed measurement. The goal is only to observe device-wide network traffic volume and convert that information into a simple real-time indicator for the user. I am currently investigating the Network Extension framework. Would NEPacketTunnelProvider be an appropriate API for this use case? If not, is there another supported Network Extension provider or other public iOS API intended for measuring device-wide network traffic in this manner? I would like to choose an architecture that is technically supported by Apple and appropriate for a consumer app distributed through the App Store before beginning implementation.
1
0
442
Sep ’26
sysextd: "no policy, cannot allow apps outside /Applications" - NEFilterDataProvider system extension on macOS 26
I'm developing a macOS security tool using NEFilterDataProvider as a system extension. On macOS 26 beta (25E241), sysextd consistently rejects my extension with: sysextd: no policy, cannot allow apps outside /Applications Configuration: App installed in /Applications/ Signed with Developer ID Application (693DSH8GN5) Entitlement: com.apple.developer.networking.networkextension = content-filter-provider com.apple.developer.system-extension.install = true Developer Mode enabled on test machine Comparison with Little Snitch: Little Snitch runs correctly on the same machine. Key differences I found: Little Snitch uses content-filter-provider-systemextension instead of content-filter-provider Little Snitch has com.apple.security.app-sandbox = false Both signed with Developer ID Application When I switch to content-filter-provider-systemextension, Xcode rejects every provisioning profile because none match that entitlement value, and the Developer Portal doesn't expose fine-grained control over the Network Extensions array values. Questions Is content-filter-provider-systemextension the correct entitlement for system extensions on macOS 26? How should the provisioning profile be configured to support it? Is there a known sysextd issue on macOS 26 beta causing this regardless of configuration? Is there - somewhere! - a guide on how to build such an extension? Thanks in advance for your help.
4
0
925
Sep ’26
NEURLFilter / SimpleURLFilter: neagent fails to open URL prefilter mmap file with errno 13 Permission denied
I am testing NEURLFilter on macOS using the SimpleURLFilter sample, and I am seeing a failure from neagent while it is saving the local URL prefilter Bloom filter to its mmap file. The relevant log is: neagent +[NEBloomFilter mmapToFile:data:dataLength:numberOfBits:numberOfHashes:murmurSeed:tag:]: NEBloomFilter - failed to open mmap file /private/var/db/urlPrefilter/com.apple.networkextension.url-prefilter-data.temp.com.example.apple-samplecode.SimpleURLFilterTC3Q7MAJXF <errno 13 - Permission denied> neagent <NEAgentURLFilterExtension: 0xc8ce64280>: -[NEAgentURLFilterExtension startURLFilter]_block_invoke - Failed to save first fetch of pre-filter data Environment: macOS: 26.5.1 (25F80) Xcode: 26.5 (17F42) Platform: macOS Signing type: Apple Development (automatically manage signing) What I am doing: Build and run the containing app. Save and enable the NEURLFilterManager configuration. The URL filter provider starts. The provider's prefilter code is reached. neagent logs the mmap failure above while trying to open a temporary file under /private/var/db/urlPrefilter. Expected result: neagent should be able to create or open its system-managed URL prefilter cache / mmap file under /private/var/db/urlPrefilter, and the local Bloom filter should be loaded successfully. Actual result: neagent fails to open the temporary mmap file with errno 13 Permission denied: /private/var/db/urlPrefilter/com.apple.networkextension.url-prefilter-data.temp.<bundle/team-specific suffix> I am not manually creating, modifying, or chmod/chown-ing /private/var/db/urlPrefilter or anything inside it. The directory and its contents are entirely system-managed. The failure appears to happen inside neagent while it is handling the system-managed URL prefilter cache. The failure occurs at the mmapToFile: step while neagent saves the Bloom filter prefilter data. Directory state: drwxr-xr-x 2 root wheel 64 /private/var/db/urlPrefilter Has anyone else encountered this? Any suggestions on what could cause neagent to fail with errno 13 on its own mmap file under /private/var/db/urlPrefilter?
9
3
1.4k
Sep ’26
iOS app loses Internet access after updates: wifiDenied and native URLSession -1009
Hello, Feedback Assistant report: FB24876147. I develop a Unity-based iOS app. Some customers in mainland China report losing Internet access after an app update, while most installations continue working. We have received similar reports since at least iOS 16, across several years and multiple app releases. Earlier iOS versions are uncertain, and we cannot confirm that all historical occurrences share the same cause. Updates without networking-code changes can be followed by failures. A later update sometimes restores connectivity, but not consistently. Customer-reported recovery attempts: The app's wireless-data permissions appear enabled in Settings. Switching the app's network permission to another setting and back did not help users who reported trying it. Reset Network Settings also did not help users who reported trying it. Some users reported that deleting and reinstalling the app restored connectivity. At least one user reported that deletion and reinstallation did not help. These are customer reports, not controlled tests on our development devices. We would prefer a recovery that preserves local save data. Captured evidence from one affected installation: App version 1.89, build 1; Unity 2022.3.62f3. Device identifier: iPhone18,1; iOS 26.2.1. App in foreground. Capture time: 2026-09-07 13:04:31–13:04:32 UTC. An unfiltered Network.framework default-path monitor reported: status=unsatisfied reason=wifiDenied interface=Wi-Fi UnityWebRequest and a newly created native ephemeral NSURLSession both failed against our public HTTPS origin and Apple's independent test endpoint: https://www.apple.com/library/test/success.html The native requests failed after approximately 1 ms and 3 ms, with NSURLErrorDomain -1009, underlying kCFErrorDomainCFNetwork -1009, and no HTTP response. The native session allowed cellular, expensive and constrained network access, used normal TLS verification, and had waitsForConnectivity=false. It bypassed Unity's reachability precheck. CTCellularData changed from unknown to notRestricted. We understand this does not establish successful cellular connectivity or Wi-Fi permission. Important limitations: The native probes ran inside the same Unity-built process, not a separate standalone native app. The captured measurements demonstrate a Wi-Fi failure. Cellular failures and enabled Settings permissions are customer reports, not independently verified by these measurements. We cannot reliably reproduce the affected state on our development devices and do not have a focused Xcode project that reproduces it. An affected-device sysdiagnose is not yet available. Unity Customer QA reviewed this evidence, assessed it as an iOS network-policy issue rather than a Unity bug, and referred us to Apple. We are seeking Apple's investigation, not presenting that assessment as a confirmed root cause. The Code-Level Support form directed us to these forums because we cannot currently provide a focused reproducer. Questions: Which affected-device diagnostics or logging profiles would help identify why the effective network policy reports wifiDenied? How should we investigate an installation-specific issue when a new minimal app may not reproduce that installation state? Is there a supported, data-preserving recovery or application-side mitigation when permission changes and network resets do not help, and reinstallation is not consistently effective? We have diagnostic screenshots and relevant probe source available. Any customer system logs would be collected with consent and shared privately with Apple, not posted publicly. Thank you.
1
0
354
Sep ’26
macos 26 - socket() syscall causes ENOBUFS "No buffer space available" error
As part of the OpenJDK testing we run several regression tests, including for Java SE networking APIs. These APIs ultimately end up calling BSD socket functions. On macos, starting macos 26, including on recent 26.2 version, we have started seeing some unexplained but consistent exception from one of these BSD socket APIs. We receive a "ENOBUFS" errno (No buffer space available) when trying to construct a socket(). These exact same tests continue to pass on many other older versions of macos (including 15.7.x). After looking into this more, we have been able to narrow this down to a very trivial C code which is as follows (also attached): #include <stdio.h> #include <sys/socket.h> #include <string.h> #include <unistd.h> #include <sys/errno.h> static int create_socket(const int attempt_number) { const int fd = socket(AF_INET6, SOCK_STREAM, 0); if (fd < 0) { fprintf(stderr, "socket creation failed on attempt %d," " due to: %s\n", attempt_number, strerror(errno)); return fd; } return fd; } int main() { const unsigned int num_times = 250000; for (unsigned int i = 1; i <= num_times; i++) { const int fd = create_socket(i); if (fd < 0) { return -1; } close(fd); } fprintf(stderr, "successfully created and closed %d sockets\n", num_times); } The code very trivially creates a socket() and close()s it. It does this repeatedly in a loop for a certain number of iterations. Compiling this as: clang sockbufspaceerr.c -o sockbufspaceerr.o and running it as: ./sockbufspaceerr.o consistently generates an error as follows on macos 26.x: socket creation failed on attempt 160995, due to: No buffer space available The iteration number on which the socket() creation fails varies, but the issue does reproduce. Running the same on older versions of macos doesn't reproduce the issue and the program terminates normally after those many iterations. Looking at the xnu source that is made available for each macos release here https://opensource.apple.com/releases/, I see that for macos 26.x there have been changes in this kernel code and there appears to be some kind of memory accountability code introduced in this code path. However, looking at the reproducer/application code in question, I believe it uses the right set of functions to both create as well as release the resources, so I can't see why this should cause the above error in macos 26.x. Does this look like some issue that needs attention in the macos kernel and should I report it through feedback assitant tool?
8
0
1.8k
Sep ’26
Unexplained behavioural changes in BSD sockets on macos 26.6.x and 27
We have started seeing some unexplained behavioural differences in the BSD socket APIs on macos 26.6.x and macos 27. On a different front, there also seems to be some changes in the ptrace area for PT_DETACH. Historically, the release notes of macos don't include any mention of such changes. And unfortunately, prior experience of filing feedback assistant issues too hasn't been very motivating due to lack of any response on those tickets. These forums have been very helpful in trying to understand some of these changes, and I plan to raise separate topics for the issues shortly. In the past, the other useful option I have used is reading up the kernel sources published at https://opensource.apple.com/releases/. But there hasn't been any updates for macos 26.6 or macos 27. It will be very useful if macos 26.6 and 27 releases are published there. That will help expedite investigating some of these failures. BSD socket APIs in the recent releases of macos have seen several issues (feedback assistant issues have been filed). The implications of these failures is that we (in OpenJDK) have had to disable several tests on recent versions of macos which has reduced the test coverage and reliability of these very primitive networking APIs on this platform.
Replies
5
Boosts
0
Views
384
Activity
3w
WCSession.sendMessage is crashing when a reply or error handler is attached, why?
The following code should send a message from the watch to the iPhone. Unfortunately, it is crashing. I have no clue why. if WCSession.isSupported() { let session = WCSession.default if ((session.activationState == .activated) && session.isReachable) { session.sendMessage(["SimpleMessages":["start"]], replyHandler:{reply in _ = 0 }, errorHandler:nil) } } If the reply handler is set to nil, the code does not crash. Anyway, in both cases the message is correctly sent from the watch to the phone. The code itself is run on the main thread (verified). I am running watchOS 26.6 and iOS 27. Here is the crash : Stack trace
Replies
3
Boosts
0
Views
307
Activity
3w
Dual-stack UDP socket bound to port 0 can get a port already in use on 127.0.0.1 (FB25058707)
I filed FB25058707 and wanted to make sure it reaches the right people, because it causes silent datagram loss that's hard to trace. On macOS, when a dual-stack UDP socket (AF_INET6 with IPV6_V6ONLY=0) binds [::]:0, the kernel sometimes gives it a port that an AF_INET socket already has bound to 127.0.0.1. Datagrams sent to 127.0.0.1 on that port then go to the AF_INET socket, so the dual-stack socket never receives them. An explicit bind of the same socket to that port fails with EADDRINUSE; only port-0 assignment hands it out. This program binds 1000 AF_INET sockets to 127.0.0.1:0, then binds dual-stack sockets to [::]:0 and checks where a datagram to 127.0.0.1:port lands whenever the port is already held. It's loopback only and runs in a few seconds: /* * A dual-stack UDP socket (AF_INET6, IPV6_V6ONLY=0) bound to [::]:0 can be * assigned a port already bound by an AF_INET socket on 127.0.0.1. Datagrams * to 127.0.0.1:port then reach the AF_INET socket, not the dual-stack one. * Loopback only. Build: cc -O2 -o dualstack_port0 dualstack_port0.c */ #include <arpa/inet.h> #include <errno.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/resource.h> #include <sys/socket.h> #include <sys/time.h> #include <unistd.h> #define HELD 1000 #define TRIALS 2000 static int held[65536]; static void die(const char *what) { perror(what); exit(1); } static int port_of(int s) { struct sockaddr_storage ss; socklen_t len = sizeof(ss); if (getsockname(s, (struct sockaddr *)&ss, &len) != 0) die("getsockname"); if (ss.ss_family == AF_INET) return ntohs(((struct sockaddr_in *)&ss)->sin_port); return ntohs(((struct sockaddr_in6 *)&ss)->sin6_port); } static int bind_v4(in_addr_t addr) { int s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) die("socket AF_INET"); struct sockaddr_in sin = { .sin_len = sizeof(sin), .sin_family = AF_INET, .sin_addr.s_addr = addr }; if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) != 0) die("bind AF_INET"); return s; } static int bind_dual(void) { int s = socket(AF_INET6, SOCK_DGRAM, 0), off = 0; if (s < 0) die("socket AF_INET6"); if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off)) != 0) die("IPV6_V6ONLY"); struct sockaddr_in6 sin6 = { .sin6_len = sizeof(sin6), .sin6_family = AF_INET6, .sin6_addr = in6addr_any }; if (bind(s, (struct sockaddr *)&sin6, sizeof(sin6)) != 0) die("bind AF_INET6"); return s; } /* Returns 1 if s receives token within 100ms, skipping other datagrams. */ static int got(int s, const char *token) { struct timeval tv = { .tv_sec = 0, .tv_usec = 100000 }; if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) != 0) die("SO_RCVTIMEO"); char buf[64]; for (;;) { ssize_t n = recv(s, buf, sizeof(buf) - 1, 0); if (n < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) return 0; die("recv"); } buf[n] = 0; if (strcmp(buf, token) == 0) return 1; } } int main(void) { struct rlimit rl; if (getrlimit(RLIMIT_NOFILE, &rl) != 0) die("getrlimit"); rl.rlim_cur = rl.rlim_max < 4096 ? rl.rlim_max : 4096; if (setrlimit(RLIMIT_NOFILE, &rl) != 0) die("setrlimit"); memset(held, -1, sizeof(held)); for (int i = 0; i < HELD;) { int s = bind_v4(htonl(INADDR_LOOPBACK)), p = port_of(s); if (held[p] >= 0) { close(s); continue; } held[p] = s; i++; } int sender = bind_v4(htonl(INADDR_LOOPBACK)); for (int dual = 1; dual >= 0; dual--) { int collisions = 0, to_held = 0, to_wild = 0; for (int i = 0; i < TRIALS; i++) { int w = dual ? bind_dual() : bind_v4(htonl(INADDR_ANY)), p = port_of(w); if (held[p] >= 0) { collisions++; char token[32]; snprintf(token, sizeof(token), "%d-%d", dual, i); struct sockaddr_in to = { .sin_len = sizeof(to), .sin_family = AF_INET, .sin_port = htons(p), .sin_addr.s_addr = htonl(INADDR_LOOPBACK) }; if (sendto(sender, token, strlen(token), 0, (struct sockaddr *)&to, sizeof(to)) < 0) die("sendto"); to_held += got(held[p], token); to_wild += got(w, token); } close(w); } printf("%s: %d/%d wildcard binds got a port held by a 127.0.0.1 socket; the probe reached that socket %d times, the wildcard socket %d times\n", dual ? "AF_INET6 V6ONLY=0 [::]:0" : "AF_INET 0.0.0.0:0 ", collisions, TRIALS, to_held, to_wild); } return 0; } On macOS 27.0 (26A428): AF_INET6 V6ONLY=0 [::]:0: 122/2000 wildcard binds got a port held by a 127.0.0.1 socket; the probe reached that socket 122 times, the wildcard socket 0 times AF_INET 0.0.0.0:0 : 0/2000 wildcard binds got a port held by a 127.0.0.1 socket; the probe reached that socket 0 times, the wildcard socket 0 times macOS 15.8.1 x86_64 gives the same pattern, and a Go version of the test reproduces on 15.7.9 and 26.6.2 as well. FreeBSD 15.1 gives 0/2000 with a dual-stack socket. From the public XNU source (xnu-12377.121.6), in6_pcbsetport checks candidate ports with in6_pcblookup_local, which skips PCBs without INP_IPV6, while in6_pcbbind does an IPv4 PCB lookup for dual-stack wildcard binds. That would explain why an explicit bind is refused but port 0 isn't. This is the cause of the long-standing Go issue golang/go#67226, since Go's net.ListenUDP("udp", 0.0.0.0:0) creates exactly this socket, and of intermittent failures in QUIC client tests. Using an AF_INET socket for IPv4-only traffic avoids it, but there's no workaround for a socket that needs both families on one port.
Replies
2
Boosts
0
Views
316
Activity
3w
macos 27 - EDOM error from setsockopt() for SO_LINGER socket option for values greater than 32767
On macos 27, there appears to be a change in the setsockopt() implementation for the SO_LINGER option. It looks like the implementation now imposes a different maximum limit on the value that is accepted for linger. Consider the trivial attached C program. Rename it from main.c.txt to main.c. Compiling it (using clang main.c) and running it (using ./a.out), on older versions of macos (like 26.x), it returns: ----------------------- MacOS version: 26.7.1 Kernel version: Darwin Kernel Version 25.6.0: Tue Aug 18 17:49:13 PDT 2026; root:xnu-12377.161.15.700.19~2/RELEASE_ARM64_T6000 ----------------------- SUCCESS - set SO_LINGER to value 10 SUCCESS - set SO_LINGER to value 42 SUCCESS - set SO_LINGER to value 1024 SUCCESS - set SO_LINGER to value 32767 SUCCESS - set SO_LINGER to value 32768 SUCCESS - set SO_LINGER to value 65535 SUCCESS - set SO_LINGER to value 65536 SUCCESS - set SO_LINGER to value 65578 However, on macos 27, this now fails with EDOM error ("Numerical argument out of domain") for values greater than 32767: ----------------------- MacOS version: 27.0.1 Kernel version: Darwin Kernel Version 27.0.0: Tue Aug 11 21:02:16 PDT 2026; root:xnu-13432.1.9~1/RELEASE_ARM64_T8112 ----------------------- SUCCESS - set SO_LINGER to value 10 SUCCESS - set SO_LINGER to value 42 SUCCESS - set SO_LINGER to value 1024 SUCCESS - set SO_LINGER to value 32767 FAILURE - failed to set SO_LINGER to value 32768, reason: Numerical argument out of domain FAILURE - failed to set SO_LINGER to value 65535, reason: Numerical argument out of domain FAILURE - failed to set SO_LINGER to value 65536, reason: Numerical argument out of domain FAILURE - failed to set SO_LINGER to value 65578, reason: Numerical argument out of domain I'm guessing this is an intentional change, but I wanted to confirm nonetheless. Should the documentation of SO_LINGER and SO_LINGER_SEC socket options, in man setsockopt, mention the acceptable value range for them? main.c.txt
Replies
2
Boosts
0
Views
302
Activity
4w
macos 27 - unexpected/new errno from BSD socket connect() when pending connections exceed backlog
Please consider the trivial C program attached to this thread. The code creates a socket() and listen()s for connections, but (intentionally) doesn't accept() the connections. The listen() is done using a small backlog (of 1). This test then does several connect() attempts and expects that the connect() attempts will accumulate in the pending queue and once the queue exceeds the backlog limit, then as specified in man listen: The backlog parameter defines the maximum length for the queue of pending connections. If a connection request arrives with the queue full, the client may receive an error with an indication of ECONNREFUSED. then the connect() attempt will receive a ECONNREFUSED. However, in macos 27, such a connect() attempt leads to ECONNRESET (Connection reset by peer) instead of ECONNREFUSED. Is this expected? Experiments show that prior versions of macos were returning a ETIMEDOUT for such connect() attempts. If this new error is expected from connect() when the backlog limit has exceeded, should it be specified in the man listen documentation? Rename the attached main.c.txt to main.c. Compiling the attached program on macos 27, using clang main.c and then running ./a.out results in: ----------------------- MacOS version: 27.0.1 Kernel version: Darwin Kernel Version 27.0.0: Tue Aug 11 21:02:16 PDT 2026; root:xnu-13432.1.9~1/RELEASE_ARM64_T8112 ----------------------- started server at at 127.0.0.1:52753 with a backlog of 1 connect() attempt 1 - connected connect() attempt 2 - connected connect() attempt 3 - connected connect() attempt 4 - connected connect() attempt 5 - failed to connect() - Connection reset by peer <-- FAILURE: Unexpected error code, expected either ETIMEDOUT or ECONNREFUSED but got 54 connect() attempt 6 - connected connect() attempt 7 - connected connect() attempt 8 - connected connect() attempt 9 - failed to connect() - Connection reset by peer <-- FAILURE: Unexpected error code, expected either ETIMEDOUT or ECONNREFUSED but got 54 connect() attempt 10 - failed to connect() - Connection reset by peer <-- FAILURE: Unexpected error code, expected either ETIMEDOUT or ECONNREFUSED but got 54 connect() attempt 11 - failed to connect() - Connection reset by peer <-- FAILURE: Unexpected error code, expected either ETIMEDOUT or ECONNREFUSED but got 54 On a related note, it's unclear why several of the connect() attempts succeeded instead of just 1 of them succeeding. On prior versions of macos, the output of the same program is: ----------------------- MacOS version: 26.7.1 Kernel version: Darwin Kernel Version 25.6.0: Tue Aug 18 17:49:13 PDT 2026; root:xnu-12377.161.15.700.19~2/RELEASE_ARM64_T6000 ----------------------- started server at at 127.0.0.1:52451 with a backlog of 1 connect() attempt 1 - connected connect() attempt 2 - failed to connect() - Operation timed out connect() attempt 3 - failed to connect() - Operation timed out connect() attempt 4 - failed to connect() - Operation timed out connect() attempt 5 - failed to connect() - Operation timed out connect() attempt 6 - failed to connect() - Operation timed out connect() attempt 7 - failed to connect() - Operation timed out connect() attempt 8 - failed to connect() - Operation timed out connect() attempt 9 - failed to connect() - Operation timed out connect() attempt 10 - failed to connect() - Operation timed out connect() attempt 11 - failed to connect() - Operation timed out and this output is much more understandable and deterministic. main.c.txt
Replies
2
Boosts
0
Views
313
Activity
4w
TCP connection in with Wi-Fi aware framework never reaches ".ready" state
While developing our wifi-aware implementation we ran into a specific issue where TCP connections seem to never reach a "ready" state (ready to transfer data). It stays in “”preparing” state trying to connect for forever. We tried to recreate a new TCP connection every time after the connection stays in "preparing" for longer than 10 seconds. This helps to "recover" eventually, but it only happens after 1.5 - 2 minutes. Creating a completely new NetworkBrowser and NetworkListener doesn’t speed up this process. The issue occurs when the browser and listener are setting up the NAN/TCP connection, at that time if the user opens the DevicePairingView it seems that it disrupts or interferes with the connection, entering an invalid state. From what we can see it takes around 2 minutes for it to recover, presumably this is when NAN drops the connection (timeout) and creates a new one.

 STEPS TO REPRODUCE Reproduction steps:

 Open the app on 2 wifi-aware devices.
 Device 1 presses “Pair with device”. Device 2 navigates to “Receive” and presses the “”Pair with sender”.
 Complete the pairing process.

 Device 1 (Send) presses the start button.
 Device 2 (receive) presses start button, Directly after the button press, device 1 presses the “”Pair with sender” button
 Observe TCP connection never fully establishes (1.5 - 2 mins) PLATFORM AND VERSION iOS Development environment: Xcode 26.3, macOS 26.4.1 Run-time configuration: iOS 26.5 test project with a recording showing the issue: https://github.com/DeveloperNiels/WAIssue
Replies
7
Boosts
0
Views
768
Activity
4w
Out-of-band data returned by recv() and read() on socket bound to non-loopback address even when SO_OOBINLINE is disabled
I've been investigating an issue with the SO_OOBINLINE socket option. When that option is disabled, the expectation is that out-of-band data that is sent on the socket will not be available through the use of read() or recv() calls on that socket. What we have been noticing is that when the socket is bound to a non-loopback address (and the communication is happening over that non-loopback address), then even when SO_OOBINLINE is disabled for the socket, the read()/recv() calls both return the out-of-band data. The issue however isn't reproducible with loopback address, and read()/recv() both correctly exclude the out-of-band data. This issue is only noticed on macos. I have been able to reproduce on macos M1, following version, but the original report which prompted me to look into this was reported on macos x64. My M1 OS version is: sw_vers ProductName: macOS ProductVersion: 14.3.1 BuildVersion: 23D60 Attached is a reproducer (main.c.txt - rename it to main.c after downloading) that I have been able to develop which reproduces this issue on macos. When you compile and run that: ./a.out it binds to a non-loopback address by default and you should see the failure log, resembling: ... ERROR: expected: 1234512345 but received: 12345U12345 To run the same reproducer against loopback address, run it as: ./a.out loopback and that should succeed (i.e. no out-of-band data) with logs resembling: ... SUCCESS: completed successfully, expected: 1234512345, received: 1234512345 Is this a bug in the OS? I would have reported this directly through feedback assistant, but my past few open issues (since more than a year) have not even seen an acknowledgement or a reply, so I decided to check here first. main.c.txt
Replies
8
Boosts
0
Views
1.3k
Activity
4w
NEURLFilterManager.localizedDescription is ignored by System Settings -> Network -> Filters
macOS 26.6, 26.7, 27.0 and 27.2 beta 1/2. Reproduced with Apple's SimpleURLFilter sample ("Filtering traffic by URL", WWDC25 session 234), built and run as a macOS app. The sample never sets localizedDescription, so I added one line to ConfigurationModel.save(configuration:) before saveToPreferences(): sharedFilterManager.localizedDescription = "Sentinel Filter Name" The property holds the value in memory: after loadFromPreferences(), the logged LocalizedStringResource still has key: "Sentinel Filter Name". But the effective configuration the system starts the session with has no localizedDescription — the session is named after the app: name = SimpleURLFilter applicationName = SimpleURLFilter application = com.example.apple-samplecode.SimpleURLFilterTC3Q7MAJXF (the rest of the nesessionmanager dump is the urlFilter dictionary, and it has no localizedDescription key). System Settings > Network > Filters shows the filter as URLFilter, not "Sentinel Filter Name". The stored configuration (/Library/Preferences/com.apple.networkextension.plist) has no localizedDescription key either, and injecting one by hand does not survive a nesessionmanager restart. Re-saving, removing and re-creating the configuration, and rebooting the Mac do not change the displayed name. Expected: the docs describe localizedDescription as "A string containing a description of the URL filter", and WWDC25 session 234's code sample ("Configure and manage URL Filter") sets it this way (manager.localizedDescription = "Alice's URL Filter"). For comparison, a NETransparentProxyManager configuration on the same Mac persists localizedDescription as the configuration's Name in the same plist, while the URL filter configuration has no such field. Filed as FB24987420.
Replies
1
Boosts
0
Views
296
Activity
Sep ’26
iOS leaves an accessory's no-internet Wi-Fi (NEHotspotConfiguration) for a saved network mid-session
We're building an iOS and Android app that transfers files to and from a device over a Wi-Fi network the device creates. That network has no internet access. The app gets the Wi-Fi credentials from the device (over Bluetooth, or from a QR code on its screen) and joins with NEHotspotConfiguration. Android works reliably. On iOS, partway through a session the phone leaves the device's network and joins a saved network that has internet, which breaks our connection to the device. Setup: iPhone 13 Pro, iOS 26.x NEHotspotConfiguration(ssid:passphrase:isWEP: false) with joinOnce = false. With joinOnce = true, iOS usually stays on the current internet Wi-Fi and never joins the device's network. WPA2. The device is at 192.168.4.1, and its DHCP server hands out the device as router and DNS. Device traffic: NWConnection (TCP) with prohibitedInterfaceTypes = [.cellular]. Server traffic: a separate NWConnection with requiredInterfaceType = .cellular. Wi-Fi Assist is off. Example: we read an 8 MB file from the device (30 s, no problem), then post it to our server over cellular (93 s). During the post, the device connection carries only a small message every ~15 s. 28 s into the post, NWPathMonitor shows Wi-Fi drop out for 3 s, and when it returns the phone is on the our primary network. Occasionally iOS shows a prompt asking whether to stay connected without internet, but usually it switches without asking. We haven't seen it switch during the file read, while the device connection is busy. Questions: Is there a supported way to keep iOS on a device's no-internet network for a whole session? Does traffic on the Wi-Fi interface (such as an active NWConnection) affect whether iOS switches away? Would a DHCP configuration without a router or DNS server change how iOS treats the network? Is joinOnce = false right for this, or can joinOnce = true join when the phone is already on an internet-capable Wi-Fi?
Replies
1
Boosts
0
Views
533
Activity
Sep ’26
macOS content filter: supported denial guarantee across provider failure for a bounded process tree
We are designing a bounded local macOS operation with a supervisor, controller and helper. All three must be unable to cause prohibited network effects, including attributable delegated requests, before admission and until quiescence. Unrelated applications must retain their normal network access. We are seeking an API contract clarification, not reporting a reproduced OS bug. No NetworkExtension provider has been activated for this design. Our reviewed SDK is MacOSX27.0.sdk; its presence is not a runtime qualification. Please identify the supported macOS versions for your answer. The design must tolerate provider crash, termination, disconnection and unresponsiveness, and operation lease expiry/revocation. Administrative filter disablement or privileged reconfiguration is a separate unresolved threat-model case, not something we assume ordinary failure handling covers. We reviewed content-filter deployment in TN3134 and the nullable/delegated audit tokens in NEFilterFlow. We understand that NEURLFilterManager.shouldFailClosed concerns URL-filter decisions, not an established guarantee for arbitrary content-filter traffic. EndpointSecurity AUTH deadlines are also a separate mechanism. The VPN routing article documents dropping during specific transitions, but has system exceptions; TN3120 excludes using a packet tunnel as a dropping content filter. We therefore have not adopted that workaround. For macOS NEFilterDataProvider / NEFilterPacketProvider, is there a supported configuration that keeps prohibited operation traffic denied when the provider crashes, is killed, disconnects, hangs or cannot deliver a decision? Please distinguish new flows, existing/previously permitted flows, queued data, restart intervals, and configuration disable/removal. What supported admission and teardown guarantees allow releasing the first protected process only after enforcement is effective, then retaining denial through lease revocation and shutdown? An enabled configuration alone would not demonstrate that barrier. How should this guarantee cover operation-caused DNS and delegated system-service traffic, including absent/ambiguous audit tokens, without denying unrelated host traffic? If content filters cannot meet that scope, can App Sandbox without network entitlements provide the independent denial boundary for these roles, and what documented exclusions or additional constraints apply? A reference to the supported contract, or a precise statement of the requirement that needs to change, would let us select an architecture before implementing and activating a native provider. We are not requesting private APIs or an unsupported packet-tunnel filter.
Replies
3
Boosts
0
Views
267
Activity
Sep ’26
Access to MAC addresses of local network interfaces in macOS 27
Hi all, we are building a custom controller for ATDECC, which is a layer 2 protocol standardized by IEEE in 1722.1. Our controller can work on multiple network interfaces at the same time . It uses the interface's MAC address to identify, on which interface a certain AVB / ATDECC device was discovered. It then sends replies for this device only to this interface. This controller worked fine up to and including macOS 26, but when running the same code on macOS 27, we cannot get the MAC addresses for the local interfaces anymore, but we receive 02:00:00:00:00:00 for each of them. This seems to indicate that the MAC address was redacted (looks like the same MAC address, that is being returned since iOS 11 due to privacy reason). Is this a bug or is macOS going to redact the MAC addresses also in the final release? If MAC addresses are being redacted, would it help to request access to the new entitlement called com.apple.developer.networking.topology-observation? I attached a little code snippet, that returns actual MAC addresses on macOS 26, but redacted ones on macOS 27. Build with clang++ -std=c++23 -o ifprobe ifprobe.cpp and then run it with ./ifprobe. ifprobe.cpp
Replies
11
Boosts
0
Views
917
Activity
Sep ’26
URLSession fails with -1009 on physical iPhone 16 Pro Max running iOS 27 beta, works in Simulator
I’m building a SwiftUI app that fetches public JSON data using URLSession.shared. The request works correctly in the iPhone 17 Pro Max Simulator, but fails on my physical iPhone 16 Pro Max running iOS 27 beta. Endpoint: https://api.jolpi.ca/ergast/f1/2026/driverstandings.json?limit=100 Error: NSURLErrorDomain Code=-1009 “The Internet connection appears to be offline.” NWPath: unsatisfied (Denied over Wi-Fi interface) Resolved 0 endpoints in 1ms The device can access the endpoint through Safari, and the same request works in Simulator. VPN, cellular permissions, Wi-Fi changes, and ATS settings have been checked. Could this be an iOS 27 beta networking regression affecting URLSession on physical devices? Are there recommended workarounds or diagnostics?
Replies
1
Boosts
0
Views
955
Activity
Sep ’26
mDNSResponder 2881.60.4 and later fail to build
I tried to compile the latest mDNSResponder (2881.120.11) for linux and discovered that it simply doesn't build: ../mDNSShared/uds_daemon.c: In function ‘resolve_result_callback’: ../mDNSShared/uds_daemon.c:3629:46: error: ‘request_state’ has no member named ‘resolve_awdl’ 3629 | const mDNSBool is_split_awdl_query = (req->resolve_awdl && question->InterfaceID == AWDLInterfaceID); | ^~ ../mDNSShared/uds_daemon.c:3629:89: error: ‘AWDLInterfaceID’ undeclared (first use in this function); did you mean ‘mDNSInterfaceID’? 3629 | const mDNSBool is_split_awdl_query = (req->resolve_awdl && question->InterfaceID == AWDLInterfaceID); | ^~~~~~~~~~~~~~~ This line was introduced in release 2881.60.4 (Jan 5, 2026), and all of the AWDL-related changes made to uds_daemon in that version look like unfinished code: The line shown above which references a non-existent struct field and nowhere-defined identifier/constant. Two functions in uds_daemon.c define a variable mDNSBool has_split_awdl_query = mDNSfalse; which is unused apart from its (unconditionally false) value being logged. The max-size-check for struct request_state in uds_daemon.h is increased but the struct itself wasn't changed (nor does the release introduce any other changes that might indirectly change the size of the struct) This code is common to all supported targets, so that means all four mDNSResponder releases done this year fail to build on all platforms. I'm a bit astonished how this even happens and has gone unnoticed for this long. Unfortunately it's not clear how to properly report this, the github repo has no issue tracker and the feedback assistant doesn't seem to have applicable options for this.
Replies
3
Boosts
0
Views
371
Activity
Sep ’26
How to do line- and message-delimination
I'm trying to write a NWProtocolFramerImplementation class that will be channeled through a Framer wrapper. There are still some parts I need figuring out. For handleOutput(framer: message: messageLength: isComplete), what do the last two parameters do? Does isComplete refer to the end of the current conversation, or the entire connection? Why would we submit a messageLength if the data size should already be implied within message? If I parse by line breaks, is there a way to indicate if the latest line is the last of the current conversation, either input or output?
Replies
1
Boosts
0
Views
229
Activity
Sep ’26
Network Interface APIs
For important background information, read Extra-ordinary Networking before reading this. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Network Interface APIs Most developers don’t need to interact directly with network interfaces. If you do, read this post for a summary of the APIs available to you. Before you read this, read Network Interface Concepts. Interface List The standard way to get a list of interfaces and their addresses is getifaddrs. To learn more about this API, see its man page. A network interface has four fundamental attributes: A set of flags — These are packed into a CUnsignedInt. The flags bits are declared in <net/if.h>, starting with IFF_UP. An interface type — See Network Interface Type, below. An interface index — Valid indexes are greater than 0. A BSD interface name. For example, an Ethernet interface might be called en0. The interface name is shared between multiple network interfaces running over a given hardware interface. For example, IPv4 and IPv6 running over that Ethernet interface will both have the name en0. WARNING BSD interface names are not considered API. There’s no guarantee, for example, that an iPhone’s Wi-Fi interface is en0. You can map between the last two using if_indextoname and if_nametoindex. See the if_indextoname man page for details. An interface may also have address information. If present, this always includes the interface address (ifa_addr) and the network mask (ifa_netmask). In addition: Broadcast-capable interfaces (IFF_BROADCAST) have a broadcast address (ifa_broadaddr, which is an alias for ifa_dstaddr). Point-to-point interfaces (IFF_POINTOPOINT) have a destination address (ifa_dstaddr). Calling getifaddrs from Swift is a bit tricky. For an example of this, see QSocket: Interfaces. IP Address List Once you have getifaddrs working, it’s relatively easy to manipulate the results to build a list of just IP addresses, a list of IP addresses for each interface, and so on. QSocket: Interfaces has some Swift snippets that show this. Interface List Updates The interface list can change over time. Hardware interfaces can be added and removed, network interfaces come up and go down, and their addresses can change. It’s best to avoid caching information from getifaddrs. If thats unavoidable, use the kNotifySCNetworkChange Darwin notification to update your cache. For information about registering for Darwin notifications, see the notify man page (in section 3). This notification just tells you that something has changed. It’s up to you to fetch the new interface list and adjust your cache accordingly. You’ll find that this notification is sometimes posted numerous times in rapid succession. To avoid unnecessary thrashing, debounce it. While the Darwin notification API is easy to call from Swift, Swift does not import kNotifySCNetworkChange. To fix that, define that value yourself, calling a C function to get the value: var kNotifySCNetworkChange: UnsafePointer<CChar> { networkChangeNotifyKey() } Here’s what that C function looks like: extern const char * networkChangeNotifyKey(void) { return kNotifySCNetworkChange; } Network Interface Type There are two ways to think about a network interface’s type. Historically there were a wide variety of weird and wonderful types of network interfaces. The following code gets this legacy value for a specific BSD interface name: func legacyTypeForInterfaceNamed(_ name: String) -> UInt8? { var addrList: UnsafeMutablePointer<ifaddrs>? = nil let err = getifaddrs(&addrList) // In theory we could check `errno` here but, honestly, what are gonna // do with that info? guard err >= 0, let first = addrList else { return nil } defer { freeifaddrs(addrList) } return sequence(first: first, next: { $0.pointee.ifa_next }) .compactMap { addr in guard let nameC = addr.pointee.ifa_name, name == String(cString: nameC), let sa = addr.pointee.ifa_addr, sa.pointee.sa_family == AF_LINK, let data = addr.pointee.ifa_data else { return nil } return data.assumingMemoryBound(to: if_data.self).pointee.ifi_type } .first } The values are defined in <net/if_types.h>, starting with IFT_OTHER. However, this value is rarely useful because many interfaces ‘look like’ Ethernet and thus have a type of IFT_ETHER. Network framework has the concept of an interface’s functional type. This is an indication of how the interface fits into the system. There are two ways to get an interface’s functional type: If you’re using Network framework and have an NWInterface value, get the type property. If not, call ioctl with a SIOCGIFFUNCTIONALTYPE request. The return values are defined in <net/if.h>, starting with IFRTYPE_FUNCTIONAL_UNKNOWN. Swift does not import SIOCGIFFUNCTIONALTYPE, so it’s best to write this code in a C: extern uint32_t functionalTypeForInterfaceNamed(const char * name) { int fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { return IFRTYPE_FUNCTIONAL_UNKNOWN; } struct ifreq ifr = {}; strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); bool success = ioctl(fd, SIOCGIFFUNCTIONALTYPE, &ifr) >= 0; int junk = close(fd); assert(junk == 0); if ( ! success ) { return IFRTYPE_FUNCTIONAL_UNKNOWN; } return ifr.ifr_ifru.ifru_functional_type; } Finally, TN3158 Resolving Xcode 15 device connection issues documents the SIOCGIFDIRECTLINK flag as a specific way to identify the network interfaces uses by Xcode for device connection traffic. Routing Sockets macOS supports the traditional BSD routine socket interface. See the route man page for details. Note You can access some routing socket functionality via sysctl, and all of this section applies to that as well. Other Apple platforms don’t support routing sockets [1]. On macOS it’s reasonable to use a routing socket to learn about the current state of the networking stack and be notified of changes to that state. Doing this on macOS 27 and later may require you to sign your code with the com.apple.developer.networking.topology-observation entitlement. In Xcode, add the Network Topology Observation capability [2] to your target. This is a restricted entitlement, which means it must be authorised by a provisioning profile. If you’re building a command-line tool, follow the advice in Signing a daemon with a restricted entitlement. Don’t use a routing socket to change the state of the networking stack. Such activities are not supported because macOS maintains its source of truth outside of the kernel, primarily in the System Configuration infrastructure [3]. If you make changes behind the back of this infrastructure then, in the best case, they’ll simply be overwritten at some point in the future, but in the worst case you could trigger stability problems. [1] You may or may not be able to open one, based on the current sandbox setup. Even if you can, that effort is not supported because the declarations required to use the socket, most obviously rt_msghdr, are only present in the macOS SDK. And no, copying declarations from one SDK to another is not supported (-; [2] There’s no link to the docs for this capability because that hasn’t yet landed (r. 181611259). [3] See System Configuration Programming Guidelines for a general introduction this architecture. Revision History 2026-09-23 Added the Routing Sockets section. 2025-12-10 Added info about SIOCGIFDIRECTLINK. 2023-07-19 First posted.
Replies
0
Boosts
0
Views
2.7k
Activity
Sep ’26
Appropriate API for measuring device-wide network traffic on iOS
I am developing a consumer iOS app for App Store distribution and would like to confirm the appropriate public API for the following use case. The app needs to measure the amount of network traffic passing through the device over short time intervals, for example once per second or more frequently. The app does not need to inspect packet contents, block or filter traffic, or provide a remote VPN service. It also should not generate dedicated network traffic solely for speed measurement. The goal is only to observe device-wide network traffic volume and convert that information into a simple real-time indicator for the user. I am currently investigating the Network Extension framework. Would NEPacketTunnelProvider be an appropriate API for this use case? If not, is there another supported Network Extension provider or other public iOS API intended for measuring device-wide network traffic in this manner? I would like to choose an architecture that is technically supported by Apple and appropriate for a consumer app distributed through the App Store before beginning implementation.
Replies
1
Boosts
0
Views
442
Activity
Sep ’26
sysextd: "no policy, cannot allow apps outside /Applications" - NEFilterDataProvider system extension on macOS 26
I'm developing a macOS security tool using NEFilterDataProvider as a system extension. On macOS 26 beta (25E241), sysextd consistently rejects my extension with: sysextd: no policy, cannot allow apps outside /Applications Configuration: App installed in /Applications/ Signed with Developer ID Application (693DSH8GN5) Entitlement: com.apple.developer.networking.networkextension = content-filter-provider com.apple.developer.system-extension.install = true Developer Mode enabled on test machine Comparison with Little Snitch: Little Snitch runs correctly on the same machine. Key differences I found: Little Snitch uses content-filter-provider-systemextension instead of content-filter-provider Little Snitch has com.apple.security.app-sandbox = false Both signed with Developer ID Application When I switch to content-filter-provider-systemextension, Xcode rejects every provisioning profile because none match that entitlement value, and the Developer Portal doesn't expose fine-grained control over the Network Extensions array values. Questions Is content-filter-provider-systemextension the correct entitlement for system extensions on macOS 26? How should the provisioning profile be configured to support it? Is there a known sysextd issue on macOS 26 beta causing this regardless of configuration? Is there - somewhere! - a guide on how to build such an extension? Thanks in advance for your help.
Replies
4
Boosts
0
Views
925
Activity
Sep ’26
NEURLFilter / SimpleURLFilter: neagent fails to open URL prefilter mmap file with errno 13 Permission denied
I am testing NEURLFilter on macOS using the SimpleURLFilter sample, and I am seeing a failure from neagent while it is saving the local URL prefilter Bloom filter to its mmap file. The relevant log is: neagent +[NEBloomFilter mmapToFile:data:dataLength:numberOfBits:numberOfHashes:murmurSeed:tag:]: NEBloomFilter - failed to open mmap file /private/var/db/urlPrefilter/com.apple.networkextension.url-prefilter-data.temp.com.example.apple-samplecode.SimpleURLFilterTC3Q7MAJXF <errno 13 - Permission denied> neagent <NEAgentURLFilterExtension: 0xc8ce64280>: -[NEAgentURLFilterExtension startURLFilter]_block_invoke - Failed to save first fetch of pre-filter data Environment: macOS: 26.5.1 (25F80) Xcode: 26.5 (17F42) Platform: macOS Signing type: Apple Development (automatically manage signing) What I am doing: Build and run the containing app. Save and enable the NEURLFilterManager configuration. The URL filter provider starts. The provider's prefilter code is reached. neagent logs the mmap failure above while trying to open a temporary file under /private/var/db/urlPrefilter. Expected result: neagent should be able to create or open its system-managed URL prefilter cache / mmap file under /private/var/db/urlPrefilter, and the local Bloom filter should be loaded successfully. Actual result: neagent fails to open the temporary mmap file with errno 13 Permission denied: /private/var/db/urlPrefilter/com.apple.networkextension.url-prefilter-data.temp.<bundle/team-specific suffix> I am not manually creating, modifying, or chmod/chown-ing /private/var/db/urlPrefilter or anything inside it. The directory and its contents are entirely system-managed. The failure appears to happen inside neagent while it is handling the system-managed URL prefilter cache. The failure occurs at the mmapToFile: step while neagent saves the Bloom filter prefilter data. Directory state: drwxr-xr-x 2 root wheel 64 /private/var/db/urlPrefilter Has anyone else encountered this? Any suggestions on what could cause neagent to fail with errno 13 on its own mmap file under /private/var/db/urlPrefilter?
Replies
9
Boosts
3
Views
1.4k
Activity
Sep ’26
iOS app loses Internet access after updates: wifiDenied and native URLSession -1009
Hello, Feedback Assistant report: FB24876147. I develop a Unity-based iOS app. Some customers in mainland China report losing Internet access after an app update, while most installations continue working. We have received similar reports since at least iOS 16, across several years and multiple app releases. Earlier iOS versions are uncertain, and we cannot confirm that all historical occurrences share the same cause. Updates without networking-code changes can be followed by failures. A later update sometimes restores connectivity, but not consistently. Customer-reported recovery attempts: The app's wireless-data permissions appear enabled in Settings. Switching the app's network permission to another setting and back did not help users who reported trying it. Reset Network Settings also did not help users who reported trying it. Some users reported that deleting and reinstalling the app restored connectivity. At least one user reported that deletion and reinstallation did not help. These are customer reports, not controlled tests on our development devices. We would prefer a recovery that preserves local save data. Captured evidence from one affected installation: App version 1.89, build 1; Unity 2022.3.62f3. Device identifier: iPhone18,1; iOS 26.2.1. App in foreground. Capture time: 2026-09-07 13:04:31–13:04:32 UTC. An unfiltered Network.framework default-path monitor reported: status=unsatisfied reason=wifiDenied interface=Wi-Fi UnityWebRequest and a newly created native ephemeral NSURLSession both failed against our public HTTPS origin and Apple's independent test endpoint: https://www.apple.com/library/test/success.html The native requests failed after approximately 1 ms and 3 ms, with NSURLErrorDomain -1009, underlying kCFErrorDomainCFNetwork -1009, and no HTTP response. The native session allowed cellular, expensive and constrained network access, used normal TLS verification, and had waitsForConnectivity=false. It bypassed Unity's reachability precheck. CTCellularData changed from unknown to notRestricted. We understand this does not establish successful cellular connectivity or Wi-Fi permission. Important limitations: The native probes ran inside the same Unity-built process, not a separate standalone native app. The captured measurements demonstrate a Wi-Fi failure. Cellular failures and enabled Settings permissions are customer reports, not independently verified by these measurements. We cannot reliably reproduce the affected state on our development devices and do not have a focused Xcode project that reproduces it. An affected-device sysdiagnose is not yet available. Unity Customer QA reviewed this evidence, assessed it as an iOS network-policy issue rather than a Unity bug, and referred us to Apple. We are seeking Apple's investigation, not presenting that assessment as a confirmed root cause. The Code-Level Support form directed us to these forums because we cannot currently provide a focused reproducer. Questions: Which affected-device diagnostics or logging profiles would help identify why the effective network policy reports wifiDenied? How should we investigate an installation-specific issue when a new minimal app may not reproduce that installation state? Is there a supported, data-preserving recovery or application-side mitigation when permission changes and network resets do not help, and reinstallation is not consistently effective? We have diagnostic screenshots and relevant probe source available. Any customer system logs would be collected with consent and shared privately with Apple, not posted publicly. Thank you.
Replies
1
Boosts
0
Views
354
Activity
Sep ’26
macos 26 - socket() syscall causes ENOBUFS "No buffer space available" error
As part of the OpenJDK testing we run several regression tests, including for Java SE networking APIs. These APIs ultimately end up calling BSD socket functions. On macos, starting macos 26, including on recent 26.2 version, we have started seeing some unexplained but consistent exception from one of these BSD socket APIs. We receive a "ENOBUFS" errno (No buffer space available) when trying to construct a socket(). These exact same tests continue to pass on many other older versions of macos (including 15.7.x). After looking into this more, we have been able to narrow this down to a very trivial C code which is as follows (also attached): #include <stdio.h> #include <sys/socket.h> #include <string.h> #include <unistd.h> #include <sys/errno.h> static int create_socket(const int attempt_number) { const int fd = socket(AF_INET6, SOCK_STREAM, 0); if (fd < 0) { fprintf(stderr, "socket creation failed on attempt %d," " due to: %s\n", attempt_number, strerror(errno)); return fd; } return fd; } int main() { const unsigned int num_times = 250000; for (unsigned int i = 1; i <= num_times; i++) { const int fd = create_socket(i); if (fd < 0) { return -1; } close(fd); } fprintf(stderr, "successfully created and closed %d sockets\n", num_times); } The code very trivially creates a socket() and close()s it. It does this repeatedly in a loop for a certain number of iterations. Compiling this as: clang sockbufspaceerr.c -o sockbufspaceerr.o and running it as: ./sockbufspaceerr.o consistently generates an error as follows on macos 26.x: socket creation failed on attempt 160995, due to: No buffer space available The iteration number on which the socket() creation fails varies, but the issue does reproduce. Running the same on older versions of macos doesn't reproduce the issue and the program terminates normally after those many iterations. Looking at the xnu source that is made available for each macos release here https://opensource.apple.com/releases/, I see that for macos 26.x there have been changes in this kernel code and there appears to be some kind of memory accountability code introduced in this code path. However, looking at the reproducer/application code in question, I believe it uses the right set of functions to both create as well as release the resources, so I can't see why this should cause the above error in macos 26.x. Does this look like some issue that needs attention in the macos kernel and should I report it through feedback assitant tool?
Replies
8
Boosts
0
Views
1.8k
Activity
Sep ’26