Commit 4d7a9801 authored by Jan Koester's avatar Jan Koester
Browse files

test

parent 89f1638d
Loading
Loading
Loading
Loading
+97 −12
Changes for modules/network/network.cpp: 97 added lines, 12 removed lines.
Original line number Diff line number Diff line
@@ -36,11 +36,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *   start | stop | restart  {interface}
 *   reload | forceReload    {interface?}          (none: all)
 *
 * Bonds and bridges (.netdev files; reload without an interface creates
 * them and adds their members):
 *   createNetdev  {netdev, kind: bond|bridge, mode?, miimon?, lacpRate?, hashPolicy?, stp?, members?[]}
 *   updateNetdev  {netdev, mode?, miimon?, lacpRate?, hashPolicy?, stp?, members?[]}
 * Bonds, bridges and WireGuard interfaces (.netdev files; reload without
 * an interface creates them, adds their members, configures WireGuard):
 *   createNetdev  {netdev, kind: bond|bridge|wireguard, mode?, miimon?, lacpRate?, hashPolicy?, stp?, members?[],
 *                  privateKey?, generateKey?, listenPort?, routes?, peers?[]}
 *   updateNetdev  {netdev, ...the same, without kind}
 *   deleteNetdev  {netdev}                        (also removes the device)
 *   generateKey                                   -> {privateKey, publicKey, presharedKey}
 *
 * A WireGuard peer: {publicKey, name?, presharedKey?, endpoint?, allowedIps?[], keepalive?};
 * without presharedKey a peer keeps the one it has, "" removes it. Private
 * and preshared keys are never listed.
 */

#include <string>
@@ -105,9 +111,73 @@ json_object *netdevJson(const sysbus::NetDevInfo &n) {
    json_object *m = json_object_new_array();
    for (auto &x : n.members) json_object_array_add(m, jstr(x));
    json_object_object_add(o, "members", m);
    if (n.kind == "wireguard") {
        json_object_object_add(o, "publicKey", jstr(n.publicKey));
        json_object_object_add(o, "listenPort", json_object_new_int(n.listenPort));
        json_object_object_add(o, "routes", json_object_new_boolean(n.routes));
        json_object *peers = json_object_new_array();
        for (auto &p : n.peers) {
            json_object *po = json_object_new_object();
            json_object_object_add(po, "name", jstr(p.name));
            json_object_object_add(po, "publicKey", jstr(p.publicKey));
            json_object_object_add(po, "hasPresharedKey", json_object_new_boolean(p.hasPresharedKey));
            json_object_object_add(po, "endpoint", jstr(p.endpoint));
            json_object *ips = json_object_new_array();
            for (auto &ip : p.allowedIps) json_object_array_add(ips, jstr(ip));
            json_object_object_add(po, "allowedIps", ips);
            json_object_object_add(po, "keepalive", json_object_new_int(p.keepalive));
            json_object_object_add(po, "currentEndpoint", jstr(p.currentEndpoint));
            json_object_object_add(po, "lastHandshake", json_object_new_int64(p.lastHandshake));
            json_object_object_add(po, "rxBytes", json_object_new_int64((int64_t)p.rxBytes));
            json_object_object_add(po, "txBytes", json_object_new_int64((int64_t)p.txBytes));
            json_object_array_add(peers, po);
        }
        json_object_object_add(o, "peers", peers);
    }
    return o;
}

// a JSON array of strings (members, AllowedIPs, ...); false if it isn't one
bool stringList(json_object *v, std::vector<std::string> &out) {
    if (!json_object_is_type(v, json_type_array)) return false;
    for (size_t i = 0; i < json_object_array_length(v); ++i) {
        const char *s = json_object_get_string(json_object_array_get_idx(v, i));
        if (s && *s) out.push_back(s);
    }
    return true;
}

bool peerSettings(json_object *peers, std::vector<sysbus::WireGuardPeerSettings> &out, std::string &err) {
    if (!json_object_is_type(peers, json_type_array)) {
        err = tr("peers must be a list", "peers muss eine Liste sein");
        return false;
    }
    for (size_t i = 0; i < json_object_array_length(peers); ++i) {
        json_object *p = json_object_array_get_idx(peers, i);
        if (!json_object_is_type(p, json_type_object)) {
            err = tr("peers must be a list of objects", "peers muss eine Liste von Objekten sein");
            return false;
        }
        sysbus::WireGuardPeerSettings ps;
        ps.publicKey = webctl::str(p, "publicKey");
        ps.name = webctl::str(p, "name");
        if (webctl::has(p, "presharedKey")) ps.presharedKey = webctl::str(p, "presharedKey");
        ps.endpoint = webctl::str(p, "endpoint");
        ps.keepalive = (int)webctl::integer(p, "keepalive", 0);
        json_object *ips = nullptr;
        if (json_object_object_get_ex(p, "allowedIps", &ips) && ips && !stringList(ips, ps.allowedIps)) {
            err = tr("allowedIps must be a list of networks", "allowedIps muss eine Liste von Netzen sein");
            return false;
        }
        if (ps.publicKey.empty()) {
            err = tr("a peer needs a public key", "ein Peer braucht einen öffentlichen Schlüssel");
            return false;
        }
        out.push_back(ps);
    }
    return true;
}

