66//!
77//! # Example
88//! ```
9- //! extern crate iptables;
10- //!
119//! fn main() {
1210//! let ipt = iptables::new(false).unwrap();
1311//! assert_eq!(ipt.new_chain("nat", "NEWCHAINNAME").unwrap(), true);
1816//! }
1917//! ```
2018
21- #[ macro_use]
22- extern crate lazy_static;
23- extern crate regex;
24- extern crate nix;
25-
2619pub mod error;
2720
28- use std:: process:: { Command , Output } ;
21+ use error:: { IPTError , IPTResult } ;
22+ use lazy_static:: lazy_static;
23+ use nix:: fcntl:: { flock, FlockArg } ;
2924use regex:: { Match , Regex } ;
30- use error :: { IPTResult , IPTError } ;
25+ use std :: ffi :: OsStr ;
3126use std:: fs:: File ;
3227use std:: os:: unix:: io:: AsRawFd ;
33- use nix :: fcntl :: { flock , FlockArg } ;
28+ use std :: process :: { Command , Output } ;
3429use std:: vec:: Vec ;
35- use std:: ffi:: OsStr ;
3630
3731// List of built-in chains taken from: man 8 iptables
3832const BUILTIN_CHAINS_FILTER : & ' static [ & ' static str ] = & [ "INPUT" , "FORWARD" , "OUTPUT" ] ;
@@ -97,24 +91,38 @@ pub fn new(is_ipv6: bool) -> IPTResult<IPTables> {
9791/// Creates a new `IPTables` Result with the command of 'iptables' if `is_ipv6` is `false`, otherwise the command is 'ip6tables'.
9892#[ cfg( target_os = "linux" ) ]
9993pub fn new ( is_ipv6 : bool ) -> IPTResult < IPTables > {
100- let cmd = if is_ipv6 {
101- "ip6tables"
102- } else {
103- "iptables"
104- } ;
94+ let cmd = if is_ipv6 { "ip6tables" } else { "iptables" } ;
10595
10696 let version_output = Command :: new ( cmd) . arg ( "--version" ) . output ( ) ?;
10797 let re = Regex :: new ( r"v(\d+)\.(\d+)\.(\d+)" ) ?;
10898 let version_string = String :: from_utf8_lossy ( & version_output. stdout ) . into_owned ( ) ;
109- let versions = re. captures ( & version_string) . ok_or ( "invalid version number" ) ?;
110- let v_major = versions. get ( 1 ) . ok_or ( "unable to get major version number" ) ?. as_str ( ) . parse :: < i32 > ( ) ?;
111- let v_minor = versions. get ( 2 ) . ok_or ( "unable to get minor version number" ) ?. as_str ( ) . parse :: < i32 > ( ) ?;
112- let v_patch = versions. get ( 3 ) . ok_or ( "unable to get patch version number" ) ?. as_str ( ) . parse :: < i32 > ( ) ?;
99+ let versions = re
100+ . captures ( & version_string)
101+ . ok_or ( "invalid version number" ) ?;
102+ let v_major = versions
103+ . get ( 1 )
104+ . ok_or ( "unable to get major version number" ) ?
105+ . as_str ( )
106+ . parse :: < i32 > ( ) ?;
107+ let v_minor = versions
108+ . get ( 2 )
109+ . ok_or ( "unable to get minor version number" ) ?
110+ . as_str ( )
111+ . parse :: < i32 > ( ) ?;
112+ let v_patch = versions
113+ . get ( 3 )
114+ . ok_or ( "unable to get patch version number" ) ?
115+ . as_str ( )
116+ . parse :: < i32 > ( ) ?;
113117
114118 Ok ( IPTables {
115119 cmd : cmd,
116- has_check : ( v_major > 1 ) || ( v_major == 1 && v_minor > 4 ) || ( v_major == 1 && v_minor == 4 && v_patch > 10 ) ,
117- has_wait : ( v_major > 1 ) || ( v_major == 1 && v_minor > 4 ) || ( v_major == 1 && v_minor == 4 && v_patch > 19 ) ,
120+ has_check : ( v_major > 1 )
121+ || ( v_major == 1 && v_minor > 4 )
122+ || ( v_major == 1 && v_minor == 4 && v_patch > 10 ) ,
123+ has_wait : ( v_major > 1 )
124+ || ( v_major == 1 && v_minor > 4 )
125+ || ( v_major == 1 && v_minor == 4 && v_patch > 19 ) ,
118126 } )
119127}
120128
@@ -123,25 +131,31 @@ impl IPTables {
123131 pub fn get_policy ( & self , table : & str , chain : & str ) -> IPTResult < String > {
124132 let builtin_chains = get_builtin_chains ( table) ?;
125133 if !builtin_chains. iter ( ) . as_slice ( ) . contains ( & chain) {
126- return Err ( IPTError :: Other ( "given chain is not a default chain in the given table, can't get policy" ) ) ;
134+ return Err ( IPTError :: Other (
135+ "given chain is not a default chain in the given table, can't get policy" ,
136+ ) ) ;
127137 }
128138
129- let output = String :: from_utf8_lossy ( & self . run ( & [ "-t" , table , "-L" , chain ] ) ? . stdout )
130- . into_owned ( ) ;
139+ let output =
140+ String :: from_utf8_lossy ( & self . run ( & [ "-t" , table , "-L" , chain ] ) ? . stdout ) . into_owned ( ) ;
131141 for item in output. trim ( ) . split ( "\n " ) {
132142 let fields = item. split ( " " ) . collect :: < Vec < & str > > ( ) ;
133143 if fields. len ( ) > 1 && fields[ 0 ] == "Chain" && fields[ 1 ] == chain {
134144 return Ok ( fields[ 3 ] . replace ( ")" , "" ) ) ;
135145 }
136146 }
137- Err ( IPTError :: Other ( "could not find the default policy for table and chain" ) )
147+ Err ( IPTError :: Other (
148+ "could not find the default policy for table and chain" ,
149+ ) )
138150 }
139151
140152 /// Set the default policy for a table/chain.
141153 pub fn set_policy ( & self , table : & str , chain : & str , policy : & str ) -> IPTResult < bool > {
142154 let builtin_chains = get_builtin_chains ( table) ?;
143155 if !builtin_chains. iter ( ) . as_slice ( ) . contains ( & chain) {
144- return Err ( IPTError :: Other ( "given chain is not a default chain in the given table, can't set policy" ) ) ;
156+ return Err ( IPTError :: Other (
157+ "given chain is not a default chain in the given table, can't set policy" ,
158+ ) ) ;
145159 }
146160
147161 match self . run ( & [ "-t" , table, "-P" , chain, policy] ) {
@@ -183,17 +197,29 @@ impl IPTables {
183197 /// Inserts `rule` in the `position` to the table/chain.
184198 /// Returns `true` if the rule is inserted.
185199 pub fn insert ( & self , table : & str , chain : & str , rule : & str , position : i32 ) -> IPTResult < bool > {
186- match self . run ( & [ & [ "-t" , table, "-I" , chain, & position. to_string ( ) ] , rule. split_quoted ( ) . as_slice ( ) ] . concat ( ) ) {
200+ match self . run (
201+ & [
202+ & [ "-t" , table, "-I" , chain, & position. to_string ( ) ] ,
203+ rule. split_quoted ( ) . as_slice ( ) ,
204+ ]
205+ . concat ( ) ,
206+ ) {
187207 Ok ( output) => Ok ( output. status . success ( ) ) ,
188208 Err ( err) => Err ( err) ,
189209 }
190210 }
191211
192212 /// Inserts `rule` in the `position` to the table/chain if it does not exist.
193213 /// Returns `true` if the rule is inserted.
194- pub fn insert_unique ( & self , table : & str , chain : & str , rule : & str , position : i32 ) -> IPTResult < bool > {
214+ pub fn insert_unique (
215+ & self ,
216+ table : & str ,
217+ chain : & str ,
218+ rule : & str ,
219+ position : i32 ,
220+ ) -> IPTResult < bool > {
195221 if self . exists ( table, chain, rule) ? {
196- return Err ( IPTError :: Other ( "the rule exists in the table/chain" ) )
222+ return Err ( IPTError :: Other ( "the rule exists in the table/chain" ) ) ;
197223 }
198224
199225 self . insert ( table, chain, rule, position)
@@ -202,7 +228,13 @@ impl IPTables {
202228 /// Replaces `rule` in the `position` to the table/chain.
203229 /// Returns `true` if the rule is replaced.
204230 pub fn replace ( & self , table : & str , chain : & str , rule : & str , position : i32 ) -> IPTResult < bool > {
205- match self . run ( & [ & [ "-t" , table, "-R" , chain, & position. to_string ( ) ] , rule. split_quoted ( ) . as_slice ( ) ] . concat ( ) ) {
231+ match self . run (
232+ & [
233+ & [ "-t" , table, "-R" , chain, & position. to_string ( ) ] ,
234+ rule. split_quoted ( ) . as_slice ( ) ,
235+ ]
236+ . concat ( ) ,
237+ ) {
206238 Ok ( output) => Ok ( output. status . success ( ) ) ,
207239 Err ( err) => Err ( err) ,
208240 }
@@ -221,7 +253,7 @@ impl IPTables {
221253 /// Returns `true` if the rule is appended.
222254 pub fn append_unique ( & self , table : & str , chain : & str , rule : & str ) -> IPTResult < bool > {
223255 if self . exists ( table, chain, rule) ? {
224- return Err ( IPTError :: Other ( "the rule exists in the table/chain" ) )
256+ return Err ( IPTError :: Other ( "the rule exists in the table/chain" ) ) ;
225257 }
226258
227259 self . append ( table, chain, rule)
@@ -325,7 +357,9 @@ impl IPTables {
325357
326358 fn exists_old_version ( & self , table : & str , chain : & str , rule : & str ) -> IPTResult < bool > {
327359 match self . run ( & [ "-t" , table, "-S" ] ) {
328- Ok ( output) => Ok ( String :: from_utf8_lossy ( & output. stdout ) . into_owned ( ) . contains ( & format ! ( "-A {} {}" , chain, rule) ) ) ,
360+ Ok ( output) => Ok ( String :: from_utf8_lossy ( & output. stdout )
361+ . into_owned ( )
362+ . contains ( & format ! ( "-A {} {}" , chain, rule) ) ) ,
329363 Err ( err) => Err ( err) ,
330364 }
331365 }
@@ -352,14 +386,18 @@ impl IPTables {
352386
353387 let mut need_retry = true ;
354388 while need_retry {
355- match flock ( file_lock. as_ref ( ) . unwrap ( ) . as_raw_fd ( ) , FlockArg :: LockExclusiveNonblock ) {
389+ match flock (
390+ file_lock. as_ref ( ) . unwrap ( ) . as_raw_fd ( ) ,
391+ FlockArg :: LockExclusiveNonblock ,
392+ ) {
356393 Ok ( _) => need_retry = false ,
357- Err ( e ) => if e . errno ( ) == nix:: errno:: EAGAIN {
394+ Err ( nix :: Error :: Sys ( en ) ) if en == nix:: errno:: Errno :: EAGAIN => {
358395 // FIXME: may cause infinite loop
359396 need_retry = true ;
360- } else {
397+ }
398+ Err ( e) => {
361399 return Err ( IPTError :: Nix ( e) ) ;
362- } ,
400+ }
363401 }
364402 }
365403 output = output_cmd. args ( args) . output ( ) ?;
0 commit comments