diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index cdc11dd1..da859c5e 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -16,6 +16,6 @@ jobs: uses: vmactions/freebsd-vm@v1 with: usesh: true - prepare: pkg install -y node24 npm-node24 go git + prepare: pkg update -y && pkg install -y node24 npm-node24 go git run: | make test diff --git a/web/src/lib/components/custom/KVTableModal.svelte b/web/src/lib/components/custom/KVTableModal.svelte index 014f453f..5808fa42 100644 --- a/web/src/lib/components/custom/KVTableModal.svelte +++ b/web/src/lib/components/custom/KVTableModal.svelte @@ -57,7 +57,9 @@
- + {#if tableHeaders.length > 0} @@ -65,8 +67,8 @@ {header} {/each} {:else} - {titles.key} - {titles.value} + {titles.key} + {titles.value} {/if} @@ -76,7 +78,7 @@ {#each KV as Array> as row} {#each tableHeaders as header} - {row[header]} + {row[header]} {/each} {/each} @@ -104,10 +106,10 @@ {#if expandedObjects[key]} {#each Object.entries(value) as [nestedKey, nestedValue]} - + {nestedKey} - + {nestedValue} @@ -115,8 +117,8 @@ {/if} {:else} - {key} - {value} + {key} + {value} {/if} {/each} diff --git a/web/src/lib/utils/network/iface.ts b/web/src/lib/utils/network/iface.ts index 1003f0a1..466ea9e7 100644 --- a/web/src/lib/utils/network/iface.ts +++ b/web/src/lib/utils/network/iface.ts @@ -2,6 +2,92 @@ import type { Column, Row } from '$lib/types/components/tree-table'; import type { Iface } from '$lib/types/network/iface'; import { generateNumberFromString } from '../numbers'; +function ipv4NetmaskToPrefix(netmask?: string | null): number | null { + if (!netmask) { + return null; + } + + const parts = netmask.split('.').map((p) => Number.parseInt(p, 10)); + if (parts.length !== 4 || parts.some((p) => Number.isNaN(p) || p < 0 || p > 255)) { + return null; + } + + let prefix = 0; + for (const part of parts) { + let n = part; + for (let i = 0; i < 8; i++) { + if ((n & 0x80) === 0x80) { + prefix++; + } + n <<= 1; + } + } + + return prefix; +} + +function formatIPv4(iface: Iface): string { + if (!iface.ipv4 || iface.ipv4.length === 0) { + return '-'; + } + + return iface.ipv4 + .map((addr) => { + const prefix = ipv4NetmaskToPrefix(addr.netmask); + const suffix = prefix !== null ? `/${prefix}` : ''; + return `${addr.ip}${suffix}`; + }) + .join('\n'); +} + +function formatIPv6(iface: Iface): string { + if (!iface.ipv6 || iface.ipv6.length === 0) { + return '-'; + } + + return iface.ipv6 + .map((addr) => { + const suffix = addr.prefixLength !== undefined ? `/${addr.prefixLength}` : ''; + return `${addr.ip}${suffix}`; + }) + .join('\n'); +} + +function getIPv4Details(iface: Iface): Record | null { + if (!iface.ipv4 || iface.ipv4.length === 0) { + return null; + } + + const details: Record = {}; + + iface.ipv4.forEach((addr, index) => { + const prefix = ipv4NetmaskToPrefix(addr.netmask); + const cidr = prefix !== null ? `${addr.ip}/${prefix}` : addr.ip || '-'; + details[`Address ${index + 1}`] = `${cidr} | Netmask: ${addr.netmask || '-'} | Broadcast: ${addr.broadcast || '-'}`; + }); + + return details; +} + +function getIPv6Details(iface: Iface): Record | null { + if (!iface.ipv6 || iface.ipv6.length === 0) { + return null; + } + + const details: Record = {}; + + iface.ipv6.forEach((addr, index) => { + const prefix = + addr.prefixLength !== undefined && addr.prefixLength !== null ? `/${addr.prefixLength}` : ''; + details[`Address ${index + 1}`] = + `${addr.ip || '-'}${prefix} | Scope: ${addr.scopeId} | Auto: ${addr.autoConf ? 'true' : 'false'} | ` + + `Detached: ${addr.detached ? 'true' : 'false'} | Deprecated: ${addr.deprecated ? 'true' : 'false'} | ` + + `Preferred: ${addr.lifeTimes?.preferred ?? '-'} | Valid: ${addr.lifeTimes?.valid ?? '-'}`; + }); + + return details; +} + export function generateTableData( columns: Column[], interfaces: Iface[] @@ -52,6 +138,8 @@ export function generateTableData( name: iface.name, model: model, description: iface.description, + ipv4: formatIPv4(iface), + ipv6: formatIPv6(iface), metric: iface.metric, mtu: iface.mtu, media: iface.media, @@ -74,6 +162,8 @@ type CleanIfaceData = { Description: string; Model: string; 'MAC Address': string; + 'IPv4 Addresses'?: Record; + 'IPv6 Addresses'?: Record; MTU: number | null | undefined; Metric: number | null | undefined; Flags: { @@ -129,6 +219,17 @@ export function getCleanIfaceData(iface: Iface): CleanIfaceData { } }; + const ipv4Details = getIPv4Details(iface); + const ipv6Details = getIPv6Details(iface); + + if (ipv4Details) { + obj['IPv4 Addresses'] = ipv4Details; + } + + if (ipv6Details) { + obj['IPv6 Addresses'] = ipv6Details; + } + if (iface.media !== null && iface.media !== undefined) { obj['Media Options'] = { ['Status']: iface.media.status, diff --git a/web/src/locales/en.po b/web/src/locales/en.po index c19bf316..9cabbaa6 100644 --- a/web/src/locales/en.po +++ b/web/src/locales/en.po @@ -5015,6 +5015,7 @@ msgstr "IPv4 Network" #: src/routes/[node]/network/dhcp/ranges/+page.svelte #: src/routes/[node]/network/firewall/nat/+page.svelte #: src/routes/[node]/network/firewall/traffic/+page.svelte +#: src/routes/[node]/network/interfaces/+page.svelte #: src/routes/[node]/network/routes/+page.svelte #: src/routes/[node]/network/switches/standard/+page.svelte #: src/routes/[node]/network/switches/standard/+page.svelte @@ -5060,6 +5061,7 @@ msgstr "IPv6 Network" #: src/routes/[node]/network/dhcp/ranges/+page.svelte #: src/routes/[node]/network/firewall/nat/+page.svelte #: src/routes/[node]/network/firewall/traffic/+page.svelte +#: src/routes/[node]/network/interfaces/+page.svelte #: src/routes/[node]/network/routes/+page.svelte #: src/routes/[node]/network/switches/standard/+page.svelte #: src/routes/[node]/network/switches/standard/+page.svelte @@ -6268,8 +6270,8 @@ msgstr "Save & Back to Sockets" #: src/routes/[node]/network/dhcp/config/+page.svelte #: src/routes/[node]/network/firewall/+page.svelte #: src/routes/[node]/network/firewall/+page.svelte -msgid "Update" -msgstr "Update" +msgid "Update " +msgstr "Update " #: src/lib/components/custom/VM/Extra/CPUSelector.svelte msgid "Apply " diff --git a/web/src/locales/hi.po b/web/src/locales/hi.po index f0f7c204..d9aa4c5f 100644 --- a/web/src/locales/hi.po +++ b/web/src/locales/hi.po @@ -5015,6 +5015,7 @@ msgstr "IPv4 नेटवर्क" #: src/routes/[node]/network/dhcp/ranges/+page.svelte #: src/routes/[node]/network/firewall/nat/+page.svelte #: src/routes/[node]/network/firewall/traffic/+page.svelte +#: src/routes/[node]/network/interfaces/+page.svelte #: src/routes/[node]/network/routes/+page.svelte #: src/routes/[node]/network/switches/standard/+page.svelte #: src/routes/[node]/network/switches/standard/+page.svelte @@ -5060,6 +5061,7 @@ msgstr "IPv6 नेटवर्क" #: src/routes/[node]/network/dhcp/ranges/+page.svelte #: src/routes/[node]/network/firewall/nat/+page.svelte #: src/routes/[node]/network/firewall/traffic/+page.svelte +#: src/routes/[node]/network/interfaces/+page.svelte #: src/routes/[node]/network/routes/+page.svelte #: src/routes/[node]/network/switches/standard/+page.svelte #: src/routes/[node]/network/switches/standard/+page.svelte @@ -6268,7 +6270,7 @@ msgstr "सहेजें और सॉकेट पर वापस जाए #: src/routes/[node]/network/dhcp/config/+page.svelte #: src/routes/[node]/network/firewall/+page.svelte #: src/routes/[node]/network/firewall/+page.svelte -msgid "Update" +msgid "Update " msgstr "अपडेट " #: src/lib/components/custom/VM/Extra/CPUSelector.svelte diff --git a/web/src/locales/mal.po b/web/src/locales/mal.po index 79f36047..28cc809a 100644 --- a/web/src/locales/mal.po +++ b/web/src/locales/mal.po @@ -5015,6 +5015,7 @@ msgstr "IPv4 നെറ്റ്‌വർക്ക്" #: src/routes/[node]/network/dhcp/ranges/+page.svelte #: src/routes/[node]/network/firewall/nat/+page.svelte #: src/routes/[node]/network/firewall/traffic/+page.svelte +#: src/routes/[node]/network/interfaces/+page.svelte #: src/routes/[node]/network/routes/+page.svelte #: src/routes/[node]/network/switches/standard/+page.svelte #: src/routes/[node]/network/switches/standard/+page.svelte @@ -5060,6 +5061,7 @@ msgstr "IPv6 നെറ്റ്‌വർക്ക്" #: src/routes/[node]/network/dhcp/ranges/+page.svelte #: src/routes/[node]/network/firewall/nat/+page.svelte #: src/routes/[node]/network/firewall/traffic/+page.svelte +#: src/routes/[node]/network/interfaces/+page.svelte #: src/routes/[node]/network/routes/+page.svelte #: src/routes/[node]/network/switches/standard/+page.svelte #: src/routes/[node]/network/switches/standard/+page.svelte @@ -6268,7 +6270,7 @@ msgstr "സേവ് ചെയ്ത് സോക്കറ്റുകളില #: src/routes/[node]/network/dhcp/config/+page.svelte #: src/routes/[node]/network/firewall/+page.svelte #: src/routes/[node]/network/firewall/+page.svelte -msgid "Update" +msgid "Update " msgstr "പുതുക്കുക " #: src/lib/components/custom/VM/Extra/CPUSelector.svelte diff --git a/web/src/locales/zh-CN.po b/web/src/locales/zh-CN.po index 683c991e..b935c3cc 100644 --- a/web/src/locales/zh-CN.po +++ b/web/src/locales/zh-CN.po @@ -5015,6 +5015,7 @@ msgstr "IPv4 网络" #: src/routes/[node]/network/dhcp/ranges/+page.svelte #: src/routes/[node]/network/firewall/nat/+page.svelte #: src/routes/[node]/network/firewall/traffic/+page.svelte +#: src/routes/[node]/network/interfaces/+page.svelte #: src/routes/[node]/network/routes/+page.svelte #: src/routes/[node]/network/switches/standard/+page.svelte #: src/routes/[node]/network/switches/standard/+page.svelte @@ -5060,6 +5061,7 @@ msgstr "IPv6 网络" #: src/routes/[node]/network/dhcp/ranges/+page.svelte #: src/routes/[node]/network/firewall/nat/+page.svelte #: src/routes/[node]/network/firewall/traffic/+page.svelte +#: src/routes/[node]/network/interfaces/+page.svelte #: src/routes/[node]/network/routes/+page.svelte #: src/routes/[node]/network/switches/standard/+page.svelte #: src/routes/[node]/network/switches/standard/+page.svelte @@ -6268,7 +6270,7 @@ msgstr "保存并返回插槽" #: src/routes/[node]/network/dhcp/config/+page.svelte #: src/routes/[node]/network/firewall/+page.svelte #: src/routes/[node]/network/firewall/+page.svelte -msgid "Update" +msgid "Update " msgstr "更新 " #: src/lib/components/custom/VM/Extra/CPUSelector.svelte diff --git a/web/src/routes/[node]/network/interfaces/+page.svelte b/web/src/routes/[node]/network/interfaces/+page.svelte index 8ec1e034..897e0663 100644 --- a/web/src/routes/[node]/network/interfaces/+page.svelte +++ b/web/src/routes/[node]/network/interfaces/+page.svelte @@ -191,6 +191,16 @@ return macAddr || '-'; } }, + { + field: 'ipv4', + title: 'IPv4', + formatter: 'textarea' + }, + { + field: 'ipv6', + title: 'IPv6', + formatter: 'textarea' + }, { field: 'metric', title: 'Metric'