IPV4 broadcast message No Route to Host

I am updating a universal app for release on iOS 17+ devices using Xcode15.2 and Solar2d v3708. The last release was 7 years ago.

The app connects to the local network and used a custom UDP protocol to connect to and control specific hardware devices. The protocol involves transmitting and receiving both broadcast and unicast messages to/from IPV4 capable proprietary devices on the local network.

When I run the app in the Solar2d simulator and when I run the current version installed from the App store on my iPad, communications work well.

When I build the same code into a new development build and transfer it to my iPad, I found that attempts to send broadcast messages are failing. When I print out the error returned from the socket interface to the console, I see the message is "No Route to Host".

I requested multicast capability from Apple and when it appeared on my development portal I updated the App Id to include the multicast entitlement. I updated the development profile to include our new 6th gen IPad and the updated AppID. I downloaded and installed the development profile. That new profile is what I am selecting / using to sign the app.

I am using lua socket library to send broadcast messages

I created a very basic project with just the basic networking code example and built this for my iPad the results are the same.

local socket = require("socket")

local main, errorMain = socket.udp6()
main:setoption('broadcast', true)		                 
local ack, mError = main:sendto("", "::FFFF:255.255.255.255", 3100)
print("My Debug Message: Main sending - " .. (ack or "nil") .. ", Error  : " .. (mError or "None"))

I also tried modifying my code to use udp4 as follows and the results were the same.


local socket = require("socket")

local main, errorMain = socket.udp4()
main:setoption('broadcast', true)		                 
local ack, mError = main:sendto("", "255.255.255.255", 3100)
print("My Debug Message: Main sending - " .. (ack or "nil") .. ", Error  : " .. (mError or "None"))

console output: My Debug Message: Main sending - nil, Error : No route to host

Any help or insight would be greatly appreciated.

Answered by AppCoder2012 in 794430022

I have come up with a workaround. I am not sure how helpful the following information will be to anyone else but I will provide some details in the off-chance that someone else runs into the same issue.

So it looks like lua socket does not provide a mechanism to allow you to identify or select specific network interfaces. Instead when a lua socket send method is called lua socket attempts to send the message over all available interfaces. In this specific case that no longer seems to work with an app built using XCode15 when targeting the IP address 255.255.255.255. Each interface is rejecting the send message to that address.

By modifying some code I discovered that using a specific subnet broadcast address like (IE: 192.168.1.255) will prevent the messages from being blocked. To calculate the subnet broadcast address, a valid IP address for the subnet( can use the iOS devices IP address) and the subnet mask are required. A simple google search for "How to calculate the broadcast address" should produce a tutorial on how to do that.

Unfortunately, the tool that I use (Solar2d) does not provide a way to get the IP address and subnet mask information. So I have added a menu for users to add this information in the app.

If I had more time to solve this issue, I would learn how to create / add a BSD sockets C library, or learn how to use Corona cards to embed my app into an Xcode Swift app. That would allow me to follow some of the code examples provided on the Apple support forums to address this specific issue.

In my experience there are two common causes of mysterious broadcast problems:

  • Local network privacy — See the Local Network Privacy FAQ.

  • Interface selection — When you broadcast you really have to select a target interface [1]. This is trickier than it sounds, and it’s something I discuss in detail in Extra-ordinary Networking > Don’t Try to Get the Device’s IP Address > Service Discovery.

It’s hard to say which of these is most likely here. While you have access to the multicast capability, your third-party tooling means it’s possible that the capability is not being enabled. So, I’m gonna recommend that you first check the entitlements claimed by your app.

You wrote:

When I build the same code into a new development build and transfer it to my iPad

Does that result in an app? Or a .ipa? If it’s the latter, rename it to a .zip and then unpack it to reveal the app.

Once you have the app, run this command to dump its entitlements:

% codesign -d --entitlements - /path/to/your.app

What do you see?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] If you don’t, the system selects one for you, and you have no control over that choice.

Thank you for the quick response.

In the build folder where the Corona Simulator dumps my app I see two files (A file with the appName and a appName.app.dSYM file). When I right click on the AppName file I can use show contents to open it like a folder. Inside there is a file called embedded.mobileprovision. I can open this via Visual Studio Code text editor even though it has binary content. Some of the content list entitlememts which look like XML

