Page MenuHomeVyOS Platform

dhcp-server does not allow valid bootfile-names
Closed, ResolvedPublicBUG

Description

Description

Clients expecting Option 67 / bootfile-name in DHCP can anticipate either a URL including the protocol, IP address or FQDN, port, and path to a file (ex: http://192.0.2.1:8080/path/to/bootfile.py), a file path (ex: /path/to/bootfile.py), or a simple filename (ex: bootfile.py, sometimes paired with Option 66 / tftp-server-name).

Currently, the dhcp-server configuration mode interface in VyOS only accepts values matching the pattern [-_a-zA-Z0-9./]+. This limitation notably rejects values with a : character, effectively disallowing URLs that specify schema or port numbers. This issue hinders the use of VyOS's DHCP server for tasks like zero-touch provisioning of network devices, which rely on Option 67 to fetch their boot instructions.

ISC DHCP's definition:

option bootfile-name text; This option is used to identify a bootstrap file. If supported by the client, it should have the same effect as the filename declaration. BOOTP clients are unlikely to support this option. Some DHCP clients will support it, and others actually require it.

ISC DHCP's manual mentions that in this context, text is any valid ASCII string:

The text data type specifies an NVT ASCII string, which must be enclosed in double quotes - for example, to specify a root-path option, the syntax would be

option root-path "10.0.1.4:/var/tmp/rootfs";

And is additionally corroborated by the following references in ISC DHCP's source:

The current issue seems to have originated from T782, as indicated in this commit.

Impact

This bug affects DHCP server configurations where a bootfile-name needs to be specified, particularly when the name is a full URL or includes a : character. In its current state, the system may reject valid configurations, causing booting issues for clients that rely on these settings. This limitation particularly hampers the usage of VyOS's DHCP server for functions like zero-touch provisioning of network devices, where clients expect Option 67 to fetch their boot instructions.

The significance of maintaining the functionality of these DHCP options is highlighted in another issue (T1129), where a user stresses the importance of these options for provisioning phones and other network devices.

This bug also prevents all service dhcp-server config with an "invalid" bootfile-name parameter present (from configs prior to the regex being implement) from being migrated during VyOS upgrade.

Workaround limitations

The possible workaround of using subnet-parameters is also blocked due to a constraint on the usage of the double quote (") character in the value string:

eric@vyos# set service dhcp-server shared-network-name TESTNET subnet 203.0.113.0/24 subnet-parameters 'option bootfile-name "http://example.com/path/to/file.py";' 

  Cannot use the double quote (") character in a value string
  Value validation failed
  Set failed

Proposed solution

Change the constraint regex pattern to: [-_a-zA-Z0-9.:/~#@!$&*+,;=~%\\\\]+

This adjustment expands the existing pattern to accommodate full URLs, file paths, and bare filenames. It also adds a subset of RFC 3886 "reserved" characters (gen-delims and sub-delims), excluding [] ' () , due to their rarity and negative interactions with the command line. Additionally, it adds simple handling of "% encoding".

Finally, the double-escaped \ enables support for Windows paths like those used for Windows Deployment Services (ex: boot\x64\wdsnbp.com). These land in dhcpd.conf as boot\\x64\\wdsnbp.com, which passes dhcpd -t. An explanation of string handling in ISC DHCP's documentation suggests that this is the correct format. See also: PXE Boot from WDS using ISC DHCPd (r/networking).

Test commands

The following commands test the proposed pattern against input validation and against dhcpd -t upon commit:

configure

cp /opt/vyatta/share/vyatta-cfg/templates/service/dhcp-server/shared-network-name/node.tag/subnet/node.tag/bootfile-name/node.def /tmp/bootfile-name-node.def.bak

# manually edit the regex in node.def to [-_a-zA-Z0-9./:?#@!$&*+,;=~%\\\\]+
sudo vi /opt/vyatta/share/vyatta-cfg/templates/service/dhcp-server/shared-network-name/node.tag/subnet/node.tag/bootfile-name/node.def

sudo systemctl restart vyos-configd

set service dhcp-server shared-network-name TESTNET subnet 203.0.113.0/24 range 0 start 203.0.113.2
set service dhcp-server shared-network-name TESTNET subnet 203.0.113.0/24 range 0 stop 203.0.113.254

set service dhcp-server shared-network-name TESTNET subnet 203.0.113.0/24 bootfile-name "http://example.com/path/to/file.py"
commit
grep "shared-network TESTNET" -A9 /run/dhcp-server/dhcpd.conf

set service dhcp-server shared-network-name TESTNET subnet 203.0.113.0/24 bootfile-name "https://192.0.2.1/path/to/file.py"
commit
grep "shared-network TESTNET" -A9 /run/dhcp-server/dhcpd.conf

set service dhcp-server shared-network-name TESTNET subnet 203.0.113.0/24 bootfile-name "/pxelinux.0"
commit
grep "shared-network TESTNET" -A9 /run/dhcp-server/dhcpd.conf

set service dhcp-server shared-network-name TESTNET subnet 203.0.113.0/24 bootfile-name "boot\x64\wdsnbp.com"
commit
grep "shared-network TESTNET" -A9 /run/dhcp-server/dhcpd.conf

delete service dhcp-server shared-network-name TESTNET
commit

sudo mv /tmp/bootfile-name-node.def.bak /opt/vyatta/share/vyatta-cfg/templates/service/dhcp-server/shared-network-name/node.tag/subnet/node.tag/bootfile-name/node.def
sudo systemctl restart vyos-configd

exit

Details

Difficulty level
Easy (less than an hour)
Version
1.4-rolling-202307280757
Why the issue appeared?
Will be filled on close
Is it a breaking change?
Stricter validation
Issue type
Bug (incorrect behavior)

Event Timeline

I have submitted PR 2118 for this issue.

I added this comment to PR 2118:

As long as VyOS supports that then this <regex>[[:ascii:]]{0,256}</regex> a better option since the source code of ISC DHCP defines that option as type "t" meaning just that:

https://github.com/isc-projects/dhcp/blob/master/common/tables.c#L165

{ "bootfile-name", "t",			&dhcp_universe,  67, 1 },
/* DHCP Option names, formats and codes, from RFC1533.
   Format codes:
...
   t - ASCII text

RFC1533 has been superseeded by RFC2132 according to IANA:

https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml

https://www.rfc-editor.org/rfc/rfc2132.html

And in RFC2132:

9.5 Bootfile name

   This option is used to identify a bootfile when the 'file' field in
   the DHCP header has been used for DHCP options.

   The code for this option is 67, and its minimum length is 1.

       Code  Len   Bootfile name
      +-----+-----+-----+-----+-----+---
      | 67  |  n  |  c1 |  c2 |  c3 | ...
      +-----+-----+-----+-----+-----+---

Since the above says that length must be at least 1 shouldnt the regex in question be this instead?

<regex>[[:ascii:]]{1,256}</regex>

Just to sync this task to PR 2118:

Current suggestion is to change to this regex:

<regex>[[:ascii:]]{1,253}</regex>

which would fulfill the demand of minimum length of 1 but also be able to fit whatever control bytes that are needed (256 bytes minus control bytes).

Isnt this resolved now by the commit of @c-po at 2 aug?

dmbaturin claimed this task.
dmbaturin added a subscriber: dmbaturin.

@Apachez I suppose it is.