Port Scanner
Lightweight TCP port scanner for Linux
Loading...
Searching...
No Matches
scanner.cpp
Go to the documentation of this file.
1#include "../include/scanner.hpp"
2
3#include <charconv>
4#include <stdexcept>
5#include <thread>
6
7#include <cstring>
8
9#include <arpa/inet.h>
10#include <fcntl.h>
11#include <netdb.h>
12#include <sys/socket.h>
13#include <sys/types.h>
14
15Scanner::Scanner(ipaddr_t const &ip, std::vector<char const *> const &ports) : m_ip{ip} {
16 if (not isIPv4(m_ip) and not isIPv6(m_ip)) [[unlikely]]
17 throw std::invalid_argument{"IP address is not valid!"};
18
19 ports_t tmpPorts{};
20 tmpPorts.reserve(ports.size());
21 for (auto const prt : ports) {
22 if (std::optional port{parsePort(prt)}) [[likely]]
23 tmpPorts.push_back(*port);
24 else [[unlikely]]
25 throw std::invalid_argument{std::string{prt} + " is not a valid port!"};
26 }
27
28 m_ports = std::move(tmpPorts);
29}
30
31[[nodiscard]] std::vector<std::pair<port_t, bool>> Scanner::scan() const {
32 std::vector<std::pair<port_t, bool>> result{};
33 result.reserve(m_ports.size());
34 std::vector<std::thread> threads{};
35 threads.reserve(m_ports.size());
36 for (auto const port : m_ports) {
37 threads.push_back(std::thread{[this, port, &result]() {
38 bool const isAccessible{isPortAccessible(port)};
39 m_mtx.lock();
40 result.push_back(std::pair{port, isAccessible});
41 m_mtx.unlock();
42 }});
43 }
44
45 for (auto &thread : threads)
46 thread.join();
47
48 return result;
49}
50
51[[nodiscard]] bool Scanner::isIPv4(ipaddr_t const &ip) const noexcept {
52 in_addr address;
53 return inet_pton(AF_INET, ip.c_str(), &address) == 1;
54}
55
56[[nodiscard]] bool Scanner::isIPv6(ipaddr_t const &ip) const noexcept {
57 in6_addr address6;
58 return inet_pton(AF_INET6, ip.c_str(), &address6) == 1;
59}
60
61[[nodiscard]] std::optional<port_t> Scanner::parsePort(char const *str) const noexcept {
62 int prt;
63 char const *strEnd{str + std::strlen(str)};
64 std::from_chars_result const res{std::from_chars(str, strEnd, prt)};
65
66 if (res.ec not_eq std::errc() or prt < MIN_PORT or prt > MAX_PORT or res.ptr not_eq strEnd)
67 [[unlikely]]
68 return {};
69
70 return {static_cast<port_t>(prt)};
71}
72
73[[nodiscard]] bool Scanner::isPortAccessible(port_t const port) const {
74 addrinfo hints{};
75 addrinfo *res{};
76 hints.ai_family = AF_UNSPEC;
77 hints.ai_socktype = SOCK_STREAM;
78
79 std::string const portStr{std::to_string(port)};
80 if (getaddrinfo(m_ip.c_str(), portStr.c_str(), &hints, &res) not_eq 0 or not res)
81 return false;
82
83 int const sockfd{socket(res->ai_family, SOCK_STREAM, 0)};
84 if (sockfd == -1) [[unlikely]] {
85 freeaddrinfo(res);
86 close(sockfd);
87 return false;
88 }
89
90 timeval constexpr timeout{TIMEOUT_MS / 1000, (TIMEOUT_MS % 1000) * 1000l};
91 setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
92
93 int const result{connect(sockfd, res->ai_addr, res->ai_addrlen)};
94 freeaddrinfo(res);
95 close(sockfd);
96
97 return result == 0;
98}
ports_t m_ports
Target ports.
Definition scanner.hpp:62
std::vector< std::pair< port_t, bool > > scan() const
Scans all specified ports on the target IP address.
Definition scanner.cpp:31
bool isIPv6(ipaddr_t const &ip) const noexcept
Checks if the given IP address string is a syntactically valid IPv6 address.
Definition scanner.cpp:56
std::mutex m_mtx
Mutable mutex for thread safety.
Definition scanner.hpp:69
bool isPortAccessible(port_t const port) const
Attempts to establish a TCP connection to the specified port. This function incorporates a timeout (T...
Definition scanner.cpp:73
std::optional< port_t > parsePort(char const *str) const noexcept
Attempts to parse a C-string into a port_t. It also validates if the parsed number falls within the [...
Definition scanner.cpp:61
bool isIPv4(ipaddr_t const &ip) const noexcept
Checks if the given IP address string is a syntactically valid IPv4 address.
Definition scanner.cpp:51
Scanner(ipaddr_t const &ip, std::vector< char const * > const &ports)
Constructs a Scanner with a target IP address and a vector of ports to scan.
Definition scanner.cpp:15
ipaddr_t m_ip
Target IP address.
Definition scanner.hpp:55
int constexpr TIMEOUT_MS
Timeout in milliseconds for socket connection attempts.
Definition scanner.hpp:10
std::vector< port_t > ports_t
Vector of ports type.
Definition types.hpp:10
uint16_t port_t
Port number type.
Definition types.hpp:9
std::string ipaddr_t
IP address type.
Definition types.hpp:8