@@ -42,9 +42,10 @@ pub struct NatPoolEntry {
42
42
port : u16 ,
43
43
}
44
44
45
- // An entry in the internal free list of `NatPool`
45
+ // A public IP and port range for NAT. Includes the list of all possible ports
46
+ // and those that are free.
46
47
#[ derive( Debug , Clone ) ]
47
- struct FreeListEntry {
48
+ struct PortList {
48
49
// The public IP address to which a private IP is mapped
49
50
ip : IpAddr ,
50
51
// The list of all possible ports available in the NAT pool
@@ -59,7 +60,7 @@ impl ResourceEntry for NatPoolEntry {}
59
60
/// NAT-ing connections.
60
61
pub struct NatPool {
61
62
// Map private IP to public IP + free list of ports
62
- free_list : KMutex < BTreeMap < IpAddr , FreeListEntry > > ,
63
+ free_list : KMutex < BTreeMap < IpAddr , PortList > > ,
63
64
}
64
65
65
66
mod private {
@@ -84,14 +85,14 @@ impl NatPool {
84
85
) {
85
86
let free_ports = pub_ports. clone ( ) . collect ( ) ;
86
87
let entry =
87
- FreeListEntry { ip : pub_ip. into ( ) , ports : pub_ports, free_ports } ;
88
+ PortList { ip : pub_ip. into ( ) , ports : pub_ports, free_ports } ;
88
89
self . free_list . lock ( ) . insert ( priv_ip. into ( ) , entry) ;
89
90
}
90
91
91
92
/// Return the number of available ports for a given private IP address.
92
93
pub fn num_avail ( & self , priv_ip : IpAddr ) -> Result < usize , ResourceError > {
93
94
match self . free_list . lock ( ) . get ( & priv_ip) {
94
- Some ( FreeListEntry { free_ports, .. } ) => Ok ( free_ports. len ( ) ) ,
95
+ Some ( PortList { free_ports, .. } ) => Ok ( free_ports. len ( ) ) ,
95
96
_ => Err ( ResourceError :: NoMatch ( priv_ip. to_string ( ) ) ) ,
96
97
}
97
98
}
@@ -104,7 +105,7 @@ impl NatPool {
104
105
self . free_list
105
106
. lock ( )
106
107
. get ( & priv_ip)
107
- . map ( |FreeListEntry { ip, ports, .. } | ( ip. clone ( ) , ports. clone ( ) ) )
108
+ . map ( |PortList { ip, ports, .. } | ( ip. clone ( ) , ports. clone ( ) ) )
108
109
}
109
110
110
111
/// Create a new NAT pool, with no entries.
@@ -121,7 +122,7 @@ impl NatPool {
121
122
pub_port : u16 ,
122
123
) -> bool {
123
124
match self . free_list . lock ( ) . get ( & priv_ip. into ( ) ) {
124
- Some ( FreeListEntry { ip, free_ports, .. } ) => {
125
+ Some ( PortList { ip, free_ports, .. } ) => {
125
126
if pub_ip. into ( ) != * ip {
126
127
return false ;
127
128
}
@@ -140,7 +141,7 @@ impl FiniteResource for NatPool {
140
141
141
142
fn obtain ( & self , priv_ip : & IpAddr ) -> Result < Self :: Entry , ResourceError > {
142
143
match self . free_list . lock ( ) . get_mut ( & priv_ip) {
143
- Some ( FreeListEntry { ip, free_ports, .. } ) => {
144
+ Some ( PortList { ip, free_ports, .. } ) => {
144
145
if let Some ( port) = free_ports. pop ( ) {
145
146
Ok ( Self :: Entry { ip : * ip, port } )
146
147
} else {
@@ -154,7 +155,7 @@ impl FiniteResource for NatPool {
154
155
155
156
fn release ( & self , priv_ip : & IpAddr , entry : Self :: Entry ) {
156
157
match self . free_list . lock ( ) . get_mut ( & priv_ip) {
157
- Some ( FreeListEntry { free_ports, .. } ) => {
158
+ Some ( PortList { free_ports, .. } ) => {
158
159
free_ports. push ( entry. port ) ;
159
160
}
160
161
@@ -211,16 +212,14 @@ impl StatefulAction for SNat {
211
212
212
213
Ok ( AllowOrDeny :: Allow ( Arc :: new ( desc) ) )
213
214
}
214
-
215
- // XXX This still needs improving.
216
215
Err ( ResourceError :: Exhausted ) => {
217
216
Err ( rule:: GenDescError :: ResourceExhausted {
218
217
name : "SNAT Pool (exhausted)" . to_string ( ) ,
219
218
} )
220
219
}
221
220
Err ( ResourceError :: NoMatch ( ip) ) => {
222
- Err ( rule:: GenDescError :: ResourceExhausted {
223
- name : format ! ( "SNAT pool (no match: {})" , ip) ,
221
+ Err ( rule:: GenDescError :: Unexpected {
222
+ msg : format ! ( "SNAT pool (no match: {})" , ip) ,
224
223
} )
225
224
}
226
225
}
@@ -341,16 +340,16 @@ mod test {
341
340
let priv_ipv4: Ipv4Addr = "10.0.0.220" . parse ( ) . unwrap ( ) ;
342
341
let priv_ip = IpAddr :: from ( priv_ipv4) ;
343
342
let priv_port = "4999" . parse ( ) . unwrap ( ) ;
344
- let pub_ipv4 : Ipv4Addr = "52.10.128.69" . parse ( ) . unwrap ( ) ;
343
+ let pub_ip : Ipv4Addr = "52.10.128.69" . parse ( ) . unwrap ( ) ;
345
344
let pub_port = "8765" . parse ( ) . unwrap ( ) ;
346
- let outside_ipv4 : Ipv4Addr = "76.76.21.21" . parse ( ) . unwrap ( ) ;
345
+ let outside_ip : Ipv4Addr = "76.76.21.21" . parse ( ) . unwrap ( ) ;
347
346
let outside_port = 80 ;
348
347
349
348
let pool = Arc :: new ( NatPool :: new ( ) ) ;
350
- pool. add ( priv_ipv4, pub_ipv4 , 8765 ..=8765 ) ;
349
+ pool. add ( priv_ipv4, pub_ip , 8765 ..=8765 ) ;
351
350
let snat = SNat :: new ( priv_ip, pool. clone ( ) ) ;
352
351
let mut action_meta = ActionMeta :: new ( ) ;
353
- assert ! ( pool. verify_available( priv_ipv4, pub_ipv4 , pub_port) ) ;
352
+ assert ! ( pool. verify_available( priv_ipv4, pub_ip , pub_port) ) ;
354
353
355
354
// ================================================================
356
355
// Build the packet metadata
@@ -362,7 +361,7 @@ mod test {
362
361
} ;
363
362
let ip = IpMeta :: from ( Ipv4Meta {
364
363
src : priv_ipv4,
365
- dst : outside_ipv4 ,
364
+ dst : outside_ip ,
366
365
proto : Protocol :: TCP ,
367
366
} ) ;
368
367
let ulp = UlpMeta :: from ( TcpMeta {
@@ -391,7 +390,7 @@ mod test {
391
390
Ok ( AllowOrDeny :: Allow ( desc) ) => desc,
392
391
_ => panic ! ( "expected AllowOrDeny::Allow(desc) result" ) ,
393
392
} ;
394
- assert ! ( !pool. verify_available( priv_ipv4, pub_ipv4 , pub_port) ) ;
393
+ assert ! ( !pool. verify_available( priv_ipv4, pub_ip , pub_port) ) ;
395
394
396
395
// ================================================================
397
396
// Verify outbound header transformation
@@ -408,8 +407,8 @@ mod test {
408
407
_ => panic ! ( "expect Ipv4Meta" ) ,
409
408
} ;
410
409
411
- assert_eq ! ( ip4_meta. src, pub_ipv4 ) ;
412
- assert_eq ! ( ip4_meta. dst, outside_ipv4 ) ;
410
+ assert_eq ! ( ip4_meta. src, pub_ip ) ;
411
+ assert_eq ! ( ip4_meta. dst, outside_ip ) ;
413
412
assert_eq ! ( ip4_meta. proto, Protocol :: TCP ) ;
414
413
415
414
let tcp_meta = match pmo. inner . ulp . as_ref ( ) . unwrap ( ) {
@@ -430,8 +429,8 @@ mod test {
430
429
ether_type : ETHER_TYPE_IPV4 ,
431
430
} ;
432
431
let ip = IpMeta :: from ( Ipv4Meta {
433
- src : outside_ipv4 ,
434
- dst : pub_ipv4 ,
432
+ src : outside_ip ,
433
+ dst : pub_ip ,
435
434
proto : Protocol :: TCP ,
436
435
} ) ;
437
436
let ulp = UlpMeta :: from ( TcpMeta {
@@ -464,7 +463,7 @@ mod test {
464
463
_ => panic ! ( "expect Ipv4Meta" ) ,
465
464
} ;
466
465
467
- assert_eq ! ( ip4_meta. src, outside_ipv4 ) ;
466
+ assert_eq ! ( ip4_meta. src, outside_ip ) ;
468
467
assert_eq ! ( ip4_meta. dst, priv_ipv4) ;
469
468
assert_eq ! ( ip4_meta. proto, Protocol :: TCP ) ;
470
469
@@ -482,21 +481,21 @@ mod test {
482
481
// handed back to the pool.
483
482
// ================================================================
484
483
drop ( desc) ;
485
- assert ! ( pool. verify_available( priv_ipv4, pub_ipv4 , pub_port) ) ;
484
+ assert ! ( pool. verify_available( priv_ipv4, pub_ip , pub_port) ) ;
486
485
}
487
486
488
487
#[ test]
489
488
fn nat_mappings ( ) {
490
489
let pool = NatPool :: new ( ) ;
491
- let priv1_ipv4 = "192.168.2.8" . parse :: < Ipv4Addr > ( ) . unwrap ( ) ;
492
- let priv1 = IpAddr :: Ip4 ( priv1_ipv4 ) ;
493
- let priv2_ipv4 = "192.168.2.33" . parse :: < Ipv4Addr > ( ) . unwrap ( ) ;
494
- let priv2 = IpAddr :: Ip4 ( priv2_ipv4 ) ;
495
- let public_ipv4 = "52.10.128.69" . parse ( ) . unwrap ( ) ;
496
- let public = IpAddr :: Ip4 ( public_ipv4 ) ;
497
-
498
- pool. add ( priv1_ipv4 , public_ipv4 , 1025 ..=4096 ) ;
499
- pool. add ( priv2_ipv4 , public_ipv4 , 4097 ..=8192 ) ;
490
+ let priv1_ip = "192.168.2.8" . parse :: < Ipv4Addr > ( ) . unwrap ( ) ;
491
+ let priv1 = IpAddr :: Ip4 ( priv1_ip ) ;
492
+ let priv2_ip = "192.168.2.33" . parse :: < Ipv4Addr > ( ) . unwrap ( ) ;
493
+ let priv2 = IpAddr :: Ip4 ( priv2_ip ) ;
494
+ let public_ip = "52.10.128.69" . parse ( ) . unwrap ( ) ;
495
+ let public = IpAddr :: Ip4 ( public_ip ) ;
496
+
497
+ pool. add ( priv1_ip , public_ip , 1025 ..=4096 ) ;
498
+ pool. add ( priv2_ip , public_ip , 4097 ..=8192 ) ;
500
499
501
500
assert_eq ! ( pool. num_avail( priv1) . unwrap( ) , 3072 ) ;
502
501
let npe1 = match pool. obtain ( & priv1) {
0 commit comments