Commit da8d8794 authored by jan.koester's avatar jan.koester
Browse files

test

parent a34154cd
Loading
Loading
Loading
Loading
+1 −1
Changes for CMakeLists.txt: 1 added line, 1 removed line.
Original line number Diff line number Diff line
cmake_minimum_required(VERSION 3.16)
project(webctl VERSION 0.2.1 LANGUAGES CXX)
project(webctl VERSION 0.2.2 LANGUAGES CXX)

# webctl: a web interface for FenrirOS.
#
+34 −7
Changes for www/modules/network.js: 34 added lines, 7 removed lines.
Original line number Diff line number Diff line
@@ -54,6 +54,9 @@
      'Namen: Buchstaben, Ziffern, „-“, „_“ und „.“, höchstens 15 Zeichen.',
    'Select at least one member.': 'Mindestens ein Mitglied auswählen.',
    '{0} saved and applied.': '{0} gespeichert und angewendet.', '{0} saved.': '{0} gespeichert.',
    'The addresses of {0} are taken over.': 'Die Adressen von {0} werden übernommen.',
    'A bond can be a port of the bridge: its addresses move to the bridge, which keeps the bond\'s MAC address, so connections survive the change. Leave STP off for that (with STP a new port forwards only after about 30 seconds).':
      'Ein Bond kann Port der Bridge sein: seine Adressen ziehen auf die Bridge um, die die MAC-Adresse des Bonds behält; bestehende Verbindungen überstehen den Umbau. Dafür STP ausgeschaltet lassen (mit STP leitet ein neuer Port erst nach etwa 30 Sekunden weiter).',
    '{0} saved and applied; the connection was interrupted meanwhile.': '{0} gespeichert und angewendet; die Verbindung wurde dabei kurz unterbrochen.',
    '{0} saved, but applying it failed: {1}': '{0} gespeichert, aber das Anwenden ist fehlgeschlagen: {1}',
    'Delete {0}?': '{0} löschen?',
@@ -82,11 +85,13 @@
  const hashPolicies = ['layer2', 'layer2+3', 'layer3+4', 'encap2+3', 'encap3+4', 'vlan+srcmac'];
  const ifnameOk = n => /^[A-Za-z0-9_.-]{1,15}$/.test(n) && n !== '.' && n !== '..';

  // interfaces that can join nd: real ones (no bond/bridge, not lo) that
  // aren't members of another bond or bridge
  function candidates(nd) {
  // interfaces that can join nd: real ones (no bond/bridge, not lo) and, for
  // a bridge, bonds too; none that is a member of another bond or bridge
  function candidates(nd, kind) {
    const name = nd ? nd.name : null;
    return interfaces.filter(i => i.name !== 'lo' && !i.kind && !netdevs.some(n => n.name === i.name) &&
    const nesting = i => kind === 'bridge' && i.kind === 'bond' && netdevs.some(n => n.name === i.name && n.kind === 'bond');
    return interfaces.filter(i => i.name !== 'lo' && i.name !== name &&
      ((!i.kind && !netdevs.some(n => n.name === i.name)) || nesting(i)) &&
      !netdevs.some(n => n.name !== name && n.members.includes(i.name)));
  }

@@ -97,7 +102,7 @@
    dialog({
      title: nd ? t('Edit {0}', nd.name) : t(kind === 'bond' ? 'New bond' : 'New bridge'),
      fields: form => {
        const pool = candidates(nd);
        const pool = candidates(nd, kind);
        for (const m of members) if (!pool.some(i => i.name === m)) pool.push({name: m, operState: ''});
        const bondOpts = h('div', {},
          h('label', {}, t('Mode'), h('select', {name: 'mode', onchange: () => toggle()},
@@ -124,7 +129,27 @@
        const dhcp = !own || iface.dhcp;
        const ipmode = (value, text) => h('label', {class: 'check'},
          h('input', {type: 'radio', name: 'ipmode', value, checked: (value === 'dhcp') === dhcp, onchange: toggleIp}), text);
        setTimeout(() => { if (kind === 'bond') toggle(); toggleIp(); });
        // a new bond/bridge takes over the addresses of its first member that
        // has its own (syslite moves them the same way): a bond with the
        // host's address becoming a bridge port keeps the host reachable
        let addressesTouched = false;
        const takeAddresses = i => {
          if (nd || own || addressesTouched || !ownConfig(i) || (!i.dhcp && !i.address)) return;
          form.querySelector(`input[name=ipmode][value=${i.dhcp ? 'dhcp' : 'static'}]`).checked = true;
          form.elements.address.value = i.dhcp ? '' : i.address;
          form.elements.gateway.value = i.dhcp ? '' : (i.gateway || '');
          form.elements.dns.value = (i.dns || []).join(', ');
          toggleIp();
          addressesTouched = true;
          if (kind === 'bridge' && i.kind === 'bond' && form.elements.stp) form.elements.stp.checked = false;
          toast(t('The addresses of {0} are taken over.', i.name));
        };
        setTimeout(() => {
          if (kind === 'bond') toggle(); toggleIp();
          for (const n of ['address', 'gateway', 'dns'])
            form.elements[n].addEventListener('input', () => { addressesTouched = true; });
          for (const r of form.querySelectorAll('input[name=ipmode]')) r.addEventListener('change', () => { addressesTouched = true; });
        });
        return [
          nd ? null : h('label', {}, t(kind === 'bond' ? 'Name (e.g. bond0)' : 'Name (e.g. br0)'),
            h('input', {name: 'name', value: kind === 'bond' ? 'bond0' : 'br0', required: true})),
@@ -135,7 +160,8 @@
          h('h3', {}, t('Member interfaces')),
          pool.length
            ? h('div', {class: 'checklist'}, pool.map(i => h('label', {class: 'check'},
                h('input', {type: 'checkbox', name: 'members', value: i.name, checked: members.includes(i.name)}),
                h('input', {type: 'checkbox', name: 'members', value: i.name, checked: members.includes(i.name),
                  onchange: e => { if (e.target.checked) takeAddresses(i); }}),
                i.name, i.addresses && i.addresses.length ? h('span', {class: 'muted'}, ' ' + i.addresses.join(', ')) : null)))
            : h('p', {class: 'empty'}, t('No free interfaces.')),
          h('h3', {}, t('Addresses of {0}', nd ? nd.name : t(kind))),
@@ -144,6 +170,7 @@
          h('label', {}, t('DNS servers (comma separated)'), h('input', {name: 'dns', value: own ? (iface.dns || []).join(', ') : ''})),
          h('label', {class: 'check'}, h('input', {type: 'checkbox', name: 'apply', checked: true}), t('Apply now')),
          h('p', {class: 'hint'}, t('Members lose their own addresses: the {0} has them. Changing the interface this page runs over can cut the connection.', t(kind))),
          kind === 'bridge' ? h('p', {class: 'hint'}, t('A bond can be a port of the bridge: its addresses move to the bridge, which keeps the bond\'s MAC address, so connections survive the change. Leave STP off for that (with STP a new port forwards only after about 30 seconds).')) : null,
        ];
      },
      onSubmit: async d => {