<key>Entitlements</key>
	<dict>
				
				<key>com.apple.developer.networking.multicast</key>
		<true/>
				
				<key>com.apple.developer.networking.wifi-info</key>
		<true/>
				
				<key>com.apple.developer.sustained-execution</key>
		<true/>
				
				<key>application-identifier</key>
		<string>(Removed For Privacy)</string>
				
				<key>keychain-access-groups</key>
		<array>
				<string>(Removed For Privacy)</string>
				<string>com.apple.token</string>
		</array>
				
				<key>get-task-allow</key>
		<true/>
				
				<key>com.apple.developer.team-identifier</key>
		<string>(Removed For Privacy)</string>
				
				<key>com.apple.developer.kernel.increased-memory-limit</key>
		<true/>
				
				<key>com.apple.developer.networking.networkextension</key>
		<array>
				<string>app-proxy-provider</string>
				<string>content-filter-provider</string>
				<string>packet-tunnel-provider</string>
				<string>dns-proxy</string>
				<string>dns-settings</string>
				<string>relay</string>
		</array>
				
				<key>com.apple.developer.coremedia.hls.low-latency</key>
		<true/>
				
				<key>com.apple.developer.user-fonts</key>
		<array>
				<string>app-usage</string>
				<string>system-installation</string>
		</array>
				
				<key>com.apple.developer.kernel.extended-virtual-addressing</key>
		<true/>

	</dict>

I am definitely not doing anything to select a specific interface. In Lua sockets. I am not sure how I would even do that through lua sockets.

I have read through your networking docs that you linked. Most of the information is regarding protocols that we do not use. From what I read / understood I believe we are taking the correct approach.

In general it seems that my app should not be trying to bind to any interfaces for sending broadcast messages, which it is not.

For the unconnected socket that we are sending from the luasocket documentation says:

unconnected:sendto(datagram, ip, port)

Sends a datagram to the specified IP address and port number.
...

If successful, the method returns 1. In case of error, the method returns nil followed by an error message.

Note: In UDP, the send method never blocks and the only way it can fail is if the underlying transport layer refuses to send a message to the specified address (i.e. no interface accepts the address).

That seems to imply that the lua socket attempts to send out the message to all interfaces. In this case none of the interfaces accepts the address.

The fact that the communication works with our latest release
on the same iPad and network that my new build is failing on, seems to indicate that the failure has something to do with the configuration.

I have a developer setting on my iPad for enabling develop mode. Are there any settings in that menu that could interfere with network communications?

I am not sure if this is relavent or not but I changed the broadcast IP to 192.168.1.255, this matches my local network broadcast address here where I work and the new build is comminicating now.

Now I have even more questions:

Does that rule out the multicast entitlement as being an issue?

Are IP addresses of "255.255.255.255" no longer supported by iOS?

I can calculate the broadcast address from the IP address and the subnet mask, is this information available in iOS?

It seems that would require me to know which interface to get that information from?

I changed the broadcast IP to 192.168.1.255 … and the new build is comminicating now.

Right. This suggests that interface selection is the issue. The 192.168.1.255 address is the broadcast address for the 192.168.1/24 network (assuming the typical 8 bit subnet mask). It’s likely that your device has just one interface for that network, and thus the system will send the datagram there.

In contrast, 255.255.255.255 is the this network broadcast address. Your device has lots of interfaces appropriate for that, and the one you get is non-deterministic. It’s likely that the, from your perspective, the device has chosen the wrong one.

The fix for this depends on the requirements of the accessory you’re talking to:

  • If the accessory accepts a network broadcast address, that’s fine.

  • If not, you’ll need to continue using the this network broadcast address.

Either way, you need to work with a specific interface. In the first case, you have to find the network address and prefix associated with interface so you can create the network broadcast address. In the second case, you have to bind your socket to that interface.

Which brings me back to my Extra-ordinary Networking post. The various subposts explains how to get the interface list, identify specific types of interfaces, and bind a socket to an interface.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Accepted Answer

I have come up with a workaround. I am not sure how helpful the following information will be to anyone else but I will provide some details in the off-chance that someone else runs into the same issue.

So it looks like lua socket does not provide a mechanism to allow you to identify or select specific network interfaces. Instead when a lua socket send method is called lua socket attempts to send the message over all available interfaces. In this specific case that no longer seems to work with an app built using XCode15 when targeting the IP address 255.255.255.255. Each interface is rejecting the send message to that address.

By modifying some code I discovered that using a specific subnet broadcast address like (IE: 192.168.1.255) will prevent the messages from being blocked. To calculate the subnet broadcast address, a valid IP address for the subnet( can use the iOS devices IP address) and the subnet mask are required. A simple google search for "How to calculate the broadcast address" should produce a tutorial on how to do that.

Unfortunately, the tool that I use (Solar2d) does not provide a way to get the IP address and subnet mask information. So I have added a menu for users to add this information in the app.

If I had more time to solve this issue, I would learn how to create / add a BSD sockets C library, or learn how to use Corona cards to embed my app into an Xcode Swift app. That would allow me to follow some of the code examples provided on the Apple support forums to address this specific issue.

IPV4 broadcast message No Route to Host
 
 
Q