Serenity Operating System
at master 105 lines 4.6 kB view raw
1/* 2 * Copyright (c) 2022, Maciej <sppmacd@pm.me> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/JsonArray.h> 8#include <AK/JsonObject.h> 9#include <AK/JsonParser.h> 10#include <LibCore/Command.h> 11#include <LibCore/ConfigFile.h> 12#include <LibCore/EventLoop.h> 13#include <LibCore/System.h> 14#include <LibMain/Main.h> 15#include <unistd.h> 16 17ErrorOr<int> serenity_main(Main::Arguments) 18{ 19 TRY(Core::System::pledge("stdio recvfd sendfd rpath unix exec proc")); 20 TRY(Core::System::unveil("/sys/kernel/net", "r")); 21 TRY(Core::System::unveil("/bin/DHCPClient", "x")); 22 TRY(Core::System::unveil("/etc/Network.ini", "r")); 23 TRY(Core::System::unveil("/bin/ifconfig", "x")); 24 TRY(Core::System::unveil("/bin/killall", "x")); 25 TRY(Core::System::unveil("/bin/route", "x")); 26 TRY(Core::System::unveil(nullptr, nullptr)); 27 28 auto config_file = TRY(Core::ConfigFile::open_for_system("Network")); 29 30 auto proc_net_adapters_file = TRY(Core::File::open("/sys/kernel/net/adapters"sv, Core::File::OpenMode::Read)); 31 auto data = TRY(proc_net_adapters_file->read_until_eof()); 32 JsonParser parser(data); 33 JsonValue proc_net_adapters_json = TRY(parser.parse()); 34 35 // Kill all previously running DHCPServers that may manage to re-assign the IP 36 // address before we clear it manually. 37 MUST(Core::command("killall"sv, { "DHCPClient" }, {})); 38 39 auto groups = config_file->groups(); 40 dbgln("Interfaces to configure: {}", groups); 41 42 struct InterfaceConfig { 43 bool enabled = false; 44 bool dhcp_enabled = false; 45 DeprecatedString ipv4_address = "0.0.0.0"sv; 46 DeprecatedString ipv4_netmask = "0.0.0.0"sv; 47 DeprecatedString ipv4_gateway = "0.0.0.0"sv; 48 }; 49 50 Vector<DeprecatedString> interfaces_with_dhcp_enabled; 51 proc_net_adapters_json.as_array().for_each([&](auto& value) { 52 auto& if_object = value.as_object(); 53 auto ifname = if_object.get_deprecated_string("name"sv).value_or({}); 54 55 if (ifname == "loop"sv) 56 return; 57 58 InterfaceConfig config; 59 if (!groups.contains_slow(ifname)) { 60 dbgln("Config for interface {} doesn't exist, enabling DHCP for it", ifname); 61 interfaces_with_dhcp_enabled.append(ifname); 62 } else { 63 config.enabled = config_file->read_bool_entry(ifname, "Enabled"sv, true); 64 config.dhcp_enabled = config_file->read_bool_entry(ifname, "DHCP"sv, false); 65 if (!config.dhcp_enabled) { 66 config.ipv4_address = config_file->read_entry(ifname, "IPv4Address"sv, "0.0.0.0"sv); 67 config.ipv4_netmask = config_file->read_entry(ifname, "IPv4Netmask"sv, "0.0.0.0"sv); 68 config.ipv4_gateway = config_file->read_entry(ifname, "IPv4Gateway"sv, "0.0.0.0"sv); 69 } 70 } 71 if (config.enabled) { 72 if (config.dhcp_enabled) 73 interfaces_with_dhcp_enabled.append(ifname); 74 else { 75 // FIXME: Propagate errors 76 // FIXME: Do this asynchronously 77 dbgln("Setting up interface {} statically ({}/{})", ifname, config.ipv4_address, config.ipv4_netmask); 78 MUST(Core::command("ifconfig"sv, { "-a", ifname.characters(), "-i", config.ipv4_address.characters(), "-m", config.ipv4_netmask.characters() }, {})); 79 if (config.ipv4_gateway != "0.0.0.0") { 80 MUST(Core::command("route"sv, { "del", "-n", "0.0.0.0", "-m", "0.0.0.0", "-i", ifname }, {})); 81 MUST(Core::command("route"sv, { "add", "-n", "0.0.0.0", "-m", "0.0.0.0", "-g", config.ipv4_gateway, "-i", ifname }, {})); 82 } 83 } 84 } else { 85 // FIXME: Propagate errors 86 dbgln("Disabling interface {}", ifname); 87 MUST(Core::command("route"sv, { "del", "-n", "0.0.0.0", "-m", "0.0.0.0", "-i", ifname }, {})); 88 MUST(Core::command("ifconfig"sv, { "-a", ifname.characters(), "-i", "0.0.0.0", "-m", "0.0.0.0" }, {})); 89 } 90 }); 91 92 if (!interfaces_with_dhcp_enabled.is_empty()) { 93 dbgln("Running DHCPClient for interfaces: {}", interfaces_with_dhcp_enabled); 94 Vector<char*> args; 95 char dhcp_client_arg[] = "DHCPClient"; 96 args.append(dhcp_client_arg); 97 for (auto& iface : interfaces_with_dhcp_enabled) 98 args.append(const_cast<char*>(iface.characters())); 99 args.append(nullptr); 100 101 auto dhcp_client_pid = TRY(Core::System::posix_spawnp("DHCPClient"sv, nullptr, nullptr, args.data(), environ)); 102 TRY(Core::System::disown(dhcp_client_pid)); 103 } 104 return 0; 105}