mirror of
https://github.com/RGBCube/serenity
synced 2025-05-25 12:45:06 +00:00
IPv4: Implement socket ioctls SIOCGIFADDR and SIOCSIFADDR
This allows userspace programs to get and set (superuser-only) the IPv4 address of a network adapter. :^)
This commit is contained in:
parent
a3575f3c60
commit
2482fc3538
7 changed files with 117 additions and 1 deletions
|
@ -13,6 +13,7 @@
|
||||||
#include <Kernel/Process.h>
|
#include <Kernel/Process.h>
|
||||||
#include <Kernel/UnixTypes.h>
|
#include <Kernel/UnixTypes.h>
|
||||||
#include <LibC/errno_numbers.h>
|
#include <LibC/errno_numbers.h>
|
||||||
|
#include <LibC/sys/ioctl_numbers.h>
|
||||||
|
|
||||||
//#define IPV4_SOCKET_DEBUG
|
//#define IPV4_SOCKET_DEBUG
|
||||||
|
|
||||||
|
@ -337,7 +338,6 @@ KResult IPv4Socket::getsockopt(int level, int option, void* value, socklen_t* va
|
||||||
if (level != IPPROTO_IP)
|
if (level != IPPROTO_IP)
|
||||||
return Socket::getsockopt(level, option, value, value_size);
|
return Socket::getsockopt(level, option, value, value_size);
|
||||||
|
|
||||||
|
|
||||||
switch (option) {
|
switch (option) {
|
||||||
case IP_TTL:
|
case IP_TTL:
|
||||||
if (*value_size < sizeof(int))
|
if (*value_size < sizeof(int))
|
||||||
|
@ -348,3 +348,36 @@ KResult IPv4Socket::getsockopt(int level, int option, void* value, socklen_t* va
|
||||||
return KResult(-ENOPROTOOPT);
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -34,6 +34,8 @@ public:
|
||||||
virtual KResult setsockopt(int level, int option, const void*, socklen_t) override;
|
virtual KResult setsockopt(int level, int option, const void*, socklen_t) override;
|
||||||
virtual KResult getsockopt(int level, int option, 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&&);
|
void did_receive(const IPv4Address& peer_address, u16 peer_port, KBuffer&&);
|
||||||
|
|
||||||
const IPv4Address& local_address() const { return m_local_address; }
|
const IPv4Address& local_address() const { return m_local_address; }
|
||||||
|
|
|
@ -32,6 +32,16 @@ WeakPtr<NetworkAdapter> NetworkAdapter::from_ipv4_address(const IPv4Address& add
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WeakPtr<NetworkAdapter> 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()
|
NetworkAdapter::NetworkAdapter()
|
||||||
{
|
{
|
||||||
// FIXME: I wanna lock :(
|
// FIXME: I wanna lock :(
|
||||||
|
|
|
@ -18,6 +18,7 @@ class NetworkAdapter : public Weakable<NetworkAdapter> {
|
||||||
public:
|
public:
|
||||||
static void for_each(Function<void(NetworkAdapter&)>);
|
static void for_each(Function<void(NetworkAdapter&)>);
|
||||||
static WeakPtr<NetworkAdapter> from_ipv4_address(const IPv4Address&);
|
static WeakPtr<NetworkAdapter> from_ipv4_address(const IPv4Address&);
|
||||||
|
static WeakPtr<NetworkAdapter> lookup_by_name(const StringView&);
|
||||||
virtual ~NetworkAdapter();
|
virtual ~NetworkAdapter();
|
||||||
|
|
||||||
virtual const char* class_name() const = 0;
|
virtual const char* class_name() const = 0;
|
||||||
|
|
|
@ -406,3 +406,33 @@ struct iovec {
|
||||||
struct sched_param {
|
struct sched_param {
|
||||||
int sched_priority;
|
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
|
||||||
|
};
|
||||||
|
|
38
Libraries/LibC/net/if.h
Normal file
38
Libraries/LibC/net/if.h
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
__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
|
|
@ -33,4 +33,6 @@ enum IOCtlNumber {
|
||||||
FB_IOCTL_SET_RESOLUTION,
|
FB_IOCTL_SET_RESOLUTION,
|
||||||
FB_IOCTL_GET_BUFFER,
|
FB_IOCTL_GET_BUFFER,
|
||||||
FB_IOCTL_SET_BUFFER,
|
FB_IOCTL_SET_BUFFER,
|
||||||
|
SIOCSIFADDR,
|
||||||
|
SIOCGIFADDR,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue