Loading CMakeLists.txt +1 −0 Changes for CMakeLists.txt: 1 added line, 0 removed lines. Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ add_executable(syslite src/service.cpp src/tty.cpp src/network.cpp src/wireguard.cpp src/busserver.cpp src/syslite.cpp ) Loading include/sysbus/client.h +58 −10 Changes for include/sysbus/client.h: 58 added lines, 10 removed lines. Original line number Diff line number Diff line Loading @@ -63,14 +63,19 @@ constexpr const char *RestartInterface = "RestartInterface"; constexpr const char *ReloadInterface = "ReloadInterface"; // no interface: all constexpr const char *ForceReloadInterface = "ForceReloadInterface"; // no interface: all // Bonds and bridges: .netdev files in /etc/syslite/network, their members // get member .network files (Bond=/Bridge=). Create/Edit change only the // files (ReloadInterface without an interface creates the device and adds // its members); Delete also removes the device. Root only. // Bonds, bridges 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 // 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 // preshared keys). constexpr const char *ListNetDevs = "ListNetDevs"; // -> netdev, ... (repeated) constexpr const char *CreateNetDev = "CreateNetDev"; // netdev, kind, ... constexpr const char *EditNetDev = "EditNetDev"; // netdev, ... constexpr const char *DeleteNetDev = "DeleteNetDev"; // netdev // -> private_key, public_key, preshared_key: new keys, e.g. for a peer constexpr const char *GenerateWireGuardKey = "GenerateWireGuardKey"; } // namespace method namespace signal { Loading Loading @@ -141,26 +146,59 @@ struct InterfaceInfo { std::string memberOf; // configured: [Network] Bond= or Bridge= }; // A bond or bridge (.netdev). For a bond: mode (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. // A WireGuard peer as configured, and what the kernel knows of it. struct WireGuardPeerInfo { std::string name; std::string publicKey; bool hasPresharedKey = false; std::string endpoint; // configured, host:port std::vector<std::string> allowedIps; int keepalive = 0; // seconds, 0: off // live (the device exists and knows the peer) std::string currentEndpoint; long long lastHandshake = 0; // unix time, 0: never unsigned long long rxBytes = 0, txBytes = 0; }; // A bond, bridge or WireGuard interface (.netdev). For a bond: mode // (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' // AllowedIPs, peers. struct NetDevInfo { std::string name; // the interface, e.g. bond0 std::string kind; // bond or bridge std::string kind; // bond, bridge or wireguard std::string mode; int miimonMs = 0; std::string lacpRate; std::string hashPolicy; bool stp = false; std::string publicKey; int listenPort = 0; // 0: the kernel picks one bool routes = false; std::vector<WireGuardPeerInfo> peers; std::string config; // file name without ".netdev" std::string configPath; bool exists = false; // the device is there std::vector<std::string> members; // configured members }; // A WireGuard peer to configure. presharedKey: unset keeps the peer's // current one (none for a new peer), "" removes it. struct WireGuardPeerSettings { std::string name; std::string publicKey; std::optional<std::string> presharedKey; std::string endpoint; std::vector<std::string> allowedIps; int keepalive = 0; }; // Create: netdev and kind required; Edit: only what is set changes, kind // can't. members, if set, becomes the complete member list. // can't. members, if set, becomes the complete member list; peers the // complete peer list. A new WireGuard interface without privateKey gets a // generated one; generateKey replaces it with a new one. struct NetDevSettings { std::string netdev; std::string kind; Loading @@ -170,6 +208,15 @@ struct NetDevSettings { std::optional<std::string> hashPolicy; std::optional<bool> stp; std::optional<std::vector<std::string>> members; std::optional<std::string> privateKey; bool generateKey = false; std::optional<int> listenPort; std::optional<bool> routes; std::optional<std::vector<WireGuardPeerSettings>> peers; }; struct WireGuardKeys { std::string privateKey, publicKey, presharedKey; }; // Create: interface is required; the configuration is named Loading Loading @@ -254,6 +301,7 @@ public: bool createNetDev(const NetDevSettings &settings); bool editNetDev(const NetDevSettings &settings); bool deleteNetDev(const std::string &netdev); bool generateWireGuardKey(WireGuardKeys &out); // Signals: subscribe once, then waitSignal() returns the next one // (false on timeout or a closed connection; timeoutMs < 0 waits forever). Loading src/network.cpp +274 −41 File changed.Preview size limit exceeded, changes collapsed. Show changes src/network.h +39 −11 Changes for src/network.h: 39 added lines, 11 removed lines. Original line number Diff line number Diff line Loading @@ -6,6 +6,8 @@ #include <set> #include <cstdint> #include "wireguard.h" namespace syslite { // Parsed from systemd-networkd .network files Loading Loading @@ -33,13 +35,14 @@ namespace syslite { std::string name; }; // Parsed from systemd-networkd .netdev files: a bond or a bridge that // syslite creates; its members are the interfaces whose .network says // Bond=<name> / Bridge=<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 struct NetDevConfig { // [NetDev] std::string ifname; // Name=bond0 std::string kind; // Kind=bond | bridge std::string kind; // Kind=bond | bridge | wireguard // [Bond] std::string mode = "balance-rr"; // Mode=balance-rr, active-backup, balance-xor, Loading @@ -51,6 +54,15 @@ namespace syslite { // [Bridge] bool stp = false; // STP=yes // [WireGuard] std::string wgPrivateKey; // PrivateKey= (base64), or std::string wgPrivateKeyFile; // PrivateKeyFile= int wgListenPort = 0; // ListenPort= (0, "auto": the kernel picks one) uint32_t wgFwMark = 0; // FirewallMark= bool wgRoutes = false; // RouteTable=main: routes for the peers' AllowedIPs // [WireGuardPeer], one section each std::vector<WireGuardPeer> wgPeers; // Metadata std::string filePath; std::string name; // file name without ".netdev" Loading @@ -64,7 +76,7 @@ namespace syslite { bool adminUp = false; // IFF_UP bool carrier = false; bool stopped = false; // stopped on request (stays down) std::string kind; // "bond", "bridge" or "" (/sys/class/net/<if>/bonding, /bridge) std::string kind; // "bond", "bridge", "wireguard" or "" std::string master; // the bond or bridge it is a member of std::vector<std::string> addresses; // "a.b.c.d/len", IPv6 too const NetworkConfig *config = nullptr; // first matching configuration Loading Loading @@ -114,7 +126,8 @@ namespace syslite { // servers; it stays down (also for new-device events) until // started again // reload: re-read the files and reconfigure without taking the // link down (empty ifname: all interfaces) // link down (empty ifname: all interfaces; a .netdev's // device that isn't there yet is created) // forceReload: re-read the files and stop + start (empty: all) bool startInterface(const std::string &ifname, std::string *err); bool stopInterface(const std::string &ifname, std::string *err); Loading @@ -134,24 +147,32 @@ namespace syslite { // Re-read the .network files only (nothing is applied) void reloadConfigs(); // Bonds and bridges (.netdev files in ConfigDir). saveNetDev writes // Bonds, bridges 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. // 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. 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; 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(); // a bond or bridge device without a .netdev (left over, e.g. from an // aborted change): the device only is deleted; false if ifname // isn't such a device // a bond, bridge or WireGuard device without a .netdev (left over, // e.g. from an aborted change): the device only is deleted; false // if ifname isn't such a device bool deleteUnconfiguredLink(const std::string &ifname, std::string *err); // A WireGuard interface's public key ("" if its private key is // missing) and what the kernel knows of its peers (by public key) std::string wireGuardPublicKey(const NetDevConfig &nd) const; std::map<std::string, WireGuardPeerStatus> wireGuardPeers(const std::string &ifname); // Start listening for new network devices (netlink RTNLGRP_LINK) // Returns fd to poll in the main loop (-1 on failure) int startDeviceMonitor(); Loading @@ -167,6 +188,7 @@ namespace syslite { bool parseNetworkFile(const std::string &path, NetworkConfig &cfg); // ...and .netdev file bool parseNetDevFile(const std::string &path, NetDevConfig &nd); bool writeNetDevFile(const NetDevConfig &nd, std::string *err); bool writeNetworkFile(const NetworkConfig &cfg, std::string *err); // Netlink: create a bond/bridge (RTM_NEWLINK with IFLA_LINKINFO), Loading @@ -179,6 +201,12 @@ namespace syslite { bool setLinkAddress(const std::string &ifname, const std::string &mac); // does the existing device match nd (kind, bond mode, STP)? 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) bool configureWireGuard(const NetDevConfig &nd, std::string *err); void addWireGuardRoutes(const NetDevConfig &nd); // Netlink: a route to cidr over ifname (no gateway) bool addPrefixRoute(const std::string &ifname, const std::string &cidr); // Match an interface name against a pattern (supports trailing *) bool matchInterface(const std::string &pattern, const std::string &ifname); Loading src/sysbus/client.cpp +42 −0 Changes for src/sysbus/client.cpp: 42 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -94,6 +94,24 @@ NetDevInfo netDevFromFields(const std::vector<std::pair<std::string, std::string else if (k == "config_path") n.configPath = v; else if (k == "exists") n.exists = v == "yes"; else if (k == "member") n.members.push_back(v); else if (k == "public_key") n.publicKey = v; else if (k == "listen_port") n.listenPort = std::atoi(v.c_str()); else if (k == "routes") n.routes = v == "yes"; else if (k == "peer") { n.peers.emplace_back(); n.peers.back().publicKey = v; } else if (k.compare(0, 5, "peer_") == 0 && !n.peers.empty()) { WireGuardPeerInfo &p = n.peers.back(); if (k == "peer_name") p.name = v; else if (k == "peer_has_psk") p.hasPresharedKey = v == "yes"; else if (k == "peer_endpoint") p.endpoint = v; else if (k == "peer_allowed_ip") p.allowedIps.push_back(v); else if (k == "peer_keepalive") p.keepalive = std::atoi(v.c_str()); else if (k == "peer_current_endpoint") p.currentEndpoint = v; else if (k == "peer_handshake") p.lastHandshake = std::strtoll(v.c_str(), nullptr, 10); else if (k == "peer_rx") p.rxBytes = std::strtoull(v.c_str(), nullptr, 10); else if (k == "peer_tx") p.txBytes = std::strtoull(v.c_str(), nullptr, 10); } } return n; } Loading Loading @@ -340,6 +358,21 @@ static std::vector<std::pair<std::string, std::string>> netDevArgs(const NetDevS a.emplace_back("set_members", "yes"); // also when empty: no members for (auto &m : *s.members) a.emplace_back("member", m); } if (s.privateKey) a.emplace_back("private_key", *s.privateKey); if (s.generateKey) a.emplace_back("generate_key", "yes"); if (s.listenPort) a.emplace_back("listen_port", std::to_string(*s.listenPort)); if (s.routes) a.emplace_back("routes", *s.routes ? "yes" : "no"); if (s.peers) { a.emplace_back("set_peers", "yes"); // also when empty: no peers for (auto &p : *s.peers) { a.emplace_back("peer", p.publicKey); // starts the peer's fields if (!p.name.empty()) a.emplace_back("peer_name", p.name); if (p.presharedKey) a.emplace_back("peer_psk", *p.presharedKey); if (!p.endpoint.empty()) a.emplace_back("peer_endpoint", p.endpoint); for (auto &ip : p.allowedIps) a.emplace_back("peer_allowed_ip", ip); if (p.keepalive) a.emplace_back("peer_keepalive", std::to_string(p.keepalive)); } } return a; } Loading @@ -362,6 +395,15 @@ std::vector<NetDevInfo> Client::listNetDevs() { bool Client::createNetDev(const NetDevSettings &s) { return checkedCall(method::CreateNetDev, netDevArgs(s)); } bool Client::editNetDev(const NetDevSettings &s) { return checkedCall(method::EditNetDev, netDevArgs(s)); } bool Client::deleteNetDev(const std::string &n) { return checkedCall(method::DeleteNetDev, {{"netdev", n}}); } bool Client::generateWireGuardKey(WireGuardKeys &out) { Message r; if (!checkedCall(method::GenerateWireGuardKey, {}, &r)) return false; out.privateKey = r.get("private_key"); out.publicKey = r.get("public_key"); out.presharedKey = r.get("preshared_key"); return true; } bool Client::editInterface(const InterfaceSettings &s) { return checkedCall(method::EditInterface, settingsArgs(s)); } bool Client::deleteInterface(const std::string &interface, const std::string &config) { Loading Loading
CMakeLists.txt +1 −0 Changes for CMakeLists.txt: 1 added line, 0 removed lines. Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ add_executable(syslite src/service.cpp src/tty.cpp src/network.cpp src/wireguard.cpp src/busserver.cpp src/syslite.cpp ) Loading
include/sysbus/client.h +58 −10 Changes for include/sysbus/client.h: 58 added lines, 10 removed lines. Original line number Diff line number Diff line Loading @@ -63,14 +63,19 @@ constexpr const char *RestartInterface = "RestartInterface"; constexpr const char *ReloadInterface = "ReloadInterface"; // no interface: all constexpr const char *ForceReloadInterface = "ForceReloadInterface"; // no interface: all // Bonds and bridges: .netdev files in /etc/syslite/network, their members // get member .network files (Bond=/Bridge=). Create/Edit change only the // files (ReloadInterface without an interface creates the device and adds // its members); Delete also removes the device. Root only. // Bonds, bridges 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 // 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 // preshared keys). constexpr const char *ListNetDevs = "ListNetDevs"; // -> netdev, ... (repeated) constexpr const char *CreateNetDev = "CreateNetDev"; // netdev, kind, ... constexpr const char *EditNetDev = "EditNetDev"; // netdev, ... constexpr const char *DeleteNetDev = "DeleteNetDev"; // netdev // -> private_key, public_key, preshared_key: new keys, e.g. for a peer constexpr const char *GenerateWireGuardKey = "GenerateWireGuardKey"; } // namespace method namespace signal { Loading Loading @@ -141,26 +146,59 @@ struct InterfaceInfo { std::string memberOf; // configured: [Network] Bond= or Bridge= }; // A bond or bridge (.netdev). For a bond: mode (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. // A WireGuard peer as configured, and what the kernel knows of it. struct WireGuardPeerInfo { std::string name; std::string publicKey; bool hasPresharedKey = false; std::string endpoint; // configured, host:port std::vector<std::string> allowedIps; int keepalive = 0; // seconds, 0: off // live (the device exists and knows the peer) std::string currentEndpoint; long long lastHandshake = 0; // unix time, 0: never unsigned long long rxBytes = 0, txBytes = 0; }; // A bond, bridge or WireGuard interface (.netdev). For a bond: mode // (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' // AllowedIPs, peers. struct NetDevInfo { std::string name; // the interface, e.g. bond0 std::string kind; // bond or bridge std::string kind; // bond, bridge or wireguard std::string mode; int miimonMs = 0; std::string lacpRate; std::string hashPolicy; bool stp = false; std::string publicKey; int listenPort = 0; // 0: the kernel picks one bool routes = false; std::vector<WireGuardPeerInfo> peers; std::string config; // file name without ".netdev" std::string configPath; bool exists = false; // the device is there std::vector<std::string> members; // configured members }; // A WireGuard peer to configure. presharedKey: unset keeps the peer's // current one (none for a new peer), "" removes it. struct WireGuardPeerSettings { std::string name; std::string publicKey; std::optional<std::string> presharedKey; std::string endpoint; std::vector<std::string> allowedIps; int keepalive = 0; }; // Create: netdev and kind required; Edit: only what is set changes, kind // can't. members, if set, becomes the complete member list. // can't. members, if set, becomes the complete member list; peers the // complete peer list. A new WireGuard interface without privateKey gets a // generated one; generateKey replaces it with a new one. struct NetDevSettings { std::string netdev; std::string kind; Loading @@ -170,6 +208,15 @@ struct NetDevSettings { std::optional<std::string> hashPolicy; std::optional<bool> stp; std::optional<std::vector<std::string>> members; std::optional<std::string> privateKey; bool generateKey = false; std::optional<int> listenPort; std::optional<bool> routes; std::optional<std::vector<WireGuardPeerSettings>> peers; }; struct WireGuardKeys { std::string privateKey, publicKey, presharedKey; }; // Create: interface is required; the configuration is named Loading Loading @@ -254,6 +301,7 @@ public: bool createNetDev(const NetDevSettings &settings); bool editNetDev(const NetDevSettings &settings); bool deleteNetDev(const std::string &netdev); bool generateWireGuardKey(WireGuardKeys &out); // Signals: subscribe once, then waitSignal() returns the next one // (false on timeout or a closed connection; timeoutMs < 0 waits forever). Loading
src/network.h +39 −11 Changes for src/network.h: 39 added lines, 11 removed lines. Original line number Diff line number Diff line Loading @@ -6,6 +6,8 @@ #include <set> #include <cstdint> #include "wireguard.h" namespace syslite { // Parsed from systemd-networkd .network files Loading Loading @@ -33,13 +35,14 @@ namespace syslite { std::string name; }; // Parsed from systemd-networkd .netdev files: a bond or a bridge that // syslite creates; its members are the interfaces whose .network says // Bond=<name> / Bridge=<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 struct NetDevConfig { // [NetDev] std::string ifname; // Name=bond0 std::string kind; // Kind=bond | bridge std::string kind; // Kind=bond | bridge | wireguard // [Bond] std::string mode = "balance-rr"; // Mode=balance-rr, active-backup, balance-xor, Loading @@ -51,6 +54,15 @@ namespace syslite { // [Bridge] bool stp = false; // STP=yes // [WireGuard] std::string wgPrivateKey; // PrivateKey= (base64), or std::string wgPrivateKeyFile; // PrivateKeyFile= int wgListenPort = 0; // ListenPort= (0, "auto": the kernel picks one) uint32_t wgFwMark = 0; // FirewallMark= bool wgRoutes = false; // RouteTable=main: routes for the peers' AllowedIPs // [WireGuardPeer], one section each std::vector<WireGuardPeer> wgPeers; // Metadata std::string filePath; std::string name; // file name without ".netdev" Loading @@ -64,7 +76,7 @@ namespace syslite { bool adminUp = false; // IFF_UP bool carrier = false; bool stopped = false; // stopped on request (stays down) std::string kind; // "bond", "bridge" or "" (/sys/class/net/<if>/bonding, /bridge) std::string kind; // "bond", "bridge", "wireguard" or "" std::string master; // the bond or bridge it is a member of std::vector<std::string> addresses; // "a.b.c.d/len", IPv6 too const NetworkConfig *config = nullptr; // first matching configuration Loading Loading @@ -114,7 +126,8 @@ namespace syslite { // servers; it stays down (also for new-device events) until // started again // reload: re-read the files and reconfigure without taking the // link down (empty ifname: all interfaces) // link down (empty ifname: all interfaces; a .netdev's // device that isn't there yet is created) // forceReload: re-read the files and stop + start (empty: all) bool startInterface(const std::string &ifname, std::string *err); bool stopInterface(const std::string &ifname, std::string *err); Loading @@ -134,24 +147,32 @@ namespace syslite { // Re-read the .network files only (nothing is applied) void reloadConfigs(); // Bonds and bridges (.netdev files in ConfigDir). saveNetDev writes // Bonds, bridges 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. // 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. 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; 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(); // a bond or bridge device without a .netdev (left over, e.g. from an // aborted change): the device only is deleted; false if ifname // isn't such a device // a bond, bridge or WireGuard device without a .netdev (left over, // e.g. from an aborted change): the device only is deleted; false // if ifname isn't such a device bool deleteUnconfiguredLink(const std::string &ifname, std::string *err); // A WireGuard interface's public key ("" if its private key is // missing) and what the kernel knows of its peers (by public key) std::string wireGuardPublicKey(const NetDevConfig &nd) const; std::map<std::string, WireGuardPeerStatus> wireGuardPeers(const std::string &ifname); // Start listening for new network devices (netlink RTNLGRP_LINK) // Returns fd to poll in the main loop (-1 on failure) int startDeviceMonitor(); Loading @@ -167,6 +188,7 @@ namespace syslite { bool parseNetworkFile(const std::string &path, NetworkConfig &cfg); // ...and .netdev file bool parseNetDevFile(const std::string &path, NetDevConfig &nd); bool writeNetDevFile(const NetDevConfig &nd, std::string *err); bool writeNetworkFile(const NetworkConfig &cfg, std::string *err); // Netlink: create a bond/bridge (RTM_NEWLINK with IFLA_LINKINFO), Loading @@ -179,6 +201,12 @@ namespace syslite { bool setLinkAddress(const std::string &ifname, const std::string &mac); // does the existing device match nd (kind, bond mode, STP)? 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) bool configureWireGuard(const NetDevConfig &nd, std::string *err); void addWireGuardRoutes(const NetDevConfig &nd); // Netlink: a route to cidr over ifname (no gateway) bool addPrefixRoute(const std::string &ifname, const std::string &cidr); // Match an interface name against a pattern (supports trailing *) bool matchInterface(const std::string &pattern, const std::string &ifname); Loading
src/sysbus/client.cpp +42 −0 Changes for src/sysbus/client.cpp: 42 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -94,6 +94,24 @@ NetDevInfo netDevFromFields(const std::vector<std::pair<std::string, std::string else if (k == "config_path") n.configPath = v; else if (k == "exists") n.exists = v == "yes"; else if (k == "member") n.members.push_back(v); else if (k == "public_key") n.publicKey = v; else if (k == "listen_port") n.listenPort = std::atoi(v.c_str()); else if (k == "routes") n.routes = v == "yes"; else if (k == "peer") { n.peers.emplace_back(); n.peers.back().publicKey = v; } else if (k.compare(0, 5, "peer_") == 0 && !n.peers.empty()) { WireGuardPeerInfo &p = n.peers.back(); if (k == "peer_name") p.name = v; else if (k == "peer_has_psk") p.hasPresharedKey = v == "yes"; else if (k == "peer_endpoint") p.endpoint = v; else if (k == "peer_allowed_ip") p.allowedIps.push_back(v); else if (k == "peer_keepalive") p.keepalive = std::atoi(v.c_str()); else if (k == "peer_current_endpoint") p.currentEndpoint = v; else if (k == "peer_handshake") p.lastHandshake = std::strtoll(v.c_str(), nullptr, 10); else if (k == "peer_rx") p.rxBytes = std::strtoull(v.c_str(), nullptr, 10); else if (k == "peer_tx") p.txBytes = std::strtoull(v.c_str(), nullptr, 10); } } return n; } Loading Loading @@ -340,6 +358,21 @@ static std::vector<std::pair<std::string, std::string>> netDevArgs(const NetDevS a.emplace_back("set_members", "yes"); // also when empty: no members for (auto &m : *s.members) a.emplace_back("member", m); } if (s.privateKey) a.emplace_back("private_key", *s.privateKey); if (s.generateKey) a.emplace_back("generate_key", "yes"); if (s.listenPort) a.emplace_back("listen_port", std::to_string(*s.listenPort)); if (s.routes) a.emplace_back("routes", *s.routes ? "yes" : "no"); if (s.peers) { a.emplace_back("set_peers", "yes"); // also when empty: no peers for (auto &p : *s.peers) { a.emplace_back("peer", p.publicKey); // starts the peer's fields if (!p.name.empty()) a.emplace_back("peer_name", p.name); if (p.presharedKey) a.emplace_back("peer_psk", *p.presharedKey); if (!p.endpoint.empty()) a.emplace_back("peer_endpoint", p.endpoint); for (auto &ip : p.allowedIps) a.emplace_back("peer_allowed_ip", ip); if (p.keepalive) a.emplace_back("peer_keepalive", std::to_string(p.keepalive)); } } return a; } Loading @@ -362,6 +395,15 @@ std::vector<NetDevInfo> Client::listNetDevs() { bool Client::createNetDev(const NetDevSettings &s) { return checkedCall(method::CreateNetDev, netDevArgs(s)); } bool Client::editNetDev(const NetDevSettings &s) { return checkedCall(method::EditNetDev, netDevArgs(s)); } bool Client::deleteNetDev(const std::string &n) { return checkedCall(method::DeleteNetDev, {{"netdev", n}}); } bool Client::generateWireGuardKey(WireGuardKeys &out) { Message r; if (!checkedCall(method::GenerateWireGuardKey, {}, &r)) return false; out.privateKey = r.get("private_key"); out.publicKey = r.get("public_key"); out.presharedKey = r.get("preshared_key"); return true; } bool Client::editInterface(const InterfaceSettings &s) { return checkedCall(method::EditInterface, settingsArgs(s)); } bool Client::deleteInterface(const std::string &interface, const std::string &config) { Loading