Skip to content

Commit 3c7c04a

Browse files
committed
✨ support domain names
1 parent 843101e commit 3c7c04a

File tree

8 files changed

+127
-99
lines changed

8 files changed

+127
-99
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
- [CHANGELOG.md](https://github.com/hronro/iPortForwarder/blob/master/CHANGELOG.md). All the notable changes will be documented in this file from this release.
1313
- Enable [App Sandbox](https://developer.apple.com/documentation/security/app-sandbox) for better security.
14+
- Allow using domain names (previously only IP addresses were allowed). Also an icon is added to indicate the type of the address.
1415

1516
### Changed
1617

core/demo.lua

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,25 +22,25 @@ local function check_ip_is_valid(ip)
2222
return ipf.ipf_check_ip_is_valid(ffi.new('char [?]', #ip + 1, ip))
2323
end
2424

25-
---Forward ip and port
26-
---@param ip string
25+
---Forward address and port
26+
---@param address string
2727
---@param remote_port number
2828
---@param local_port number
2929
---@param allow_lan boolean
3030
---@return number forward_rule_id
31-
local function forward(ip, remote_port, local_port, allow_lan)
32-
return ipf.ipf_forward(ffi.new('char [?]', #ip + 1, ip), remote_port, local_port, allow_lan)
31+
local function forward(address, remote_port, local_port, allow_lan)
32+
return ipf.ipf_forward(ffi.new('char [?]', #address + 1, address), remote_port, local_port, allow_lan)
3333
end
3434

35-
---Forward ip and a range of ports
36-
---@param ip string
35+
---Forward address and a range of ports
36+
---@param address string
3737
---@param remote_port_start number
3838
---@param remote_port_end number
3939
---@param local_port_start number
4040
---@param allow_lan boolean
4141
---@return number forward_rule_id
42-
local function forward_range(ip, remote_port_start, remote_port_end, local_port_start, allow_lan)
43-
return ipf.ipf_forward_range(ffi.new('char [?]', #ip + 1, ip), remote_port_start, remote_port_end, local_port_start, allow_lan)
42+
local function forward_range(address, remote_port_start, remote_port_end, local_port_start, allow_lan)
43+
return ipf.ipf_forward_range(ffi.new('char [?]', #address + 1, address), remote_port_start, remote_port_end, local_port_start, allow_lan)
4444
end
4545

4646
---Cancel forward
@@ -57,17 +57,18 @@ local function error_message(error)
5757
local message_table = {
5858
[-1] = 'Unknown error',
5959
[-10] = 'Invalid string',
60-
[-11] = 'Invalid IP address',
61-
[-12] = 'Too many rules',
62-
[-13] = 'Invalid rule ID',
63-
[-14] = 'Invalid local start port',
64-
[-15] = 'Invalid remote end port',
65-
[-16] = 'Error handler is already registered',
60+
[-11] = 'Too many rules',
61+
[-12] = 'Invalid rule ID',
62+
[-13] = 'Invalid local start port',
63+
[-14] = 'Invalid remote end port',
64+
[-15] = 'Error handler is already registered',
6665
[-51] = 'Permission denied',
6766
[-52] = 'Address in use',
6867
[-53] = 'Already exists',
6968
[-54] = 'Out of memory',
7069
[-55] = 'Too many open files',
70+
[-56] = 'Address can not be resolved',
71+
7172
}
7273

7374
return message_table[error]
@@ -126,9 +127,10 @@ print 'Please input IP address you want to forward:'
126127

127128
local ip = io.read()
128129

129-
if check_ip_is_valid(ip) == false then
130-
print("IP address " .. ip .. " is invalid.")
131-
os.exit(1)
130+
if check_ip_is_valid(ip) then
131+
print 'Detecting IP address, skip DNS lockup.'
132+
else
133+
print 'Detecting domian name, performing DNS lockup...'
132134
end
133135

134136
print 'Please input how long (in seconds, empty means forever) you want to forward:'
@@ -149,6 +151,11 @@ else
149151
os.exit(1)
150152
end
151153

154+
if forward_rule_id < 0 then
155+
print('Error: ' .. error_message(forward_rule_id))
156+
os.exit(1)
157+
end
158+
152159
print 'Forwarding started.'
153160

154161
if time ~= nil then

core/src/error.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,21 @@ pub enum Error {
1010
/// Invalid C format string.
1111
InvalidString = -10,
1212

13-
/// The IP address is invalid.
14-
InvalidIpAddr = -11,
15-
1613
/// At most 128 rules are allowed.
17-
TooManyRules = -12,
14+
TooManyRules = -11,
1815

1916
/// The rule ID is invalid.
20-
InvalidRuleId = -13,
17+
InvalidRuleId = -12,
2118

2219
/// The local port start is invalid,
2320
/// which will make the local port end greater than 65535.
24-
InvalidLocalPortStart = -14,
21+
InvalidLocalPortStart = -13,
2522

2623
/// The remote port end is invalid.
27-
InvalidRemotePortEnd = -15,
24+
InvalidRemotePortEnd = -14,
2825

2926
/// The error handler has already been registered.
30-
HandlerAlreadyRegistered = -16,
27+
HandlerAlreadyRegistered = -15,
3128

3229
// OS errors, from -51 to -127.
3330
/// Permission denied.
@@ -45,6 +42,9 @@ pub enum Error {
4542

4643
/// Too many open files.
4744
TooManyOpenFiles = -55,
45+
46+
/// Address can not be resolved.
47+
AddressCantBeResolved = -56,
4848
}
4949
impl From<io::Error> for Error {
5050
fn from(io_error: io::Error) -> Self {

core/src/lib.rs

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
use std::collections::HashMap;
44
use std::ffi::CStr;
5-
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
5+
use std::net::{IpAddr, Ipv4Addr, SocketAddr, ToSocketAddrs};
66
use std::os::raw::c_char;
77
use std::sync::{LazyLock, Mutex, OnceLock};
88

@@ -87,21 +87,25 @@ pub extern "C" fn ipf_check_ip_is_valid(ip_c_string: *const c_char) -> bool {
8787
#[no_mangle]
8888
#[allow(clippy::not_unsafe_ptr_arg_deref)]
8989
pub extern "C" fn ipf_forward(
90-
ip_c_string: *const c_char,
90+
address_c_string: *const c_char,
9191
remote_port: u16,
9292
local_port: u16,
9393
allow_lan: bool,
9494
) -> i8 {
95+
println!("hi");
9596
if let Some(rule_id) = get_new_rule_id() {
96-
let ip_str = unsafe {
97-
match CStr::from_ptr(ip_c_string).to_str() {
98-
Ok(ip_str) => ip_str,
97+
let addr_str = unsafe {
98+
match CStr::from_ptr(address_c_string).to_str() {
99+
Ok(addr_str) => addr_str,
99100
Err(_) => return Error::InvalidString as i8,
100101
}
101102
};
102-
let ip: IpAddr = match ip_str.parse() {
103-
Ok(ip) => ip,
104-
Err(_) => return Error::InvalidIpAddr as i8,
103+
let socket_addr = match addr_str.parse::<IpAddr>() {
104+
Ok(ip) => SocketAddr::new(ip, remote_port),
105+
Err(_) => match (addr_str, remote_port).to_socket_addrs() {
106+
Ok(mut socket_addrs) => socket_addrs.next().unwrap(),
107+
Err(_) => return Error::AddressCantBeResolved as i8,
108+
},
105109
};
106110

107111
let join_handler = RT.spawn(async move {
@@ -116,7 +120,7 @@ pub extern "C" fn ipf_forward(
116120
Ok(listener) => loop {
117121
if let Ok((mut ingress, _)) = listener.accept().await {
118122
if let Ok(mut egress) =
119-
TcpStream::connect(SocketAddr::new(ip, remote_port)).await
123+
TcpStream::connect(socket_addr).await
120124
{
121125
RT.spawn(async move {
122126
_ = copy_bidirectional(&mut ingress, &mut egress).await;
@@ -147,7 +151,7 @@ pub extern "C" fn ipf_forward(
147151
#[no_mangle]
148152
#[allow(clippy::not_unsafe_ptr_arg_deref)]
149153
pub extern "C" fn ipf_forward_range(
150-
ip_c_string: *const c_char,
154+
address_c_string: *const c_char,
151155
remote_port_start: u16,
152156
remote_port_end: u16,
153157
local_port_start: u16,
@@ -162,15 +166,18 @@ pub extern "C" fn ipf_forward_range(
162166
}
163167

164168
if let Some(rule_id) = get_new_rule_id() {
165-
let ip_str = unsafe {
166-
match CStr::from_ptr(ip_c_string).to_str() {
169+
let addr_str = unsafe {
170+
match CStr::from_ptr(address_c_string).to_str() {
167171
Ok(ip_str) => ip_str,
168172
Err(_) => return Error::InvalidString as i8,
169173
}
170174
};
171-
let ip: IpAddr = match ip_str.parse() {
175+
let ip = match addr_str.parse::<IpAddr>() {
172176
Ok(ip) => ip,
173-
Err(_) => return Error::InvalidIpAddr as i8,
177+
Err(_) => match (addr_str, 0).to_socket_addrs() {
178+
Ok(mut socket_addrs) => socket_addrs.next().unwrap().ip(),
179+
Err(_) => return Error::AddressCantBeResolved as i8,
180+
},
174181
};
175182

176183
let join_handlers = (remote_port_start..=remote_port_end)

0 commit comments

Comments
 (0)