diff --git a/Kernel/Net/IPv4Socket.cpp b/Kernel/Net/IPv4Socket.cpp index 1b6951021b..2eb02b368c 100644 --- a/Kernel/Net/IPv4Socket.cpp +++ b/Kernel/Net/IPv4Socket.cpp @@ -13,6 +13,7 @@ #include #include #include +#include //#define IPV4_SOCKET_DEBUG @@ -337,7 +338,6 @@ KResult IPv4Socket::getsockopt(int level, int option, void* value, socklen_t* va if (level != IPPROTO_IP) return Socket::getsockopt(level, option, value, value_size); - switch (option) { case IP_TTL: if (*value_size < sizeof(int)) @@ -348,3 +348,36 @@ KResult IPv4Socket::getsockopt(int level, int option, void* value, socklen_t* va return KResult(-ENOPROTOOPT); } } + +int IPv4Socket::ioctl(FileDescription&, unsigned request, unsigned arg) +{ + auto* ifr = (ifreq*)arg; + if (!current->process().validate_read_typed(ifr)) + return -EFAULT; + + char namebuf[IFNAMSIZ + 1]; + memcpy(namebuf, ifr->ifr_name, IFNAMSIZ); + namebuf[sizeof(namebuf) - 1] = '\0'; + auto adapter = NetworkAdapter::lookup_by_name(namebuf); + if (!adapter) + return -ENODEV; + + switch (request) { + case SIOCSIFADDR: + if (!current->process().is_superuser()) + return -EPERM; + if (ifr->ifr_addr.sa_family != AF_INET) + return -EAFNOSUPPORT; + adapter->set_ipv4_address(IPv4Address(((sockaddr_in&)ifr->ifr_addr).sin_addr.s_addr)); + return 0; + + case SIOCGIFADDR: + if (!current->process().validate_write_typed(ifr)) + return -EFAULT; + ifr->ifr_addr.sa_family = AF_INET; + ((sockaddr_in&)ifr->ifr_addr).sin_addr.s_addr = adapter->ipv4_address().to_u32(); + return 0; + } + + return -EINVAL; +} diff --git a/Kernel/Net/IPv4Socket.h b/Kernel/Net/IPv4Socket.h index 2480634bee..ff59ae3831 100644 --- a/Kernel/Net/IPv4Socket.h +++ b/Kernel/Net/IPv4Socket.h @@ -34,6 +34,8 @@ public: virtual KResult setsockopt(int level, int option, const void*, socklen_t) override; virtual KResult getsockopt(int level, int option, void*, socklen_t*) override; + virtual int ioctl(FileDescription&, unsigned request, unsigned arg) override; + void did_receive(const IPv4Address& peer_address, u16 peer_port, KBuffer&&); const IPv4Address& local_address() const { return m_local_address; } diff --git a/Kernel/Net/NetworkAdapter.cpp b/Kernel/Net/NetworkAdapter.cpp index 9cba392b71..8c8dedbbdd 100644 --- a/Kernel/Net/NetworkAdapter.cpp +++ b/Kernel/Net/NetworkAdapter.cpp @@ -32,6 +32,16 @@ WeakPtr NetworkAdapter::from_ipv4_address(const IPv4Address& add return nullptr; } +WeakPtr NetworkAdapter::lookup_by_name(const StringView& name) +{ + NetworkAdapter* found_adapter = nullptr; + for_each([&](auto& adapter) { + if (adapter.name() == name) + found_adapter = &adapter; + }); + return found_adapter ? found_adapter->make_weak_ptr() : nullptr; +} + NetworkAdapter::NetworkAdapter() { // FIXME: I wanna lock :( diff --git a/Kernel/Net/NetworkAdapter.h b/Kernel/Net/NetworkAdapter.h index 9f145870b9..f1270ef552 100644 --- a/Kernel/Net/NetworkAdapter.h +++ b/Kernel/Net/NetworkAdapter.h @@ -18,6 +18,7 @@ class NetworkAdapter : public Weakable { public: static void for_each(Function); static WeakPtr from_ipv4_address(const IPv4Address&); + static WeakPtr lookup_by_name(const StringView&); virtual ~NetworkAdapter(); virtual const char* class_name() const = 0; diff --git a/Kernel/UnixTypes.h b/Kernel/UnixTypes.h index 34047f2916..9f69f7ef55 100644 --- a/Kernel/UnixTypes.h +++ b/Kernel/UnixTypes.h @@ -406,3 +406,33 @@ struct iovec { struct sched_param { int sched_priority; }; + +struct ifreq { +#define IFNAMSIZ 16 + char ifr_name[IFNAMSIZ]; + union { + struct sockaddr ifru_addr; + struct sockaddr ifru_dstaddr; + struct sockaddr ifru_broadaddr; + short ifru_flags; + int ifru_metric; + int64_t ifru_vnetid; + uint64_t ifru_media; + void* ifru_data; + unsigned int ifru_index; + } ifr_ifru; +#define ifr_addr ifr_ifru.ifru_addr // address +#define ifr_dstaddr ifr_ifru.ifru_dstaddr // other end of p-to-p link +#define ifr_broadaddr ifr_ifru.ifru_broadaddr // broadcast address +#define ifr_flags ifr_ifru.ifru_flags // flags +#define ifr_metric ifr_ifru.ifru_metric // metric +#define ifr_mtu ifr_ifru.ifru_metric // mtu (overload) +#define ifr_hardmtu ifr_ifru.ifru_metric // hardmtu (overload) +#define ifr_media ifr_ifru.ifru_media // media options +#define ifr_rdomainid ifr_ifru.ifru_metric // VRF instance (overload) +#define ifr_vnetid ifr_ifru.ifru_vnetid // Virtual Net Id +#define ifr_ttl ifr_ifru.ifru_metric // tunnel TTL (overload) +#define ifr_data ifr_ifru.ifru_data // for use by interface +#define ifr_index ifr_ifru.ifru_index // interface index +#define ifr_llprio ifr_ifru.ifru_metric // link layer priority +}; diff --git a/Libraries/LibC/net/if.h b/Libraries/LibC/net/if.h new file mode 100644 index 0000000000..9a5db281b9 --- /dev/null +++ b/Libraries/LibC/net/if.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include + +__BEGIN_DECLS + +struct ifreq { +#define IFNAMSIZ 16 + char ifr_name[IFNAMSIZ]; + union { + struct sockaddr ifru_addr; + struct sockaddr ifru_dstaddr; + struct sockaddr ifru_broadaddr; + short ifru_flags; + int ifru_metric; + int64_t ifru_vnetid; + uint64_t ifru_media; + void* ifru_data; + unsigned int ifru_index; + } ifr_ifru; +#define ifr_addr ifr_ifru.ifru_addr // address +#define ifr_dstaddr ifr_ifru.ifru_dstaddr // other end of p-to-p link +#define ifr_broadaddr ifr_ifru.ifru_broadaddr // broadcast address +#define ifr_flags ifr_ifru.ifru_flags // flags +#define ifr_metric ifr_ifru.ifru_metric // metric +#define ifr_mtu ifr_ifru.ifru_metric // mtu (overload) +#define ifr_hardmtu ifr_ifru.ifru_metric // hardmtu (overload) +#define ifr_media ifr_ifru.ifru_media // media options +#define ifr_rdomainid ifr_ifru.ifru_metric // VRF instance (overload) +#define ifr_vnetid ifr_ifru.ifru_vnetid // Virtual Net Id +#define ifr_ttl ifr_ifru.ifru_metric // tunnel TTL (overload) +#define ifr_data ifr_ifru.ifru_data // for use by interface +#define ifr_index ifr_ifru.ifru_index // interface index +#define ifr_llprio ifr_ifru.ifru_metric // link layer priority +}; + +__END_DECLS diff --git a/Libraries/LibC/sys/ioctl_numbers.h b/Libraries/LibC/sys/ioctl_numbers.h index 3156b950fa..2e0209adea 100644 --- a/Libraries/LibC/sys/ioctl_numbers.h +++ b/Libraries/LibC/sys/ioctl_numbers.h @@ -33,4 +33,6 @@ enum IOCtlNumber { FB_IOCTL_SET_RESOLUTION, FB_IOCTL_GET_BUFFER, FB_IOCTL_SET_BUFFER, + SIOCSIFADDR, + SIOCGIFADDR, };