Loading include/sysbus/client.h +12 −5 Changes for include/sysbus/client.h: 12 added lines, 5 removed lines. Original line number Diff line number Diff line Loading @@ -70,9 +70,10 @@ constexpr const char *RestartInterface = "RestartInterface"; constexpr const char *ReloadInterface = "ReloadInterface"; // no interface: all constexpr const char *ForceReloadInterface = "ForceReloadInterface"; // no interface: all // Bonds, bridges and WireGuard interfaces: .netdev files in // Bonds, bridges, VLANs and WireGuard interfaces: .netdev files in // /etc/syslite/network; members of bonds and bridges get member .network // files (Bond=/Bridge=), a WireGuard interface has peers. Create/Edit // files (Bond=/Bridge=), a VLAN's parent gets VLAN= in its own .network, // a WireGuard interface has peers. Create/Edit // change only the files (ReloadInterface without an interface creates the // device, adds its members, configures WireGuard); Delete also removes the // device. Root only, except ListNetDevs (which never shows private or Loading Loading @@ -148,9 +149,11 @@ struct InterfaceInfo { std::string configAddress; // [Network] Address= std::string gateway; std::vector<std::string> dns; std::string kind; // "bond", "bridge" or "" (what the device is) std::string kind; // "bond", "bridge", "vlan", "wireguard", "veth" or "" (what the device is) std::string master; // the bond/bridge it is a member of now std::string parent; // a VLAN: the interface it is on now std::string memberOf; // configured: [Network] Bond= or Bridge= std::vector<std::string> vlans; // configured: [Network] VLAN= }; // A WireGuard peer as configured, and what the kernel knows of it. Loading @@ -171,16 +174,18 @@ struct WireGuardPeerInfo { // (balance-rr, active-backup, balance-xor, broadcast, 802.3ad, balance-tlb, // balance-alb), MII monitoring interval, LACP rate (802.3ad: slow/fast), // transmit hash policy (layer2, layer3+4, layer2+3, ...). For a bridge: // STP. For WireGuard: its public key, listen port, routes for the peers' // STP. For a VLAN: its id (1-4094) and the interface it is on. For WireGuard: its public key, listen port, routes for the peers' // AllowedIPs, peers. struct NetDevInfo { std::string name; // the interface, e.g. bond0 std::string kind; // bond, bridge or wireguard std::string kind; // bond, bridge, vlan or wireguard std::string mode; int miimonMs = 0; std::string lacpRate; std::string hashPolicy; bool stp = false; int vlanId = 0; std::string parent; // configured: the interface carrying the VLAN std::string publicKey; int listenPort = 0; // 0: the kernel picks one bool routes = false; Loading Loading @@ -216,6 +221,8 @@ struct NetDevSettings { std::optional<std::string> lacpRate; std::optional<std::string> hashPolicy; std::optional<bool> stp; std::optional<int> vlanId; std::optional<std::string> parent; // a VLAN: the interface it is on std::optional<std::vector<std::string>> members; std::optional<std::string> privateKey; bool generateKey = false; Loading src/network.cpp +258 −23 File changed.Preview size limit exceeded, changes collapsed. Show changes src/network.h +36 −15 Changes for src/network.h: 36 added lines, 15 removed lines. Original line number Diff line number Diff line Loading @@ -26,6 +26,8 @@ namespace syslite { // bridge (and gets no addresses of its own) std::string bond; std::string bridge; // [Network] VLAN= (repeatable): the VLANs on top of this interface std::vector<std::string> vlans; // [Link] bool linkUp = true; Loading @@ -35,14 +37,15 @@ namespace syslite { std::string name; }; // Parsed from systemd-networkd .netdev files: a bond, a bridge or a // WireGuard interface that syslite creates; the members of a bond or // bridge are the interfaces whose .network says Bond=<name> / // Bridge=<name>; a WireGuard interface has its peers instead // Parsed from systemd-networkd .netdev files: a bond, a bridge, an // 802.1Q VLAN or a WireGuard interface that syslite creates; the members // of a bond or bridge are the interfaces whose .network says // Bond=<name> / Bridge=<name>; a VLAN's parent is the interface whose // .network says VLAN=<name>; a WireGuard interface has its peers instead struct NetDevConfig { // [NetDev] std::string ifname; // Name=bond0 std::string kind; // Kind=bond | bridge | wireguard std::string kind; // Kind=bond | bridge | vlan | wireguard // [Bond] std::string mode = "balance-rr"; // Mode=balance-rr, active-backup, balance-xor, Loading @@ -54,6 +57,12 @@ namespace syslite { // [Bridge] bool stp = false; // STP=yes // [VLAN] int vlanId = 0; // Id= (1-4094) // not in the .netdev: the interface carrying it (VLAN= in its // .network); saveNetDev() writes that, vlanParent() finds it std::string parent; // [WireGuard] std::string wgPrivateKey; // PrivateKey= (base64), or std::string wgPrivateKeyFile; // PrivateKeyFile= Loading @@ -76,8 +85,9 @@ namespace syslite { bool adminUp = false; // IFF_UP bool carrier = false; bool stopped = false; // stopped on request (stays down) std::string kind; // "bond", "bridge", "wireguard" or "" std::string kind; // "bond", "bridge", "vlan", "wireguard", "veth" or "" std::string master; // the bond or bridge it is a member of std::string parent; // a VLAN: the interface it is on std::vector<std::string> addresses; // "a.b.c.d/len", IPv6 too const NetworkConfig *config = nullptr; // first matching configuration }; Loading Loading @@ -147,19 +157,27 @@ namespace syslite { // Re-read the .network files only (nothing is applied) void reloadConfigs(); // Bonds, bridges and WireGuard interfaces (.netdev files in // Bonds, bridges, VLANs and WireGuard interfaces (.netdev files in // ConfigDir). saveNetDev writes // ConfigDir/<nd.name>.netdev and makes exactly `members` its members: // each gets a member configuration ConfigDir/10-<member>.network // (Bond=/Bridge=), former members lose theirs. deleteNetDev removes // the file, the member configurations and the device itself. Both // re-read the files; applyNetDevs() (also part of applyAll/reload) // creates what is missing and configures the WireGuard interfaces. // A WireGuard .netdev holds its private key: written 0600, and // saveNetDev generates one if nd has none. // (Bond=/Bridge=), former members lose theirs. A VLAN has no members // but nd.parent: the parent's own configuration (10-<parent>, a copy // of the one that applies to it now if it has none) gets VLAN=, a // former parent loses it. deleteNetDev removes the file, the member // configurations and the device itself (a bond or bridge carrying // VLANs only once they are gone). Both re-read the files; // applyNetDevs() (also part of applyAll/reload) creates what is // missing (VLANs last, on their parents) and configures the // WireGuard interfaces. A WireGuard .netdev holds its private key: // written 0600, and saveNetDev generates one if nd has none. const std::vector<NetDevConfig> &netDevs() const { return _netdevs; } const NetDevConfig *findNetDev(const std::string &ifname) const; std::vector<std::string> membersOf(const std::string &ifname) const; // the interface whose (applying) configuration says VLAN=ifname ("": none) std::string vlanParent(const std::string &ifname) const; // the VLANs (.netdev) on ifname std::vector<std::string> vlansOn(const std::string &ifname) const; bool saveNetDev(const NetDevConfig &nd, const std::vector<std::string> &members, std::string *err); bool deleteNetDev(const std::string &ifname, std::string *err); void applyNetDevs(); Loading Loading @@ -192,6 +210,8 @@ namespace syslite { bool parseNetDevFile(const std::string &path, NetDevConfig &nd); bool writeNetDevFile(const NetDevConfig &nd, std::string *err); bool writeNetworkFile(const NetworkConfig &cfg, std::string *err); // VLAN=<nd.ifname> into nd.parent's own .network (out of the others) bool writeVlanParent(const NetDevConfig &nd, std::string *err); // Netlink: create a bond/bridge (RTM_NEWLINK with IFLA_LINKINFO), // delete a link, make ifname a member of master ("": none) Loading @@ -201,7 +221,8 @@ namespace syslite { // fixes ifname's MAC address ("aa:bb:cc:dd:ee:ff"; a bridge keeps it // instead of following its ports) bool setLinkAddress(const std::string &ifname, const std::string &mac); // does the existing device match nd (kind, bond mode, STP)? // does the existing device match nd (kind, bond mode, STP, VLAN // id and parent)? bool linkMatches(const NetDevConfig &nd); // WireGuard: keys, port and peers into the kernel; routes for the // peers' AllowedIPs (RouteTable=main; once the link is up) Loading Loading @@ -257,7 +278,7 @@ namespace syslite { std::map<std::string, std::vector<std::string>> _dnsByIf; // DNS servers per interface std::set<std::string> _configured; // interfaces configureInterface() set up std::set<std::string> _stopped; // interfaces stopped on request std::set<std::string> _createdLinks; // bonds/bridges created by applyNetDevs std::set<std::string> _createdLinks; // bonds/bridges/VLANs created by applyNetDevs std::map<std::string, std::string> _netDevErrors; // applyNetDevs() failures by ifname bool _resolvWritten = false; // resolv.yaml is ours once written int _monitorFd = -1; Loading src/sysbus/client.cpp +6 −0 Changes for src/sysbus/client.cpp: 6 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -74,7 +74,9 @@ InterfaceInfo interfaceFromFields(const std::vector<std::pair<std::string, std:: else if (k == "dns") i.dns.push_back(v); else if (k == "kind") i.kind = v; else if (k == "master") i.master = v; else if (k == "parent") i.parent = v; else if (k == "member_of") i.memberOf = v; else if (k == "vlan") i.vlans.push_back(v); } return i; } Loading @@ -90,6 +92,8 @@ NetDevInfo netDevFromFields(const std::vector<std::pair<std::string, std::string else if (k == "lacp_rate") n.lacpRate = v; else if (k == "hash_policy") n.hashPolicy = v; else if (k == "stp") n.stp = v == "yes"; else if (k == "vlan_id") n.vlanId = std::atoi(v.c_str()); else if (k == "parent") n.parent = v; else if (k == "config") n.config = v; else if (k == "config_path") n.configPath = v; else if (k == "exists") n.exists = v == "yes"; Loading Loading @@ -356,6 +360,8 @@ static std::vector<std::pair<std::string, std::string>> netDevArgs(const NetDevS if (s.lacpRate) a.emplace_back("lacp_rate", *s.lacpRate); if (s.hashPolicy) a.emplace_back("hash_policy", *s.hashPolicy); if (s.stp) a.emplace_back("stp", *s.stp ? "yes" : "no"); if (s.vlanId) a.emplace_back("vlan_id", std::to_string(*s.vlanId)); if (s.parent) a.emplace_back("parent", *s.parent); if (s.members) { a.emplace_back("set_members", "yes"); // also when empty: no members for (auto &m : *s.members) a.emplace_back("member", m); Loading src/syslite.cpp +8 −1 Changes for src/syslite.cpp: 8 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -388,6 +388,7 @@ namespace syslite { m.add("stopped", st.stopped ? "yes" : "no"); if (!st.kind.empty()) m.add("kind", st.kind); if (!st.master.empty()) m.add("master", st.master); if (!st.parent.empty()) m.add("parent", st.parent); for (auto &a : st.addresses) m.add("address", a); if (const NetworkConfig *cfg = st.config) { m.add("config", cfg->name); Loading @@ -399,6 +400,7 @@ namespace syslite { for (auto &d : cfg->dns) m.add("dns", d); if (!cfg->bond.empty()) m.add("member_of", cfg->bond); else if (!cfg->bridge.empty()) m.add("member_of", cfg->bridge); for (auto &v : cfg->vlans) m.add("vlan", v); } } Loading Loading @@ -479,7 +481,7 @@ namespace syslite { if (call.has("set_dns")) cfg.dns = call.getAll("dns"); if (cfg.matchName.empty()) return Message::error(call, err::InvalidArgs, "a configuration needs a match (interface name or pattern)"); if (!cfg.dhcp && cfg.address.empty() && cfg.bond.empty() && cfg.bridge.empty()) if (!cfg.dhcp && cfg.address.empty() && cfg.bond.empty() && cfg.bridge.empty() && cfg.vlans.empty()) return Message::error(call, err::InvalidArgs, "a configuration without DHCP needs an address"); return done(_network.saveConfig(cfg, &why), {}); } Loading Loading @@ -518,6 +520,9 @@ namespace syslite { if (!nd.hashPolicy.empty()) r.add("hash_policy", nd.hashPolicy); } else if (nd.kind == "bridge") { r.add("stp", nd.stp ? "yes" : "no"); } else if (nd.kind == "vlan") { r.add("vlan_id", std::to_string(nd.vlanId)); r.add("parent", nd.parent); } else { // never the private or preshared keys: this is open to everyone r.add("public_key", _network.wireGuardPublicKey(nd)); Loading Loading @@ -601,6 +606,8 @@ namespace syslite { if (call.has("lacp_rate")) nd.lacpRate = call.get("lacp_rate"); if (call.has("hash_policy")) nd.hashPolicy = call.get("hash_policy"); if (call.has("stp")) nd.stp = call.get("stp") == "yes"; if (call.has("vlan_id")) nd.vlanId = std::atoi(call.get("vlan_id").c_str()); if (call.has("parent")) nd.parent = call.get("parent"); if (call.has("set_members")) members = call.getAll("member"); if (nd.kind == "wireguard") { if (call.has("private_key")) { Loading Loading
include/sysbus/client.h +12 −5 Changes for include/sysbus/client.h: 12 added lines, 5 removed lines. Original line number Diff line number Diff line Loading @@ -70,9 +70,10 @@ constexpr const char *RestartInterface = "RestartInterface"; constexpr const char *ReloadInterface = "ReloadInterface"; // no interface: all constexpr const char *ForceReloadInterface = "ForceReloadInterface"; // no interface: all // Bonds, bridges and WireGuard interfaces: .netdev files in // Bonds, bridges, VLANs and WireGuard interfaces: .netdev files in // /etc/syslite/network; members of bonds and bridges get member .network // files (Bond=/Bridge=), a WireGuard interface has peers. Create/Edit // files (Bond=/Bridge=), a VLAN's parent gets VLAN= in its own .network, // a WireGuard interface has peers. Create/Edit // change only the files (ReloadInterface without an interface creates the // device, adds its members, configures WireGuard); Delete also removes the // device. Root only, except ListNetDevs (which never shows private or Loading Loading @@ -148,9 +149,11 @@ struct InterfaceInfo { std::string configAddress; // [Network] Address= std::string gateway; std::vector<std::string> dns; std::string kind; // "bond", "bridge" or "" (what the device is) std::string kind; // "bond", "bridge", "vlan", "wireguard", "veth" or "" (what the device is) std::string master; // the bond/bridge it is a member of now std::string parent; // a VLAN: the interface it is on now std::string memberOf; // configured: [Network] Bond= or Bridge= std::vector<std::string> vlans; // configured: [Network] VLAN= }; // A WireGuard peer as configured, and what the kernel knows of it. Loading @@ -171,16 +174,18 @@ struct WireGuardPeerInfo { // (balance-rr, active-backup, balance-xor, broadcast, 802.3ad, balance-tlb, // balance-alb), MII monitoring interval, LACP rate (802.3ad: slow/fast), // transmit hash policy (layer2, layer3+4, layer2+3, ...). For a bridge: // STP. For WireGuard: its public key, listen port, routes for the peers' // STP. For a VLAN: its id (1-4094) and the interface it is on. For WireGuard: its public key, listen port, routes for the peers' // AllowedIPs, peers. struct NetDevInfo { std::string name; // the interface, e.g. bond0 std::string kind; // bond, bridge or wireguard std::string kind; // bond, bridge, vlan or wireguard std::string mode; int miimonMs = 0; std::string lacpRate; std::string hashPolicy; bool stp = false; int vlanId = 0; std::string parent; // configured: the interface carrying the VLAN std::string publicKey; int listenPort = 0; // 0: the kernel picks one bool routes = false; Loading Loading @@ -216,6 +221,8 @@ struct NetDevSettings { std::optional<std::string> lacpRate; std::optional<std::string> hashPolicy; std::optional<bool> stp; std::optional<int> vlanId; std::optional<std::string> parent; // a VLAN: the interface it is on std::optional<std::vector<std::string>> members; std::optional<std::string> privateKey; bool generateKey = false; Loading
src/network.h +36 −15 Changes for src/network.h: 36 added lines, 15 removed lines. Original line number Diff line number Diff line Loading @@ -26,6 +26,8 @@ namespace syslite { // bridge (and gets no addresses of its own) std::string bond; std::string bridge; // [Network] VLAN= (repeatable): the VLANs on top of this interface std::vector<std::string> vlans; // [Link] bool linkUp = true; Loading @@ -35,14 +37,15 @@ namespace syslite { std::string name; }; // Parsed from systemd-networkd .netdev files: a bond, a bridge or a // WireGuard interface that syslite creates; the members of a bond or // bridge are the interfaces whose .network says Bond=<name> / // Bridge=<name>; a WireGuard interface has its peers instead // Parsed from systemd-networkd .netdev files: a bond, a bridge, an // 802.1Q VLAN or a WireGuard interface that syslite creates; the members // of a bond or bridge are the interfaces whose .network says // Bond=<name> / Bridge=<name>; a VLAN's parent is the interface whose // .network says VLAN=<name>; a WireGuard interface has its peers instead struct NetDevConfig { // [NetDev] std::string ifname; // Name=bond0 std::string kind; // Kind=bond | bridge | wireguard std::string kind; // Kind=bond | bridge | vlan | wireguard // [Bond] std::string mode = "balance-rr"; // Mode=balance-rr, active-backup, balance-xor, Loading @@ -54,6 +57,12 @@ namespace syslite { // [Bridge] bool stp = false; // STP=yes // [VLAN] int vlanId = 0; // Id= (1-4094) // not in the .netdev: the interface carrying it (VLAN= in its // .network); saveNetDev() writes that, vlanParent() finds it std::string parent; // [WireGuard] std::string wgPrivateKey; // PrivateKey= (base64), or std::string wgPrivateKeyFile; // PrivateKeyFile= Loading @@ -76,8 +85,9 @@ namespace syslite { bool adminUp = false; // IFF_UP bool carrier = false; bool stopped = false; // stopped on request (stays down) std::string kind; // "bond", "bridge", "wireguard" or "" std::string kind; // "bond", "bridge", "vlan", "wireguard", "veth" or "" std::string master; // the bond or bridge it is a member of std::string parent; // a VLAN: the interface it is on std::vector<std::string> addresses; // "a.b.c.d/len", IPv6 too const NetworkConfig *config = nullptr; // first matching configuration }; Loading Loading @@ -147,19 +157,27 @@ namespace syslite { // Re-read the .network files only (nothing is applied) void reloadConfigs(); // Bonds, bridges and WireGuard interfaces (.netdev files in // Bonds, bridges, VLANs and WireGuard interfaces (.netdev files in // ConfigDir). saveNetDev writes // ConfigDir/<nd.name>.netdev and makes exactly `members` its members: // each gets a member configuration ConfigDir/10-<member>.network // (Bond=/Bridge=), former members lose theirs. deleteNetDev removes // the file, the member configurations and the device itself. Both // re-read the files; applyNetDevs() (also part of applyAll/reload) // creates what is missing and configures the WireGuard interfaces. // A WireGuard .netdev holds its private key: written 0600, and // saveNetDev generates one if nd has none. // (Bond=/Bridge=), former members lose theirs. A VLAN has no members // but nd.parent: the parent's own configuration (10-<parent>, a copy // of the one that applies to it now if it has none) gets VLAN=, a // former parent loses it. deleteNetDev removes the file, the member // configurations and the device itself (a bond or bridge carrying // VLANs only once they are gone). Both re-read the files; // applyNetDevs() (also part of applyAll/reload) creates what is // missing (VLANs last, on their parents) and configures the // WireGuard interfaces. A WireGuard .netdev holds its private key: // written 0600, and saveNetDev generates one if nd has none. const std::vector<NetDevConfig> &netDevs() const { return _netdevs; } const NetDevConfig *findNetDev(const std::string &ifname) const; std::vector<std::string> membersOf(const std::string &ifname) const; // the interface whose (applying) configuration says VLAN=ifname ("": none) std::string vlanParent(const std::string &ifname) const; // the VLANs (.netdev) on ifname std::vector<std::string> vlansOn(const std::string &ifname) const; bool saveNetDev(const NetDevConfig &nd, const std::vector<std::string> &members, std::string *err); bool deleteNetDev(const std::string &ifname, std::string *err); void applyNetDevs(); Loading Loading @@ -192,6 +210,8 @@ namespace syslite { bool parseNetDevFile(const std::string &path, NetDevConfig &nd); bool writeNetDevFile(const NetDevConfig &nd, std::string *err); bool writeNetworkFile(const NetworkConfig &cfg, std::string *err); // VLAN=<nd.ifname> into nd.parent's own .network (out of the others) bool writeVlanParent(const NetDevConfig &nd, std::string *err); // Netlink: create a bond/bridge (RTM_NEWLINK with IFLA_LINKINFO), // delete a link, make ifname a member of master ("": none) Loading @@ -201,7 +221,8 @@ namespace syslite { // fixes ifname's MAC address ("aa:bb:cc:dd:ee:ff"; a bridge keeps it // instead of following its ports) bool setLinkAddress(const std::string &ifname, const std::string &mac); // does the existing device match nd (kind, bond mode, STP)? // does the existing device match nd (kind, bond mode, STP, VLAN // id and parent)? bool linkMatches(const NetDevConfig &nd); // WireGuard: keys, port and peers into the kernel; routes for the // peers' AllowedIPs (RouteTable=main; once the link is up) Loading Loading @@ -257,7 +278,7 @@ namespace syslite { std::map<std::string, std::vector<std::string>> _dnsByIf; // DNS servers per interface std::set<std::string> _configured; // interfaces configureInterface() set up std::set<std::string> _stopped; // interfaces stopped on request std::set<std::string> _createdLinks; // bonds/bridges created by applyNetDevs std::set<std::string> _createdLinks; // bonds/bridges/VLANs created by applyNetDevs std::map<std::string, std::string> _netDevErrors; // applyNetDevs() failures by ifname bool _resolvWritten = false; // resolv.yaml is ours once written int _monitorFd = -1; Loading
src/sysbus/client.cpp +6 −0 Changes for src/sysbus/client.cpp: 6 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -74,7 +74,9 @@ InterfaceInfo interfaceFromFields(const std::vector<std::pair<std::string, std:: else if (k == "dns") i.dns.push_back(v); else if (k == "kind") i.kind = v; else if (k == "master") i.master = v; else if (k == "parent") i.parent = v; else if (k == "member_of") i.memberOf = v; else if (k == "vlan") i.vlans.push_back(v); } return i; } Loading @@ -90,6 +92,8 @@ NetDevInfo netDevFromFields(const std::vector<std::pair<std::string, std::string else if (k == "lacp_rate") n.lacpRate = v; else if (k == "hash_policy") n.hashPolicy = v; else if (k == "stp") n.stp = v == "yes"; else if (k == "vlan_id") n.vlanId = std::atoi(v.c_str()); else if (k == "parent") n.parent = v; else if (k == "config") n.config = v; else if (k == "config_path") n.configPath = v; else if (k == "exists") n.exists = v == "yes"; Loading Loading @@ -356,6 +360,8 @@ static std::vector<std::pair<std::string, std::string>> netDevArgs(const NetDevS if (s.lacpRate) a.emplace_back("lacp_rate", *s.lacpRate); if (s.hashPolicy) a.emplace_back("hash_policy", *s.hashPolicy); if (s.stp) a.emplace_back("stp", *s.stp ? "yes" : "no"); if (s.vlanId) a.emplace_back("vlan_id", std::to_string(*s.vlanId)); if (s.parent) a.emplace_back("parent", *s.parent); if (s.members) { a.emplace_back("set_members", "yes"); // also when empty: no members for (auto &m : *s.members) a.emplace_back("member", m); Loading
src/syslite.cpp +8 −1 Changes for src/syslite.cpp: 8 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -388,6 +388,7 @@ namespace syslite { m.add("stopped", st.stopped ? "yes" : "no"); if (!st.kind.empty()) m.add("kind", st.kind); if (!st.master.empty()) m.add("master", st.master); if (!st.parent.empty()) m.add("parent", st.parent); for (auto &a : st.addresses) m.add("address", a); if (const NetworkConfig *cfg = st.config) { m.add("config", cfg->name); Loading @@ -399,6 +400,7 @@ namespace syslite { for (auto &d : cfg->dns) m.add("dns", d); if (!cfg->bond.empty()) m.add("member_of", cfg->bond); else if (!cfg->bridge.empty()) m.add("member_of", cfg->bridge); for (auto &v : cfg->vlans) m.add("vlan", v); } } Loading Loading @@ -479,7 +481,7 @@ namespace syslite { if (call.has("set_dns")) cfg.dns = call.getAll("dns"); if (cfg.matchName.empty()) return Message::error(call, err::InvalidArgs, "a configuration needs a match (interface name or pattern)"); if (!cfg.dhcp && cfg.address.empty() && cfg.bond.empty() && cfg.bridge.empty()) if (!cfg.dhcp && cfg.address.empty() && cfg.bond.empty() && cfg.bridge.empty() && cfg.vlans.empty()) return Message::error(call, err::InvalidArgs, "a configuration without DHCP needs an address"); return done(_network.saveConfig(cfg, &why), {}); } Loading Loading @@ -518,6 +520,9 @@ namespace syslite { if (!nd.hashPolicy.empty()) r.add("hash_policy", nd.hashPolicy); } else if (nd.kind == "bridge") { r.add("stp", nd.stp ? "yes" : "no"); } else if (nd.kind == "vlan") { r.add("vlan_id", std::to_string(nd.vlanId)); r.add("parent", nd.parent); } else { // never the private or preshared keys: this is open to everyone r.add("public_key", _network.wireGuardPublicKey(nd)); Loading Loading @@ -601,6 +606,8 @@ namespace syslite { if (call.has("lacp_rate")) nd.lacpRate = call.get("lacp_rate"); if (call.has("hash_policy")) nd.hashPolicy = call.get("hash_policy"); if (call.has("stp")) nd.stp = call.get("stp") == "yes"; if (call.has("vlan_id")) nd.vlanId = std::atoi(call.get("vlan_id").c_str()); if (call.has("parent")) nd.parent = call.get("parent"); if (call.has("set_members")) members = call.getAll("member"); if (nd.kind == "wireguard") { if (call.has("private_key")) { Loading