luci-mod-network: split PXE into dnsmasq/odhcpd functions in dhcp.js
authorDavid Härdeman <[email protected]>
Tue, 21 Oct 2025 21:53:29 +0000 (23:53 +0200)
committerPaul Donald <[email protected]>
Fri, 24 Oct 2025 13:57:43 +0000 (15:57 +0200)
This makes it clearer which daemon each part belongs to. But more
importantly, it lays the ground for the next patch.

Signed-off-by: David Härdeman <[email protected]>
modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js

index 0e625a442d4e93ea65de73b3a99b9dbcc8cf4200..30070522bc8d473d831d920073a20813a85ac993 100644 (file)
@@ -242,140 +242,6 @@ return view.extend({
 
                this.add_leases_cfg(s, hosts, duids, pools, macdata);
 
-               s.tab('pxe_tftp', _('PXE/TFTP'));
-
-               // Begin pxe_tftp
-               o = s.taboption('pxe_tftp', form.Flag, 'enable_tftp',
-                       _('Enable TFTP server'),
-                       _('Enable the built-in single-instance TFTP server.'));
-               o.optional = true;
-
-               o = s.taboption('pxe_tftp', form.Value, 'tftp_root',
-                       _('TFTP server root'),
-                       _('Root directory for files served via TFTP. <em>Enable TFTP server</em> and <em>TFTP server root</em> turn on the TFTP server and serve files from <em>TFTP server root</em>.'));
-               o.depends('enable_tftp', '1');
-               o.optional = true;
-               o.placeholder = '/';
-
-               o = s.taboption('pxe_tftp', form.Value, 'dhcp_boot',
-                       _('Network boot image'),
-                       _('Filename of the boot image advertised to clients.'));
-               o.depends('enable_tftp', '1');
-               o.optional = true;
-               o.placeholder = 'pxelinux.0';
-
-               /* PXE - https://openwrt.org/docs/guide-user/base-system/dhcp#booting_options */
-               o = s.taboption('pxe_tftp', form.SectionValue, '__pxe__', form.GridSection, 'boot', null,
-                       _('Special <abbr title="Preboot eXecution Environment">PXE</abbr> boot options for Dnsmasq.'));
-               ss = o.subsection;
-               ss.addremove = true;
-               ss.anonymous = true;
-               ss.modaltitle = _('Edit PXE/TFTP/BOOTP Host');
-               ss.nodescriptions = true;
-
-               so = ss.option(form.Value, 'filename',
-                       _('Filename'),
-                       _('Host requests this filename from the boot server.'));
-               so.optional = false;
-               so.placeholder = 'pxelinux.0';
-
-               so = ss.option(form.Value, 'servername',
-                       _('Server name'),
-                       _('The hostname of the boot server'));
-               so.optional = false;
-               so.placeholder = 'myNAS';
-
-               so = ss.option(form.Value, 'serveraddress',
-                       _('Server address'),
-                       _('The IP address of the boot server'));
-               so.optional = false;
-               so.placeholder = '192.168.1.2';
-
-               so = ss.option(form.DynamicList, 'dhcp_option',
-                       _('DHCP Options'),
-                       _('Additional options to send to the below match tags.') + '<br />' +
-                       _('%s means "the address of the system running dnsmasq".').format('<code>0.0.0.0</code>'));
-               so.optional = true;
-               so.placeholder = 'option:root-path,192.168.1.2:/data/netboot/root';
-
-               so = ss.option(form.Value, 'networkid',
-                       _('Match this Tag'),
-                       _('Only DHCP Clients with this tag are sent this boot option.'));
-               so.optional = true;
-               so.noaliases = true;
-
-               so = ss.option(form.Flag, 'force',
-                       _('Force'),
-                       _('Always send the chosen DHCP options. Sometimes needed, with e.g. PXELinux.'));
-               so.optional = true;
-
-               so = ss.option(form.Value, 'instance',
-                       _('Instance'),
-                       _('Dnsmasq instance to which this boot section is bound. If unspecified, the section is valid for all dnsmasq instances.'));
-               so.optional = true;
-
-               Object.values(L.uci.sections('dhcp', 'dnsmasq')).forEach(function(val, index) {
-                       var [name, display_str] = generateDnsmasqInstanceEntry(val);
-                       so.value(name, display_str);
-               });
-
-               o = s.taboption('pxe_tftp', form.SectionValue, '__pxe6__', form.TableSection, 'boot6', null,
-                       _('Special <abbr title="Preboot eXecution Environment">PXE</abbr> boot options for odhcpd IPv6.') + ' ' +
-                       _('The last entry absent architecture becomes the default.'));
-               ss = o.subsection;
-               ss.addremove = true;
-               ss.anonymous = true;
-               ss.nodescriptions = true;
-               ss.sortable = true;
-
-               /* URL https://www.rfc-editor.org/rfc/rfc5970.html#section-3.1 i.e. https://www.rfc-editor.org/rfc/rfc3986 */
-               so = ss.option(form.Value, 'url', _('URL'));
-               so.optional = false;
-               so.datatype = 'string';
-               so.placeholder = 'tftp://[fd11::1]/pxe.efi';
-
-               // Arch https://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xhtml#processor-architecture
-               so = ss.option(form.Value, 'arch', _('Architecture'));
-               so.optional = true;
-               so.rmempty = true;
-               so.datatype = 'range(0,65535)';
-               so.default = '';
-               so.value('');
-               so.value('0', _('00: x86 BIOS'));
-               so.value('6', _('06: x86 UEFI (IA32)'));
-               so.value('7', _('07: x64 UEFI'));
-               so.value('10', _('10: ARM 32-bit UEFI'));
-               so.value('11', _('11: ARM 64-bit UEFI'));
-               so.value('15', _('15: x86 UEFI boot from HTTP'));
-               so.value('16', _('16: x64 UEFI boot from HTTP'));
-               so.value('17', _('17: ebc boot from HTTP'));
-               so.value('18', _('18: ARM UEFI 32 boot from HTTP'));
-               so.value('19', _('19: ARM UEFI 64 boot from HTTP'));
-               so.value('20', _('20: pc/at bios boot from HTTP'));
-               so.value('21', _('21: ARM 32 uboot'));
-               so.value('22', _('22: ARM 64 uboot'));
-               so.value('23', _('23: ARM uboot 32 boot from HTTP'));
-               so.value('24', _('24: ARM uboot 64 boot from HTTP'));
-               so.value('25', _('25: RISC-V 32-bit UEFI'));
-               so.value('26', _('26: RISC-V 32-bit UEFI boot from HTTP'));
-               so.value('27', _('27: RISC-V 64-bit UEFI'));
-               so.value('28', _('28: RISC-V 64-bit UEFI boot from HTTP'));
-               so.value('29', _('29: RISC-V 128-bit UEFI'));
-               so.value('30', _('30: RISC-V 128-bit UEFI boot from HTTP'));
-               so.value('31', _('31: s390 Basic'));
-               so.value('32', _('32: s390 Extended'));
-               so.value('33', _('33: MIPS 32-bit UEFI'));
-               so.value('34', _('34: MIPS 64-bit UEFI'));
-               so.value('35', _('35: Sunway 32-bit UEFI'));
-               so.value('36', _('36: Sunway 64-bit UEFI'));
-               so.value('37', _('37: LoongArch 32-bit UEFI'));
-               so.value('38', _('38: LoongArch 32-bit UEFI boot from HTTP'));
-               so.value('39', _('39: LoongArch 64-bit UEFI'));
-               so.value('39', _('40: LoongArch 64-bit UEFI boot from HTTP'));
-               so.value('41', _('41: ARM rpiboot'));
-               // End pxe_tftp
-
-
                return m.render().then(function(mapEl) {
                        poll.add(function() {
                                return callDHCPLeases().then(function(leaseinfo) {
@@ -662,6 +528,83 @@ return view.extend({
                so.placeholder = 'lan';
                // End relay
 
+               // Begin pxe_tftp
+               s.tab('pxe_tftp', _('PXE/TFTP'));
+               o = s.taboption('pxe_tftp', form.Flag, 'enable_tftp',
+                       _('Enable TFTP server'),
+                       _('Enable the built-in single-instance TFTP server.'));
+               o.optional = true;
+
+               o = s.taboption('pxe_tftp', form.Value, 'tftp_root',
+                       _('TFTP server root'),
+                       _('Root directory for files served via TFTP. <em>Enable TFTP server</em> and <em>TFTP server root</em> turn on the TFTP server and serve files from <em>TFTP server root</em>.'));
+               o.depends('enable_tftp', '1');
+               o.optional = true;
+               o.placeholder = '/';
+
+               o = s.taboption('pxe_tftp', form.Value, 'dhcp_boot',
+                       _('Network boot image'),
+                       _('Filename of the boot image advertised to clients.'));
+               o.depends('enable_tftp', '1');
+               o.optional = true;
+               o.placeholder = 'pxelinux.0';
+
+               // PXE - https://openwrt.org/docs/guide-user/base-system/dhcp#booting_options
+               o = s.taboption('pxe_tftp', form.SectionValue, '__pxe__', form.GridSection, 'boot', null,
+                       _('Special <abbr title="Preboot eXecution Environment">PXE</abbr> boot options for Dnsmasq.'));
+               ss = o.subsection;
+               ss.addremove = true;
+               ss.anonymous = true;
+               ss.modaltitle = _('Edit PXE/TFTP/BOOTP Host');
+               ss.nodescriptions = true;
+
+               so = ss.option(form.Value, 'filename',
+                       _('Filename'),
+                       _('Host requests this filename from the boot server.'));
+               so.optional = false;
+               so.placeholder = 'pxelinux.0';
+
+               so = ss.option(form.Value, 'servername',
+                       _('Server name'),
+                       _('The hostname of the boot server'));
+               so.optional = false;
+               so.placeholder = 'myNAS';
+
+               so = ss.option(form.Value, 'serveraddress',
+                       _('Server address'),
+                       _('The IP address of the boot server'));
+               so.optional = false;
+               so.placeholder = '192.168.1.2';
+
+               so = ss.option(form.DynamicList, 'dhcp_option',
+                       _('DHCP Options'),
+                       _('Additional options to send to the below match tags.') + '<br />' +
+                       _('%s means "the address of the system running dnsmasq".').format('<code>0.0.0.0</code>'));
+               so.optional = true;
+               so.placeholder = 'option:root-path,192.168.1.2:/data/netboot/root';
+
+               so = ss.option(form.Value, 'networkid',
+                       _('Match this Tag'),
+                       _('Only DHCP Clients with this tag are sent this boot option.'));
+               so.optional = true;
+               so.noaliases = true;
+
+               so = ss.option(form.Flag, 'force',
+                       _('Force'),
+                       _('Always send the chosen DHCP options. Sometimes needed, with e.g. PXELinux.'));
+               so.optional = true;
+
+               so = ss.option(form.Value, 'instance',
+                       _('Instance'),
+                       _('Dnsmasq instance to which this boot section is bound. If unspecified, the section is valid for all dnsmasq instances.'));
+               so.optional = true;
+
+               Object.values(L.uci.sections('dhcp', 'dnsmasq')).forEach(function(val, index) {
+                       var [name, display_str] = generateDnsmasqInstanceEntry(val);
+                       so.value(name, display_str);
+               });
+               // End pxe_tftp
+
                return s;
        },
 
@@ -707,6 +650,63 @@ return view.extend({
                so.value('5', 'Notice');
                so.value('6', 'Info');
                so.value('7', 'Debug');
+
+               // Begin pxe_tftp
+               o = s.taboption('pxe_tftp', form.SectionValue, '__pxe6__', form.TableSection, 'boot6', null,
+                       _('Special <abbr title="Preboot eXecution Environment">PXE</abbr> boot options for odhcpd IPv6.') + ' ' +
+                       _('The last entry absent architecture becomes the default.'));
+               ss = o.subsection;
+               ss.addremove = true;
+               ss.anonymous = true;
+               ss.nodescriptions = true;
+               ss.sortable = true;
+
+               // URL https://www.rfc-editor.org/rfc/rfc5970.html#section-3.1 i.e. https://www.rfc-editor.org/rfc/rfc3986
+               so = ss.option(form.Value, 'url', _('URL'));
+               so.optional = false;
+               so.datatype = 'string';
+               so.placeholder = 'tftp://[fd11::1]/pxe.efi';
+
+               // Arch https://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xhtml#processor-architecture
+               so = ss.option(form.Value, 'arch', _('Architecture'));
+               so.optional = true;
+               so.rmempty = true;
+               so.datatype = 'range(0,65535)';
+               so.default = '';
+               so.value('');
+               so.value('0', _('00: x86 BIOS'));
+               so.value('6', _('06: x86 UEFI (IA32)'));
+               so.value('7', _('07: x64 UEFI'));
+               so.value('10', _('10: ARM 32-bit UEFI'));
+               so.value('11', _('11: ARM 64-bit UEFI'));
+               so.value('15', _('15: x86 UEFI boot from HTTP'));
+               so.value('16', _('16: x64 UEFI boot from HTTP'));
+               so.value('17', _('17: ebc boot from HTTP'));
+               so.value('18', _('18: ARM UEFI 32 boot from HTTP'));
+               so.value('19', _('19: ARM UEFI 64 boot from HTTP'));
+               so.value('20', _('20: pc/at bios boot from HTTP'));
+               so.value('21', _('21: ARM 32 uboot'));
+               so.value('22', _('22: ARM 64 uboot'));
+               so.value('23', _('23: ARM uboot 32 boot from HTTP'));
+               so.value('24', _('24: ARM uboot 64 boot from HTTP'));
+               so.value('25', _('25: RISC-V 32-bit UEFI'));
+               so.value('26', _('26: RISC-V 32-bit UEFI boot from HTTP'));
+               so.value('27', _('27: RISC-V 64-bit UEFI'));
+               so.value('28', _('28: RISC-V 64-bit UEFI boot from HTTP'));
+               so.value('29', _('29: RISC-V 128-bit UEFI'));
+               so.value('30', _('30: RISC-V 128-bit UEFI boot from HTTP'));
+               so.value('31', _('31: s390 Basic'));
+               so.value('32', _('32: s390 Extended'));
+               so.value('33', _('33: MIPS 32-bit UEFI'));
+               so.value('34', _('34: MIPS 64-bit UEFI'));
+               so.value('35', _('35: Sunway 32-bit UEFI'));
+               so.value('36', _('36: Sunway 64-bit UEFI'));
+               so.value('37', _('37: LoongArch 32-bit UEFI'));
+               so.value('38', _('38: LoongArch 32-bit UEFI boot from HTTP'));
+               so.value('39', _('39: LoongArch 64-bit UEFI'));
+               so.value('39', _('40: LoongArch 64-bit UEFI boot from HTTP'));
+               so.value('41', _('41: ARM rpiboot'));
+               // End pxe_tftp
        },
 
        add_leases_cfg: function(s, hosts, duids, pools, macdata) {