diff --git a/kernel/include/net/network.hpp b/kernel/include/net/network.hpp index d189c5bb..0e35833c 100644 --- a/kernel/include/net/network.hpp +++ b/kernel/include/net/network.hpp @@ -159,6 +159,13 @@ std::expected listen(socket_fd_t socket_fd, bool listen); */ std::expected client_bind(socket_fd_t socket_fd, network::ip::address address); +/*! + * \brief Bind a socket datagram as a client (bind a local random port) + * \param socket_fd The file descriptor of the packet + * \return the allocated port on success and a negative error code otherwise + */ +std::expected client_bind(socket_fd_t socket_fd, network::ip::address address, size_t port); + /*! * \brief Unbind a socket datagram as a client * \param socket_fd The file descriptor of the packet diff --git a/kernel/src/net/network.cpp b/kernel/src/net/network.cpp index e35ddce4..71e951b5 100644 --- a/kernel/src/net/network.cpp +++ b/kernel/src/net/network.cpp @@ -488,7 +488,27 @@ std::expected network::client_bind(socket_fd_t socket_fd, network::ip::a switch(datagram_protocol(socket.protocol)){ case socket_protocol::UDP: - return network::udp::client_bind(socket, 53, address); + return network::udp::client_bind(socket, /* TODO PORT */ 53, address); + + default: + return std::make_unexpected(std::ERROR_SOCKET_INVALID_TYPE_PROTOCOL); + } +} + +std::expected network::client_bind(socket_fd_t socket_fd, network::ip::address address, size_t port){ + if(!scheduler::has_socket(socket_fd)){ + return std::make_unexpected(std::ERROR_SOCKET_INVALID_FD); + } + + auto& socket = scheduler::get_socket(socket_fd); + + if(socket.type != socket_type::DGRAM){ + return std::make_unexpected(std::ERROR_SOCKET_INVALID_TYPE); + } + + switch(datagram_protocol(socket.protocol)){ + case socket_protocol::UDP: + return network::udp::client_bind(socket, port, address); default: return std::make_unexpected(std::ERROR_SOCKET_INVALID_TYPE_PROTOCOL); diff --git a/kernel/src/system_calls.cpp b/kernel/src/system_calls.cpp index 99fd2fb6..2bc3ab01 100644 --- a/kernel/src/system_calls.cpp +++ b/kernel/src/system_calls.cpp @@ -443,6 +443,15 @@ void sc_client_bind(interrupt::syscall_regs* regs){ regs->rax = expected_to_i64(status); } +void sc_client_bind_port(interrupt::syscall_regs* regs){ + auto socket_fd = regs->rbx; + auto server_ip = regs->rcx; + auto port = regs->rdx; + + auto status = network::client_bind(socket_fd, server_ip, port); + regs->rax = expected_to_i64(status); +} + void sc_client_unbind(interrupt::syscall_regs* regs){ auto socket_fd = regs->rbx; @@ -754,6 +763,10 @@ void system_call_entry(interrupt::syscall_regs* regs){ sc_receive(regs); break; + case 0x300D: + sc_client_bind_port(regs); + break; + // Special system calls case 0x6666: diff --git a/tlib/include/tlib/net.hpp b/tlib/include/tlib/net.hpp index cd5df646..97aacfc5 100644 --- a/tlib/include/tlib/net.hpp +++ b/tlib/include/tlib/net.hpp @@ -122,6 +122,14 @@ std::expected listen(size_t socket_fd, bool l); */ std::expected client_bind(size_t socket_fd, tlib::ip::address server); +/*! + * \brief Bind a destination to the datagram socket + * \param socket_fd The socket file descriptor + * \param server The server address + * \return the local port, or an error + */ +std::expected client_bind(size_t socket_fd, tlib::ip::address server, size_t port); + /*! * \brief Unbind from destination from the datagram socket * \param socket_fd The socket file descriptor @@ -220,6 +228,12 @@ struct socket { */ void client_bind(tlib::ip::address server); + /*! + * \brief Bind the socket as a client + * \param server The IP address + */ + void client_bind(tlib::ip::address server, size_t port); + /*! * \brief Unbind the client socket */ diff --git a/tlib/src/net.cpp b/tlib/src/net.cpp index d0d1a524..182ba36e 100644 --- a/tlib/src/net.cpp +++ b/tlib/src/net.cpp @@ -154,6 +154,20 @@ std::expected tlib::client_bind(size_t socket_fd, tlib::ip::address serv } } +std::expected tlib::client_bind(size_t socket_fd, tlib::ip::address server, size_t port) { + int64_t code; + asm volatile("mov rax, 0x300D; mov rbx, %[socket]; mov rcx, %[ip]; mov rdx, %[port]; int 50; mov %[code], rax" + : [code] "=m"(code) + : [socket] "g"(socket_fd), [ip] "g" (size_t(server.raw_address)), [port] "g" (port) + : "rax", "rbx", "rcx"); + + if (code < 0) { + return std::make_unexpected(-code); + } else { + return std::make_expected(code); + } +} + std::expected tlib::client_unbind(size_t socket_fd) { int64_t code; asm volatile("mov rax, 0x300A; mov rbx, %[socket]; int 50; mov %[code], rax" @@ -315,6 +329,19 @@ void tlib::socket::client_bind(tlib::ip::address server) { } } +void tlib::socket::client_bind(tlib::ip::address server, size_t port) { + if (!good() || !open()) { + return; + } + + auto status = tlib::client_bind(fd, server, port); + if (!status) { + _bound = false; + } else { + error_code = status.error(); + } +} + void tlib::socket::client_unbind() { if (!good() || !open()) { return;