Skip to content

Commit d865066

Browse files
fix net to_ip4 and to_ip6 (#1937)
fix: correct handle for ip to ip4 or ip6 Signed-off-by: Lan Liang <[email protected]>
1 parent 1b93b97 commit d865066

File tree

5 files changed

+134
-3
lines changed

5 files changed

+134
-3
lines changed

kclvm/runtime/src/net/mod.rs

Lines changed: 126 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,32 @@ pub extern "C-unwind" fn kclvm_net_to_IP4(
192192
args: *const kclvm_value_ref_t,
193193
kwargs: *const kclvm_value_ref_t,
194194
) -> *const kclvm_value_ref_t {
195-
kclvm_net_IP_string(ctx, args, kwargs)
195+
let args = ptr_as_ref(args);
196+
let kwargs = ptr_as_ref(kwargs);
197+
let ctx = mut_ptr_as_ref(ctx);
198+
if let Some(ip) = get_call_arg_str(args, kwargs, 0, Some("ip")) {
199+
match Ipv4Addr::from_str(ip.as_ref()) {
200+
Ok(addr) => {
201+
let s = format!("{addr}");
202+
return ValueRef::str(s.as_ref()).into_raw(ctx);
203+
}
204+
Err(_e) => match Ipv6Addr::from_str(ip.as_ref()) {
205+
Ok(addr) => {
206+
if let Some(v4) = addr.to_ipv4() {
207+
let s = format!("{v4}");
208+
return ValueRef::str(s.as_ref()).into_raw(ctx);
209+
}
210+
let s = format!("can not parse {} ipv6 to ipv4!", ip);
211+
return ValueRef::str(s.as_ref()).into_raw(ctx);
212+
}
213+
Err(e) => {
214+
let s = format!("can not both parse {} to ipv6 and ipv4,err:{}", ip, e);
215+
return ValueRef::str(s.as_ref()).into_raw(ctx);
216+
}
217+
},
218+
}
219+
}
220+
panic!("IP_string() missing 1 required positional argument: 'ip'");
196221
}
197222

198223
// to_IP16(ip) -> int
@@ -204,7 +229,33 @@ pub extern "C-unwind" fn kclvm_net_to_IP16(
204229
args: *const kclvm_value_ref_t,
205230
kwargs: *const kclvm_value_ref_t,
206231
) -> *const kclvm_value_ref_t {
207-
kclvm_net_IP_string(ctx, args, kwargs)
232+
let args = ptr_as_ref(args);
233+
let kwargs = ptr_as_ref(kwargs);
234+
let ctx = mut_ptr_as_ref(ctx);
235+
if let Some(ip) = get_call_arg_str(args, kwargs, 0, Some("ip")) {
236+
match Ipv6Addr::from_str(ip.as_ref()) {
237+
Ok(addr) => {
238+
let s = format!("{addr}");
239+
return ValueRef::str(s.as_ref()).into_raw(ctx);
240+
}
241+
Err(e) => {
242+
// print!("can not parse {} to ipv6:{},parsing {} to ipv4", ip, e, ip);
243+
match Ipv4Addr::from_str(ip.as_ref()) {
244+
Ok(addr) => {
245+
// Convert IPv4 to IPv6-mapped address (::ffff:0:0/96)
246+
let v6 = addr.to_ipv6_mapped();
247+
let s = format!("{v6}");
248+
return ValueRef::str(s.as_ref()).into_raw(ctx);
249+
}
250+
Err(e) => {
251+
let s = format!("can not both parse {} to ipv6 and ipv4,err:{}", ip, e);
252+
return ValueRef::str(s.as_ref()).into_raw(ctx);
253+
}
254+
}
255+
}
256+
}
257+
}
258+
panic!("IP_string() missing 1 required positional argument: 'ip'");
208259
}
209260

210261
// IP_string(ip: str) -> str
@@ -911,6 +962,79 @@ pub extern "C-unwind" fn kclvm_net_CIDR_netmask(
911962
mod test_net {
912963
use super::*;
913964

965+
#[test]
966+
#[allow(non_snake_case)]
967+
fn test_to_ip4() {
968+
let cases = [
969+
("::FFFF:192.168.1.10", "192.168.1.10"),
970+
(
971+
"::FFFF:192.168.x.10",
972+
"can not both parse ::FFFF:192.168.x.10 to ipv6 and ipv4,err:invalid IPv6 address syntax",
973+
),
974+
("::FFFF:10.0.0.1", "10.0.0.1"),
975+
("::FFFF:172.16.0.1", "172.16.0.1"),
976+
("::FFFF:127.0.0.1", "127.0.0.1"),
977+
("0000:0000:0000:0000:0000:FFFF:0A00:0001", "10.0.0.1"),
978+
("::FFFF:224.0.0.1", "224.0.0.1"),
979+
(
980+
"::FFFF:invalid.ip",
981+
"can not both parse ::FFFF:invalid.ip to ipv6 and ipv4,err:invalid IPv6 address syntax"
982+
),
983+
// IPv4-mapped IPv6 addresses
984+
("::FFFF:0A00:0001", "10.0.0.1"),
985+
("0:0:0:0:0:FFFF:AC10:0001", "172.16.0.1"),
986+
];
987+
let mut ctx = Context::default();
988+
for (ip6, expected) in cases.iter() {
989+
unsafe {
990+
let actual = &*kclvm_net_to_IP4(
991+
&mut ctx,
992+
&ValueRef::list(Some(&[&ValueRef::str(ip6)])),
993+
&ValueRef::dict(None),
994+
);
995+
assert_eq!(&ValueRef::str(expected), actual, "{} positional", ip6,);
996+
}
997+
}
998+
}
999+
1000+
#[test]
1001+
#[allow(non_snake_case)]
1002+
fn test_to_ip6() {
1003+
let cases = [
1004+
("192.168.1.10", "::ffff:192.168.1.10"),
1005+
(
1006+
"192.168.x.10",
1007+
"can not both parse 192.168.x.10 to ipv6 and ipv4,err:invalid IPv4 address syntax",
1008+
),
1009+
("10.0.0.1", "::ffff:10.0.0.1"),
1010+
("172.16.0.1", "::ffff:172.16.0.1"),
1011+
("127.0.0.1", "::ffff:127.0.0.1"),
1012+
("224.0.0.1", "::ffff:224.0.0.1"),
1013+
(
1014+
"invalid.ip",
1015+
"can not both parse invalid.ip to ipv6 and ipv4,err:invalid IPv4 address syntax",
1016+
),
1017+
// IPv6 addresses
1018+
("2001:db8::1", "2001:db8::1"),
1019+
("::1", "::1"),
1020+
(
1021+
"2001:db8:::1",
1022+
"can not both parse 2001:db8:::1 to ipv6 and ipv4,err:invalid IPv4 address syntax",
1023+
),
1024+
];
1025+
let mut ctx = Context::default();
1026+
for (ip4, expected) in cases.iter() {
1027+
unsafe {
1028+
let actual = &*kclvm_net_to_IP16(
1029+
&mut ctx,
1030+
&ValueRef::list(Some(&[&ValueRef::str(ip4)])),
1031+
&ValueRef::dict(None),
1032+
);
1033+
assert_eq!(&ValueRef::str(expected), actual, "{} positional", ip4,);
1034+
}
1035+
}
1036+
}
1037+
9141038
#[test]
9151039
fn test_split_host_port() {
9161040
let cases = [
@@ -950,7 +1074,6 @@ mod test_net {
9501074
}
9511075
}
9521076
}
953-
9541077
#[test]
9551078
fn test_split_host_port_invalid() {
9561079
let prev_hook = std::panic::take_hook();
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import net
2+
3+
ip0 = net.to_IP4("::FFFF:192.168.1.10")
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ip0: 192.168.1.10
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import net
2+
3+
ip0 = net.to_IP16("192.168.1.10")
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ip0: ::ffff:192.168.1.10

0 commit comments

Comments
 (0)