Serenity Operating System
at hosted 578 lines 19 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <AK/StringBuilder.h> 28#include <Kernel/FileSystem/FileDescription.h> 29#include <Kernel/Net/ARP.h> 30#include <Kernel/Net/ICMP.h> 31#include <Kernel/Net/IPv4.h> 32#include <Kernel/Net/IPv4Socket.h> 33#include <Kernel/Net/NetworkAdapter.h> 34#include <Kernel/Net/Routing.h> 35#include <Kernel/Net/TCP.h> 36#include <Kernel/Net/TCPSocket.h> 37#include <Kernel/Net/UDP.h> 38#include <Kernel/Net/UDPSocket.h> 39#include <Kernel/Process.h> 40#include <Kernel/UnixTypes.h> 41#include <LibC/errno_numbers.h> 42#include <LibC/sys/ioctl_numbers.h> 43 44//#define IPV4_SOCKET_DEBUG 45 46namespace Kernel { 47 48Lockable<HashTable<IPv4Socket*>>& IPv4Socket::all_sockets() 49{ 50 static Lockable<HashTable<IPv4Socket*>>* s_table; 51 if (!s_table) 52 s_table = new Lockable<HashTable<IPv4Socket*>>; 53 return *s_table; 54} 55 56KResultOr<NonnullRefPtr<Socket>> IPv4Socket::create(int type, int protocol) 57{ 58 if (type == SOCK_STREAM) 59 return TCPSocket::create(protocol); 60 if (type == SOCK_DGRAM) 61 return UDPSocket::create(protocol); 62 if (type == SOCK_RAW) 63 return adopt(*new IPv4Socket(type, protocol)); 64 return KResult(-EINVAL); 65} 66 67IPv4Socket::IPv4Socket(int type, int protocol) 68 : Socket(AF_INET, type, protocol) 69{ 70#ifdef IPV4_SOCKET_DEBUG 71 dbg() << "IPv4Socket{" << this << "} created with type=" << type << ", protocol=" << protocol; 72#endif 73 m_buffer_mode = type == SOCK_STREAM ? BufferMode::Bytes : BufferMode::Packets; 74 if (m_buffer_mode == BufferMode::Bytes) { 75 m_scratch_buffer = KBuffer::create_with_size(65536); 76 } 77 LOCKER(all_sockets().lock()); 78 all_sockets().resource().set(this); 79} 80 81IPv4Socket::~IPv4Socket() 82{ 83 LOCKER(all_sockets().lock()); 84 all_sockets().resource().remove(this); 85} 86 87void IPv4Socket::get_local_address(sockaddr* address, socklen_t* address_size) 88{ 89 sockaddr_in local_address = { AF_INET, htons(m_local_port), { m_local_address.to_in_addr_t() }, { 0 } }; 90 memcpy(address, &local_address, min(static_cast<size_t>(*address_size), sizeof(sockaddr_in))); 91 *address_size = sizeof(sockaddr_in); 92} 93 94void IPv4Socket::get_peer_address(sockaddr* address, socklen_t* address_size) 95{ 96 sockaddr_in peer_address = { AF_INET, htons(m_peer_port), { m_peer_address.to_in_addr_t() }, { 0 } }; 97 memcpy(address, &peer_address, min(static_cast<size_t>(*address_size), sizeof(sockaddr_in))); 98 *address_size = sizeof(sockaddr_in); 99} 100 101KResult IPv4Socket::bind(const sockaddr* user_address, socklen_t address_size) 102{ 103 ASSERT(setup_state() == SetupState::Unstarted); 104 if (address_size != sizeof(sockaddr_in)) 105 return KResult(-EINVAL); 106 107 sockaddr_in address; 108 copy_from_user(&address, user_address, sizeof(sockaddr_in)); 109 110 if (address.sin_family != AF_INET) 111 return KResult(-EINVAL); 112 113 auto requested_local_port = ntohs(address.sin_port); 114 if (!Process::current->is_superuser()) { 115 if (requested_local_port < 1024) { 116 dbg() << "UID " << Process::current->uid() << " attempted to bind " << class_name() << " to port " << requested_local_port; 117 return KResult(-EACCES); 118 } 119 } 120 121 m_local_address = IPv4Address((const u8*)&address.sin_addr.s_addr); 122 m_local_port = requested_local_port; 123 124#ifdef IPV4_SOCKET_DEBUG 125 dbg() << "IPv4Socket::bind " << class_name() << "{" << this << "} to " << m_local_address << ":" << m_local_port; 126#endif 127 128 return protocol_bind(); 129} 130 131KResult IPv4Socket::listen(size_t backlog) 132{ 133 int rc = allocate_local_port_if_needed(); 134 if (rc < 0) 135 return KResult(-EADDRINUSE); 136 137 set_backlog(backlog); 138 m_role = Role::Listener; 139 140#ifdef IPV4_SOCKET_DEBUG 141 dbg() << "IPv4Socket{" << this << "} listening with backlog=" << backlog; 142#endif 143 144 return protocol_listen(); 145} 146 147KResult IPv4Socket::connect(FileDescription& description, const sockaddr* address, socklen_t address_size, ShouldBlock should_block) 148{ 149 if (address_size != sizeof(sockaddr_in)) 150 return KResult(-EINVAL); 151 if (address->sa_family != AF_INET) 152 return KResult(-EINVAL); 153 if (m_role == Role::Connected) 154 return KResult(-EISCONN); 155 156 auto& ia = *(const sockaddr_in*)address; 157 m_peer_address = IPv4Address((const u8*)&ia.sin_addr.s_addr); 158 m_peer_port = ntohs(ia.sin_port); 159 160 return protocol_connect(description, should_block); 161} 162 163void IPv4Socket::attach(FileDescription&) 164{ 165} 166 167void IPv4Socket::detach(FileDescription&) 168{ 169} 170 171bool IPv4Socket::can_read(const FileDescription&) const 172{ 173 if (m_role == Role::Listener) 174 return can_accept(); 175 if (protocol_is_disconnected()) 176 return true; 177 return m_can_read; 178} 179 180bool IPv4Socket::can_write(const FileDescription&) const 181{ 182 return is_connected(); 183} 184 185int IPv4Socket::allocate_local_port_if_needed() 186{ 187 if (m_local_port) 188 return m_local_port; 189 int port = protocol_allocate_local_port(); 190 if (port < 0) 191 return port; 192 m_local_port = (u16)port; 193 return port; 194} 195 196ssize_t IPv4Socket::sendto(FileDescription&, const void* data, size_t data_length, int flags, const sockaddr* addr, socklen_t addr_length) 197{ 198 (void)flags; 199 if (addr && addr_length != sizeof(sockaddr_in)) 200 return -EINVAL; 201 202 if (addr) { 203 if (addr->sa_family != AF_INET) { 204 klog() << "sendto: Bad address family: " << addr->sa_family << " is not AF_INET!"; 205 return -EAFNOSUPPORT; 206 } 207 208 auto& ia = *(const sockaddr_in*)addr; 209 m_peer_address = IPv4Address((const u8*)&ia.sin_addr.s_addr); 210 m_peer_port = ntohs(ia.sin_port); 211 } 212 213 auto routing_decision = route_to(m_peer_address, m_local_address, bound_interface()); 214 if (routing_decision.is_zero()) 215 return -EHOSTUNREACH; 216 217 if (m_local_address.to_u32() == 0) 218 m_local_address = routing_decision.adapter->ipv4_address(); 219 220 int rc = allocate_local_port_if_needed(); 221 if (rc < 0) 222 return rc; 223 224#ifdef IPV4_SOCKET_DEBUG 225 klog() << "sendto: destination=" << m_peer_address.to_string().characters() << ":" << m_peer_port; 226#endif 227 228 if (type() == SOCK_RAW) { 229 routing_decision.adapter->send_ipv4(routing_decision.next_hop, m_peer_address, (IPv4Protocol)protocol(), (const u8*)data, data_length, m_ttl); 230 return data_length; 231 } 232 233 int nsent = protocol_send(data, data_length); 234 if (nsent > 0) 235 Thread::current->did_ipv4_socket_write(nsent); 236 return nsent; 237} 238 239ssize_t IPv4Socket::receive_byte_buffered(FileDescription& description, void* buffer, size_t buffer_length, int, sockaddr*, socklen_t*) 240{ 241 Locker locker(lock()); 242 if (m_receive_buffer.is_empty()) { 243 if (protocol_is_disconnected()) 244 return 0; 245 if (!description.is_blocking()) 246 return -EAGAIN; 247 248 locker.unlock(); 249 auto res = Thread::current->block<Thread::ReadBlocker>(description); 250 locker.lock(); 251 252 if (!m_can_read) { 253 if (res != Thread::BlockResult::WokeNormally) 254 return -EINTR; 255 256 // Unblocked due to timeout. 257 return -EAGAIN; 258 } 259 } 260 261 ASSERT(!m_receive_buffer.is_empty()); 262 int nreceived = m_receive_buffer.read((u8*)buffer, buffer_length); 263 if (nreceived > 0) 264 Thread::current->did_ipv4_socket_read((size_t)nreceived); 265 266 m_can_read = !m_receive_buffer.is_empty(); 267 return nreceived; 268} 269 270ssize_t IPv4Socket::receive_packet_buffered(FileDescription& description, void* buffer, size_t buffer_length, int flags, sockaddr* addr, socklen_t* addr_length) 271{ 272 Locker locker(lock()); 273 ReceivedPacket packet; 274 { 275 if (m_receive_queue.is_empty()) { 276 // FIXME: Shouldn't this return -ENOTCONN instead of EOF? 277 // But if so, we still need to deliver at least one EOF read to userspace.. right? 278 if (protocol_is_disconnected()) 279 return 0; 280 if (!description.is_blocking()) 281 return -EAGAIN; 282 } 283 284 if (!m_receive_queue.is_empty()) { 285 packet = m_receive_queue.take_first(); 286 m_can_read = !m_receive_queue.is_empty(); 287#ifdef IPV4_SOCKET_DEBUG 288 dbg() << "IPv4Socket(" << this << "): recvfrom without blocking " << packet.data.value().size() << " bytes, packets in queue: " << m_receive_queue.size_slow(); 289#endif 290 } 291 } 292 if (!packet.data.has_value()) { 293 if (protocol_is_disconnected()) { 294 dbg() << "IPv4Socket{" << this << "} is protocol-disconnected, returning 0 in recvfrom!"; 295 return 0; 296 } 297 298 locker.unlock(); 299 auto res = Thread::current->block<Thread::ReadBlocker>(description); 300 locker.lock(); 301 302 if (!m_can_read) { 303 if (res != Thread::BlockResult::WokeNormally) 304 return -EINTR; 305 306 // Unblocked due to timeout. 307 return -EAGAIN; 308 } 309 ASSERT(m_can_read); 310 ASSERT(!m_receive_queue.is_empty()); 311 packet = m_receive_queue.take_first(); 312 m_can_read = !m_receive_queue.is_empty(); 313#ifdef IPV4_SOCKET_DEBUG 314 dbg() << "IPv4Socket(" << this << "): recvfrom with blocking " << packet.data.value().size() << " bytes, packets in queue: " << m_receive_queue.size_slow(); 315#endif 316 } 317 ASSERT(packet.data.has_value()); 318 auto& ipv4_packet = *(const IPv4Packet*)(packet.data.value().data()); 319 320 if (addr) { 321#ifdef IPV4_SOCKET_DEBUG 322 dbg() << "Incoming packet is from: " << packet.peer_address << ":" << packet.peer_port; 323#endif 324 auto& ia = *(sockaddr_in*)addr; 325 memcpy(&ia.sin_addr, &packet.peer_address, sizeof(IPv4Address)); 326 ia.sin_port = htons(packet.peer_port); 327 ia.sin_family = AF_INET; 328 ASSERT(addr_length); 329 *addr_length = sizeof(sockaddr_in); 330 } 331 332 if (type() == SOCK_RAW) { 333 ASSERT(buffer_length >= ipv4_packet.payload_size()); 334 memcpy(buffer, ipv4_packet.payload(), ipv4_packet.payload_size()); 335 return ipv4_packet.payload_size(); 336 } 337 338 return protocol_receive(packet.data.value(), buffer, buffer_length, flags); 339} 340 341ssize_t IPv4Socket::recvfrom(FileDescription& description, void* buffer, size_t buffer_length, int flags, sockaddr* addr, socklen_t* addr_length) 342{ 343 if (addr_length && *addr_length < sizeof(sockaddr_in)) 344 return -EINVAL; 345 346#ifdef IPV4_SOCKET_DEBUG 347 klog() << "recvfrom: type=" << type() << ", local_port=" << local_port(); 348#endif 349 350 ssize_t nreceived = 0; 351 if (buffer_mode() == BufferMode::Bytes) 352 nreceived = receive_byte_buffered(description, buffer, buffer_length, flags, addr, addr_length); 353 else 354 nreceived = receive_packet_buffered(description, buffer, buffer_length, flags, addr, addr_length); 355 356 if (nreceived > 0) 357 Thread::current->did_ipv4_socket_read(nreceived); 358 return nreceived; 359} 360 361bool IPv4Socket::did_receive(const IPv4Address& source_address, u16 source_port, KBuffer&& packet) 362{ 363 LOCKER(lock()); 364 365 if (is_shut_down_for_reading()) 366 return false; 367 368 auto packet_size = packet.size(); 369 370 if (buffer_mode() == BufferMode::Bytes) { 371 size_t space_in_receive_buffer = m_receive_buffer.space_for_writing(); 372 if (packet_size > space_in_receive_buffer) { 373 dbg() << "IPv4Socket(" << this << "): did_receive refusing packet since buffer is full."; 374 ASSERT(m_can_read); 375 return false; 376 } 377 int nreceived = protocol_receive(packet, m_scratch_buffer.value().data(), m_scratch_buffer.value().size(), 0); 378 m_receive_buffer.write(m_scratch_buffer.value().data(), nreceived); 379 m_can_read = !m_receive_buffer.is_empty(); 380 } else { 381 // FIXME: Maybe track the number of packets so we don't have to walk the entire packet queue to count them.. 382 if (m_receive_queue.size_slow() > 2000) { 383 dbg() << "IPv4Socket(" << this << "): did_receive refusing packet since queue is full."; 384 return false; 385 } 386 m_receive_queue.append({ source_address, source_port, move(packet) }); 387 m_can_read = true; 388 } 389 m_bytes_received += packet_size; 390#ifdef IPV4_SOCKET_DEBUG 391 if (buffer_mode() == BufferMode::Bytes) 392 dbg() << "IPv4Socket(" << this << "): did_receive " << packet_size << " bytes, total_received=" << m_bytes_received; 393 else 394 dbg() << "IPv4Socket(" << this << "): did_receive " << packet_size << " bytes, total_received=" << m_bytes_received << ", packets in queue: " << m_receive_queue.size_slow(); 395#endif 396 return true; 397} 398 399String IPv4Socket::absolute_path(const FileDescription&) const 400{ 401 if (m_role == Role::None) 402 return "socket"; 403 404 StringBuilder builder; 405 builder.append("socket:"); 406 407 builder.appendf("%s:%d", m_local_address.to_string().characters(), m_local_port); 408 if (m_role == Role::Accepted || m_role == Role::Connected) 409 builder.appendf(" / %s:%d", m_peer_address.to_string().characters(), m_peer_port); 410 411 switch (m_role) { 412 case Role::Listener: 413 builder.append(" (listening)"); 414 break; 415 case Role::Accepted: 416 builder.append(" (accepted)"); 417 break; 418 case Role::Connected: 419 builder.append(" (connected)"); 420 break; 421 case Role::Connecting: 422 builder.append(" (connecting)"); 423 break; 424 default: 425 ASSERT_NOT_REACHED(); 426 } 427 428 return builder.to_string(); 429} 430 431KResult IPv4Socket::setsockopt(int level, int option, const void* value, socklen_t value_size) 432{ 433 if (level != IPPROTO_IP) 434 return Socket::setsockopt(level, option, value, value_size); 435 436 switch (option) { 437 case IP_TTL: 438 if (value_size < sizeof(int)) 439 return KResult(-EINVAL); 440 if (*(const int*)value < 0 || *(const int*)value > 255) 441 return KResult(-EINVAL); 442 m_ttl = (u8) * (const int*)value; 443 return KSuccess; 444 default: 445 return KResult(-ENOPROTOOPT); 446 } 447} 448 449KResult IPv4Socket::getsockopt(FileDescription& description, int level, int option, void* value, socklen_t* value_size) 450{ 451 if (level != IPPROTO_IP) 452 return Socket::getsockopt(description, level, option, value, value_size); 453 454 switch (option) { 455 case IP_TTL: 456 if (*value_size < sizeof(int)) 457 return KResult(-EINVAL); 458 *(int*)value = m_ttl; 459 return KSuccess; 460 default: 461 return KResult(-ENOPROTOOPT); 462 } 463} 464 465int IPv4Socket::ioctl(FileDescription&, unsigned request, unsigned arg) 466{ 467 REQUIRE_PROMISE(inet); 468 469 auto ioctl_route = [request, arg]() { 470 auto* route = (rtentry*)arg; 471 if (!Process::current->validate_read_typed(route)) 472 return -EFAULT; 473 474 char namebuf[IFNAMSIZ + 1]; 475 memcpy(namebuf, route->rt_dev, IFNAMSIZ); 476 namebuf[sizeof(namebuf) - 1] = '\0'; 477 478 auto adapter = NetworkAdapter::lookup_by_name(namebuf); 479 if (!adapter) 480 return -ENODEV; 481 482 switch (request) { 483 case SIOCADDRT: 484 if (!Process::current->is_superuser()) 485 return -EPERM; 486 if (route->rt_gateway.sa_family != AF_INET) 487 return -EAFNOSUPPORT; 488 if ((route->rt_flags & (RTF_UP | RTF_GATEWAY)) != (RTF_UP | RTF_GATEWAY)) 489 return -EINVAL; // FIXME: Find the correct value to return 490 adapter->set_ipv4_gateway(IPv4Address(((sockaddr_in&)route->rt_gateway).sin_addr.s_addr)); 491 return 0; 492 493 case SIOCDELRT: 494 // FIXME: Support gateway deletion 495 return 0; 496 } 497 498 return -EINVAL; 499 }; 500 501 auto ioctl_interface = [request, arg]() { 502 auto* ifr = (ifreq*)arg; 503 if (!Process::current->validate_read_typed(ifr)) 504 return -EFAULT; 505 506 char namebuf[IFNAMSIZ + 1]; 507 memcpy(namebuf, ifr->ifr_name, IFNAMSIZ); 508 namebuf[sizeof(namebuf) - 1] = '\0'; 509 510 auto adapter = NetworkAdapter::lookup_by_name(namebuf); 511 if (!adapter) 512 return -ENODEV; 513 514 switch (request) { 515 case SIOCSIFADDR: 516 if (!Process::current->is_superuser()) 517 return -EPERM; 518 if (ifr->ifr_addr.sa_family != AF_INET) 519 return -EAFNOSUPPORT; 520 adapter->set_ipv4_address(IPv4Address(((sockaddr_in&)ifr->ifr_addr).sin_addr.s_addr)); 521 return 0; 522 523 case SIOCSIFNETMASK: 524 if (!Process::current->is_superuser()) 525 return -EPERM; 526 if (ifr->ifr_addr.sa_family != AF_INET) 527 return -EAFNOSUPPORT; 528 adapter->set_ipv4_netmask(IPv4Address(((sockaddr_in&)ifr->ifr_netmask).sin_addr.s_addr)); 529 return 0; 530 531 case SIOCGIFADDR: 532 if (!Process::current->validate_write_typed(ifr)) 533 return -EFAULT; 534 ifr->ifr_addr.sa_family = AF_INET; 535 ((sockaddr_in&)ifr->ifr_addr).sin_addr.s_addr = adapter->ipv4_address().to_u32(); 536 return 0; 537 538 case SIOCGIFHWADDR: 539 if (!Process::current->validate_write_typed(ifr)) 540 return -EFAULT; 541 ifr->ifr_hwaddr.sa_family = AF_INET; 542 { 543 auto mac_address = adapter->mac_address(); 544 memcpy(ifr->ifr_hwaddr.sa_data, &mac_address, sizeof(MACAddress)); 545 } 546 return 0; 547 } 548 549 return -EINVAL; 550 }; 551 552 switch (request) { 553 case SIOCSIFADDR: 554 case SIOCSIFNETMASK: 555 case SIOCGIFADDR: 556 case SIOCGIFHWADDR: 557 return ioctl_interface(); 558 559 case SIOCADDRT: 560 case SIOCDELRT: 561 return ioctl_route(); 562 } 563 564 return -EINVAL; 565} 566 567void IPv4Socket::close() 568{ 569 shutdown(SHUT_RDWR); 570} 571 572void IPv4Socket::shut_down_for_reading() 573{ 574 Socket::shut_down_for_reading(); 575 m_can_read = true; 576} 577 578}