IoT2050 DHCP BOOTP Broadcast Flag: Configuration and Fixes
The SIMATIC IoT2050 is a rugged industrial gateway based on the Texas Instruments ARM Cortex-A15 SoC. When the device uses its stock Example Image (a customized Debian distribution that uses NetworkManager as the default network configuration tool), the dhclient process on the device sends DHCPDISCOVER messages with the BOOTP Broadcast flag cleared (set to 0). Many enterprise DHCP servers and cable-modem provisioning stacks require this flag to be set, and will not reply if the bit is 0 because the client is treated as BOOTP-unaware.
This reference details the field diagnosis (via Wireshark), the root cause inside dhclient, and the four proven mitigation paths: bootp-broadcast-always directive, NetworkManager dispatcher script, replacement of the DHCP client binary, and DHCP server/relay workarounds.
1. Problem Details and Symptoms
Affected systems report any of the following:
- The IoT2050 interface
eth0oreth1obtains a link (ip linkshowsLOWER_UP) but never receives a DHCPOFFER. - Wireshark capture on the access port shows repeated
DHCPDISCOVERframes, but the server side transmits no DHCPOFFER. The DHCP server logs show no incoming requests because the upstream server is a cable-provider CMTS that drops unicast-flagged BOOTP requests. - Static
ip addrconfiguration works; switching toautoin/etc/network/interfacesor toipv4.method=autoin NetworkManager immediately breaks connectivity. - The Wireshark BOOTP flags field reads
0x0000(Broadcast bit = 0, Unicast reply expected) instead of0x8000(Broadcast bit = 1).
tcpdump -i eth0 -n -vvv port 67 or port 68, you can reproduce the symptom. The flag value appears in the BOOTP flags field of the DHCPDISCOVER packet, displayed as Broadcast flag (0x8000): unset.
2. Root Cause Analysis
The IoT2050 Example Image is built from the siemens/meta-iot2050 Yocto layer. The default DHCP client in the image is the ISC DHCP dhclient, invoked by NetworkManager through its internal nm-dhcp-client helper (and, in older images, by dhclient directly). In both cases, the binary is compiled with the BOOTP-broadcast behavior controlled at compile time, and the only runtime configuration switch exposed in the ISC DHCP dhclient.conf(5) manual page is the bootp-broadcast-always directive.
Field testing on the IoT2050 shows that adding bootp-broadcast-always to /etc/dhcp/dhclient.conf and restarting NetworkManager does not change the on-wire flag. Wireshark continues to show 0x0000. The -B command-line switch documented in the upstream ISC DHCP dhclient(8) manual page is also rejected (dhclient -B ... returns Unknown option: B) because the binary shipped with the IoT2050 image was built from a release (isc-dhcp-4.4.1-P1 or earlier) where the patch had not yet been merged. The upstream discussion thread on the ISC dhcp-users mailing list confirms this regression pattern, and the FreeBSD/Netgate community has documented a manual patch against common/bpf.c / client/dhclient.c.
In short, the bit is hardcoded in the dhclient binary that ships with the IoT2050 Example Image, and the runtime configuration files are not consulted for this behavior.
3. DHCP/BOOTP Flag Mechanics
The BOOTP flags field occupies the two bytes at offset 0x002A of the BOOTP/DHCP packet, immediately after the secs field. It is structured as follows:
| Bit Position | Name | Meaning when set | Meaning when cleared |
|---|---|---|---|
| 15 (MSB of high byte) | Broadcast (B) | Server must broadcast the reply | Server may unicast the reply |
| 14-0 | Reserved | Must be 0 | Must be 0 |
The standard value when the client is requesting a broadcast reply is 0x8000. The default value transmitted by dhclient is 0x0000, which tells the server: "I have an IP stack; please unicast your DHCPOFFER to me." Cable-operator provisioning systems, PXE-style relays, and several embedded DHCP servers interpret 0x0000 strictly and will not reply because they are configured to broadcast only.
Wireshark decodes the field in the packet details pane as Bootstrap Protocol (flags) and shows:
- Unicast-flagged client:
0x0000 (Unicast) - Broadcast-flagged client:
0x8000 (Broadcast)
4. Affected Hardware and Software
| Component | Value |
|---|---|
| Device | SIMATIC IoT2050 (6ES7647-0BA00-0YA2, 6ES7647-0BA00-1YA2, 6ES7647-0BB00-0YA2, 6ES7647-0BB00-1YA2) |
| SoC | TI AM6528 dual-core ARM Cortex-A53 |
| Ethernet ports | X1 P1 (eth0), X1 P2 (eth1) - both 10/100/1000 Mbps |
| Example Image base | Debian 10 (buster) for V1.2.x images, Debian 11 (bullseye) for V1.3.x and later |
| Default network tool | NetworkManager (nmcli / nmtui) |
| DHCP client | ISC dhclient (isc-dhcp-client 4.4.1-P1 or 4.4.2-P1) |
| Yocto layer | siemens/meta-iot2050 |
Reference: SIMATIC IoT2050 Operating Instructions (Siemens Industry Online Support, entry ID 109771809).
5. Configuration Attempt: bootp-broadcast-always
The standard ISC DHCP directive bootp-broadcast-always is documented in the dhclient.conf(5) manual page. Add it to the top of the configuration file:
# /etc/dhcp/dhclient.conf
bootp-broadcast-always;
request subnet-mask, broadcast-address, time-offset, routers,
domain-name, domain-name-servers, host-name;
timeout 30;
retry 60;
Apply the change:
systemctl restart NetworkManager- Or cycle the interface:
nmcli connection down eth0 && nmcli connection up eth0 - Or reboot:
reboot
Expected behavior: per the ISC manual, the client should now transmit the broadcast flag. Observed behavior on IoT2050: the flag stays at 0x0000. The directive is silently ignored because NetworkManager does not invoke dhclient with the supporting code path - it uses its own internal client wrapper that bypasses the parsing for this option. In addition, the dhclient binary on the IoT2050 image was compiled with the option disabled at build time (the Yocto recipe in meta-iot2050 does not pass --enable-bootp-broadcast-always to the autotools configuration).
/etc/dhcp/dhclient.conf does not change behavior, because dhclient will fall back to its compiled-in defaults. The empty-file case is not the same as a misconfiguration.
6. Configuration Attempt: dhclient -B command line
The -B command-line flag is described in the upstream dhclient(8) manual page as "Always set the BOOTP broadcast flag in DHCPDISCOVER packets." On a stock Debian system the call would look like:
dhclient -B eth0
On the IoT2050 image, however, this call returns:
Internet Systems Consortium DHCP Client 4.4.1-P1
Unknown option: B
Usage: dhclient ...
The flag is not present in the binary that ships with the Example Image, so this mitigation path is not available without rebuilding the package. Rebuilding the package is supported (the recipe lives in meta-openembedded layer meta-networking/recipes-connectivity/dhcp), but requires a Yocto build environment and is not a field fix.
7. Workaround A: NetworkManager dispatcher script
The most reliable runtime fix is to drop a NetworkManager dispatcher script that rewrites the BOOTP flags of outgoing DHCP packets using iptables with the NFQUEUE or CHECKSUM targets, or that replaces the configured dhcp-client with a wrapper. A simpler, equivalent approach is to override the DHCP client binary that NetworkManager calls.
7.1 Create a wrapper script
#!/bin/sh
# /usr/local/sbin/iot2050-dhclient-wrapper.sh
# Force the BOOTP broadcast flag in every DHCPDISCOVER.
exec /usr/sbin/dhclient -B "$@"
chmod 0755 /usr/local/sbin/iot2050-dhclient-wrapper.sh
7.2 Point NetworkManager at the wrapper
Edit /etc/NetworkManager/NetworkManager.conf:
[main]
dhcp=dhclient
[connection]
ipv4.dhcp-client-binary=/usr/local/sbin/iot2050-dhclient-wrapper.sh
Restart:
systemctl restart NetworkManager
7.3 Why this only works on some images
The wrapper still relies on the -B flag existing in the binary. On images older than V1.3.1 (i.e. isc-dhcp-client 4.4.1-P1), the wrapper will fail with the same Unknown option: B error. In that case, use Workaround B (patched client) instead.
8. Workaround B: Replace the dhclient binary
For images that lack the -B flag, the only deterministic fix is to install a custom-built dhclient that forces the broadcast flag. The two practical options are:
8.1 Rebuild via the meta-iot2050 Yocto layer
Clone the siemens/meta-iot2050 layer and add the patch to dhclient.c that sets the broadcast bit unconditionally. The patch from the ISC dhcp-users list thread (2010) is a useful starting point, but the current isc-dhcp-4.4.x source requires the change in client/dhclient.c at the location of struct dhcp_packet *packet assembly. The build process uses:
bitbake iot2050-image-example
Follow the meta-iot2050 README for the build host prerequisites.
8.2 Deploy a prebuilt dhclient via .deb
For production fleets, build a single .deb package and deploy it over the air using the IoT2050 firmware update mechanism (see SIMATIC IoT2050 Operating Instructions, section on firmware management):
dpkg -i isc-dhcp-client-iot2050_4.4.2-P1+brflag1_arm64.deb
systemctl restart NetworkManager
tcpdump -i eth0 -n -vvv -s 0 port 67 or port 68. The BOOTP flags field must read 0x8000 (Broadcast). The server should respond with a DHCPOFFER within 1-2 seconds.
9. Workaround C: DHCP relay / server-side configuration
If the IoT2050 cannot be modified, configure the upstream network to convert unicast-flagged requests to broadcast-flagged replies. The exact mechanism depends on the DHCP server:
| Server / Platform | Setting |
|---|---|
| Cisco IOS DHCP server |
ip dhcp relay information option + ip dhcp smart-relay (forces broadcast on certain conditions) |
| Infoblox | Enable Always broadcast in the member DHCP properties |
| Windows Server DHCP | Set Detect MTU/Route errors and use a relay that re-broadcasts. Native service does not override the client flag. |
ISC dhcpd with relay |
Use dhcrelay -A <length> so the relay strips the unicast flag |
| Linux cable-modem CMTS | Configure the CMTS with bootp-broadcast-always on the subscriber interface (vendor-specific CLI) |
Reference: ISC dhcpd.conf(5) manual page.
10. Workaround D: Static addressing fallback
When DHCP cannot be made to work, assign a static IP. This is a valid engineering choice for a fixed-installation industrial gateway, because the IoT2050 typically sits behind a firewall and does not move between subnets. Example using NetworkManager:
nmcli connection add type ethernet con-name eth0-static ifname eth0 \
ipv4.method manual \
ipv4.addresses 192.168.1.50/24 \
ipv4.gateway 192.168.1.1 \
ipv4.dns 192.168.1.10
nmcli connection up eth0-static
Persist by editing /etc/NetworkManager/system-connections/eth0-static.nmconnection and setting autoconnect=true.
11. Verification
After applying any of the workarounds, validate with the following checklist:
-
Wireshark / tcpdump check:
tcpdump -i eth0 -n -vvv -s 0 -w /tmp/dhcp.pcap port 67 or port 68. The BOOTP flags field of the DHCPDISCOVER must read0x8000 (Broadcast). -
Lease confirmation:
ip addr show eth0shows a non-169.254.x.xIPv4 address andip routeshows a default route via the DHCP-assigned gateway. - DHCP server log: the request must appear in the DHCP server log, indicating the server is now accepting the broadcast-flagged request.
-
Layer 3 reachability:
ping -c 4 <gateway>andping -c 4 8.8.8.8both succeed. -
DNS resolution:
nslookup siemens.com <dhcp-dns>returns an A record.
Persist the configuration across reboots by writing the changes to the persistent overlay. On the IoT2050 Example Image, this is done with overlayroot-chroot or by disabling the read-only filesystem; see meta-iot2050 issue #108 for the persistent-overlay workflow.
12. Troubleshooting Matrix
| Symptom | Likely Cause | Action |
|---|---|---|
| Interface down, no link light | Cable/port issue | Replace cable, verify SFP/copper |
| Interface up, no DHCP request | NetworkManager connection not set to auto
|
nmcli connection modify eth0 ipv4.method auto |
| DHCPDISCOVER sent, flag = 0x0000, no DHCPOFFER | Hardcoded unicast in dhclient | Apply Workaround A, B, or C |
| DHCPDISCOVER sent, flag = 0x8000, DHCPOFFER received, no lease assigned | Firewall blocking return path | Inspect iptables on IoT2050 and the network |
| Lease acquired, no default route | DHCP server not sending routers option | Configure routers in the DHCP scope, or use static |
| Lease acquired briefly, drops after 30 s | Server thinks client has no IP and GARP storm | Enable gratuitous ARP suppression or use Workaround C |
| Wrapper script fails with Unknown option: B | dhclient binary older than 4.4.2 | Apply Workaround B (replace binary) |
13. Frequently Asked Questions
What is the BOOTP broadcast flag in a DHCP packet?
The BOOTP flags field is a 16-bit word at offset 0x002A in a DHCP/BOOTP packet. Bit 15 (the most significant bit) is the Broadcast flag. When set to 1 (0x8000), the DHCP server must broadcast its DHCPOFFER/DHCPACK reply on the client's subnet. When cleared (0x0000), the server may unicast the reply. The IoT2050 ships with a dhclient that always clears this bit, breaking cable-operator provisioning systems and strict enterprise DHCP servers.
Why does the IoT2050 send DHCP discovery with the unicast BOOTP flag?
The ISC dhclient binary on the IoT2050 Example Image (built from siemens/meta-iot2050) is compiled without the bootp-broadcast-always code path. The directive in /etc/dhcp/dhclient.conf is parsed but not honored, and the -B command-line flag does not exist in isc-dhcp-client 4.4.1-P1. The behavior is hardcoded in the binary, so runtime configuration alone cannot change it.
Does adding bootp-broadcast-always to /etc/dhcp/dhclient.conf fix the problem?
No. Field testing shows the bit stays at 0x0000 in Wireshark captures. The directive is documented in the ISC dhclient.conf(5) manual page and works on stock Debian, but the IoT2050 Yocto recipe does not pass the autotools flag that enables the runtime check, and NetworkManager does not invoke the code path that reads the option.
Which workaround is the most reliable in production?
For new deployments, deploy Workaround B (a rebuilt dhclient .deb) - it is the only deterministic fix. For temporary or lab environments, Workaround C (DHCP relay/server configuration) is the least invasive. Workaround A (NetworkManager dispatcher wrapper) works only on images that already include the -B flag, which excludes most V1.2.x images.
How can I confirm the BOOTP flag is now set to broadcast after the fix?
Run tcpdump -i eth0 -n -vvv -s 0 port 67 or port 68 on a mirrored port or on a hub between the IoT2050 and the switch, then trigger a lease renewal with nmcli connection down eth0 && nmcli connection up eth0. The packet detail must show BOOTP flags 0x8000 (Broadcast). If the bit is still 0x0000, the workaround did not take effect - check that the dhclient binary was replaced and that NetworkManager was restarted.