bool netdevSettings(json_object *a, sysbus::NetDevSettings &s, std::string &err) {
    s.netdev = webctl::str(a, "netdev");
    s.kind = webctl::str(a, "kind");
@@ -118,17 +188,23 @@ bool netdevSettings(json_object *a, sysbus::NetDevSettings &s, std::string &err)
    if (webctl::has(a, "stp")) s.stp = webctl::boolean(a, "stp");
    json_object *members = nullptr;
    if (json_object_object_get_ex(a, "members", &members) && members) {
        if (!json_object_is_type(members, json_type_array)) {
        std::vector<std::string> list;
        if (!stringList(members, list)) {
            err = tr("members must be a list of interfaces", "members muss eine Liste von Interfaces sein");
            return false;
        }
        std::vector<std::string> list;
        for (size_t i = 0; i < json_object_array_length(members); ++i) {
            const char *m = json_object_get_string(json_object_array_get_idx(members, i));
            if (m && *m) list.push_back(m);
        }
        s.members = list;
    }
    if (webctl::has(a, "privateKey")) s.privateKey = webctl::str(a, "privateKey");
    s.generateKey = webctl::boolean(a, "generateKey");
    if (webctl::has(a, "listenPort")) s.listenPort = (int)webctl::integer(a, "listenPort", 0);
    if (webctl::has(a, "routes")) s.routes = webctl::boolean(a, "routes");
    json_object *peers = nullptr;
    if (json_object_object_get_ex(a, "peers", &peers) && peers) {
        std::vector<sysbus::WireGuardPeerSettings> list;
        if (!peerSettings(peers, list, err)) return false;
        s.peers = list;
    }
    if (s.netdev.empty()) {
        err = tr("no bond or bridge name", "kein Name für Bond oder Bridge angegeben");
        return false;
@@ -190,11 +266,20 @@ json_object *call(const webctl_request *req) {
        sysbus::NetDevSettings s;
        std::string err;
        if (!netdevSettings(a, s, err)) return error(err);
        if (action == "createNetdev" && s.kind != "bond" && s.kind != "bridge")
            return error(tr("kind must be bond or bridge", "Art muss bond oder bridge sein"));
        if (action == "createNetdev" && s.kind != "bond" && s.kind != "bridge" && s.kind != "wireguard")
            return error(tr("kind must be bond, bridge or wireguard", "Art muss bond, bridge oder wireguard sein"));
        bool done = action == "createNetdev" ? bus.createNetDev(s) : bus.editNetDev(s);
        return done ? webctl::ok() : busError(bus);
    }
    if (action == "generateKey") {
        sysbus::WireGuardKeys k;
        if (!bus.generateWireGuardKey(k)) return busError(bus);
        json_object *out = json_object_new_object();
        json_object_object_add(out, "privateKey", jstr(k.privateKey));
        json_object_object_add(out, "publicKey", jstr(k.publicKey));
        json_object_object_add(out, "presharedKey", jstr(k.presharedKey));
        return out;
    }
    if (action == "deleteNetdev") {
        std::string n = webctl::str(a, "netdev");
        if (n.empty()) return error(tr("no bond or bridge name", "kein Name für Bond oder Bridge angegeben"));
+8 −0
Changes for www/app.css: 8 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -141,6 +141,14 @@ dialog h2 { font-size: 1.1rem; }
.row { display: flex; gap: 10px; }
.row > * { flex: 1; }

/* ---- WireGuard (network) ---- */
.wg + .wg { margin-top: 1.4em; padding-top: 1em; border-top: 1px solid var(--line); }
.wg .toolbar h3 { margin: 0; color: var(--text); }
.wg .toolbar .badge { margin-right: auto; }
.wg-info { display: grid; grid-template-columns: max-content 1fr; gap: .25em 1em; margin: 0 0 1em; }
.wg-info dt { color: var(--muted); }
.wg-info dd { margin: 0; overflow-wrap: anywhere; }

/* ---- toasts ---- */
.toasts { position: fixed; right: 16px; bottom: 16px; display: grid; gap: 8px; z-index: 10; }
.toast {
+334 −13

File changed.

Preview size limit exceeded, changes collapsed.