2007-02-14 16:26:42 +00:00
/*
* Copyright ( C ) 2007 Red Hat , Inc .
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*
* Authors :
* Mark McLoughlin < markmc @ redhat . com >
*/
# include <config.h>
# include "iptables.h"
# include <stdio.h>
# include <stdlib.h>
# include <stdarg.h>
# include <string.h>
# include <errno.h>
# include <limits.h>
# include <unistd.h>
# include <fcntl.h>
# include <paths.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <sys/wait.h>
2007-03-30 16:25:02 +00:00
# include "internal.h"
2007-02-14 16:26:42 +00:00
enum {
ADD = 0 ,
REMOVE
} ;
enum {
WITH_ERRORS = 0 ,
NO_ERRORS
} ;
2007-03-30 16:25:02 +00:00
typedef struct
{
char * rule ;
char * * argv ;
int flipflop ;
} iptRule ;
2007-02-14 16:26:42 +00:00
typedef struct
{
char * table ;
char * chain ;
2007-03-30 16:25:02 +00:00
int nrules ;
iptRule * rules ;
2007-03-30 16:24:13 +00:00
2007-02-14 16:26:42 +00:00
# ifdef IPTABLES_DIR
char dir [ PATH_MAX ] ;
char path [ PATH_MAX ] ;
# endif /* IPTABLES_DIR */
} iptRules ;
struct _iptablesContext
{
iptRules * input_filter ;
iptRules * forward_filter ;
iptRules * nat_postrouting ;
} ;
# ifdef IPTABLES_DIR
static int
writeRules ( const char * path ,
2007-03-30 16:25:02 +00:00
const iptRules * rules ,
2007-02-14 16:26:42 +00:00
int nrules )
{
char tmp [ PATH_MAX ] ;
FILE * f ;
int istmp ;
int i ;
if ( nrules = = 0 & & unlink ( path ) = = 0 )
return 0 ;
if ( snprintf ( tmp , PATH_MAX , " %s.new " , path ) > = PATH_MAX )
return EINVAL ;
istmp = 1 ;
if ( ! ( f = fopen ( tmp , " w " ) ) ) {
istmp = 0 ;
if ( ! ( f = fopen ( path , " w " ) ) )
return errno ;
}
for ( i = 0 ; i < nrules ; i + + ) {
2007-03-30 16:25:02 +00:00
if ( fputs ( rules [ i ] . rule , f ) = = EOF | |
2007-02-14 16:26:42 +00:00
fputc ( ' \n ' , f ) = = EOF ) {
fclose ( f ) ;
if ( istmp )
unlink ( tmp ) ;
return errno ;
}
}
fclose ( f ) ;
if ( istmp & & rename ( tmp , path ) < 0 ) {
unlink ( tmp ) ;
return errno ;
}
if ( istmp )
unlink ( tmp ) ;
return 0 ;
}
static int
ensureDir ( const char * path )
{
struct stat st ;
char parent [ PATH_MAX ] ;
char * p ;
int err ;
if ( stat ( path , & st ) > = 0 )
return 0 ;
strncpy ( parent , path , PATH_MAX ) ;
parent [ PATH_MAX - 1 ] = ' \0 ' ;
if ( ! ( p = strrchr ( parent , ' / ' ) ) )
return EINVAL ;
if ( p = = parent )
return EPERM ;
* p = ' \0 ' ;
if ( ( err = ensureDir ( parent ) ) )
return err ;
if ( mkdir ( path , 0700 ) < 0 & & errno ! = EEXIST )
return errno ;
return 0 ;
}
static int
buildDir ( const char * table ,
char * path ,
int maxlen )
{
if ( snprintf ( path , maxlen , IPTABLES_DIR " /%s " , table ) > = maxlen )
return EINVAL ;
else
return 0 ;
}
static int
buildPath ( const char * table ,
const char * chain ,
char * path ,
int maxlen )
{
if ( snprintf ( path , maxlen , IPTABLES_DIR " /%s/%s.chain " , table , chain ) > = maxlen )
return EINVAL ;
else
return 0 ;
}
2007-03-30 16:24:13 +00:00
# endif /* IPTABLES_DIR */
2007-02-14 16:26:42 +00:00
2007-03-30 16:25:02 +00:00
static void
iptRuleFree ( iptRule * rule )
{
if ( rule - > rule )
free ( rule - > rule ) ;
rule - > rule = NULL ;
if ( rule - > argv ) {
int i = 0 ;
while ( rule - > argv [ i ] )
free ( rule - > argv [ i + + ] ) ;
free ( rule - > argv ) ;
rule - > argv = NULL ;
}
}
2007-02-14 16:26:42 +00:00
static int
iptRulesAppend ( iptRules * rules ,
2007-03-30 16:25:02 +00:00
char * rule ,
char * * argv ,
int flipflop )
2007-02-14 16:26:42 +00:00
{
2007-03-30 16:25:02 +00:00
iptRule * r ;
2007-02-14 16:26:42 +00:00
2007-03-30 16:25:02 +00:00
if ( ! ( r = ( iptRule * ) realloc ( rules - > rules , sizeof ( iptRule ) * ( rules - > nrules + 1 ) ) ) ) {
int i = 0 ;
while ( argv [ i ] )
free ( argv [ i + + ] ) ;
free ( argv ) ;
2007-02-14 16:26:42 +00:00
return ENOMEM ;
2007-03-30 16:25:02 +00:00
}
2007-02-14 16:26:42 +00:00
rules - > rules = r ;
2007-03-30 16:25:02 +00:00
rules - > rules [ rules - > nrules ] . rule = rule ;
rules - > rules [ rules - > nrules ] . argv = argv ;
rules - > rules [ rules - > nrules ] . flipflop = flipflop ;
2007-02-14 16:26:42 +00:00
rules - > nrules + + ;
2007-03-30 16:24:13 +00:00
# ifdef IPTABLES_DIR
{
int err ;
2007-02-14 16:26:42 +00:00
2007-03-30 16:24:13 +00:00
if ( ( err = ensureDir ( rules - > dir ) ) )
return err ;
if ( ( err = writeRules ( rules - > path , rules - > rules , rules - > nrules ) ) )
return err ;
}
# endif /* IPTABLES_DIR */
2007-02-14 16:26:42 +00:00
return 0 ;
}
static int
iptRulesRemove ( iptRules * rules ,
2007-03-30 16:24:13 +00:00
char * rule )
2007-02-14 16:26:42 +00:00
{
int i ;
for ( i = 0 ; i < rules - > nrules ; i + + )
2007-03-30 16:25:02 +00:00
if ( ! strcmp ( rules - > rules [ i ] . rule , strdup ( rule ) ) )
2007-02-14 16:26:42 +00:00
break ;
if ( i > = rules - > nrules )
return EINVAL ;
2007-03-30 16:25:02 +00:00
iptRuleFree ( & rules - > rules [ i ] ) ;
2007-02-14 16:26:42 +00:00
memmove ( & rules - > rules [ i ] ,
& rules - > rules [ i + 1 ] ,
2007-03-30 16:25:02 +00:00
( rules - > nrules - i - 1 ) * sizeof ( iptRule ) ) ;
2007-02-14 16:26:42 +00:00
rules - > nrules - - ;
2007-03-30 16:24:13 +00:00
# ifdef IPTABLES_DIR
{
int err ;
if ( ( err = writeRules ( rules - > path , rules - > rules , rules - > nrules ) ) )
return err ;
}
# endif /* IPTABLES_DIR */
2007-02-14 16:26:42 +00:00
return 0 ;
}
static void
iptRulesFree ( iptRules * rules )
{
2007-03-30 16:24:13 +00:00
int i ;
2007-02-14 16:26:42 +00:00
if ( rules - > table ) {
2007-02-20 17:51:41 +00:00
free ( rules - > table ) ;
rules - > table = NULL ;
2007-02-14 16:26:42 +00:00
}
if ( rules - > chain ) {
free ( rules - > chain ) ;
rules - > chain = NULL ;
}
2007-03-30 16:24:13 +00:00
if ( rules - > rules ) {
2007-03-30 16:25:02 +00:00
for ( i = 0 ; i < rules - > nrules ; i + + )
iptRuleFree ( & rules - > rules [ i ] ) ;
2007-03-30 16:24:13 +00:00
free ( rules - > rules ) ;
rules - > rules = NULL ;
2007-03-30 16:25:02 +00:00
rules - > nrules = 0 ;
2007-02-14 16:26:42 +00:00
}
2007-03-30 16:24:13 +00:00
# ifdef IPTABLES_DIR
rules - > dir [ 0 ] = ' \0 ' ;
rules - > path [ 0 ] = ' \0 ' ;
2007-02-14 16:26:42 +00:00
# endif /* IPTABLES_DIR */
free ( rules ) ;
}
static iptRules *
iptRulesNew ( const char * table ,
const char * chain )
{
iptRules * rules ;
2007-03-22 18:30:57 +00:00
if ( ! ( rules = ( iptRules * ) calloc ( 1 , sizeof ( iptRules ) ) ) )
2007-02-14 16:26:42 +00:00
return NULL ;
if ( ! ( rules - > table = strdup ( table ) ) )
goto error ;
if ( ! ( rules - > chain = strdup ( chain ) ) )
goto error ;
2007-03-30 16:24:13 +00:00
rules - > rules = NULL ;
rules - > nrules = 0 ;
2007-02-14 16:26:42 +00:00
# ifdef IPTABLES_DIR
if ( buildDir ( table , rules - > dir , sizeof ( rules - > dir ) ) )
goto error ;
if ( buildPath ( table , chain , rules - > path , sizeof ( rules - > path ) ) )
goto error ;
# endif /* IPTABLES_DIR */
return rules ;
error :
iptRulesFree ( rules ) ;
return NULL ;
}
static int
iptablesSpawn ( int errors , char * const * argv )
{
pid_t pid , ret ;
int status ;
int null = - 1 ;
if ( errors = = NO_ERRORS & & ( null = open ( _PATH_DEVNULL , O_RDONLY ) ) < 0 )
return errno ;
pid = fork ( ) ;
if ( pid = = - 1 ) {
if ( errors = = NO_ERRORS )
close ( null ) ;
return errno ;
}
if ( pid = = 0 ) { /* child */
2007-02-16 18:26:18 +00:00
if ( errors = = NO_ERRORS ) {
dup2 ( null , STDIN_FILENO ) ;
dup2 ( null , STDOUT_FILENO ) ;
dup2 ( null , STDERR_FILENO ) ;
close ( null ) ;
2007-02-14 16:26:42 +00:00
}
execvp ( argv [ 0 ] , argv ) ;
_exit ( 1 ) ;
}
if ( errors = = NO_ERRORS )
close ( null ) ;
while ( ( ret = waitpid ( pid , & status , 0 ) = = - 1 ) & & errno = = EINTR ) ;
if ( ret = = - 1 )
return errno ;
if ( errors = = NO_ERRORS )
return 0 ;
else
return ( WIFEXITED ( status ) & & WEXITSTATUS ( status ) = = 0 ) ? 0 : EINVAL ;
}
static int
iptablesAddRemoveChain ( iptRules * rules , int action )
{
char * * argv ;
int retval = ENOMEM ;
int n ;
n = 1 + /* /sbin/iptables */
2 + /* --table foo */
2 ; /* --new-chain bar */
2007-03-22 18:30:57 +00:00
if ( ! ( argv = ( char * * ) calloc ( n + 1 , sizeof ( char * ) ) ) )
2007-02-14 16:26:42 +00:00
goto error ;
n = 0 ;
if ( ! ( argv [ n + + ] = strdup ( IPTABLES_PATH ) ) )
goto error ;
if ( ! ( argv [ n + + ] = strdup ( " --table " ) ) )
goto error ;
if ( ! ( argv [ n + + ] = strdup ( rules - > table ) ) )
goto error ;
if ( ! ( argv [ n + + ] = strdup ( action = = ADD ? " --new-chain " : " --delete-chain " ) ) )
goto error ;
if ( ! ( argv [ n + + ] = strdup ( rules - > chain ) ) )
goto error ;
retval = iptablesSpawn ( NO_ERRORS , argv ) ;
error :
if ( argv ) {
n = 0 ;
while ( argv [ n ] )
free ( argv [ n + + ] ) ;
free ( argv ) ;
}
return retval ;
}
static int
iptablesAddRemoveRule ( iptRules * rules , int action , const char * arg , . . . )
{
va_list args ;
int retval = ENOMEM ;
char * * argv ;
char * rule = NULL , * p ;
const char * s ;
2007-03-30 16:25:02 +00:00
int n , rulelen , flipflop ;
2007-02-14 16:26:42 +00:00
n = 1 + /* /sbin/iptables */
2 + /* --table foo */
2 + /* --insert bar */
1 ; /* arg */
rulelen = strlen ( arg ) + 1 ;
va_start ( args , arg ) ;
while ( ( s = va_arg ( args , const char * ) ) ) {
n + + ;
rulelen + = strlen ( s ) + 1 ;
}
va_end ( args ) ;
2007-03-22 18:30:57 +00:00
if ( ! ( argv = ( char * * ) calloc ( n + 1 , sizeof ( char * ) ) ) )
2007-02-14 16:26:42 +00:00
goto error ;
if ( ! ( rule = ( char * ) malloc ( rulelen ) ) )
goto error ;
n = 0 ;
if ( ! ( argv [ n + + ] = strdup ( IPTABLES_PATH ) ) )
goto error ;
if ( ! ( argv [ n + + ] = strdup ( " --table " ) ) )
goto error ;
if ( ! ( argv [ n + + ] = strdup ( rules - > table ) ) )
goto error ;
2007-03-30 16:25:02 +00:00
flipflop = n ;
2007-02-14 16:26:42 +00:00
if ( ! ( argv [ n + + ] = strdup ( action = = ADD ? " --insert " : " --delete " ) ) )
goto error ;
if ( ! ( argv [ n + + ] = strdup ( rules - > chain ) ) )
goto error ;
if ( ! ( argv [ n + + ] = strdup ( arg ) ) )
goto error ;
p = strcpy ( rule , arg ) ;
p + = strlen ( arg ) ;
va_start ( args , arg ) ;
while ( ( s = va_arg ( args , const char * ) ) ) {
if ( ! ( argv [ n + + ] = strdup ( s ) ) )
goto error ;
* ( p + + ) = ' ' ;
strcpy ( p , s ) ;
p + = strlen ( s ) ;
}
va_end ( args ) ;
* p = ' \0 ' ;
if ( action = = ADD & &
( retval = iptablesAddRemoveChain ( rules , action ) ) )
goto error ;
if ( ( retval = iptablesSpawn ( WITH_ERRORS , argv ) ) )
goto error ;
if ( action = = REMOVE & &
( retval = iptablesAddRemoveChain ( rules , action ) ) )
goto error ;
2007-03-30 16:25:02 +00:00
if ( action = = ADD ) {
retval = iptRulesAppend ( rules , rule , argv , flipflop ) ;
rule = NULL ;
argv = NULL ;
} else {
2007-02-14 16:26:42 +00:00
retval = iptRulesRemove ( rules , rule ) ;
2007-03-30 16:25:02 +00:00
}
2007-02-14 16:26:42 +00:00
error :
if ( rule )
free ( rule ) ;
if ( argv ) {
n = 0 ;
while ( argv [ n ] )
free ( argv [ n + + ] ) ;
free ( argv ) ;
}
return retval ;
}
iptablesContext *
iptablesContextNew ( void )
{
iptablesContext * ctx ;
2007-03-30 16:20:19 +00:00
if ( ! ( ctx = ( iptablesContext * ) calloc ( 1 , sizeof ( iptablesContext ) ) ) )
2007-02-14 16:26:42 +00:00
return NULL ;
if ( ! ( ctx - > input_filter = iptRulesNew ( " filter " , IPTABLES_PREFIX " INPUT " ) ) )
goto error ;
if ( ! ( ctx - > forward_filter = iptRulesNew ( " filter " , IPTABLES_PREFIX " FORWARD " ) ) )
goto error ;
if ( ! ( ctx - > nat_postrouting = iptRulesNew ( " nat " , IPTABLES_PREFIX " POSTROUTING " ) ) )
goto error ;
return ctx ;
error :
iptablesContextFree ( ctx ) ;
return NULL ;
}
void
iptablesContextFree ( iptablesContext * ctx )
{
2007-03-30 16:20:19 +00:00
if ( ctx - > input_filter )
iptRulesFree ( ctx - > input_filter ) ;
if ( ctx - > forward_filter )
iptRulesFree ( ctx - > forward_filter ) ;
if ( ctx - > nat_postrouting )
iptRulesFree ( ctx - > nat_postrouting ) ;
2007-02-14 16:26:42 +00:00
free ( ctx ) ;
}
2007-03-30 16:25:02 +00:00
static void
iptRulesReload ( iptRules * rules )
{
int i ;
int retval ;
for ( i = 0 ; i < rules - > nrules ; i + + ) {
iptRule * rule = & rules - > rules [ i ] ;
char * orig ;
orig = rule - > argv [ rule - > flipflop ] ;
rule - > argv [ rule - > flipflop ] = ( char * ) " --delete " ;
if ( ( retval = iptablesSpawn ( WITH_ERRORS , rule - > argv ) ) )
qemudLog ( QEMUD_WARN , " Failed to remove iptables rule '%s' from chain '%s' in table '%s': %s " ,
rule - > rule , rules - > chain , rules - > table , strerror ( errno ) ) ;
rule - > argv [ rule - > flipflop ] = orig ;
}
if ( ( retval = iptablesAddRemoveChain ( rules , REMOVE ) ) | |
( retval = iptablesAddRemoveChain ( rules , ADD ) ) )
qemudLog ( QEMUD_WARN , " Failed to re-create chain '%s' in table '%s': %s " ,
rules - > chain , rules - > table , strerror ( retval ) ) ;
for ( i = 0 ; i < rules - > nrules ; i + + )
if ( ( retval = iptablesSpawn ( WITH_ERRORS , rules - > rules [ i ] . argv ) ) )
qemudLog ( QEMUD_WARN , " Failed to add iptables rule '%s' to chain '%s' in table '%s': %s " ,
rules - > rules [ i ] . rule , rules - > chain , rules - > table , strerror ( retval ) ) ;
}
void
iptablesReloadRules ( iptablesContext * ctx )
{
iptRulesReload ( ctx - > input_filter ) ;
iptRulesReload ( ctx - > forward_filter ) ;
iptRulesReload ( ctx - > nat_postrouting ) ;
}
2007-02-14 16:26:42 +00:00
static int
iptablesInput ( iptablesContext * ctx ,
const char * iface ,
int port ,
int action ,
int tcp )
{
char portstr [ 32 ] ;
snprintf ( portstr , sizeof ( portstr ) , " %d " , port ) ;
portstr [ sizeof ( portstr ) - 1 ] = ' \0 ' ;
2007-03-13 22:43:22 +00:00
return iptablesAddRemoveRule ( ctx - > input_filter ,
action ,
" --in-interface " , iface ,
" --protocol " , tcp ? " tcp " : " udp " ,
" --destination-port " , portstr ,
" --jump " , " ACCEPT " ,
NULL ) ;
2007-02-14 16:26:42 +00:00
}
int
iptablesAddTcpInput ( iptablesContext * ctx ,
const char * iface ,
int port )
{
return iptablesInput ( ctx , iface , port , ADD , 1 ) ;
}
int
iptablesRemoveTcpInput ( iptablesContext * ctx ,
const char * iface ,
int port )
{
return iptablesInput ( ctx , iface , port , REMOVE , 1 ) ;
}
int
iptablesAddUdpInput ( iptablesContext * ctx ,
const char * iface ,
int port )
{
return iptablesInput ( ctx , iface , port , ADD , 0 ) ;
}
int
iptablesRemoveUdpInput ( iptablesContext * ctx ,
const char * iface ,
int port )
{
return iptablesInput ( ctx , iface , port , REMOVE , 0 ) ;
}
2007-04-10 23:17:46 +00:00
/* Allow all traffic coming from the bridge, with a valid network address
* to proceed to WAN
*/
2007-02-14 16:26:42 +00:00
static int
2007-04-10 23:17:46 +00:00
iptablesForwardAllowOut ( iptablesContext * ctx ,
const char * network ,
2007-02-14 16:26:42 +00:00
const char * iface ,
2007-04-10 23:17:46 +00:00
const char * physdev ,
2007-02-14 16:26:42 +00:00
int action )
{
2007-04-10 23:17:46 +00:00
if ( physdev & & physdev [ 0 ] ) {
2007-03-13 22:43:22 +00:00
return iptablesAddRemoveRule ( ctx - > forward_filter ,
action ,
2007-04-10 23:17:46 +00:00
" --source " , network ,
2007-03-13 22:43:22 +00:00
" --in-interface " , iface ,
2007-04-10 23:17:46 +00:00
" --out-interface " , physdev ,
2007-03-13 22:43:22 +00:00
" --jump " , " ACCEPT " ,
NULL ) ;
} else {
return iptablesAddRemoveRule ( ctx - > forward_filter ,
action ,
2007-04-10 23:17:46 +00:00
" --source " , network ,
2007-03-13 22:43:22 +00:00
" --in-interface " , iface ,
" --jump " , " ACCEPT " ,
NULL ) ;
}
2007-02-14 16:26:42 +00:00
}
int
2007-04-10 23:17:46 +00:00
iptablesAddForwardAllowOut ( iptablesContext * ctx ,
const char * network ,
2007-03-13 22:43:22 +00:00
const char * iface ,
2007-04-10 23:17:46 +00:00
const char * physdev )
2007-02-14 16:26:42 +00:00
{
2007-04-10 23:17:46 +00:00
return iptablesForwardAllowOut ( ctx , network , iface , physdev , ADD ) ;
2007-02-14 16:26:42 +00:00
}
int
2007-04-10 23:17:46 +00:00
iptablesRemoveForwardAllowOut ( iptablesContext * ctx ,
const char * network ,
2007-03-13 22:43:22 +00:00
const char * iface ,
2007-04-10 23:17:46 +00:00
const char * physdev )
2007-02-14 16:26:42 +00:00
{
2007-04-10 23:17:46 +00:00
return iptablesForwardAllowOut ( ctx , network , iface , physdev , REMOVE ) ;
2007-02-14 16:26:42 +00:00
}
2007-04-10 23:17:46 +00:00
/* Allow all traffic destined to the bridge, with a valid network address
* and associated with an existing connection
*/
2007-02-14 16:26:42 +00:00
static int
2007-04-10 23:17:46 +00:00
iptablesForwardAllowIn ( iptablesContext * ctx ,
const char * network ,
const char * iface ,
const char * physdev ,
int action )
2007-02-14 16:26:42 +00:00
{
2007-04-10 23:17:46 +00:00
if ( physdev & & physdev [ 0 ] ) {
2007-03-13 22:43:22 +00:00
return iptablesAddRemoveRule ( ctx - > forward_filter ,
action ,
2007-04-10 23:17:46 +00:00
" --destination " , network ,
" --in-interface " , physdev ,
2007-03-13 22:43:22 +00:00
" --out-interface " , iface ,
" --match " , " state " ,
" --state " , " ESTABLISHED,RELATED " ,
" --jump " , " ACCEPT " ,
NULL ) ;
} else {
return iptablesAddRemoveRule ( ctx - > forward_filter ,
action ,
2007-04-10 23:17:46 +00:00
" --destination " , network ,
2007-03-13 22:43:22 +00:00
" --out-interface " , iface ,
" --match " , " state " ,
" --state " , " ESTABLISHED,RELATED " ,
" --jump " , " ACCEPT " ,
NULL ) ;
}
2007-02-14 16:26:42 +00:00
}
int
2007-04-10 23:17:46 +00:00
iptablesAddForwardAllowIn ( iptablesContext * ctx ,
const char * network ,
const char * iface ,
const char * physdev )
{
return iptablesForwardAllowIn ( ctx , network , iface , physdev , ADD ) ;
}
int
iptablesRemoveForwardAllowIn ( iptablesContext * ctx ,
const char * network ,
const char * iface ,
const char * physdev )
{
return iptablesForwardAllowIn ( ctx , network , iface , physdev , REMOVE ) ;
}
/* Allow all traffic between guests on the same bridge,
* with a valid network address
*/
static int
iptablesForwardAllowCross ( iptablesContext * ctx ,
const char * iface ,
int action )
{
return iptablesAddRemoveRule ( ctx - > forward_filter ,
action ,
" --in-interface " , iface ,
" --out-interface " , iface ,
" --jump " , " ACCEPT " ,
NULL ) ;
}
int
iptablesAddForwardAllowCross ( iptablesContext * ctx ,
const char * iface ) {
return iptablesForwardAllowCross ( ctx , iface , ADD ) ;
}
int
iptablesRemoveForwardAllowCross ( iptablesContext * ctx ,
const char * iface ) {
return iptablesForwardAllowCross ( ctx , iface , REMOVE ) ;
}
/* Drop all traffic trying to forward from the bridge.
* ie the bridge is the in interface
*/
static int
iptablesForwardRejectOut ( iptablesContext * ctx ,
const char * iface ,
int action )
{
return iptablesAddRemoveRule ( ctx - > forward_filter ,
action ,
" --in-interface " , iface ,
" --jump " , " REJECT " ,
NULL ) ;
}
int
iptablesAddForwardRejectOut ( iptablesContext * ctx ,
const char * iface )
{
return iptablesForwardRejectOut ( ctx , iface , ADD ) ;
}
int
iptablesRemoveForwardRejectOut ( iptablesContext * ctx ,
const char * iface )
{
return iptablesForwardRejectOut ( ctx , iface , REMOVE ) ;
}
/* Drop all traffic trying to forward to the bridge.
* ie the bridge is the out interface
*/
static int
iptablesForwardRejectIn ( iptablesContext * ctx ,
2007-03-13 22:43:22 +00:00
const char * iface ,
2007-04-10 23:17:46 +00:00
int action )
{
return iptablesAddRemoveRule ( ctx - > forward_filter ,
action ,
" --out-interface " , iface ,
" --jump " , " REJECT " ,
NULL ) ;
}
int
iptablesAddForwardRejectIn ( iptablesContext * ctx ,
const char * iface )
2007-02-14 16:26:42 +00:00
{
2007-04-10 23:17:46 +00:00
return iptablesForwardRejectIn ( ctx , iface , ADD ) ;
2007-02-14 16:26:42 +00:00
}
int
2007-04-10 23:17:46 +00:00
iptablesRemoveForwardRejectIn ( iptablesContext * ctx ,
const char * iface )
2007-02-14 16:26:42 +00:00
{
2007-04-10 23:17:46 +00:00
return iptablesForwardRejectIn ( ctx , iface , REMOVE ) ;
2007-02-14 16:26:42 +00:00
}
2007-04-10 23:17:46 +00:00
/* Masquerade all traffic coming from the network associated
* with the bridge
*/
2007-02-14 16:26:42 +00:00
static int
2007-04-10 23:17:46 +00:00
iptablesForwardMasquerade ( iptablesContext * ctx ,
const char * network ,
const char * physdev ,
2007-02-14 16:26:42 +00:00
int action )
{
2007-04-10 23:17:46 +00:00
if ( physdev & & physdev [ 0 ] ) {
2007-03-13 22:43:22 +00:00
return iptablesAddRemoveRule ( ctx - > nat_postrouting ,
action ,
2007-04-10 23:17:46 +00:00
" --source " , network ,
" --out-interface " , physdev ,
2007-03-13 22:43:22 +00:00
" --jump " , " MASQUERADE " ,
NULL ) ;
} else {
return iptablesAddRemoveRule ( ctx - > nat_postrouting ,
action ,
2007-04-10 23:17:46 +00:00
" --source " , network ,
2007-03-13 22:43:22 +00:00
" --jump " , " MASQUERADE " ,
NULL ) ;
}
2007-02-14 16:26:42 +00:00
}
int
2007-04-10 23:17:46 +00:00
iptablesAddForwardMasquerade ( iptablesContext * ctx ,
const char * network ,
const char * physdev )
2007-02-14 16:26:42 +00:00
{
2007-04-10 23:17:46 +00:00
return iptablesForwardMasquerade ( ctx , network , physdev , ADD ) ;
2007-02-14 16:26:42 +00:00
}
int
2007-04-10 23:17:46 +00:00
iptablesRemoveForwardMasquerade ( iptablesContext * ctx ,
const char * network ,
const char * physdev )
2007-02-14 16:26:42 +00:00
{
2007-04-10 23:17:46 +00:00
return iptablesForwardMasquerade ( ctx , network , physdev , REMOVE ) ;
2007-02-14 16:26:42 +00:00
}
/*
* Local variables :
* indent - tabs - mode : nil
* c - indent - level : 4
* c - basic - offset : 4
* tab - width : 4
* End :
*/