@@ -574,71 +574,36 @@ pub extern "C-unwind" fn kclvm_net_is_IP_in_CIDR(
574
574
let kwargs = ptr_as_ref ( kwargs) ;
575
575
576
576
let ip = match get_call_arg_str ( args, kwargs, 0 , Some ( "ip" ) ) {
577
- Some ( ip) => ip,
578
577
None => {
579
578
panic ! ( "is_IP_in_CIDR() missing 2 required positional arguments: 'ip' and 'cidr'" ) ;
580
579
}
580
+ Some ( ip) => match IpAddr :: from_str ( ip. as_str ( ) ) {
581
+ Err ( err) => panic ! ( "is_IP_in_CIDR() invalid ip: {}" , err) ,
582
+ Ok ( ip) => ip,
583
+ } ,
581
584
} ;
582
585
let cidr = match get_call_arg_str ( args, kwargs, 1 , Some ( "cidr" ) ) {
583
- Some ( cidr) => cidr,
584
586
None => {
585
587
panic ! ( "is_IP_in_CIDR() missing 2 required positional arguments: 'ip' and 'cidr'" ) ;
586
588
}
589
+ Some ( cidr) => match IpCidr :: from_str ( & cidr. as_str ( ) ) {
590
+ Err ( err) => panic ! ( "is_IP_in_CIDR() invalid cidr: {}" , err) ,
591
+ Ok ( cidr) => cidr,
592
+ } ,
587
593
} ;
588
594
589
- let ( cidr_ip, mask_bits) = match _parse_cidr ( & cidr) {
590
- Some ( ( ip, bits) ) => ( ip, bits) ,
591
- None => return kclvm_value_False ( ctx) ,
592
- } ;
593
-
594
- match ( _parse_ip ( & ip) , cidr_ip) {
595
- ( Ok ( IpAddr :: V4 ( ip) ) , IpAddr :: V4 ( cidr_ip) ) => {
596
- let mask_bits = match mask_bits {
597
- Some ( bits) if bits <= 32 => bits,
598
- _ => return kclvm_value_False ( ctx) ,
599
- } ;
600
- kclvm_value_Bool ( ctx, _check_ipv4_cidr ( ip, cidr_ip, mask_bits) as i8 )
601
- }
602
- ( Ok ( IpAddr :: V6 ( ip) ) , IpAddr :: V6 ( cidr_ip) ) => {
603
- let mask_bits = match mask_bits {
604
- Some ( bits) if bits <= 128 => bits,
605
- _ => return kclvm_value_False ( ctx) ,
606
- } ;
607
- kclvm_value_Bool ( ctx, _check_ipv6_cidr ( ip, cidr_ip, mask_bits) as i8 )
595
+ if cidr. is_ipv6 ( ) {
596
+ match ip {
597
+ IpAddr :: V4 ( ip) => {
598
+ return kclvm_value_Bool (
599
+ ctx,
600
+ cidr. contains ( & IpAddr :: V6 ( ip. to_ipv6_mapped ( ) ) ) as i8 ,
601
+ ) ;
602
+ }
603
+ IpAddr :: V6 ( _ip) => { }
608
604
}
609
- _ => kclvm_value_False ( ctx) ,
610
- }
611
- }
612
-
613
- fn _parse_cidr ( cidr : & str ) -> Option < ( IpAddr , Option < u32 > ) > {
614
- let parts: Vec < & str > = cidr. split ( '/' ) . collect ( ) ;
615
- if parts. len ( ) != 2 {
616
- return None ;
617
605
}
618
- let ip = IpAddr :: from_str ( parts[ 0 ] ) . ok ( ) ?;
619
- let mask_bits = parts[ 1 ] . parse :: < u32 > ( ) . ok ( ) ;
620
- Some ( ( ip, mask_bits) )
621
- }
622
-
623
- fn _parse_ip ( ip : & str ) -> Result < IpAddr , ( ) > {
624
- IpAddr :: from_str ( ip) . map_err ( |_| ( ) )
625
- }
626
-
627
- fn _check_ipv4_cidr ( ip : Ipv4Addr , cidr_ip : Ipv4Addr , mask_bits : u32 ) -> bool {
628
- let mask = !( ( 1u32 << ( 32 - mask_bits) ) - 1 ) ;
629
- let ip_u32 = u32:: from ( ip) ;
630
- let cidr_u32 = u32:: from ( cidr_ip) ;
631
- ( ip_u32 & mask) == ( cidr_u32 & mask)
632
- }
633
-
634
- fn _check_ipv6_cidr ( ip : Ipv6Addr , cidr_ip : Ipv6Addr , mask_bits : u32 ) -> bool {
635
- let mask = match 128 - mask_bits {
636
- shift @ 0 ..=128 => !( ( 1u128 << shift) - 1 ) ,
637
- _ => return false ,
638
- } ;
639
- let ip_u128 = u128:: from ( ip) ;
640
- let cidr_u128 = u128:: from ( cidr_ip) ;
641
- ( ip_u128 & mask) == ( cidr_u128 & mask)
606
+ return kclvm_value_Bool ( ctx, cidr. contains ( & ip) as i8 ) ;
642
607
}
643
608
644
609
#[ allow( non_camel_case_types, non_snake_case) ]
@@ -1050,4 +1015,196 @@ mod test_net {
1050
1015
) ;
1051
1016
std:: panic:: set_hook ( prev_hook) ;
1052
1017
}
1018
+
1019
+ #[ test]
1020
+ #[ allow( non_snake_case) ]
1021
+ fn test_is_IP_in_CIDR ( ) {
1022
+ let cases = [
1023
+ (
1024
+ "0.0.0.0/0" ,
1025
+ vec ! [ "0.0.0.0" , "255.255.255.255" ] ,
1026
+ vec ! [ "::" , "2001:db8::" ] ,
1027
+ ) ,
1028
+ (
1029
+ "::/0" ,
1030
+ vec ! [
1031
+ "::" ,
1032
+ "2001:db8::" ,
1033
+ "10.1.2.3" ,
1034
+ "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" ,
1035
+ ] ,
1036
+ vec ! [ ] ,
1037
+ ) ,
1038
+ (
1039
+ "10.0.0.0/8" ,
1040
+ vec ! [ "10.0.0.0" , "10.1.2.3" , "10.255.255.255" ] ,
1041
+ vec ! [ "9.255.255.255" , "11.0.0.0" , "a000::" ] ,
1042
+ ) ,
1043
+ (
1044
+ "2001:db8::/56" ,
1045
+ vec ! [ "2001:db8::" , "2001:db8:0000:ff:ffff:ffff:ffff:ffff" ] ,
1046
+ vec ! [
1047
+ "2001:db7:ffff:ffff:ffff:ffff:ffff:ffff" ,
1048
+ "2001:db8:0:100::" ,
1049
+ "10.1.2.3" ,
1050
+ ] ,
1051
+ ) ,
1052
+ (
1053
+ "10.1.2.3/32" ,
1054
+ vec ! [ "10.1.2.3" ] ,
1055
+ vec ! [ "10.1.2.2" , "10.1.2.4" , "0a01:0203::" ] ,
1056
+ ) ,
1057
+ (
1058
+ "2001:db8:1:2:3:4:5:7/128" ,
1059
+ vec ! [ "2001:db8:1:2:3:4:5:7" ] ,
1060
+ vec ! [ "2001:db8:1:2:3:4:5:6" , "2001:db8:1:2:3:4:5:8" , "10.1.2.3" ] ,
1061
+ ) ,
1062
+ (
1063
+ "10.1.2.3" ,
1064
+ vec ! [ "10.1.2.3" ] ,
1065
+ vec ! [ "10.1.2.2" , "10.1.2.4" , "0a01:0203::" ] ,
1066
+ ) ,
1067
+ (
1068
+ "2001:db8:1:2:3:4:5:7" ,
1069
+ vec ! [ "2001:db8:1:2:3:4:5:7" ] ,
1070
+ vec ! [ "2001:db8:1:2:3:4:5:6" , "2001:db8:1:2:3:4:5:8" , "10.1.2.3" ] ,
1071
+ ) ,
1072
+ ] ;
1073
+ let mut ctx = Context :: default ( ) ;
1074
+ for ( cidr, expect_in, expect_not_in) in cases. iter ( ) {
1075
+ for ip in expect_in. iter ( ) {
1076
+ unsafe {
1077
+ let actual = & * kclvm_net_is_IP_in_CIDR (
1078
+ & mut ctx,
1079
+ & ValueRef :: list ( Some ( & [ & ValueRef :: str ( ip) , & ValueRef :: str ( cidr) ] ) ) ,
1080
+ & ValueRef :: dict ( None ) ,
1081
+ ) ;
1082
+ assert_eq ! (
1083
+ & ValueRef :: bool ( true ) ,
1084
+ actual,
1085
+ "{} in {} positional" ,
1086
+ ip,
1087
+ cidr
1088
+ ) ;
1089
+ }
1090
+ unsafe {
1091
+ let actual = & * kclvm_net_is_IP_in_CIDR (
1092
+ & mut ctx,
1093
+ & ValueRef :: list ( None ) ,
1094
+ & ValueRef :: dict ( Some ( & [
1095
+ ( "cidr" , & ValueRef :: str ( cidr) ) ,
1096
+ ( "ip" , & ValueRef :: str ( ip) ) ,
1097
+ ] ) ) ,
1098
+ ) ;
1099
+ assert_eq ! ( & ValueRef :: bool ( true ) , actual, "{} in {} named" , ip, cidr) ;
1100
+ }
1101
+ }
1102
+ for ip in expect_not_in. iter ( ) {
1103
+ unsafe {
1104
+ let actual = & * kclvm_net_is_IP_in_CIDR (
1105
+ & mut ctx,
1106
+ & ValueRef :: list ( Some ( & [ & ValueRef :: str ( ip) , & ValueRef :: str ( cidr) ] ) ) ,
1107
+ & ValueRef :: dict ( None ) ,
1108
+ ) ;
1109
+ assert_eq ! (
1110
+ & ValueRef :: bool ( false ) ,
1111
+ actual,
1112
+ "{} not in {} positional" ,
1113
+ ip,
1114
+ cidr
1115
+ ) ;
1116
+ }
1117
+ unsafe {
1118
+ let actual = & * kclvm_net_is_IP_in_CIDR (
1119
+ & mut ctx,
1120
+ & ValueRef :: list ( None ) ,
1121
+ & ValueRef :: dict ( Some ( & [
1122
+ ( "cidr" , & ValueRef :: str ( cidr) ) ,
1123
+ ( "ip" , & ValueRef :: str ( ip) ) ,
1124
+ ] ) ) ,
1125
+ ) ;
1126
+ assert_eq ! (
1127
+ & ValueRef :: bool ( false ) ,
1128
+ actual,
1129
+ "{} not in {} named" ,
1130
+ ip,
1131
+ cidr
1132
+ ) ;
1133
+ }
1134
+ }
1135
+ }
1136
+ }
1137
+
1138
+ #[ test]
1139
+ #[ allow( non_snake_case) ]
1140
+ fn test_is_IP_in_CIDR_invalid ( ) {
1141
+ let prev_hook = std:: panic:: take_hook ( ) ;
1142
+ // Disable print panic info in stderr.
1143
+ std:: panic:: set_hook ( Box :: new ( |_| { } ) ) ;
1144
+ assert_panic (
1145
+ "is_IP_in_CIDR() missing 2 required positional arguments: 'ip' and 'cidr'" ,
1146
+ || {
1147
+ let mut ctx = Context :: new ( ) ;
1148
+ let args = ValueRef :: list ( None ) . into_raw ( & mut ctx) ;
1149
+ let kwargs = ValueRef :: dict ( None ) . into_raw ( & mut ctx) ;
1150
+ kclvm_net_is_IP_in_CIDR ( ctx. into_raw ( ) , args, kwargs) ;
1151
+ } ,
1152
+ ) ;
1153
+ assert_panic (
1154
+ "is_IP_in_CIDR() missing 2 required positional arguments: 'ip' and 'cidr'" ,
1155
+ || {
1156
+ let mut ctx = Context :: new ( ) ;
1157
+ let args = ValueRef :: list ( Some ( & [ & ValueRef :: str ( "10.1.2.3" ) ] ) ) . into_raw ( & mut ctx) ;
1158
+ let kwargs = ValueRef :: dict ( None ) . into_raw ( & mut ctx) ;
1159
+ kclvm_net_is_IP_in_CIDR ( ctx. into_raw ( ) , args, kwargs) ;
1160
+ } ,
1161
+ ) ;
1162
+ assert_panic (
1163
+ "is_IP_in_CIDR() missing 2 required positional arguments: 'ip' and 'cidr'" ,
1164
+ || {
1165
+ let mut ctx = Context :: new ( ) ;
1166
+ let args = ValueRef :: list ( None ) . into_raw ( & mut ctx) ;
1167
+ let kwargs =
1168
+ ValueRef :: dict ( Some ( & [ ( "ip" , & ValueRef :: str ( "10.1.2.3" ) ) ] ) ) . into_raw ( & mut ctx) ;
1169
+ kclvm_net_is_IP_in_CIDR ( ctx. into_raw ( ) , args, kwargs) ;
1170
+ } ,
1171
+ ) ;
1172
+ assert_panic (
1173
+ "is_IP_in_CIDR() missing 2 required positional arguments: 'ip' and 'cidr'" ,
1174
+ || {
1175
+ let mut ctx = Context :: new ( ) ;
1176
+ let args = ValueRef :: list ( None ) . into_raw ( & mut ctx) ;
1177
+ let kwargs = ValueRef :: dict ( Some ( & [ ( "cidr" , & ValueRef :: str ( "10.0.0.0/8" ) ) ] ) )
1178
+ . into_raw ( & mut ctx) ;
1179
+ kclvm_net_is_IP_in_CIDR ( ctx. into_raw ( ) , args, kwargs) ;
1180
+ } ,
1181
+ ) ;
1182
+ let cases = [
1183
+ ( "10.0.0/8" , "10.0.0.1" , "is_IP_in_CIDR() invalid cidr: couldn't parse address in network: invalid IP address syntax" ) ,
1184
+ ( "10.0.0.0/33" , "10.0.0.1" , "is_IP_in_CIDR() invalid cidr: invalid length for network: Network length 33 is too long for Ipv4 (maximum: 32)" ) ,
1185
+ ( "2001:db8:1:2:3:4:5:7/129" , "2001:db8::" , "is_IP_in_CIDR() invalid cidr: invalid length for network: Network length 129 is too long for Ipv6 (maximum: 128)" ) ,
1186
+ ( "0.0.0.0/256" , "10.0.0.1" , "is_IP_in_CIDR() invalid cidr: couldn't parse length in network: number too large to fit in target type" ) ,
1187
+ ( "::/256" , "2001:db8::" , "is_IP_in_CIDR() invalid cidr: couldn't parse length in network: number too large to fit in target type" ) ,
1188
+ ( "10.0.0.0/8/8" , "10.0.0.1" , "is_IP_in_CIDR() invalid cidr: couldn't parse address in network: invalid IP address syntax" ) ,
1189
+ ( "2001:db8::/56/56" , "2001:db8::" , "is_IP_in_CIDR() invalid cidr: couldn't parse address in network: invalid IP address syntax" ) ,
1190
+ ( "0.0.0.0/-1" , "10.0.0.1" , "is_IP_in_CIDR() invalid cidr: couldn't parse length in network: invalid digit found in string" ) ,
1191
+ ( "::/-1" , "2001:db8::" , "is_IP_in_CIDR() invalid cidr: couldn't parse length in network: invalid digit found in string" ) ,
1192
+ ( "10.128.0.0/8" , "10.0.0.1" , "is_IP_in_CIDR() invalid cidr: host part of address was not zero" ) ,
1193
+ ( "2001:db8::/16" , "2001:db8::" , "is_IP_in_CIDR() invalid cidr: host part of address was not zero" ) ,
1194
+ ( "10.1.2.3/31" , "10.0.0.1" , "is_IP_in_CIDR() invalid cidr: host part of address was not zero" ) ,
1195
+ ( "2001:db8:1:2:3:4:5:7/127" , "2001:db8::" , "is_IP_in_CIDR() invalid cidr: host part of address was not zero" ) ,
1196
+ ( "10.0.0.0/8" , "10.0.0" , "is_IP_in_CIDR() invalid ip: invalid IP address syntax" ) ,
1197
+ ( "2001:db8::/56" , "2001:db8:::" , "is_IP_in_CIDR() invalid ip: invalid IP address syntax" ) ,
1198
+ ] ;
1199
+ for ( cidr, ip, expect_error) in cases. iter ( ) {
1200
+ assert_panic ( expect_error, || {
1201
+ let mut ctx = Context :: new ( ) ;
1202
+ let args = ValueRef :: list ( Some ( & [ & ValueRef :: str ( ip) , & ValueRef :: str ( cidr) ] ) )
1203
+ . into_raw ( & mut ctx) ;
1204
+ let kwargs = ValueRef :: dict ( None ) . into_raw ( & mut ctx) ;
1205
+ kclvm_net_is_IP_in_CIDR ( ctx. into_raw ( ) , args, kwargs) ;
1206
+ } ) ;
1207
+ }
1208
+ std:: panic:: set_hook ( prev_hook) ;
1209
+ }
1053
1210
}
0 commit comments