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}