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

Networking Resources
General: Forums subtopic: App & System Services > Networking TN3151 Choosing the right networking API Networking Overview document — Despite the fact that this is in the archive, this is still really useful. TLS for App Developers forums post Choosing a Network Debugging Tool documentation WWDC 2019 Session 712 Advances in Networking, Part 1 — This explains the concept of constrained networking, which is Apple’s preferred solution to questions like How do I check whether I’m on Wi-Fi? TN3135 Low-level networking on watchOS TN3179 Understanding local network privacy Adapt to changing network conditions tech talk Understanding Also-Ran Connections forums post Extra-ordinary Networking forums post Foundation networking: Forums tags: Foundation, CFNetwork URL Loading System documentation — NSURLSession, or URLSession in Swift, is the recommended API for HTTP[S] on Apple platforms. Moving to Fewer, Larger Transfers forums post Testing Background Session Code forums post Network framework: Forums tag: Network Network framework documentation — Network framework is the recommended API for TCP, UDP, and QUIC on Apple platforms. Building a custom peer-to-peer protocol sample code (aka TicTacToe) Implementing netcat with Network Framework sample code (aka nwcat) Configuring a Wi-Fi accessory to join a network sample code Moving from Multipeer Connectivity to Network Framework forums post NWEndpoint History and Advice forums post Network Extension (including Wi-Fi on iOS): See Network Extension Resources Wi-Fi Fundamentals TN3111 iOS Wi-Fi API overview Wi-Fi Aware framework documentation Wi-Fi on macOS: Forums tag: Core WLAN Core WLAN framework documentation Wi-Fi Fundamentals Secure networking: Forums tags: Security Apple Platform Security support document Preventing Insecure Network Connections documentation — This is all about App Transport Security (ATS). WWDC 2017 Session 701 Your Apps and Evolving Network Security Standards [1] — This is generally interesting, but the section starting at 17:40 is, AFAIK, the best information from Apple about how certificate revocation works on modern systems. Available trusted root certificates for Apple operating systems support article Requirements for trusted certificates in iOS 13 and macOS 10.15 support article About upcoming limits on trusted certificates support article Apple’s Certificate Transparency policy support article What’s new for enterprise in iOS 18 support article — This discusses new key usage requirements. Technote 2232 HTTPS Server Trust Evaluation Technote 2326 Creating Certificates for TLS Testing QA1948 HTTPS and Test Servers Miscellaneous: More network-related forums tags: 5G, QUIC, Bonjour On FTP forums post Using the Multicast Networking Additional Capability forums post Investigating Network Latency Problems forums post WirelessInsights framework documentation iOS Network Signal Strength forums post Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" [1] This video is no longer available from Apple, but the URL should help you locate other sources of this info.
0
0
4.0k
Dec ’25
sendto() system call doesn't return an error even when there is one
Please consider this very trivial C code, which was run on 15.3.1 of macos: #include <stdio.h> #include <stdlib.h> #include <netinet/in.h> #include <arpa/inet.h> #include "sys/socket.h" #include <string.h> #include <unistd.h> #include <ifaddrs.h> #include <net/if.h> // prints out the sockaddr_in6 void print_addr(const char *msg_prefix, struct sockaddr_in6 sa6) { char addr_text[INET6_ADDRSTRLEN] = {0}; printf("%s%s:%d, addr family=%u\n", msg_prefix, inet_ntop(AF_INET6, &sa6.sin6_addr, (char *) &addr_text, INET6_ADDRSTRLEN), sa6.sin6_port, sa6.sin6_family); } // creates a datagram socket int create_dgram_socket() { const int fd = socket(AF_INET6, SOCK_DGRAM, 0); if (fd < 0) { perror("Socket creation failed"); return -1; } return fd; } int main() { printf("current process id:%ld parent process id: %ld\n", (long) getpid(), (long) getppid()); // // hardcode a link-local IPv6 address of a interface which is down // ifconfig: // ,,, // awdl0: flags=8822<BROADCAST,SMART,SIMPLEX,MULTICAST> mtu 1500 // options=6460<TSO4,TSO6,CHANNEL_IO,PARTIAL_CSUM,ZEROINVERT_CSUM> // ... // inet6 fe80::34be:50ff:fe14:ecd7%awdl0 prefixlen 64 scopeid 0x10 // nd6 options=201<PERFORMNUD,DAD> // media: autoselect (<unknown type>) // status: inactive // const char *ip6_addr_str = "fe80::34be:50ff:fe14:ecd7"; // link-local ipv6 address from above ifconfig output // parse the string literal to in6_addr struct in6_addr ip6_addr; int rv = inet_pton(AF_INET6, ip6_addr_str, &ip6_addr); if (rv != 1) { fprintf(stderr, "failed to parse ipv6 addr %s\n", ip6_addr_str); exit(EXIT_FAILURE); } // create a AF_INET6 SOCK_DGRAM socket const int sock_fd = create_dgram_socket(); if (sock_fd < 0) { exit(EXIT_FAILURE); } printf("created a socket, descriptor=%d\n", sock_fd); // create a destination sockaddr which points to the above // ipv6 link-local address and an arbitrary port const int dest_port = 12345; struct sockaddr_in6 dest_sock_addr; memset((char *) &dest_sock_addr, 0, sizeof(struct sockaddr_in6)); dest_sock_addr.sin6_addr = ip6_addr; dest_sock_addr.sin6_port = htons(dest_port); dest_sock_addr.sin6_family = AF_INET6; dest_sock_addr.sin6_scope_id = 0x10; // scopeid from the above ifconfig output // now sendto() to that address, whose network interface is down. // we expect sendto() to return an error print_addr("sendto() to ", dest_sock_addr); const char *msg = "hello"; const size_t msg_len = strlen(msg) + 1; rv = sendto(sock_fd, msg, msg_len, 0, (struct sockaddr *) &dest_sock_addr, sizeof(dest_sock_addr)); if (rv == -1) { perror("sendto() expectedly failed"); close(sock_fd); exit(EXIT_FAILURE); } printf("sendto() unexpectedly succeeded\n"); // should not reach here, we expect sendto() to return an error return 0; } It creates a SOCK_DGRAM socket and attempts to sendto() to a link-local IPv6 address of a local network interface which is not UP. The sendto() is expected to fail with a "network is down" (or at least fail with some error). Let's see how it behaves. Copy that code to a file called netdown.c and compile it as follows: clang netdown.c Now run the program: ./a.out That results in the following output: current process id:29290 parent process id: 21614 created a socket, descriptor=3 sendto() to fe80::34be:50ff:fe14:ecd7:14640, addr family=30 sendto() unexpectedly succeeded (To reproduce this locally, replace the IPv6 address in that code with a link-local IPv6 address of an interface that is not UP on your system) Notice how the sendto() returned successfully without any error giving an impression to the application code that the message has been sent. In reality, the message isn't really sent. Here's the system logs from that run: PID Type Date & Time Process Message debug 2025-03-13 23:36:36.830147 +0530 kernel Process (a.out) allowed via dev tool environment (/System/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal) debug 2025-03-13 23:36:36.833054 +0530 kernel [SPI][HIDSPI] TX: 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 RX: 20 02 00 00 00 00 38 00 10 02 00 17 00 00 2E 00 26700 error 2025-03-13 23:36:36.838607 +0530 nehelper Failed to get the signing identifier for 29290: No such process 26700 error 2025-03-13 23:36:36.838608 +0530 nehelper Failed to get the code directory hash for 29290: No such process default 2025-03-13 23:36:36.840070 +0530 kernel cfil_dispatch_attach_event:3507 CFIL: Failed to get effective audit token for <sockID 22289651233205710 <4f3051d7ec2dce>> 26700 error 2025-03-13 23:36:36.840678 +0530 nehelper Failed to get the signing identifier for 29290: No such process 26700 error 2025-03-13 23:36:36.840679 +0530 nehelper Failed to get the code directory hash for 29290: No such process default 2025-03-13 23:36:36.841742 +0530 kernel cfil_hash_entry_log:6082 <CFIL: Error: sosend_reinject() failed>: [29290 ] <UDP(17) out so 891be95f39bd0385 22289651233205710 22289651233205710 age 0> lport 60244 fport 12345 laddr fe80::34be:50ff:fe14:ecd7 faddr fe80::34be:50ff:fe14:ecd7 hash D7EC2DCE default 2025-03-13 23:36:36.841756 +0530 kernel cfil_service_inject_queue:4466 CFIL: sosend() failed 50 Notice the last line where it states the sosend() (and internal impl detail of macos) failed with error code 50, which corresponds to ENETDOWN ("Network is down"). However, like I noted, this error was never propagated back to the application from the sendto() system call. The documentation of sendto() system call states: man sendto ... Locally detected errors are indicated by a return value of -1. ... RETURN VALUES Upon successful completion, the number of bytes which were sent is returned. Otherwise, -1 is returned and the global variable errno is set to indicate the error. So I would expect sendto() to return -1, which it isn't. The 15.3.1 source of xnu hasn't yet been published but there is the 15.3 version here https://github.com/apple-oss-distributions/xnu/tree/xnu-11215.81.4 and looking at the corresponding function cfil_service_inject_queue, line 4466 (the one which is reported in the logs) https://github.com/apple-oss-distributions/xnu/blob/xnu-11215.81.4/bsd/net/content_filter.c#L4466, the code there logs this error and the cfil_service_inject_queue function then returns back the error. However, looking at the call sites of the call to cfil_service_inject_queue(...), there are several places within that file which don't track the return value (representing an error value) and just ignore it. Is that intentional and does that explain this issue? Does this deserve to be reported as a bug through feedback assistant?
2
0
448
Mar ’25
TLS for App Developers
Transport Layer Security (TLS) is the most important security protocol on the Internet today. Most notably, TLS puts the S into HTTPS, adding security to the otherwise insecure HTTP protocol. IMPORTANT TLS is the successor to the Secure Sockets Layer (SSL) protocol. SSL is no longer considered secure and it’s now rarely used in practice, although many folks still say SSL when they mean TLS. TLS is a complex protocol. Much of that complexity is hidden from app developers but there are places where it’s important to understand specific details of the protocol in order to meet your requirements. This post explains the fundamentals of TLS, concentrating on the issues that most often confuse app developers. Note The focus of this is TLS-PKI, where PKI stands for public key infrastructure. This is the standard TLS as deployed on the wider Internet. There’s another flavour of TLS, TLS-PSK, where PSK stands for pre-shared key. This has a variety of uses, but an Apple platforms we most commonly see it with local traffic, for example, to talk to a Wi-Fi based accessory. For more on how to use TLS, both TLS-PKI and TLS-PSK, in a local context, see TLS For Accessory Developers. Server Certificates For standard TLS to work the server must have a digital identity, that is, the combination of a certificate and the private key matching the public key embedded in that certificate. TLS Crypto Magic™ ensures that: The client gets a copy of the server’s certificate. The client knows that the server holds the private key matching the public key in that certificate. In a typical TLS handshake the server passes the client a list of certificates, where item 0 is the server’s certificate (the leaf certificate), item N is (optionally) the certificate of the certificate authority that ultimately issued that certificate (the root certificate), and items 1 through N-1 are any intermediate certificates required to build a cryptographic chain of trust from 0 to N. Note The cryptographic chain of trust is established by means of digital signatures. Certificate X in the chain is issued by certificate X+1. The owner of certificate X+1 uses their private key to digitally sign certificate X. The client verifies this signature using the public key embedded in certificate X+1. Eventually this chain terminates in a trusted anchor, that is, a certificate that the client trusts by default. Typically this anchor is a self-signed root certificate from a certificate authority. Note Item N is optional for reasons I’ll explain below. Also, the list of intermediate certificates may be empty (in the case where the root certificate directly issued the leaf certificate) but that’s uncommon for servers in the real world. Once the client gets the server’s certificate, it evaluates trust on that certificate to confirm that it’s talking to the right server. There are three levels of trust evaluation here: Basic X.509 trust evaluation checks that there’s a cryptographic chain of trust from the leaf through the intermediates to a trusted root certificate. The client has a set of trusted root certificates built in (these are from well-known certificate authorities, or CAs), and a site admin can add more via a configuration profile. This step also checks that none of the certificates have expired, and various other more technical criteria (like the Basic Constraints extension). Note This explains why the server does not have to include the root certificate in the list of certificates it passes to the client; the client has to have the root certificate installed if trust evaluation is to succeed. In addition, TLS trust evaluation (per RFC 2818) checks that the DNS name that you connected to matches the DNS name in the certificate. Specifically, the DNS name must be listed in the Subject Alternative Name extension. Note The Subject Alternative Name extension can also contain IP addresses, although that’s a much less well-trodden path. Also, historically it was common to accept DNS names in the Common Name element of the Subject but that is no longer the case on Apple platforms. App Transport Security (ATS) adds its own security checks. Basic X.509 and TLS trust evaluation are done for all TLS connections. ATS is only done on TLS connections made by URLSession and things layered on top URLSession (like WKWebView). In many situations you can override trust evaluation; for details, see Technote 2232 HTTPS Server Trust Evaluation). Such overrides can either tighten or loosen security. For example: You might tighten security by checking that the server certificate was issued by a specific CA. That way, if someone manages to convince a poorly-managed CA to issue them a certificate for your server, you can detect that and fail. You might loosen security by adding your own CA’s root certificate as a trusted anchor. IMPORTANT If you rely on loosened security you have to disable ATS. If you leave ATS enabled, it requires that the default server trust evaluation succeeds regardless of any customisations you do. Mutual TLS The previous section discusses server trust evaluation, which is required for all standard TLS connections. That process describes how the client decides whether to trust the server. Mutual TLS (mTLS) is the opposite of that, that is, it’s the process by which the server decides whether to trust the client. Note mTLS is commonly called client certificate authentication. I avoid that term because of the ongoing industry-wide confusion between certificates and digital identities. While it’s true that, in mTLS, the server authenticates the client certificate, to set this up on the client you need a digital identity, not a certificate. mTLS authentication is optional. The server must request a certificate from the client and the client may choose to supply one or not (although if the server requests a certificate and the client doesn’t supply one it’s likely that the server will then fail the connection). At the TLS protocol level this works much like it does with the server certificate. For the client to provide this certificate it must apply a digital identity, known as the client identity, to the connection. TLS Crypto Magic™ assures the server that, if it gets a certificate from the client, the client holds the private key associated with that certificate. Where things diverge is in trust evaluation. Trust evaluation of the client certificate is done on the server, and the server uses its own rules to decided whether to trust a specific client certificate. For example: Some servers do basic X.509 trust evaluation and then check that the chain of trust leads to one specific root certificate; that is, a client is trusted if it holds a digital identity whose certificate was issued by a specific CA. Some servers just check the certificate against a list of known trusted client certificates. When the client sends its certificate to the server it actually sends a list of certificates, much as I’ve described above for the server’s certificates. In many cases the client only needs to send item 0, that is, its leaf certificate. That’s because: The server already has the intermediate certificates required to build a chain of trust from that leaf to its root. There’s no point sending the root, as I discussed above in the context of server trust evaluation. However, there are no hard and fast rules here; the server does its client trust evaluation using its own internal logic, and it’s possible that this logic might require the client to present intermediates, or indeed present the root certificate even though it’s typically redundant. If you have problems with this, you’ll have to ask the folks running the server to explain its requirements. Note If you need to send additional certificates to the server, pass them to the certificates parameter of the method you use to create your URLCredential (typically init(identity:certificates:persistence:)). One thing that bears repeating is that trust evaluation of the client certificate is done on the server, not the client. The client doesn’t care whether the client certificate is trusted or not. Rather, it simply passes that certificate the server and it’s up to the server to make that decision. When a server requests a certificate from the client, it may supply a list of acceptable certificate authorities [1]. Safari uses this to filter the list of client identities it presents to the user. If you are building an HTTPS server and find that Safari doesn’t show the expected client identity, make sure you have this configured correctly. If you’re building an iOS app and want to implement a filter like Safari’s, get this list using: The distinguishedNames property, if you’re using URLSession The sec_protocol_metadata_access_distinguished_names routine, if you’re using Network framework [1] See the certificate_authorities field in Section 7.4.4 of RFC 5246, and equivalent features in other TLS versions. Self-Signed Certificates Self-signed certificates are an ongoing source of problems with TLS. There’s only one unequivocally correct place to use a self-signed certificate: the trusted anchor provided by a certificate authority. One place where a self-signed certificate might make sense is in a local environment, that is, securing a connection between peers without any centralised infrastructure. However, depending on the specific circumstances there may be a better option. TLS For Accessory Developers discusses this topic in detail. Finally, it’s common for folks to use self-signed certificates for testing. I’m not a fan of that approach. Rather, I recommend the approach described in QA1948 HTTPS and Test Servers. For advice on how to set that up using just your Mac, see TN2326 Creating Certificates for TLS Testing. TLS Standards RFC 6101 The Secure Sockets Layer (SSL) Protocol Version 3.0 (historic) RFC 2246 The TLS Protocol Version 1.0 RFC 4346 The Transport Layer Security (TLS) Protocol Version 1.1 RFC 5246 The Transport Layer Security (TLS) Protocol Version 1.2 RFC 8446 The Transport Layer Security (TLS) Protocol Version 1.3 RFC 4347 Datagram Transport Layer Security RFC 6347 Datagram Transport Layer Security Version 1.2 RFC 9147 The Datagram Transport Layer Security (DTLS) Protocol Version 1.3 Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Revision History: 2025-11-21 Clearly defined the terms TLS-PKI and TLS-PSK. 2024-03-19 Adopted the term mutual TLS in preference to client certificate authentication throughout, because the latter feeds into the ongoing certificate versus digital identity confusion. Defined the term client identity. Added the Self-Signed Certificates section. Made other minor editorial changes. 2023-02-28 Added an explanation mTLS acceptable certificate authorities. 2022-12-02 Added links to the DTLS RFCs. 2022-08-24 Added links to the TLS RFCs. Made other minor editorial changes. 2022-06-03 Added a link to TLS For Accessory Developers. 2021-02-26 Fixed the formatting. Clarified that ATS only applies to URLSession. Minor editorial changes. 2020-04-17 Updated the discussion of Subject Alternative Name to account for changes in the 2019 OS releases. Minor editorial updates. 2018-10-29 Minor editorial updates. 2016-11-11 First posted.
0
0
8.3k
Nov ’25
TCP socket disconnection with EBROKENPIPE during file copy of signed app bundle
We are developing a client server application using TCP bsd sockets. When our client is connected to the server, copying another client .app bundle from a file server on the same machine (using Finder or terminal using cp), occasionally causes the first client to disconnect. The client receives an EBROKENPIPE error when attempting to write to its socket. In the Console, the following message appears just before the disconnection: necp_socket_find_policy_match: Marking socket in state 258 as defunct This issue seems to occur only when copying an .app bundle signed with the same TeamIdentifier as the running client. Copying arbitrary files or bundles with a different TeamIdentifier does not trigger the problem. We are running on macOS 15.5. The issue appears specific to macOS 15 and was not observed on earlier versions. Any help or pointers would be greatly appreciated!
2
0
214
Jul ’25
Determine outgoing flow source IPs without allowing data leakage using NEFilterDataProvider
I'm looking for help with a network extension filtering issue. Specifically, we have a subclass of NEFilterDataProvider that is used to filter flows based upon a set of rules, including source IP and destination IP. We've run into an issue where the source IP is frequently 0.0.0.0 (or the IPv6 equivalent) on outgoing flows. This has made it so rules based upon source IP don't work. This is also an issue as we report these connections, but we're lacking critical data. We were able to work around the issue somewhat by keeping a list of flows that we allow that we periodically check to see if the source IP is available, and then report after it becomes available. We also considered doing a "peekBytes" to allow a bit of data to flow and then recheck the flow, but we don't want to allow data leakage on connections that should be blocked because of the source IP. Is there a way to force the operating system or network extension frameworks to determine the source IP for an outbound flow without allowing any bytes to flow to the network? STEPS TO REPRODUCE Create a network filtering extension for filtering flows using NEFilterDataProvider See that when handleNewFlow: is called, the outgoing flow lacks the source IP (is 0.0.0.0) in most cases There is this post that is discussing a similar question, though for a slightly different reason. I imagine the answer to this and the other post will be related, at least as far as NEFilterDataProvider:handleNewFlow not having source IP is considered. Thanks!
1
0
169
Apr ’25
About the Relay payload
ios構成プロファイルの制限のallowCloudPrivateRelayのプライベートリレーの制御とRelayペイロードの機能は関係がありますか? それとも別々の機能でしょうか? ↓ s there a relationship between the private relay control in the iOS configuration profile restriction allowCloudPrivateRelay and the functionality of the Relay payload? Or are they separate features?
0
0
25
Apr ’25
NEAppPushProvider lifecycle guarantees for safety-critical local networking
We have an iOS companion app that talks to our IoT device over the device’s own Wi‑Fi network (often with no internet). The app performs bi-directional, safety-critical duties over that link. We use an NEAppPushProvider extension so the handset can keep exchanging data while the UI is backgrounded. During testing we noticed that if the user backgrounds the app (still connected to the device’s Wi‑Fi) and opens Safari, the extension’s stop is invoked with NEProviderStopReason.unrecoverableNetworkChange / noNetworkAvailable, and iOS tears the extension down. Until the system restarts the extension (e.g. the user foregrounds our app again), the app cannot send/receive its safety-critical data. Questions: Is there a supported way to stop a safety-critical NEAppPushProvider from being terminated in this “background app → open Safari” scenario when the device remains on the same Wi‑Fi network (possibly without internet)? If not, is NEAppPushProvider the correct extension type for an always-on local-network use case like this, or is there another API we should be using? For safety-critical applications, can Apple grant entitlements/exemptions so the system does not terminate the extension when the user switches apps but stays on the local Wi‑Fi? Any guidance on the expected lifecycle or alternative patterns for safety-critical local connectivity would be greatly appreciated.
1
0
60
Nov ’25
ISP DNS Resolution in Full-Tunnel VPN
I am running a full-tunnel VPN using a Packet Tunnel Provider. During VPN setup, we configure DNS setting with specific DNS servers for all domains to be used by the tunnel. However, our project requires DNS resolution for every domain from both the VPN-provided DNS servers and the ISP’s DNS servers. When I attempt to use c-ares or other third-party libraries to resolve domains via the ISP DNS servers, these libraries only detect and use the VPN DNS servers instead. As a result, all queries fail. Is there a way on iOS to programmatically determine the ISP DNS servers while a full-tunnel VPN is active, or a system API that allows DNS queries to be explicitly resolved using the ISP’s DNS servers?
1
0
101
Sep ’25
NWPathMonitor Reports Unexpected satisfied→unsatisfied→satisfied Sequence After WiFi Re-enablement
I am developing an iOS application using NWPathMonitor for network connectivity monitoring. We discovered a reproducible issue where disabling and re-enabling WiFi triggers an unexpected network status sequence. ENVIRONMENT: iOS Version: 17.x Device: iPhone (various models tested) Network Framework: NWPathMonitor from iOS Network framework STEPS TO REPRODUCE: Device connected to WiFi normally Disable WiFi via Settings or Control Center Re-enable WiFi via Settings or Control Center EXPECTED BEHAVIOR: WiFi reconnects and NWPathMonitor reports stable satisfied status ACTUAL BEHAVIOR: T+0s: WiFi re-enables, NWPathMonitor reports path.status = .satisfied T+8s: NWPathMonitor unexpectedly reports path.status = .unsatisfied with unsatisfiedReason = .notAvailable T+9-10s: NWPathMonitor reports path.status = .satisfied again Connection becomes stable afterward NETWORK PATH TIMELINE: T+0s: satisfied (IPv4: true, DNS: false) T+140ms: satisfied (IPv4: true, DNS: true) T+8.0s: unsatisfied (reason: notAvailable, no interfaces available) T+10.0s: satisfied (IPv4: true, DNS: true) KEY OBSERVATIONS: Timing consistency: unsatisfied event always occurs ~8 seconds after reconnection resolution: "Reset Network Settings" eliminates this behavior TECHNICAL QUESTIONS: What causes the 8-second delayed unsatisfied status after WiFi re-enablement? Is this expected behavior that applications should handle? Why does reset network setting in iPhone fix this issue?
1
0
110
Jul ’25
in-addr.arpa default search domains
Hi, I observed some unexpected behavior and hope that someone can enlighten me as to what this is about: mDNSResponder prepends IP / network based default search domains that are checked before any other search domain. E.g. 0.1.168.192.in-addr.arpa. would be used for an interface with an address in the the 192.168.1.0/24 subnet. This is done for any configured non-link-local IP address. I tried to find any mention of an approach like this in RFCs but couldn't spot anything. Please note that this is indeed a search domain and different from reverse-DNS lookups. Example output of tcpdump for ping devtest: 10:02:13.850802 IP (tos 0x0, ttl 64, id 43461, offset 0, flags [none], proto UDP (17), length 92) 192.168.1.2.52319 &gt; 192.168.1.1.53: 54890+ [1au] A? devtest.0.1.168.192.in-addr.arpa. (64) I was able to identify the code that adds those default IP subnet based search domains but failed to spot any indication as to what this is about: https://github.com/apple-oss-distributions/mDNSResponder/blob/d5029b5/mDNSMacOSX/mDNSMacOSX.c#L4171-L4211 Does anyone here have an ideas as to what this might be about?
1
0
770
Apr ’25
Broadcasts and Multicasts, Hints and Tips
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" Broadcasts and Multicasts, Hints and Tips I regularly see folks struggle with broadcasts and multicasts on Apple platforms. This post is my attempt to clear up some of the confusion. This post covers both IPv4 and IPv6. There is, however, a key difference. In IPv4, broadcasts and multicasts are distinct concepts. In contrast, IPv6 doesn’t support broadcast as such; rather, it treats broadcasts as a special case of multicasts. IPv6 does have an all nodes multicast address, but it’s rarely used. Before reading this post, I suggest you familiarise yourself with IP addresses in general. A good place to start is The Fount of All Knowledge™. Service Discovery A lot of broadcast and multicast questions come from folks implementing their own service discovery protocol. I generally recommend against doing that, for the reasons outlined in the Service Discovery section of Don’t Try to Get the Device’s IP Address. There are, however, some good reasons to implement a custom service discovery protocol. For example, you might be working with an accessory that only supports this custom protocol [1]. If you must implement your own service discovery protocol, read this post and also read the advice in Don’t Try to Get the Device’s IP Address. IMPORTANT Sometimes I see folks implementing their own version of mDNS. This is almost always a mistake: If you’re using third-party tooling that includes its own mDNS implementation, it’s likely that this tooling allows you to disable that implementation and instead rely on the Bonjour support that’s built-in to all Apple platforms. If you’re doing some weird low-level thing with mDNS or DNS-SD, it’s likely that you can do that with the low-level DNS-SD API. [1] And whose firmware you can’t change! I talk more about this in Working with a Wi-Fi Accessory. API Choice Broadcasts and multicasts typically use UDP [1]. TN3151 Choosing the right networking API describes two recommended UDP APIs: Network framework BSD Sockets Our general advice is to prefer Network framework over BSD Sockets, but UDP broadcasts and multicasts are an exception to that rule. Network framework has very limited UDP broadcast support. And while it’s support for UDP multicasts is less limited, it’s still not sufficient for all UDP applications. In cases where Network framework is not sufficient, BSD Sockets is your only option. [1] It is possible to broadcast and multicast at the Ethernet level, but I almost never see questions about that. UDP Broadcasts in Network Framework Historically I’ve claimed that Network framework was useful for UDP broadcasts is very limited circumstances (for example, in the footnote on this post). I’ve since learnt that this isn’t the case. Or, more accurately, this support is so limited (r. 122924701) as to be useless in practice. For the moment, if you want to work with UDP broadcasts, your only option is BSD Sockets. UDP Multicasts in Network Framework Network framework supports UDP multicast using the NWConnectionGroup class with the NWMulticastGroup group descriptor. This support has limits. The most significant limit is that it doesn’t support broadcasts; it’s for multicasts only. Note This only relevant to IPv4. Remember that IPv6 doesn’t support broadcasts as a separate concept. There are other limitations, but I don’t have a good feel for them. I’ll update this post as I encounter issues. Local Network Privacy Some Apple platforms support local network privacy. This impacts broadcasts and multicasts in two ways: Broadcasts and multicasts require local network access, something that’s typically granted by the user. Broadcasts and multicasts are limited by a managed entitlement (except on macOS). TN3179 Understanding local network privacy has lots of additional info on this topic, including the list of platforms to which it applies. Send, Receive, and Interfaces When you broadcast or multicast, there’s a fundamental asymmetry between send and receive: You can reasonable receive datagrams on all broadcast-capable interfaces. But when you send a datagram, it has to target a specific interface. The sending behaviour is the source of many weird problems. Consider the IPv4 case. If you send a directed broadcast, you can reasonably assume it’ll be routed to the correct interface based on the network prefix. But folks commonly send an all-hosts broadcast (255.255.255.255), and it’s not obvious what happens in that case. Note If you’re unfamiliar with the terms directed broadcast and all-hosts broadcast, see IP address. The exact rules for this are complex, vary by platform, and can change over time. For that reason, it’s best to write your broadcast code to be interface specific. That is: Identify the interfaces on which you want to work. Create a socket per interface. Bind that socket to that interface. Note Use the IP_BOUND_IF (IPv4) or IPV6_BOUND_IF (IPv6) socket options rather than binding to the interface address, because the interface address can change over time. Extra-ordinary Networking has links to other posts which discuss these concepts and the specific APIs in more detail. Miscellaneous Gotchas A common cause of mysterious broadcast and multicast problems is folks who hard code BSD interface names, like en0. Doing that might work for the vast majority of users but then fail in some obscure scenarios. BSD interface names are not considered API and you must not hard code them. Extra-ordinary Networking has links to posts that describe how to enumerate the interface list and identify interfaces of a specific type. Don’t assume that there’ll be only one interface of a given type. This might seem obviously true, but it’s not. For example, our platforms support peer-to-peer Wi-Fi, so each device has multiple Wi-Fi interfaces. When sending a broadcast, don’t forget to enable the SO_BROADCAST socket option. If you’re building a sandboxed app on the Mac, working with UDP requires both the com.apple.security.network.client and com.apple.security.network.server entitlements. Some folks reach for broadcasts or multicasts because they’re sending the same content to multiple devices and they believe that it’ll be faster than unicasts. That’s not true in many cases, especially on Wi-Fi. For more on this, see the Broadcasts section of Wi-Fi Fundamentals. Snippets To send a UDP broadcast: func broadcast(message: Data, to interfaceName: String) throws { let fd = try FileDescriptor.socket(AF_INET, SOCK_DGRAM, 0) defer { try! fd.close() } try fd.setSocketOption(SOL_SOCKET, SO_BROADCAST, 1 as CInt) let interfaceIndex = if_nametoindex(interfaceName) guard interfaceIndex > 0 else { throw … } try fd.setSocketOption(IPPROTO_IP, IP_BOUND_IF, interfaceIndex) try fd.send(data: message, to: ("255.255.255.255", 2222)) } Note These snippet uses the helpers from Calling BSD Sockets from Swift. To receive UDP broadcasts: func receiveBroadcasts(from interfaceName: String) throws { let fd = try FileDescriptor.socket(AF_INET, SOCK_DGRAM, 0) defer { try! fd.close() } let interfaceIndex = if_nametoindex(interfaceName) guard interfaceIndex > 0 else { fatalError() } try fd.setSocketOption(IPPROTO_IP, IP_BOUND_IF, interfaceIndex) try fd.setSocketOption(SOL_SOCKET, SO_REUSEADDR, 1 as CInt) try fd.setSocketOption(SOL_SOCKET, SO_REUSEPORT, 1 as CInt) try fd.bind("0.0.0.0", 2222) while true { let (data, (sender, port)) = try fd.receiveFrom() … } } IMPORTANT This code runs synchronously, which is less than ideal. In a real app you’d run the receive asynchronously, for example, using a Dispatch read source. For an example of how to do that, see this post. If you need similar snippets for multicast, lemme know. I’ve got them lurking on my hard disk somewhere (-: Other Resources Apple’s official documentation for BSD Sockets is in the man pages. See Reading UNIX Manual Pages. Of particular interest are: setsockopt man page ip man page ip6 man page If you’re not familiar with BSD Sockets, I strongly recommend that you consult third-party documentation for it. BSD Sockets is one of those APIs that looks simple but, in reality, is ridiculously complicated. That’s especially true if you’re trying to write code that works on BSD-based platforms, like all of Apple’s platforms, and non-BSD-based platforms, like Linux. I specifically recommend UNIX Network Programming, by Stevens et al, but there are lots of good alternatives. https://unpbook.com Revision History 2025-09-01 Fixed a broken link. 2025-01-16 First posted.
0
0
609
Sep ’25
After creating the profile using eapolcfg and attempting to connect to the enterprise network, eapolclient connection fails.
I use eapolcfg in Apple's open source eap8021x repository to connect to the enterprise network. 1.https://github.com/gfleury/eap8021x-debug https://opensource.apple.com/source/eap8021x/eap8021x-304.100.1/ Our enterprise network authentication is PEAP. So far, I have created a profile using the following commands and have done the access. ./eapolcfg createProfile --authType PEAP --SSID myssid --securityType WPA2 --userDefinedName MyProfile ./eapolcfg setPasswordItem --password mypassword --name myname --SSID myssid ./eapolcfg startAuthentication --interface en0 --SSID myssid After I performed this series of operations, I passed BOOL success = [self.interface associateToEnterpriseNetwork:network identity:nil username:username password:password error:&amp;error]; Connection will pop up the following pop-up window, sometimes associateToEnterpriseNetwork will fail. I don't know what went wrong, is it that I missed some steps through the eapolcfg [tool?] This function also reports the following error:Error Domain=com.apple.coreWLAN.EAPOL.error Code=1 "(null)" Please answer my questions. Thank you very much
1
0
459
Mar ’25
Running headless app as root for handling VPN and launching microservices
Hello to all I have coded in swift a headless app, that launches 3 go microservices and itself. The app listens via unix domain sockets for commands from the microservices and executes different VPN related operations, using the NEVPNManager extension. Because there are certificates and VPN operations, the headless app and two Go microservices must run as root. The app and microservices run perfectly when I run in Xcode launching the swift app as root. However, I have been trying for some weeks already to modify the application so at startup it requests the password and runs as root or something similar, so all forked apps also run as root. I have not succeeded. I have tried many things, the last one was using SMApp but as the swift app is a headless app and not a CLI command app it can not be embedded. And CLI apps can not get the VPN entitlements. Can anybody please give me some pointers how can I launch the app so it requests the password and runs as root in background or what is the ideal framework here? thank you again.
5
0
362
Dec ’25
Network Extension Framework Entitlements
At WWDC 2015 Apple announced two major enhancements to the Network Extension framework: Network Extension providers — These are app extensions that let you insert your code at various points within the networking stack, including: Packet tunnels via NEPacketTunnelProvider App proxies via NEAppProxyProvider Content filters via NEFilterDataProvider and NEFilterControlProvider Hotspot Helper (NEHotspotHelper) — This allows you to create an app that assists the user in navigating a hotspot (a Wi-Fi network where the user must interact with the network in order to get access to the wider Internet). Originally, using any of these facilities required authorisation from Apple. Specifically, you had to apply for, and be granted access to, a managed capability. In Nov 2016 this policy changed for Network Extension providers. Any developer can now use the Network Extension provider capability like they would any other capability. There is one exception to this rule: Network Extension app push providers, introduced by iOS 14 in 2020, still requires that Apple authorise the use of a managed capability. To apply for that, follow the link in Local push connectivity. Also, the situation with Hotspot Helpers remains the same: Using a Hotspot Helper, requires that Apple authorise that use via a managed capability. To apply for that, follow the link in Hotspot helper. IMPORTANT Pay attention to this quote from the documentation: NEHotspotHelper is only useful for hotspot integration. There are both technical and business restrictions that prevent it from being used for other tasks, such as accessory integration or Wi-Fi based location. The rest of this document answers some frequently asked questions about the Nov 2016 change. #1 — Has there been any change to the OS itself? No, this change only affects the process by which you get the capabilities you need in order to use existing Network Extension framework facilities. Previously these were managed capabilities, meaning their use was authorised by Apple. Now, except for app push providers and Hotspot Helper, you can enable the necessary capabilities using Xcode’s Signing & Capabilities editor or the Developer website. IMPORTANT Some Network Extension providers have other restrictions on their use. For example, a content filter can only be used on a supervised device. These restrictions are unchanged. See TN3134 Network Extension provider deployment for the details. #2 — How exactly do I enable the Network Extension provider capability? In the Signing & Capabilities editor, add the Network Extensions capability and then check the box that matches the provider you’re creating. In the Certificates, Identifiers & Profiles section of the Developer website, when you add or edit an App ID, you’ll see a new capability listed, Network Extensions. Enable that capability in your App ID and then regenerate the provisioning profiles based on that App ID. A newly generated profile will include the com.apple.developer.networking.networkextension entitlement in its allowlist; this is an array with an entry for each of the supported Network Extension providers. To confirm that this is present, dump the profile as shown below. $ security cms -D -i NETest.mobileprovision … <plist version="1.0"> <dict> … <key>Entitlements</key> <dict> <key>com.apple.developer.networking.networkextension</key> <array> <string>packet-tunnel-provider</string> <string>content-filter-provider</string> <string>app-proxy-provider</string> … and so on … </array> … </dict> … </dict> </plist> #3 — I normally use Xcode’s Signing & Capabilities editor to manage my entitlements. Do I have to use the Developer website for this? No. Xcode 11 and later support this capability in the Signing & Capabilities tab of the target editor (r. 28568128 ). #4 — Can I still use Xcode’s “Automatically manage signing” option? Yes. Once you modify your App ID to add the Network Extension provider capability, Xcode’s automatic code signing support will include the entitlement in the allowlist of any profiles that it generates based on that App ID. #5 — What should I do if I previously applied for the Network Extension provider managed capability and I’m still waiting for a reply? Consider your current application cancelled, and use the new process described above. #6 — What should I do if I previously applied for the Hotspot Helper managed capability and I’m still waiting for a reply? Apple will continue to process Hotspot Helper managed capability requests and respond to you in due course. #7 — What if I previously applied for both Network Extension provider and Hotspot Helper managed capabilities? Apple will ignore your request for the Network Extension provider managed capability and process it as if you’d only asked for the Hotspot Helper managed capability. #8 — On the Mac, can Developer ID apps host Network Extension providers? Yes, but there are some caveats: This only works on macOS 10.15 or later. Your Network Extension provider must be packaged as a system extension, not an app extension. You must use the *-systemextension values for the Network Extension entitlement (com.apple.developer.networking.networkextension). For more on this, see Exporting a Developer ID Network Extension. #9 — After moving to the new process, my app no longer has access to the com.apple.managed.vpn.shared keychain access group. How can I regain that access? Access to this keychain access group requires another managed capability. If you need that, please open a DTS code-level support request and we’ll take things from there. IMPORTANT This capability is only necessary if your VPN supports configuration via a configuration profile and needs to access credentials from that profile (as discussed in the Profile Configuration section of the NETunnelProviderManager Reference). Many VPN apps don’t need this facility. If you were previously granted the Network Extension managed capability (via the process in place before Nov 2016), make sure you mention that; restoring your access to the com.apple.managed.vpn.shared keychain access group should be straightforward in that case. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Revision History 2025-11-11 Removed the discussion of TSI assets because those are no longer a thing. 2025-09-12 Adopted the code-level support request terminology. Made other minor editorial changes. 2023-01-11 Added a discussion of Network Extension app push providers. Added a link to Exporting a Developer ID Network Extension. Added a link to TN3134. Made significant editorial changes. 2020-02-27 Fixed the formatting. Updated FAQ#3. Made minor editorial changes. 2020-02-16 Updated FAQ#8 to account for recent changes. Updated FAQ#3 to account for recent Xcode changes. Made other editorial changes. 2016-01-25 Added FAQ#9. 2016-01-6 Added FAQ#8. 2016-11-11 Added FAQ#5, FAQ#6 and FAQ#7. 2016-11-11 First posted.
0
0
23k
Nov ’25
SwiftSMTP broken: Error ioOnClosedChannel on latest macOS
Hi! I wrote an internal used backup command line tool which is in use since several years. Today I got an error while sending an email: “Failed: ioOnClosedChannel”. I assume that the latest macOS updates did break my app. On the server I use macOS 15.7 and on my development machine macOS 26. Here is the related code: private func sendMail() { var a : [Email.Attachment] = [] if self.imageData != nil { switch self.imageType { case .tiff: a.append(Email.Attachment(name: "Statistics.tif", contentType: #"image/tiff"#, contents: ByteBuffer(bytes: self.imageData!))) case .pdf: a.append(Email.Attachment(name: "Statistics.pdf", contentType: #"application/pdf"#, contents: ByteBuffer(bytes: self.imageData!))) case .unknown: fatalError("Unimplemented attachment type!") } } mailHtml = mailHtml.replacingOccurrences(of: "<br>", with: "<br>\n") let email = Email(sender: .init(name: "Backup", emailAddress: "SENDER@MYDOMAIN"), replyTo: nil, recipients: recipients, cc: [], bcc: [], subject: self.subject, body: .universal(plain: self.mailText, html: mailHtml), attachments: a) let evg = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount) let mailer = Mailer(group: evg, configuration: smtpConfig, transmissionLogger: nil) do { print("Sending mail... ", terminator: "") try mailer.send(email: email).wait() // <-- ERROR HERE Failed: ioOnClosedChannel print("done.") } catch { print("Failed: \(error)") } do { try evg.syncShutdownGracefully() } catch { print("Failed shutdown: \(error)") } } I use https://github.com/sersoft-gmbh/swift-smtp. Any clue about the reason of this error? TIA, GreatOm
2
0
248
Sep ’25