port_scanner/
lib.rs

1use std::net::{SocketAddr, TcpListener, TcpStream, ToSocketAddrs};
2use std::ops::Range;
3
4/// Scan a port and return true if it's open.
5///
6/// # Example
7/// ```no_run
8/// use port_scanner::scan_port;
9/// println!("Port 8000 open? {}", scan_port(8000));
10/// ```
11pub fn scan_port(port: u16) -> bool {
12    match TcpStream::connect(("0.0.0.0", port)) {
13        Ok(_) => true,
14        Err(_) => false,
15    }
16}
17
18/// Scan port of an address and return true if it's open.
19///
20/// # Example
21/// ```no_run
22/// use port_scanner::scan_port_addr;
23/// println!("IP 192.168.1.1 has port 8000 open? {}", scan_port_addr("192.168.1.1:8000"));
24/// ```
25pub fn scan_port_addr<A: ToSocketAddrs>(addr: A) -> bool {
26    match TcpStream::connect(addr) {
27        Ok(_) => true,
28        Err(_) => false,
29    }
30}
31
32/// Scan specified ports and return a list of all open ports.
33///
34/// # Example
35/// ```no_run
36/// use port_scanner::scan_ports;
37/// for open_port in scan_ports(vec![8000, 9000, 8888]) {
38///     println!("Port {} is open", open_port);
39/// }
40/// ```
41pub fn scan_ports(ports: Vec<u16>) -> Vec<u16> {
42    let mut open_ports = Vec::new();
43    for port in ports {
44        if scan_port(port) {
45            open_ports.push(port);
46        }
47    }
48    open_ports
49}
50
51/// Scan specified ports of addresses and return a list of all addresses with open ports.
52///
53/// # Example
54/// ```no_run
55/// use port_scanner::scan_ports_addrs;
56/// for open_addr in scan_ports_addrs(vec!["192.168.1.1:8000", "192.168.1.2:8000"]) {
57///     println!("IP {} has port {} open.", open_addr.ip(), open_addr.port());
58/// }
59/// ```
60pub fn scan_ports_addrs<A: ToSocketAddrs>(addrs: Vec<A>) -> Vec<SocketAddr> {
61    let mut open_addrs = Vec::new();
62    for addr in addrs {
63        if scan_port_addr(&addr) {
64            let addr = addr.to_socket_addrs().unwrap().next().unwrap();
65            open_addrs.push(addr);
66        }
67    }
68    open_addrs
69}
70
71/// Scan a port range and return a list of all open ports.
72///
73/// # Example
74/// ```no_run
75/// use port_scanner::scan_ports_range;
76/// for open_port in scan_ports_range(8000..9000) {
77///     println!("Port {} is open", open_port);
78/// }
79/// ```
80pub fn scan_ports_range(port_range: Range<u16>) -> Vec<u16> {
81    let mut open_ports = Vec::new();
82    for port in port_range {
83        if scan_port(port) {
84            open_ports.push(port);
85        }
86    }
87    open_ports
88}
89
90/// Request to the os the next open port.
91///
92/// # Example
93/// ```no_run
94/// use port_scanner::request_open_port;
95/// println!("Port {}", request_open_port().unwrap_or(0));
96/// ```
97pub fn request_open_port() -> Option<u16> {
98    match TcpListener::bind("0.0.0.0:0") {
99        Ok(a) => {
100            match a.local_addr() {
101                Ok(a) => Some(a.port()),
102                Err(_) => None,
103            }
104        }
105        Err(_) => None,
106    }
107}
108
109/// Check if the local port is available.
110///
111/// # Example
112/// ```no_run
113/// use port_scanner::local_port_available;
114/// println!("Is port 80 available to use? {}", local_port_available(80));
115/// ```
116pub fn local_port_available(port: u16) -> bool {
117    match TcpListener::bind(("127.0.0.1", port)) {
118        Ok(_) => true,
119        Err(_) => false,
120    }
121}
122
123/// Check if the local ports are available.
124///
125/// # Example
126/// ```no_run
127/// use port_scanner::local_ports_available;
128/// for available in local_ports_available(vec![80, 81]) {
129///     println!("Port {} is available to use", available);
130/// }
131/// ```
132pub fn local_ports_available(ports: Vec<u16>) -> Vec<u16> {
133    let mut available = Vec::new();
134    for port in ports {
135        if local_port_available(port) {
136            available.push(port);
137        }
138    }
139    available
140}
141
142/// Check if the local ports are available.
143///
144/// # Example
145/// ```no_run
146/// use port_scanner::local_ports_available_range;
147/// for available in local_ports_available_range(1..80) {
148///     println!("Port {} is available to use", available);
149/// }
150/// ```
151pub fn local_ports_available_range(port_range: Range<u16>) -> Vec<u16> {
152    let mut available = Vec::new();
153    for port in port_range {
154        if local_port_available(port) {
155            available.push(port);
156        }
157    }
158    available
159}