dhcp: auto-populate IP range when selecting interface
- QuickModal: add postRender callback for DOM-level initialization - dhcp: derive start/end from interface CIDR on change
This commit is contained in:
@@ -243,6 +243,7 @@ export function QuickModal(props = {}) {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
formModal(inner, title, fields, actions);
|
formModal(inner, title, fields, actions);
|
||||||
|
if (props.postRender) props.postRender(inner, data);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { html, PageHeader, ConfirmDelete, Tabs, Table, ServiceStatus, renderGuardMulti, esc, enc, $val, apiFetch, toast, definePage, getModel, ActionButton, ActionGroup, QuickModal } from '/static/hoover/index.js?v=7';
|
import { html, PageHeader, ConfirmDelete, Tabs, Table, ServiceStatus, renderGuardMulti, esc, enc, $val, apiFetch, toast, definePage, getModel, ActionButton, ActionGroup, QuickModal } from '/static/hoover/index.js?v=7';
|
||||||
|
|
||||||
function makeAddRange(activeZones) {
|
function makeAddRange(activeZones, interfaces) {
|
||||||
const opts = [
|
const opts = [
|
||||||
['', '(global)'],
|
['', '(global)'],
|
||||||
...Object.entries(activeZones || {})
|
...Object.entries(activeZones || {})
|
||||||
@@ -13,6 +13,27 @@ function makeAddRange(activeZones) {
|
|||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const ranges = {};
|
||||||
|
(interfaces || []).forEach(iface => {
|
||||||
|
for (const cidr of (iface.ips || [])) {
|
||||||
|
if (cidr.indexOf('/') === -1) continue;
|
||||||
|
const parts = cidr.split('/');
|
||||||
|
const addr = parts[0].split('.').map(Number);
|
||||||
|
const prefix = parseInt(parts[1], 10);
|
||||||
|
if (prefix > 30 || prefix < 8) continue;
|
||||||
|
const mask = (0xFFFFFFFF << (32 - prefix)) >>> 0;
|
||||||
|
const netA = ((addr[0] << 24) + (addr[1] << 16) + (addr[2] << 8) + addr[3]) & mask;
|
||||||
|
const broadcast = (netA | (~mask >>> 0)) >>> 0;
|
||||||
|
const s = (netA + 100) >>> 0;
|
||||||
|
const e = Math.min((netA + 200) >>> 0, broadcast - 1);
|
||||||
|
const toIp = (n) => [n >> 24 & 0xFF, n >> 16 & 0xFF, n >> 8 & 0xFF, n & 0xFF].join('.');
|
||||||
|
if (s <= e) {
|
||||||
|
ranges[iface.name] = { start: toIp(s), end: toIp(e) };
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return QuickModal({
|
return QuickModal({
|
||||||
title: 'Add DHCP Range',
|
title: 'Add DHCP Range',
|
||||||
fields: [
|
fields: [
|
||||||
@@ -21,6 +42,23 @@ function makeAddRange(activeZones) {
|
|||||||
{ label: 'End IP', id: 'r-end', placeholder: '192.168.1.200' },
|
{ label: 'End IP', id: 'r-end', placeholder: '192.168.1.200' },
|
||||||
{ label: 'Lease Time', id: 'r-lease', placeholder: '12h' },
|
{ label: 'Lease Time', id: 'r-lease', placeholder: '12h' },
|
||||||
],
|
],
|
||||||
|
postRender: (inner) => {
|
||||||
|
const select = inner.querySelector('#r-iface');
|
||||||
|
const startInput = inner.querySelector('#r-start');
|
||||||
|
const endInput = inner.querySelector('#r-end');
|
||||||
|
if (select && startInput && endInput) {
|
||||||
|
select.addEventListener('change', () => {
|
||||||
|
const r = ranges[select.value];
|
||||||
|
if (r) {
|
||||||
|
startInput.value = r.start;
|
||||||
|
endInput.value = r.end;
|
||||||
|
} else {
|
||||||
|
startInput.value = '';
|
||||||
|
endInput.value = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
submit: {
|
submit: {
|
||||||
url: '/api/dhcp/ranges',
|
url: '/api/dhcp/ranges',
|
||||||
body: () => ({
|
body: () => ({
|
||||||
@@ -131,7 +169,7 @@ export default definePage({
|
|||||||
|
|
||||||
const tabNames = ['ranges', 'leases', 'dns', 'active'];
|
const tabNames = ['ranges', 'leases', 'dns', 'active'];
|
||||||
const actions = ActionGroup(
|
const actions = ActionGroup(
|
||||||
html`<button class="btn btn-primary" onClick=${() => makeAddRange(state.firewall.data?.zones?.active)(state)}>Add Range</button>`,
|
html`<button class="btn btn-primary" onClick=${() => makeAddRange(state.firewall.data?.zones?.active, state.firewall.data?.interfaces)(state)}>Add Range</button>`,
|
||||||
html`<button class="btn btn-outline" onClick=${() => addLease(state)}>Static Lease</button>`,
|
html`<button class="btn btn-outline" onClick=${() => addLease(state)}>Static Lease</button>`,
|
||||||
html`<button class="btn btn-outline" onClick=${() => addDns(state)}>DNS Record</button>`,
|
html`<button class="btn btn-outline" onClick=${() => addDns(state)}>DNS Record</button>`,
|
||||||
ActionButton({
|
ActionButton({
|
||||||
|
|||||||
Reference in New Issue
Block a user