Loading include/sysbus/client.h +11 −1 Changes for include/sysbus/client.h: 11 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -154,6 +154,8 @@ struct InterfaceInfo { std::string configAddress6; // [Network] Address= (IPv6) std::string gateway6; std::string ipv6AcceptRA; // [Network] IPv6AcceptRA=: yes, no, "" (the kernel's default) std::string ipForward; // [Network] IPForward=: yes, ipv4, ipv6, no, "" std::string ipMasquerade; // [Network] IPMasquerade=: yes, ipv4, ipv6, no, "" (firewalld does the NAT) std::vector<std::string> dns; 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 Loading Loading @@ -250,7 +252,10 @@ struct WireGuardKeys { // IPv6, next to DHCP or an IPv4 address; ipv6AcceptRA: yes (router // advertisements: default route, SLAAC address), no, "" (the kernel's // default). dhcp6: DHCPv6, started when router advertisements ask for it // (M flag: an address, O flag: name servers only). // (M flag: an address, O flag: name servers only). ipForward: yes, ipv4, // ipv6, no, "" -- routing on (global, as in networkd); ipMasquerade: the // same values -- what comes from this interface's networks is masqueraded // when it leaves by another one (by firewalld; implies ipForward). struct InterfaceSettings { std::string interface; std::string config; Loading @@ -262,6 +267,8 @@ struct InterfaceSettings { std::optional<std::string> address6; std::optional<std::string> gateway6; std::optional<std::string> ipv6AcceptRA; std::optional<std::string> ipForward; std::optional<std::string> ipMasquerade; std::optional<std::vector<std::string>> dns; }; Loading @@ -277,6 +284,9 @@ public: bool connect(const std::string &path = SYSBUS_SOCKET); bool connected() const { return _fd >= 0; } // for poll(): readable when a signal (or a reply) may have arrived; // then waitSignal(out, 0) until it returns false int fd() const { return _fd; } void close(); // Sends a method call and waits up to timeoutMs for its reply. Signals Loading src/network.cpp +31 −1 Changes for src/network.cpp: 31 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -244,6 +244,12 @@ bool NetworkManager::parseNetworkFile(const std::string &path, NetworkConfig &cf cfg.ipv6AcceptRA = val == "yes" || val == "true" || val == "1" ? "yes" : val == "no" || val == "false" || val == "0" ? "no" : ""; } else if (key == "IPForward" || key == "IPMasquerade") { (key == "IPForward" ? cfg.ipForward : cfg.ipMasquerade) = val == "yes" || val == "true" || val == "1" || val == "both" ? "yes" : val == "ipv4" || val == "ipv6" ? val : val == "no" || val == "false" || val == "0" ? "no" : ""; } else if (key == "DNS") { cfg.dns.push_back(val); } Loading Loading @@ -612,6 +618,7 @@ void NetworkManager::configureInterface(const std::string &ifname, const Network // Bring interface up (IPv6AcceptRA= first: SLAAC starts with the link) setIpv6Sysctls(ifname, cfg); setForwarding(ifname, cfg); if (cfg.linkUp) setLinkUp(ifname); Loading Loading @@ -960,6 +967,8 @@ bool NetworkManager::writeNetworkFile(const NetworkConfig &cfg, std::string *err if (!cfg.address6.empty()) f << "Address=" << cfg.address6 << "\n"; if (!cfg.gateway6.empty()) f << "Gateway=" << cfg.gateway6 << "\n"; if (!cfg.ipv6AcceptRA.empty()) f << "IPv6AcceptRA=" << cfg.ipv6AcceptRA << "\n"; if (!cfg.ipForward.empty()) f << "IPForward=" << cfg.ipForward << "\n"; if (!cfg.ipMasquerade.empty()) f << "IPMasquerade=" << cfg.ipMasquerade << "\n"; for (auto &d : cfg.dns) f << "DNS=" << d << "\n"; if (!cfg.bond.empty()) f << "Bond=" << cfg.bond << "\n"; if (!cfg.bridge.empty()) f << "Bridge=" << cfg.bridge << "\n"; Loading Loading @@ -1243,6 +1252,8 @@ bool NetworkManager::saveNetDev(const NetDevConfig &in, const std::vector<std::s cfg.address6.clear(); cfg.gateway6.clear(); cfg.ipv6AcceptRA.clear(); cfg.ipForward.clear(); cfg.ipMasquerade.clear(); cfg.dns.clear(); cfg.bond = nd.kind == "bond" ? nd.ifname : ""; cfg.bridge = nd.kind == "bridge" ? nd.ifname : ""; Loading Loading @@ -1300,7 +1311,7 @@ bool NetworkManager::writeNetDevFile(const NetDevConfig &nd, std::string *err) { static bool onlyCarriedVlans(const NetworkConfig &cfg) { return cfg.vlans.empty() && cfg.name == "10-" + cfg.matchName && !cfg.dhcp && !cfg.dhcp6 && cfg.address.empty() && cfg.gateway.empty() && cfg.address6.empty() && cfg.gateway6.empty() && cfg.ipv6AcceptRA.empty() && cfg.dns.empty() && cfg.bond.empty() && cfg.bridge.empty(); cfg.ipForward.empty() && cfg.ipMasquerade.empty() && cfg.dns.empty() && cfg.bond.empty() && cfg.bridge.empty(); } // VLAN=<nd.ifname> in the own configuration of nd.parent (10-<parent>: a Loading Loading @@ -1802,6 +1813,25 @@ void NetworkManager::setIpv6Sysctls(const std::string &ifname, const NetworkConf set("autoconf", on ? "1" : "0"); } void NetworkManager::setForwarding(const std::string &ifname, const NetworkConfig &cfg) { auto wants = [&](const char *family) { return cfg.ipForward == "yes" || cfg.ipForward == family || cfg.ipMasquerade == "yes" || cfg.ipMasquerade == family; }; const std::pair<const char *, const char *> sysctls[] = {{"ipv4", "/proc/sys/net/ipv4/ip_forward"}, {"ipv6", "/proc/sys/net/ipv6/conf/all/forwarding"}}; for (auto &[family, path] : sysctls) { if (!wants(family)) continue; std::ifstream in(path); std::string now; if (in.is_open() && std::getline(in, now) && trim(now) == "1") continue; int fd = ::open(path, O_WRONLY | O_CLOEXEC); bool ok = fd >= 0 && ::write(fd, "1", 1) == 1; if (fd >= 0) ::close(fd); if (ok) std::cout << "[syslite/net] " << ifname << ": " << family << " forwarding on" << std::endl; else std::cerr << "[syslite/net] " << ifname << ": cannot set " << path << std::endl; } } // ─── Netlink: set link up ─────────────────────────────────────────────────── bool NetworkManager::setLinkUp(const std::string &ifname) { Loading src/network.h +11 −0 Changes for src/network.h: 11 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -32,6 +32,15 @@ namespace syslite { // forwarding on; "": the kernel's default (accept_ra and autoconf as // they are) std::string ipv6AcceptRA; // IPForward=yes|ipv4|ipv6|no: packets are routed (as in networkd // the switch is global: net.ipv4.ip_forward, // net.ipv6.conf.all.forwarding; syslite only turns it on, firewalld // keeps it as its settings and all interfaces ask); "": not asked for std::string ipForward; // IPMasquerade=yes|ipv4|ipv6|no: what comes from this interface's // networks leaves the others with their address (firewalld does // the NAT); implies IPForward= for the family std::string ipMasquerade; std::vector<std::string> dns; // DNS=8.8.8.8 // [Network] Bond=/Bridge=: the interface is a member of that bond or Loading Loading @@ -289,6 +298,8 @@ namespace syslite { void flushAddresses(const std::string &ifname); // the IPv6 sysctls of cfg (IPv6AcceptRA=): before the link goes up void setIpv6Sysctls(const std::string &ifname, const NetworkConfig &cfg); // IPForward=/IPMasquerade=: forwarding on for the families they name void setForwarding(const std::string &ifname, const NetworkConfig &cfg); // Helper: get interface index int getIfIndex(const std::string &ifname); Loading src/service.cpp +14 −1 Changes for src/service.cpp: 14 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -103,7 +103,12 @@ namespace syslite { } // Simple dependency-based ordering: start services whose After // dependencies have already been started first // dependencies (and the units naming them in Before=) have already // been started first auto bare = [](std::string n) { if (n.size() > 8 && n.substr(n.size() - 8) == ".service") n = n.substr(0, n.size() - 8); return n; }; std::vector<std::string> pending; for (auto &name : toStart) if (_services[name].unit.kind != UnitKind::Mount) pending.push_back(name); Loading Loading @@ -131,6 +136,14 @@ namespace syslite { } } } for (auto &other : pending) { if (!depsReady) break; if (other == name) continue; auto *o = findService(other); if (!o) continue; for (auto &b : o->unit.before) if (bare(b) == name) depsReady = false; } if (depsReady) { startService(name); Loading src/sysbus/client.cpp +4 −0 Changes for src/sysbus/client.cpp: 4 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -76,6 +76,8 @@ InterfaceInfo interfaceFromFields(const std::vector<std::pair<std::string, std:: else if (k == "config_address6") i.configAddress6 = v; else if (k == "gateway6") i.gateway6 = v; else if (k == "ipv6_accept_ra") i.ipv6AcceptRA = v; else if (k == "ip_forward") i.ipForward = v; else if (k == "ip_masquerade") i.ipMasquerade = v; else if (k == "dns") i.dns.push_back(v); else if (k == "kind") i.kind = v; else if (k == "master") i.master = v; Loading Loading @@ -327,6 +329,8 @@ static std::vector<std::pair<std::string, std::string>> settingsArgs(const Inter if (s.address6) a.emplace_back("address6", *s.address6); if (s.gateway6) a.emplace_back("gateway6", *s.gateway6); if (s.ipv6AcceptRA) a.emplace_back("ipv6_accept_ra", *s.ipv6AcceptRA); if (s.ipForward) a.emplace_back("ip_forward", *s.ipForward); if (s.ipMasquerade) a.emplace_back("ip_masquerade", *s.ipMasquerade); if (s.dns) { a.emplace_back("set_dns", "yes"); // also when the list is empty: clears it for (auto &d : *s.dns) a.emplace_back("dns", d); Loading Loading
include/sysbus/client.h +11 −1 Changes for include/sysbus/client.h: 11 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -154,6 +154,8 @@ struct InterfaceInfo { std::string configAddress6; // [Network] Address= (IPv6) std::string gateway6; std::string ipv6AcceptRA; // [Network] IPv6AcceptRA=: yes, no, "" (the kernel's default) std::string ipForward; // [Network] IPForward=: yes, ipv4, ipv6, no, "" std::string ipMasquerade; // [Network] IPMasquerade=: yes, ipv4, ipv6, no, "" (firewalld does the NAT) std::vector<std::string> dns; 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 Loading Loading @@ -250,7 +252,10 @@ struct WireGuardKeys { // IPv6, next to DHCP or an IPv4 address; ipv6AcceptRA: yes (router // advertisements: default route, SLAAC address), no, "" (the kernel's // default). dhcp6: DHCPv6, started when router advertisements ask for it // (M flag: an address, O flag: name servers only). // (M flag: an address, O flag: name servers only). ipForward: yes, ipv4, // ipv6, no, "" -- routing on (global, as in networkd); ipMasquerade: the // same values -- what comes from this interface's networks is masqueraded // when it leaves by another one (by firewalld; implies ipForward). struct InterfaceSettings { std::string interface; std::string config; Loading @@ -262,6 +267,8 @@ struct InterfaceSettings { std::optional<std::string> address6; std::optional<std::string> gateway6; std::optional<std::string> ipv6AcceptRA; std::optional<std::string> ipForward; std::optional<std::string> ipMasquerade; std::optional<std::vector<std::string>> dns; }; Loading @@ -277,6 +284,9 @@ public: bool connect(const std::string &path = SYSBUS_SOCKET); bool connected() const { return _fd >= 0; } // for poll(): readable when a signal (or a reply) may have arrived; // then waitSignal(out, 0) until it returns false int fd() const { return _fd; } void close(); // Sends a method call and waits up to timeoutMs for its reply. Signals Loading
src/network.cpp +31 −1 Changes for src/network.cpp: 31 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -244,6 +244,12 @@ bool NetworkManager::parseNetworkFile(const std::string &path, NetworkConfig &cf cfg.ipv6AcceptRA = val == "yes" || val == "true" || val == "1" ? "yes" : val == "no" || val == "false" || val == "0" ? "no" : ""; } else if (key == "IPForward" || key == "IPMasquerade") { (key == "IPForward" ? cfg.ipForward : cfg.ipMasquerade) = val == "yes" || val == "true" || val == "1" || val == "both" ? "yes" : val == "ipv4" || val == "ipv6" ? val : val == "no" || val == "false" || val == "0" ? "no" : ""; } else if (key == "DNS") { cfg.dns.push_back(val); } Loading Loading @@ -612,6 +618,7 @@ void NetworkManager::configureInterface(const std::string &ifname, const Network // Bring interface up (IPv6AcceptRA= first: SLAAC starts with the link) setIpv6Sysctls(ifname, cfg); setForwarding(ifname, cfg); if (cfg.linkUp) setLinkUp(ifname); Loading Loading @@ -960,6 +967,8 @@ bool NetworkManager::writeNetworkFile(const NetworkConfig &cfg, std::string *err if (!cfg.address6.empty()) f << "Address=" << cfg.address6 << "\n"; if (!cfg.gateway6.empty()) f << "Gateway=" << cfg.gateway6 << "\n"; if (!cfg.ipv6AcceptRA.empty()) f << "IPv6AcceptRA=" << cfg.ipv6AcceptRA << "\n"; if (!cfg.ipForward.empty()) f << "IPForward=" << cfg.ipForward << "\n"; if (!cfg.ipMasquerade.empty()) f << "IPMasquerade=" << cfg.ipMasquerade << "\n"; for (auto &d : cfg.dns) f << "DNS=" << d << "\n"; if (!cfg.bond.empty()) f << "Bond=" << cfg.bond << "\n"; if (!cfg.bridge.empty()) f << "Bridge=" << cfg.bridge << "\n"; Loading Loading @@ -1243,6 +1252,8 @@ bool NetworkManager::saveNetDev(const NetDevConfig &in, const std::vector<std::s cfg.address6.clear(); cfg.gateway6.clear(); cfg.ipv6AcceptRA.clear(); cfg.ipForward.clear(); cfg.ipMasquerade.clear(); cfg.dns.clear(); cfg.bond = nd.kind == "bond" ? nd.ifname : ""; cfg.bridge = nd.kind == "bridge" ? nd.ifname : ""; Loading Loading @@ -1300,7 +1311,7 @@ bool NetworkManager::writeNetDevFile(const NetDevConfig &nd, std::string *err) { static bool onlyCarriedVlans(const NetworkConfig &cfg) { return cfg.vlans.empty() && cfg.name == "10-" + cfg.matchName && !cfg.dhcp && !cfg.dhcp6 && cfg.address.empty() && cfg.gateway.empty() && cfg.address6.empty() && cfg.gateway6.empty() && cfg.ipv6AcceptRA.empty() && cfg.dns.empty() && cfg.bond.empty() && cfg.bridge.empty(); cfg.ipForward.empty() && cfg.ipMasquerade.empty() && cfg.dns.empty() && cfg.bond.empty() && cfg.bridge.empty(); } // VLAN=<nd.ifname> in the own configuration of nd.parent (10-<parent>: a Loading Loading @@ -1802,6 +1813,25 @@ void NetworkManager::setIpv6Sysctls(const std::string &ifname, const NetworkConf set("autoconf", on ? "1" : "0"); } void NetworkManager::setForwarding(const std::string &ifname, const NetworkConfig &cfg) { auto wants = [&](const char *family) { return cfg.ipForward == "yes" || cfg.ipForward == family || cfg.ipMasquerade == "yes" || cfg.ipMasquerade == family; }; const std::pair<const char *, const char *> sysctls[] = {{"ipv4", "/proc/sys/net/ipv4/ip_forward"}, {"ipv6", "/proc/sys/net/ipv6/conf/all/forwarding"}}; for (auto &[family, path] : sysctls) { if (!wants(family)) continue; std::ifstream in(path); std::string now; if (in.is_open() && std::getline(in, now) && trim(now) == "1") continue; int fd = ::open(path, O_WRONLY | O_CLOEXEC); bool ok = fd >= 0 && ::write(fd, "1", 1) == 1; if (fd >= 0) ::close(fd); if (ok) std::cout << "[syslite/net] " << ifname << ": " << family << " forwarding on" << std::endl; else std::cerr << "[syslite/net] " << ifname << ": cannot set " << path << std::endl; } } // ─── Netlink: set link up ─────────────────────────────────────────────────── bool NetworkManager::setLinkUp(const std::string &ifname) { Loading
src/network.h +11 −0 Changes for src/network.h: 11 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -32,6 +32,15 @@ namespace syslite { // forwarding on; "": the kernel's default (accept_ra and autoconf as // they are) std::string ipv6AcceptRA; // IPForward=yes|ipv4|ipv6|no: packets are routed (as in networkd // the switch is global: net.ipv4.ip_forward, // net.ipv6.conf.all.forwarding; syslite only turns it on, firewalld // keeps it as its settings and all interfaces ask); "": not asked for std::string ipForward; // IPMasquerade=yes|ipv4|ipv6|no: what comes from this interface's // networks leaves the others with their address (firewalld does // the NAT); implies IPForward= for the family std::string ipMasquerade; std::vector<std::string> dns; // DNS=8.8.8.8 // [Network] Bond=/Bridge=: the interface is a member of that bond or Loading Loading @@ -289,6 +298,8 @@ namespace syslite { void flushAddresses(const std::string &ifname); // the IPv6 sysctls of cfg (IPv6AcceptRA=): before the link goes up void setIpv6Sysctls(const std::string &ifname, const NetworkConfig &cfg); // IPForward=/IPMasquerade=: forwarding on for the families they name void setForwarding(const std::string &ifname, const NetworkConfig &cfg); // Helper: get interface index int getIfIndex(const std::string &ifname); Loading
src/service.cpp +14 −1 Changes for src/service.cpp: 14 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -103,7 +103,12 @@ namespace syslite { } // Simple dependency-based ordering: start services whose After // dependencies have already been started first // dependencies (and the units naming them in Before=) have already // been started first auto bare = [](std::string n) { if (n.size() > 8 && n.substr(n.size() - 8) == ".service") n = n.substr(0, n.size() - 8); return n; }; std::vector<std::string> pending; for (auto &name : toStart) if (_services[name].unit.kind != UnitKind::Mount) pending.push_back(name); Loading Loading @@ -131,6 +136,14 @@ namespace syslite { } } } for (auto &other : pending) { if (!depsReady) break; if (other == name) continue; auto *o = findService(other); if (!o) continue; for (auto &b : o->unit.before) if (bare(b) == name) depsReady = false; } if (depsReady) { startService(name); Loading
src/sysbus/client.cpp +4 −0 Changes for src/sysbus/client.cpp: 4 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -76,6 +76,8 @@ InterfaceInfo interfaceFromFields(const std::vector<std::pair<std::string, std:: else if (k == "config_address6") i.configAddress6 = v; else if (k == "gateway6") i.gateway6 = v; else if (k == "ipv6_accept_ra") i.ipv6AcceptRA = v; else if (k == "ip_forward") i.ipForward = v; else if (k == "ip_masquerade") i.ipMasquerade = v; else if (k == "dns") i.dns.push_back(v); else if (k == "kind") i.kind = v; else if (k == "master") i.master = v; Loading Loading @@ -327,6 +329,8 @@ static std::vector<std::pair<std::string, std::string>> settingsArgs(const Inter if (s.address6) a.emplace_back("address6", *s.address6); if (s.gateway6) a.emplace_back("gateway6", *s.gateway6); if (s.ipv6AcceptRA) a.emplace_back("ipv6_accept_ra", *s.ipv6AcceptRA); if (s.ipForward) a.emplace_back("ip_forward", *s.ipForward); if (s.ipMasquerade) a.emplace_back("ip_masquerade", *s.ipMasquerade); if (s.dns) { a.emplace_back("set_dns", "yes"); // also when the list is empty: clears it for (auto &d : *s.dns) a.emplace_back("dns", d); Loading