Serenity Operating System
at master 120 lines 4.7 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * Copyright (c) 2022, Alex Major 4 * 5 * SPDX-License-Identifier: BSD-2-Clause 6 */ 7 8#include <AK/Assertions.h> 9#include <AK/IPv4Address.h> 10#include <AK/JsonArray.h> 11#include <AK/JsonObject.h> 12#include <AK/NumberFormat.h> 13#include <LibCore/ArgsParser.h> 14#include <LibCore/File.h> 15#include <LibCore/System.h> 16#include <LibMain/Main.h> 17#include <net/if.h> 18#include <netinet/in.h> 19 20ErrorOr<int> serenity_main(Main::Arguments arguments) 21{ 22 StringView value_ipv4 {}; 23 StringView value_adapter {}; 24 StringView value_mask {}; 25 26 Core::ArgsParser args_parser; 27 args_parser.set_general_help("Display or modify the configuration of each network interface."); 28 args_parser.add_option(value_ipv4, "Set the IP address of the selected network", "ipv4", 'i', "ip"); 29 args_parser.add_option(value_adapter, "Select a specific network adapter to configure", "adapter", 'a', "adapter"); 30 args_parser.add_option(value_mask, "Set the network mask of the selected network", "mask", 'm', "mask"); 31 args_parser.parse(arguments); 32 33 if (value_ipv4.is_empty() && value_adapter.is_empty() && value_mask.is_empty()) { 34 auto file = TRY(Core::File::open("/sys/kernel/net/adapters"sv, Core::File::OpenMode::Read)); 35 auto file_contents = TRY(file->read_until_eof()); 36 auto json = TRY(JsonValue::from_string(file_contents)); 37 38 json.as_array().for_each([](auto& value) { 39 auto& if_object = value.as_object(); 40 41 auto name = if_object.get_deprecated_string("name"sv).value_or({}); 42 auto class_name = if_object.get_deprecated_string("class_name"sv).value_or({}); 43 auto mac_address = if_object.get_deprecated_string("mac_address"sv).value_or({}); 44 auto ipv4_address = if_object.get_deprecated_string("ipv4_address"sv).value_or({}); 45 auto netmask = if_object.get_deprecated_string("ipv4_netmask"sv).value_or({}); 46 auto packets_in = if_object.get_u32("packets_in"sv).value_or(0); 47 auto bytes_in = if_object.get_u32("bytes_in"sv).value_or(0); 48 auto packets_out = if_object.get_u32("packets_out"sv).value_or(0); 49 auto bytes_out = if_object.get_u32("bytes_out"sv).value_or(0); 50 auto mtu = if_object.get_u32("mtu"sv).value_or(0); 51 52 outln("{}:", name); 53 outln("\tmac: {}", mac_address); 54 outln("\tipv4: {}", ipv4_address); 55 outln("\tnetmask: {}", netmask); 56 outln("\tclass: {}", class_name); 57 outln("\tRX: {} packets {} bytes ({})", packets_in, bytes_in, human_readable_size(bytes_in)); 58 outln("\tTX: {} packets {} bytes ({})", packets_out, bytes_out, human_readable_size(bytes_out)); 59 outln("\tMTU: {}", mtu); 60 outln(); 61 }); 62 } else { 63 64 if (value_adapter.is_empty()) { 65 warnln("No network adapter was specified."); 66 return 1; 67 } 68 69 DeprecatedString ifname = value_adapter; 70 71 if (!value_ipv4.is_empty()) { 72 auto address = IPv4Address::from_string(value_ipv4); 73 74 if (!address.has_value()) { 75 warnln("Invalid IPv4 address: '{}'", value_ipv4); 76 return 1; 77 } 78 79 auto fd = TRY(Core::System::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)); 80 81 struct ifreq ifr; 82 memset(&ifr, 0, sizeof(ifr)); 83 84 bool fits = ifname.copy_characters_to_buffer(ifr.ifr_name, IFNAMSIZ); 85 if (!fits) { 86 warnln("Interface name '{}' is too long", ifname); 87 return 1; 88 } 89 ifr.ifr_addr.sa_family = AF_INET; 90 ((sockaddr_in&)ifr.ifr_addr).sin_addr.s_addr = address.value().to_in_addr_t(); 91 92 TRY(Core::System::ioctl(fd, SIOCSIFADDR, &ifr)); 93 } 94 95 if (!value_mask.is_empty()) { 96 auto address = IPv4Address::from_string(value_mask); 97 98 if (!address.has_value()) { 99 warnln("Invalid IPv4 mask: '{}'", value_mask); 100 return 1; 101 } 102 103 auto fd = TRY(Core::System::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)); 104 105 struct ifreq ifr; 106 memset(&ifr, 0, sizeof(ifr)); 107 108 bool fits = ifname.copy_characters_to_buffer(ifr.ifr_name, IFNAMSIZ); 109 if (!fits) { 110 warnln("Interface name '{}' is too long", ifname); 111 return 1; 112 } 113 ifr.ifr_netmask.sa_family = AF_INET; 114 ((sockaddr_in&)ifr.ifr_netmask).sin_addr.s_addr = address.value().to_in_addr_t(); 115 116 TRY(Core::System::ioctl(fd, SIOCSIFNETMASK, &ifr)); 117 } 118 } 119 return 0; 120}