I have been polishing an app that connects and communicates between a tvOS app I created and a iPadOS app that I also created. Connection works fantastic! However, for some reason when the user selects the button to open the DevicePicker provided by this API and then selects a iPad device the notification that comes across the the iPad reads, "Connect your Apple TV to "AppName" on this iPhone.
Is this a bug or am I missing some configuration in maybe Info.plist or a modifier I need to add the DevicePicker for it to communicate the proper device identification? I have everything setup in both app Info.plist files to connect and work fine, but the notification saying iPhone on an iPad is sadly a small detail I would love to change. So...not sure if I found a bug or if I am missing something.
Networking
RSS for tagExplore the networking protocols and technologies used by the device to connect to Wi-Fi networks, Bluetooth devices, and cellular data services.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
My external device can generate a fixed Wi-Fi network. When I connect to this Wi-Fi using my iPhone 17 Pro Max (iOS version 26.0.1), and my app tries to establish a connection using the following method, this method returns -1
int connect(int, const struct sockaddr *, socklen_t) __DARWIN_ALIAS_C(connect);
However, when I use other phones, such as iPhone 12, iPhone 8, iPhone 11, etc., to connect to this external device, the above method always returns successfully, with the parameters passed to the method remaining the same.
I also tried resetting the network settings on the iPhone 17 Pro Max (iOS version 26.0.1), but it still cannot establish a connection.
Topic:
App & System Services
SubTopic:
Networking
Hi everyone,
I'm currently experimenting with building a simple DNS filter using Apple's Packet Tunnel framework. Here's the flow I'm trying to implement:
Create a TUN interface
Set up a UDP socket
Read packets via packetFlow.readPackets
Parse the raw IP packet
Forward the UDP payload through the socket
Receive the response from the server
Reconstruct the IP packet with the response
Write it back to the TUN interface using packetFlow.writePackets
Here’s an example of an intercepted IP packet (DNS request):
45 00 00 3c 15 c4 00 00 40 11 93 d1 c0 a8 00 64 08 08 08 08 ed 6e 00 35 00 28 e5 c9 7f da 01 00 00 01 00 00 00 00 00 00 04 74 69 6d 65 05 61 70 70 6c 65 03 63 6f 6d 00 00 01 00 01
And here’s the IP packet I tried writing back into the TUN interface (DNS response):
45 00 00 89 5e 37 40 00 40 11 0b 11 08 08 08 08 c0 a8 00 64 00 35 ed 6e 00 75 91 e8 7f da 81 80 00 01 00 04 00 00 00 00 04 74 69 6d 65 05 61 70 70 6c 65 03 63 6f 6d 00 00 01 00 01 c0 0c 00 05 00 01 00 00 0c fb 00 11 04 74 69 6d 65 01 67 07 61 61 70 6c 69 6d 67 c0 17 c0 2c 00 01 00 01 00 00 03 04 00 04 11 fd 74 fd c0 2c 00 01 00 01 00 00 03 04 00 04 11 fd 74 7d c0 2c 00 01 00 01 00 00 03 04 00 04 11 fd 54 fb
Unfortunately, it seems the packet is not being written back correctly to the TUN interface. I'm not seeing any expected DNS response behavior on the device.
Also, I noticed that after creating the TUN, the interface address shows up as 0.0.0.0:0 in Xcode. The system log includes this message when connecting the VPN:
NWPath does not have valid interface: satisfied (Path is satisfied), interface: utun20[endc_sub6], ipv4, dns, expensive, uses cellular
Does anyone know how to properly initialize the TUN so that the system recognizes it with a valid IP configuration? Or why my written-back packet might be getting ignored?
Any help would be appreciated!
I'm trying to use NEHotspotNetwork to configure an IoT. I've read all the issues that have plagued other developers when using this framework, and I was under the impression that bugs were filed and fixed.
Here are my issues in hopes that someone can catch my bug, or has finally figured this out and it's not a bug in the framework with no immediate fix on the horizon.
If I use the following code:
let config = NEHotspotConfiguration(ssid: ssid)
config.joinOnce = true
KiniStatusBanner.shared.show(text: "Connecting to Kini", in: presentingVC.view)
NEHotspotConfigurationManager.shared.apply(config) { error in
DispatchQueue.main.async {
if let nsError = error as NSError?,
nsError.domain == NEHotspotConfigurationErrorDomain,
nsError.code == NEHotspotConfigurationError.alreadyAssociated.rawValue {
print("Already connected to \(self.ssid)")
KiniStatusBanner.shared.dismiss()
self.presentCaptivePortal(from: presentingVC, activationCode: activationCode)
} else if let error = error {
// This doesn't happen
print("❌ Failed to connect: \(error.localizedDescription)")
KiniStatusBanner.shared.update(text: "Failed to Connect to Kini. Try again later.")
KiniStatusBanner.shared.dismiss(after: 2.5)
} else {
// !!!! Most often, this is the path the code takes
NEHotspotNetwork.fetchCurrent { current in
if let ssid = current?.ssid, ssid == self.ssid {
log("✅✅ 1st attempt: connected to \(self.ssid)")
KiniStatusBanner.shared.dismiss()
self.presentCaptivePortal(from: presentingVC, activationCode: activationCode)
} else {
// Dev forums talked about giving things a bit of time to settle and then try again
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
NEHotspotNetwork.fetchCurrent { current in
if let ssid = current?.ssid, ssid == self.ssid {
log("✅✅✅ 2nd attempt: connected to \(self.ssid)")
KiniStatusBanner.shared.dismiss()
self.presentCaptivePortal(from: presentingVC, activationCode: activationCode)
} else {
log("❌❌❌ 2nd attempt: Failed to connect: \(self.ssid)")
KiniStatusBanner.shared.update(text: "Could not join Kini network. Try again.")
KiniStatusBanner.shared.dismiss(after: 2.5)
self.cleanupHotspot()
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
print("cleanup again")
self.cleanupHotspot()
}
}
}
}
log("❌❌ 1st attempt: Failed to connect: \(self.ssid)")
KiniStatusBanner.shared.update(text: "Could not join Kini network. Try again.")
KiniStatusBanner.shared.dismiss(after: 2.5)
self.cleanupHotspot()
}
As you can see, one can't just use NEHotspotConfigurationManager.shared.apply and has to double-check to make sure that it actually succeeds, by checking to see if the SSID desired, matches the one that the device is using.
Ok, but about 50% of the time, the call to NEHotspotNetwork.fetchCurrent gives me this error:
NEHotspotNetwork nehelper sent invalid result code [1] for Wi-Fi information request
Well, there is a workaround for that randomness too. At some point before calling this code, one can:
let locationManager = CLLocationManager()
locationManager.requestWhenInUseAuthorization()
That eliminates the NEHotspotNetwork nehelper sent invalid result code [1] for Wi-Fi information request
BUT... three issues.
The user is presented with an authorization alert: Allow "Kini" to use your location? This app needs access to you Wi-Fi name to connect to your Kini device. Along with a map with a location pin on it. This gives my users a completely wrong impression, especially for a device/app where we promise users not to track their location. They actually see a map with their location pinned on it, implying something that would freak out anyone who was expecting no tracking. I understand why an authorization is normally required, but since all we are getting is our own IoT's SSID, there should be no need for an authorization for this, and no map associated with the request. Again, they are accessing my IoT's network, NOT their home/location Wi-Fi SSID. My app already knows and specifies that network, and all I am trying to do is to work around a bug that makes it look like I have a successful return from NEHotspotConfigurationManager.shared.apply() when in fact the network I was looking for wasn't even on.
Not only do I get instances where the network doesn't connect, and result codes show no errors, but I also get instances where I get an alert that says that the network is unreachable, yet my IoT shows that the app is connected to its Wi-Fi. On the iOS device, I go to the Wi-Fi settings, and see that I am on the IoT's network. So basically, sometimes I connect, but the frameworks says that there is no connection, and sometimes it reports a connection when there is none.
As you can see in the code, I call cleanupHotspot() to make the iOS device get off of my temp Wi-Fi SSID. This is the code:
func cleanupHotspot() {
NEHotspotConfigurationManager.shared.removeConfiguration(forSSID: ssid)
}
That code gets called by the above code when things aren't as I expect and need to cleanup. And I also call it when the user dismisses the viewcontroller that is attempting to make the connection.
It doesn't always work. I get stuck on the tempo SSID, unless I go through this whole thing again: try to make the connection again, this time it succeeds quickly, and then I can disconnect.
Any ideas?
I'm on iOS18.5, and have tried this on multiple iPhones including 11, 13 and 16.
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.
Before iOS16, we can use
https://developer.apple.com/documentation/coretelephony/ctcarrier
But after iOS this is deprecated and has no replacement.
There are some discussions on it, eg.
https://developer.apple.com/forums/thread/714876
https://developer.apple.com/forums/thread/770400
Now I asked AI, then it provided this solution, to check the serviceCurrentRadioAccessTechnology, so it this ok to check the SIM card status?
var hasSIMCard = false
let info = CTTelephonyNetworkInfo()
if let rat = info.serviceCurrentRadioAccessTechnology,
rat.values.contains(where: { !$0.isEmpty }) {
hasSIMCard = true. // has RAT
}
BTW, I can see a lot of changes in the Core Telephony framework.
https://developer.apple.com/documentation/coretelephony
1.isSIMInserted
https://developer.apple.com/documentation/coretelephony/ctsubscriber/issiminserted
A Boolean property that indicates whether a SIM is present. iOS 18.0+ iPadOS 18.0+
This value property is true if the system finds a SIM matching the Info.plist carrier information (MCC / MNC / GID1 / GID2).
Is this ok to check SIM insert status, this seems must preconfig some info in the info.plist.
2.iOS26 provide CTCellularPlanStatus
https://developer.apple.com/documentation/coretelephony/ctcellularplanstatus
Can I use this to check SIM status?
1、已经检查过手机的存储空间,还有一百多G的空间。app端进行网络接口情况的时候报错了,报错信息如下:
Error : Error Domain=NSPOSIXErrorDomain Code=28 "No space left on device" UserInfo={_NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <7DB1CBFD-B9BE-422D-9C9A-78D8FC04DC1B>.<76>, _kCFStreamErrorDomainKey=1, _kCFStreamErrorCodeKey=28, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <7DB1CBFD-B9BE-422D-9C9A-78D8FC04DC1B>.<76>"
), _NSURLErrorNWPathKey=satisfied (Path is satisfied), interface: pdp_ip0[lte], ipv4, ipv6, dns, expensive, estimated upload: 65536Bps, uses cell}
2、手机型号是iPhone 15 Plus,iOS 17.6.1
Topic:
App & System Services
SubTopic:
Networking
Hi,
I have a problem with my OpenVPN connection on my app with iOS 14.4.
I perform my VPN configuration from an oven file, with a NETunnelProviderManager protocol, but when I perform the startVPNTunnel, it starts connecting and immediately disconnects. The error I see in the logs is the following:
NESMVPNSession[Primary Tunnel:OpenVPN Client: -----(null)]: status changed to disconnected, last stop reason Plugin was disabled
This happens to me when running my app on a physical iPad.
Regards
import NetworkExtension
import OpenVPNAdapter
class VPNConnection {
var connectionStatus = "Disconnected"
var myProviderManager: NETunnelProviderManager?
func manageConnectionChanges( manager:NETunnelProviderManager ) - String {
NSLog("Waiting for changes");
var status = "Disconnected"
NotificationCenter.default.addObserver(forName: NSNotification.Name.NEVPNStatusDidChange, object: manager.connection, queue: OperationQueue.main, using: { notification in
let baseText = "VPN Status is "
switch manager.connection.status {
case .connected:
status = "Connected"
case .connecting:
status = "Connecting"
case .disconnected:
status = "Disconnected"
case .disconnecting:
status = "Disconnecting"
case .invalid:
status = "Invalid"
case .reasserting:
status = "Reasserting"
default:
status = "Connected"
}
self.connectionStatus = status
NSLog(baseText+status)
});
return status
}
func createProtocolConfiguration() - NETunnelProviderProtocol {
guard
let configurationFileURL = Bundle.main.url(forResource: "app-vpn", withExtension: "ovpn"),
let configurationFileContent = try? Data(contentsOf: configurationFileURL)
else {
fatalError()
}
let tunnelProtocol = NETunnelProviderProtocol()
tunnelProtocol.serverAddress = ""
tunnelProtocol.providerBundleIdentifier = "com.app.ios"
tunnelProtocol.providerConfiguration = ["ovpn": String(data: configurationFileContent, encoding: .utf8)! as Any]
tunnelProtocol.disconnectOnSleep = false
return tunnelProtocol
}
func startConnection(completion:@escaping () - Void){
self.myProviderManager?.loadFromPreferences(completionHandler: { (error) in
guard error == nil else {
// Handle an occurred error
return
}
do {
try self.myProviderManager?.connection.startVPNTunnel()
print("Tunnel started")
} catch {
fatalError()
}
})
}
func loadProviderManager(completion:@escaping () - Void) {
NETunnelProviderManager.loadAllFromPreferences { (managers, error) in
guard error == nil else {
fatalError()
return
}
self.myProviderManager = managers?.first ?? NETunnelProviderManager()
self.manageConnectionChanges(manager: self.myProviderManager!)
self.myProviderManager?.loadFromPreferences(completionHandler: { (error) in
guard error == nil else {
fatalError()
return
}
let tunnelProtocol = self.createProtocolConfiguration()
self.myProviderManager?.protocolConfiguration = tunnelProtocol
self.myProviderManager?.localizedDescription = "OpenVPN Client Ubic"
self.myProviderManager?.isEnabled = true
self.myProviderManager?.isOnDemandEnabled = false
self.myProviderManager?.saveToPreferences(completionHandler: { (error) in
if error != nil {
// Handle an occurred error
fatalError()
}
self.startConnection {
print("VPN loaded")
}
})
})
}
}
}
Hi!
I'm working on a solution (iOS 18) that uses Network Extensions PacketTunnelProvider and Content Filter. Currently I'm trying to integrate it with another extension – DNSProxyProvider. My goal is to process dns queries and use resolved ips and names for additional routing inside of the packet tunnel. I'm running into a major issue: whenever both VPN and DNS proxy are active simultaneously, the device completely loses internet connectivity — no traffic goes through, and DNS resolution seems to stop working entirely.
I know about the mdm supervision requirement to use DNSProxyProvider and that's covered as I work with a managed device and install a DNS proxy profile, here's how its .mobileconfig file looks like:
The DNS proxy itself works fine when working by itself (without VPN being turned on), as I implemented it that it successfully processes DNS packets flows while collecting information about domains etc, and everything works perfectly. Problems begin when using VPN at the same time. I'm aware that tunnel settings include dns related options that can affect this, but I haven't had much luck with tweaking them. Here's how they look right now for reference:
let settings: NEPacketTunnelNetworkSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "240.0.0.1")
// let dnsSettings = NEDNSSettings(servers: "8.8.8.8,8.8.4.4".components(separatedBy: ","))
// dnsSettings.matchDomains = [""]
// settings.dnsSettings = dnsSettings
settings.proxySettings = nil
/* ipv4 settings */
let ipv4Settings = NEIPv4Settings(addresses: ["240.0.0.2"], subnetMasks: ["255.255.255.0"])
ipv4Settings.includedRoutes = [NEIPv4Route.default()]
settings.ipv4Settings = ipv4Settings
/* MTU */
settings.mtu = 1500
return settings
I've tried excluding some dns related ip routes and dns settings shenanigans but nothing.
I haven't found any information that might suggest that using both of these extensions at the same time doesn't work, on the contrary, this page in the official documentation about the expected use of packet tunnel provider the expected use of packet tunnel provider, as it talks about the fact that you should not use it for interception of all of DNS traffic, as the use of DNSPRoxyProvider (or dns settings) are built for that, which in my mind, suggests that there should be no problem with using them both and just splitting the dns traffic handling to the proxy.
Will be thankful for any help!
Starting in iOS 26, two notable changes have been made to CallKit, LiveCommunicationKit, and the PushToTalk framework:
As a diagnostic aid, we're introducing new dialogs to warn apps of voip push related issue, for example when they fail to report a call or when when voip push delivery stops. The specific details of that behavior are still being determined and are likely to change over time, however, the critical point here is that these alerts are only intended to help developers debug and improve their app. Because of that, they're specifically tied to development and TestFlight signed builds, so the alert dialogs will not appear for customers running app store builds. The existing termination/crashes will still occur, but the new warning alerts will not appear.
As PushToTalk developers have previously been warned, the last unrestricted PushKit entitlement ("com.apple.developer.pushkit.unrestricted-voip.ptt") has been disabled in the iOS 26 SDK. ALL apps that link against the iOS 26 SDK which receive a voip push through PushKit and which fail to report a call to CallKit will be now be terminated by the system, as the API contract has long specified.
__
Kevin Elliott
DTS Engineer, CoreOS/Hardware
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.
I'm developing a Matter-over-thread generic switch with 2 generic switch endpoints. This is configured as an Intermittently Connected Device with Long Idle Time.
I have an Apple TV serving as the thread border router.
I'm able to commission the device successfully in the Home app and assign actions to each of the buttons however when the device is rebooted the subscription doesn't appear to resume successfully and the buttons no longer work.
I've tested this on various SOC's with their respective SDKs including ESP32-C6, nrf52840 and EFR32MG24 and the behaviour was consistent across all of them.
It was working originally when I first started out on the ESP32-C6, then the issue popped up first when I was testing the nrf52840. In that SDK I set persistent subscriptions explicitly and it seemed to resolve the issue until it popped up again when I found that unplugging and restarting the Apple TV completely which appeared to fix the issue with subscriptions not resuming.
Recently I've added a Home Pod Mini Gen 2 to the matter fabric so there are now two TBR on the network and restarting both the Apple TV and the HomePod doesn't appear to resolve the issue anymore and the subscriptions are not resuming across all three SOC's on device reboot
I'm wondering if there might be something preventing the subscriptions from resuming?
Most apps perform ordinary network operations, like fetching an HTTP resource with URLSession and opening a TCP connection to a mail server with Network framework. These operations are not without their challenges, but they’re the well-trodden path.
If your app performs ordinary networking, see TN3151 Choosing the right networking API for recommendations as to where to start.
Some apps have extra-ordinary networking requirements. For example, apps that:
Help the user configure a Wi-Fi accessory
Require a connection to run over a specific interface
Listen for incoming connections
Building such an app is tricky because:
Networking is hard in general.
Apple devices support very dynamic networking, and your app has to work well in whatever environment it’s running in.
Documentation for the APIs you need is tucked away in man pages and doc comments.
In many cases you have to assemble these APIs in creative ways.
If you’re developing an app with extra-ordinary networking requirements, this post is for you.
Note If you have questions or comments about any of the topics discussed here, put them in a new thread here on DevForums. Make sure I see it by putting it in the App & System Services > Networking area. And feel free to add tags appropriate to the specific technology you’re using, like Foundation, CFNetwork, Network, or Network Extension.
Links, Links, and More Links
Each topic is covered in a separate post:
The iOS Wi-Fi Lifecycle describes how iOS joins and leaves Wi-Fi networks. Understanding this is especially important if you’re building an app that works with a Wi-Fi accessory.
Network Interface Concepts explains how Apple platforms manage network interfaces. If you’ve got this far, you definitely want to read this.
Network Interface Techniques offers a high-level overview of some of the more common techniques you need when working with network interfaces.
Network Interface APIs describes APIs and core techniques for working with network interfaces. It’s referenced by many other posts.
Running an HTTP Request over WWAN explains why most apps should not force an HTTP request to run over WWAN, what they should do instead, and what to do if you really need that behaviour.
If you’re building an iOS app with an embedded network server, see Showing Connection Information in an iOS Server for details on how to get the information to show to your user so they can connect to your server.
Many folks run into trouble when they try to find the device’s IP address, or other seemingly simple things, like the name of the Wi-Fi interface. Don’t Try to Get the Device’s IP Address explains why these problems are hard, and offers alternative approaches that function correctly in all network environments.
Similarly, folks also run into trouble when trying to get the host name. On Host Names explains why that’s more complex than you might think.
If you’re working with broadcasts or multicasts, see Broadcasts and Multicasts, Hints and Tips.
If you’re building an app that works with a Wi-Fi accessory, see Working with a Wi-Fi Accessory.
If you’re trying to gather network interface statistics, see Network Interface Statistics.
There are also some posts that are not part of this series but likely to be of interest if you’re working in this space:
TN3179 Understanding local network privacy discusses the local network privacy feature.
Calling BSD Sockets from Swift does what it says on the tin, that is, explains how to call BSD Sockets from Swift. When doing weird things with the network, you often find yourself having to use BSD Sockets, and that API is not easy to call from Swift. The code therein is primarily for the benefit of test projects, oh, and DevForums posts like these.
TN3111 iOS Wi-Fi API overview is a critical resource if you’re doing Wi-Fi specific stuff on iOS.
TLS For Accessory Developers tackles the tricky topic of how to communicate securely with a network-based accessory.
A Peek Behind the NECP Curtain discusses NECP, a subsystem that control which programs have access to which network interfaces.
Networking Resources has links to many other useful resources.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Revision History
2025-07-31 Added a link to A Peek Behind the NECP Curtain.
2025-03-28 Added a link to On Host Names.
2025-01-16 Added a link to Broadcasts and Multicasts, Hints and Tips. Updated the local network privacy link to point to TN3179. Made other minor editorial changes.
2024-04-30 Added a link to Network Interface Statistics.
2023-09-14 Added a link to TLS For Accessory Developers.
2023-07-23 First posted.
Hello,
Our app uses Network Extension / Packet Tunnel Provider to establish VPN connections on macOS and iOS.
We have observed that after creating a utun device and adding any IPv4 routes (NEPacketTunnelNetworkSettings.IPv4Settings), the OS automatically adds several host routes via utun to services such as Akamai, Apple Push, etc. These routes appear to correspond to TCP flows that were active at the moment the VPN connection was established. When a particular TCP flow ends, the corresponding host route is deleted. We understand this is likely intended to avoid breaking existing TCP connections.
However, we find the behavior of migrating existing TCP flows to the new utun interface simply because any IPv4 route is added somewhat questionable. This approach would make sense in a "full-tunnel" scenario — for example, when all IPv4 traffic (e.g., 0.0.0.0/0) is routed through the tunnel — but not necessarily in a "split-tunnel" configuration where only specific IPv4 routes are added.
Is there any way to control or influence this behavior?
Would it be possible for FlowDivert to differentiate between full-tunnel and split-tunnel cases, and only preserve existing TCP flows via utun in the full-tunnel scenario?
Thank you.
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.
Revision History
2025-12-10 Added info about SIOCGIFDIRECTLINK.
2023-07-19 First posted.
I had noticed that my slaac address changed between one beta and the other, but wasn't sure. Now with the RC 15.4 RC (24E247) I made point of preserving the info before updating from the previous beta.
What I noticed is that not only the slaac address changes, but also the my ether address, even though I have it on Fixed in the settings.
Is it expected that the ether, and the slaac, not be rotated after a OS update?
Topic:
App & System Services
SubTopic:
Networking
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"
Don’t Try to Get the Device’s IP Address
I regularly see questions like:
How do I find the IP address of the device?
How do I find the IP address of the Wi-Fi interface?
How do I identify the Wi-Fi interface?
I also see a lot of really bad answers to these questions. That’s understandable, because the questions themselves don’t make sense. Networking on Apple platforms is complicated and many of the things that are ‘obviously’ true are, in fact, not true at all. For example:
There’s no single IP address that represents the device, or an interface. A device can have 0 or more interfaces, each of which can have 0 or more IP addresses, each of which can be IPv4 and IPv6.
A device can have multiple interfaces of a given type. It’s common for iPhones to have multiple WWAN interfaces, for example.
It’s not possible to give a simple answer to any of these questions, because the correct answer depends on the context. Why do you need this particular information? What are you planning to do with it?
This post describes the scenarios I most commonly encounter, with my advice on how to handle each scenario.
IMPORTANT BSD interface names, like en0, are not considered API. There’s no guarantee, for example, that an iPhone’s Wi-Fi interface is en0. If you write code that relies on a hard-coded interface name, it will fail in some situations.
Service Discovery
Some folks want to identify the Wi-Fi interface so that they can run a custom service discovery protocol over it. Before you do that, I strongly recommend that you look at Bonjour. This has a bunch of advantages:
It’s an industry standard [1].
It’s going to be more efficient on the ‘wire’.
You don’t have to implement it yourself, you can just call an API [2].
For information about the APIs available, see TN3151 Choosing the right networking API.
If you must implement your own service discovery protocol, don’t think in terms of finding the Wi-Fi interface. Rather, write your code to work with all Wi-Fi interfaces, or perhaps even all Ethernet-like interfaces. That’s what Apple’s Bonjour implementation does, and it means that things will work in odd situations [3].
To find all Wi-Fi interfaces, get the interface list and filter it for ones with the Wi-Fi functional type. To find all broadcast-capable interfaces, get the interface list and filter it for interfaces with the IFF_BROADCAST flag set. If the service you’re trying to discover only supports IPv4, filter out any IPv6-only interfaces.
For advice on how to do this, see Interface List and Network Interface Type in Network Interface APIs.
When working with multiple interfaces, it’s generally a good idea to create a socket per interface and then bind that socket to the interface. That ensures that, when you send a packet, it’ll definitely go out the interface you expect.
For more information on how to implement broadcasts correctly, see Broadcasts and Multicasts, Hints and Tips.
[1] Bonjour is an Apple term for:
RFC 3927 Dynamic Configuration of IPv4 Link-Local Addresses
RFC 6762 Multicast DNS
RFC 6763 DNS-Based Service Discovery
[2] That’s true even on non-Apple platforms. It’s even true on most embedded platforms. If you’re talking to a Wi-Fi accessory, see Working with a Wi-Fi Accessory.
[3] Even if the service you’re trying to discover can only be found on Wi-Fi, it’s possible for a user to have their iPhone on an Ethernet that’s bridged to a Wi-Fi. Why on earth would they do that? Well, security, of course. Some organisations forbid their staff from using Wi-Fi.
Logging and Diagnostics
Some folks want to log the IP address of the Wi-Fi interface, or the WWAN, or both for diagnostic purposes. This is quite feasible, with the only caveat being there may be multiple interfaces of each type.
To find all interfaces of a particular type, get the interface list and filter it for interfaces with that functional type. See Interface List and Network Interface Type in Network Interface APIs.
Interface for an Outgoing Connection
There are situations where you need to get the interface used by a particular connection. A classic example of that is FTP. When you set up a transfer in FTP, you start with a control connection to the FTP server. You then open a listener and send its IP address and port to the FTP server over your control connection. What IP address should you use?
There’s an easy answer here: Use the local IP address for the control connection. That’s the one that the server is most likely to be able to connect to.
To get the local address of a connection:
In Network framework, first get the currentPath property and then get its localEndpoint property.
In BSD Sockets, use getsockname. See its man page for details.
Now, this isn’t a particularly realistic example. Most folks don’t use FTP these days [1] but, even if they do, they use FTP passive mode, which avoids the need for this technique. However, this sort of thing still does come up in practice. I recently encountered two different variants of the same problem:
One developer was implementing VoIP software and needed to pass the devices IP address to their VoIP stack. The best IP address to use was the local IP address of their control connection to the VoIP server.
A different developer was upgrading the firmware of an accessory. They do this by starting a server within their app and sending a command to the accessory to download the firmware from that server. Again, the best IP address to use is the local address of the control connection.
[1] See the discussion in TN3151 Choosing the right networking API.
Listening for Connections
If you’re listening for incoming network connections, you don’t need to bind to a specific address. Rather, listen on all local addresses. In Network framework, this is the default for NWListener. In BSD Sockets, set the address to INADDR_ANY (IPv4) or in6addr_any (IPv6).
If you only want to listen on a specific interface, don’t try to bind to that interface’s IP address. If you do that, things will go wrong if the interface’s IP address changes. Rather, bind to the interface itself:
In Network framework, set either the requiredInterfaceType property or the requiredInterface property on the NWParameters you use to create your NWListener.
In BSD Sockets, set the IP_BOUND_IF (IPv4) or IPV6_BOUND_IF (IPv6) socket option.
How do you work out what interface to use? The standard technique is to get the interface list and filter it for interfaces with the desired functional type. See Interface List and Network Interface Type in Network Interface APIs. Remember that their may be multiple interfaces of a given type. If you’re using BSD Sockets, where you can only bind to a single interface, you’ll need to create multiple listeners, one for each interface.
Listener UI
Some apps have an embedded network server and they want to populate a UI with information on how to connect to that server. This is a surprisingly tricky task to do correctly. For the details, see Showing Connection Information for a Local Server.
Outgoing Connections
In some situations you might want to force an outgoing connection to run over a specific interface. There are four common cases here:
Set the local address of a connection [1].
Force a connection to run over a specific interface.
Force a connection to run over a type of interface.
Force a connection to run over an interface with specific characteristics. For example, you want to download some large resource without exhausting the user’s cellular data allowance.
The last case should be the most common — see the Constraints section of Network Interface Techniques — but all four are useful in specific circumstances.
The following sections explain how to tackle these tasks in the most common networking APIs.
[1] This implicitly forces the connection to use the interface with that address. For an explanation as to why, see the discussion of scoped routing in Network Interface Techniques.
Network Framework
Network framework has good support for all of these cases. Set one or more of the following properties on the NWParameters object you use to create your NWConnection:
requiredLocalEndpoint property
requiredInterface property
prohibitedInterfaces property
requiredInterfaceType property
prohibitedInterfaceTypes property
prohibitConstrainedPaths property
prohibitExpensivePaths property
Foundation URL Loading System
URLSession has fewer options than Network framework but they work in a similar way: Set one or more of the following properties on the URLSessionConfiguration object you use to create your session:
allowsCellularAccess property
allowsConstrainedNetworkAccess property
allowsExpensiveNetworkAccess property
Note While these session configuration properties are also available on URLRequest, it’s better to configure this on the session.
There’s no option that forces a connection to run over a specific interface. In most cases you don’t need this — it’s better to use the allowsConstrainedNetworkAccess and allowsExpensiveNetworkAccess properties — but there are some situations where that’s necessary. For advice on this front, see Running an HTTP Request over WWAN.
BSD Sockets
BSD Sockets has very few options in this space. One thing that’s easy and obvious is setting the local address of a connection: Do that by passing the address to bind.
Alternatively, to force a connection to run over a specific interface, set the IP_BOUND_IF (IPv4) or IPV6_BOUND_IF (IPv6) socket options.
Revision History
2025-01-21 Added a link to Broadcasts and Multicasts, Hints and Tips. Made other minor editorial changes.
2023-07-18 First posted.
Apology for repost. I needed to fix the tags for original thread.
https://developer.apple.com/forums/thread/777159
On iOS 18.3, I noted that partition "HTTPCookiePropertyKey: StoragePartition" is not observed to be set for cookies returned from the wkwebview cookie store.
Now on 18.4 beta 4 we are now seeing those same cookies are populated with a partition property. Is there documentation for this change? Is it intended to be suddenly populated in 18.4?
Now that partition property is set, HTTPCookieStorage.shared.cookies(for: serverUri) doesn't seem to return the expected cookies correctly. For context, we are using the cookies extracted from wkwebview, setting them in HTTPCookieStorage.shared and using URLSession to make network calls outside the webivew. Works fine once I forcefully set partition on the cookie to nil.
More details on what the cookie looks like here: https://feedbackassistant.apple.com/feedback/16906526
Hopefully this is on your radar?
After dropping an A-record TTL to 60 secs (it was previously no higher than 600 secs for several weeks) and making an IP change for a small business website on Monday, I took down the old web service just over 24 hours later on Tuesday evening. We then had reports of some customers not being able to access the website on Wednesday morning. On investigation using my iPhone it would appear that Apple Private Relay is still directing clients to the old IP address.
It's just as well I have iCloud+ as I would never have seen this issue otherwise and would have been none the wiser as to why some customers were having problems.
Has anyone else seen this and/or have a fix other than waiting longer? Do you know how long it takes for Apple Private Relay to update? This isn't expected behaviour of DNS?
I spoke to someone at Apple yesterday and there wasn't much they can do. I hope they're escalating internally as almost 3 days later it's still pointing users to the old IP address despite having ample time for proper DNS propagation.
Topic:
App & System Services
SubTopic:
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.