Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
adam.huang
Pkg Iptables
Commits
dab1e98e
Commit
dab1e98e
authored
Oct 24, 2018
by
Arturo Borrero Gonzalez
Browse files
New upstream version 1.8.1
parent
f1f129da
Changes
268
Show whitespace changes
Inline
Side-by-side
iptables/tests/shell/testcases/iptables/0001-chain-refs_0
0 → 100755
View file @
dab1e98e
#!/bin/bash
# make sure rules are not counted in references of iptables output
set
-e
$XT_MULTI
iptables
-N
foo
$XT_MULTI
iptables
-L
|
grep
'Chain foo (0 references)'
$XT_MULTI
iptables
-A
foo
-j
ACCEPT
$XT_MULTI
iptables
-L
|
grep
'Chain foo (0 references)'
$XT_MULTI
iptables
-A
FORWARD
-j
foo
$XT_MULTI
iptables
-L
|
grep
'Chain foo (1 references)'
iptables/tests/shell/testcases/iptables/0002-verbose-output_0
0 → 100755
View file @
dab1e98e
#!/bin/bash
set
-e
#set -x
# ensure verbose output is identical between legacy and nft tools
RULE1
=
'-i eth2 -o eth3 -s 10.0.0.1 -d 10.0.0.2 -j ACCEPT'
VOUT1
=
'ACCEPT all opt -- in eth2 out eth3 10.0.0.1 -> 10.0.0.2'
RULE2
=
'-i eth2 -o eth3 -s 10.0.0.4 -d 10.0.0.5 -j ACCEPT'
VOUT2
=
'ACCEPT all opt -- in eth2 out eth3 10.0.0.4 -> 10.0.0.5'
diff
-u
-Z
<
(
echo
-e
"
$VOUT1
"
)
<
(
$XT_MULTI
iptables
-v
-A
FORWARD
$RULE1
)
diff
-u
-Z
<
(
echo
-e
"
$VOUT2
"
)
<
(
$XT_MULTI
iptables
-v
-I
FORWARD 2
$RULE2
)
diff
-u
-Z
<
(
echo
-e
"
$VOUT1
"
)
<
(
$XT_MULTI
iptables
-v
-C
FORWARD
$RULE1
)
diff
-u
-Z
<
(
echo
-e
"
$VOUT2
"
)
<
(
$XT_MULTI
iptables
-v
-C
FORWARD
$RULE2
)
EXPECT
=
'Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- eth2 eth3 10.0.0.1 10.0.0.2
0 0 ACCEPT all -- eth2 eth3 10.0.0.4 10.0.0.5
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination'
diff
-u
-Z
<
(
echo
-e
"
$EXPECT
"
)
<
(
$XT_MULTI
iptables
-v
-n
-L
)
diff
-u
-Z
<
(
echo
-e
"
$VOUT1
"
)
<
(
$XT_MULTI
iptables
-v
-D
FORWARD
$RULE1
)
diff
-u
-Z
<
(
echo
-e
"
$VOUT2
"
)
<
(
$XT_MULTI
iptables
-v
-D
FORWARD
$RULE2
)
EXPECT
=
"Flushing chain
\`
INPUT'
Flushing chain
\`
FORWARD'
Flushing chain
\`
OUTPUT'"
diff
-u
<
(
echo
-e
"
$EXPECT
"
)
<
(
$XT_MULTI
iptables
-v
-F
)
EXPECT
=
"Zeroing chain
\`
INPUT'
Zeroing chain
\`
FORWARD'
Zeroing chain
\`
OUTPUT'"
diff
-u
<
(
echo
-e
"
$EXPECT
"
)
<
(
$XT_MULTI
iptables
-v
-Z
)
diff
-u
<
(
echo
"Flushing chain
\`
OUTPUT'"
)
<
(
$XT_MULTI
iptables
-v
-F
OUTPUT
)
diff
-u
<
(
echo
"Zeroing chain
\`
OUTPUT'"
)
<
(
$XT_MULTI
iptables
-v
-Z
OUTPUT
)
$XT_MULTI
iptables
-N
foo
diff
-u
<
(
echo
"Deleting chain
\`
foo'"
)
<
(
$XT_MULTI
iptables
-v
-X
foo
)
iptables/tests/shell/testcases/iptables/0003-list-rules_0
0 → 100755
View file @
dab1e98e
#!/bin/bash
set
-e
$XT_MULTI
iptables
-N
foo
$XT_MULTI
iptables
-A
FORWARD
-i
eth23
-o
eth42
-j
ACCEPT
$XT_MULTI
iptables
-A
FORWARD
-i
eth42
-o
eth23
-g
foo
$XT_MULTI
iptables
-t
nat
-A
OUTPUT
-o
eth123
-m
mark
--mark
0x42
-j
ACCEPT
EXPECT
=
'-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-N foo
-A FORWARD -i eth23 -o eth42 -j ACCEPT
-A FORWARD -i eth42 -o eth23 -g foo'
diff
-u
-Z
<
(
echo
-e
"
$EXPECT
"
)
<
(
$XT_MULTI
iptables
-S
)
EXPECT
=
'-P INPUT ACCEPT -c 0 0
-P FORWARD ACCEPT -c 0 0
-P OUTPUT ACCEPT -c 0 0
-N foo
-A FORWARD -i eth23 -o eth42 -c 0 0 -j ACCEPT
-A FORWARD -i eth42 -o eth23 -c 0 0 -g foo'
diff
-u
-Z
<
(
echo
-e
"
$EXPECT
"
)
<
(
$XT_MULTI
iptables
-v
-S
)
EXPECT
=
'-P FORWARD ACCEPT
-A FORWARD -i eth23 -o eth42 -j ACCEPT
-A FORWARD -i eth42 -o eth23 -g foo'
diff
-u
-Z
<
(
echo
-e
"
$EXPECT
"
)
<
(
$XT_MULTI
iptables
-S
FORWARD
)
EXPECT
=
'-P FORWARD ACCEPT -c 0 0
-A FORWARD -i eth23 -o eth42 -c 0 0 -j ACCEPT
-A FORWARD -i eth42 -o eth23 -c 0 0 -g foo'
diff
-u
-Z
<
(
echo
-e
"
$EXPECT
"
)
<
(
$XT_MULTI
iptables
-v
-S
FORWARD
)
EXPECT
=
'-P OUTPUT ACCEPT
-A OUTPUT -o eth123 -m mark --mark 0x42 -j ACCEPT'
diff
-u
-Z
<
(
echo
-e
"
$EXPECT
"
)
<
(
$XT_MULTI
iptables
-t
nat
-S
OUTPUT
)
EXPECT
=
'-P OUTPUT ACCEPT -c 0 0
-A OUTPUT -o eth123 -m mark --mark 0x42 -c 0 0 -j ACCEPT'
diff
-u
-Z
<
(
echo
-e
"
$EXPECT
"
)
<
(
$XT_MULTI
iptables
-v
-t
nat
-S
OUTPUT
)
# some of the following commands are supposed to fail
set
+e
$XT_MULTI
iptables
-S
nonexistent
&&
{
echo
"list-rules in non-existent chain should fail"
exit
1
}
$XT_MULTI
iptables
-S
nonexistent 23
&&
{
echo
"list-rules in non-existent chain with given rule number should fail"
exit
1
}
$XT_MULTI
iptables
-S
FORWARD 234
||
{
echo
"list-rules in existent chain with invalid rule number should succeed"
exit
1
}
iptables/tests/shell/testcases/iptables/0004-return-codes_0
0 → 100755
View file @
dab1e98e
#!/bin/sh
# make sure error return codes are as expected useful cases
# (e.g. commands to check ruleset state)
global_rc
=
0
cmd
()
{
# (rc, cmd, [args ...])
rc_exp
=
$1
;
shift
$XT_MULTI
"
$@
"
rc
=
$?
[
$rc
-eq
$rc_exp
]
||
{
echo
"---> expected
$rc_exp
, got
$rc
for command '
$@
'"
global_rc
=
1
}
}
# test chain creation
cmd 0 iptables
-N
foo
cmd 1 iptables
-N
foo
# iptables-nft allows this - bug or feature?
#cmd 2 iptables -N "invalid name"
# test rule adding
cmd 0 iptables
-A
INPUT
-j
ACCEPT
cmd 1 iptables
-A
noexist
-j
ACCEPT
# test rule checking
cmd 0 iptables
-C
INPUT
-j
ACCEPT
cmd 1 iptables
-C
FORWARD
-j
ACCEPT
cmd 1 iptables
-C
nonexist
-j
ACCEPT
cmd 2 iptables
-C
INPUT
-j
foobar
cmd 2 iptables
-C
INPUT
-m
foobar
-j
ACCEPT
cmd 3 iptables
-t
foobar
-C
INPUT
-j
ACCEPT
exit
$global_rc
iptables/tests/shell/testcases/nft-only/0001compat_0
0 → 100755
View file @
dab1e98e
#!/bin/sh
# test case for bug fixed in
# commit 873c5d5d293991ee3c06aed2b1dfc5764872582f (HEAD -> master)
# xtables: avoid bogus 'is incompatible' warning
case
"
$XT_MULTI
"
in
*
/xtables-nft-multi
)
nft
-v
>
/dev/null
||
exit
0
nft
'add table ip nft-test; add chain ip nft-test foobar { type filter hook forward priority 42; }'
||
exit
1
nft
'add table ip6 nft-test; add chain ip6 nft-test foobar { type filter hook forward priority 42; }'
||
exit
1
$XT_MULTI
iptables
-L
-t
filter
||
exit
1
$XT_MULTI
ip6tables
-L
-t
filter
||
exit
1
;;
*
)
echo
skip
$XT_MULTI
;;
esac
exit
0
iptables/tests/shell/testcases/nft-only/0002invflags_0
0 → 100755
View file @
dab1e98e
#!/bin/sh
set
-e
[[
$XT_MULTI
==
*
/xtables-nft-multi
]]
||
{
echo
"skip
$XT_MULTI
"
;
exit
0
;
}
$XT_MULTI
iptables
-A
INPUT
-p
tcp
--dport
53
!
-s
192.168.0.1
-j
ACCEPT
$XT_MULTI
ip6tables
-A
INPUT
-p
tcp
--dport
53
!
-s
feed:babe::1
-j
ACCEPT
$XT_MULTI
ebtables
-A
INPUT
-p
IPv4
--ip-src
10.0.0.1
!
-i
lo
-j
ACCEPT
iptables/tests/shell/testcases/nft-only/0003delete-with-comment_0
0 → 100755
View file @
dab1e98e
#!/bin/bash
set
-e
[[
$XT_MULTI
==
*
/xtables-nft-multi
]]
||
{
echo
"skip
$XT_MULTI
"
;
exit
0
;
}
comment1
=
"foo bar"
comment2
=
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
for
ipt
in
iptables ip6tables
;
do
for
comment
in
"
$comment1
"
"
$comment2
"
;
do
$XT_MULTI
$ipt
-A
INPUT
-m
comment
--comment
"
$comment
"
-j
ACCEPT
$XT_MULTI
$ipt
-D
INPUT
-m
comment
--comment
"
$comment
"
-j
ACCEPT
done
done
iptables/xshared.c
View file @
dab1e98e
#include <config.h>
#include <ctype.h>
#include <getopt.h>
#include <errno.h>
#include <libgen.h>
#include <netdb.h>
#include <stdbool.h>
...
...
@@ -16,9 +19,6 @@
#include <math.h>
#include "xshared.h"
#define XT_LOCK_NAME "/run/xtables.lock"
#define BASE_MICROSECONDS 100000
/*
* Print out any special helps. A user might like to be able to add a --help
* to the commandline, and see expected results. So we call help for all
...
...
@@ -247,51 +247,106 @@ void xs_init_match(struct xtables_match *match)
match
->
init
(
match
->
m
);
}
bool
xtables_lock
(
int
wait
,
struct
timeval
*
wait_interval
)
static
int
xtables_lock
(
int
wait
,
struct
timeval
*
wait_interval
)
{
struct
timeval
time_left
,
wait_time
,
waited_time
;
struct
timeval
time_left
,
wait_time
;
int
fd
,
i
=
0
;
time_left
.
tv_sec
=
wait
;
time_left
.
tv_usec
=
0
;
waited_time
.
tv_sec
=
0
;
waited_time
.
tv_usec
=
0
;
fd
=
open
(
XT_LOCK_NAME
,
O_CREAT
,
0600
);
if
(
fd
<
0
)
return
true
;
if
(
fd
<
0
)
{
fprintf
(
stderr
,
"Fatal: can't open lock file %s: %s
\n
"
,
XT_LOCK_NAME
,
strerror
(
errno
));
return
XT_LOCK_FAILED
;
}
if
(
wait
==
-
1
)
{
if
(
flock
(
fd
,
LOCK_EX
)
==
0
)
return
fd
;
fprintf
(
stderr
,
"Can't lock %s: %s
\n
"
,
XT_LOCK_NAME
,
strerror
(
errno
));
return
XT_LOCK_BUSY
;
}
while
(
1
)
{
if
(
flock
(
fd
,
LOCK_EX
|
LOCK_NB
)
==
0
)
return
true
;
return
fd
;
else
if
(
timercmp
(
&
time_left
,
wait_interval
,
<
))
return
XT_LOCK_BUSY
;
if
(
++
i
%
10
==
0
)
{
if
(
wait
!=
-
1
)
fprintf
(
stderr
,
"Another app is currently holding the xtables lock; "
"still %lds %ldus time ahead to have a chance to grab the lock...
\n
"
,
time_left
.
tv_sec
,
time_left
.
tv_usec
);
else
fprintf
(
stderr
,
"Another app is currently holding the xtables lock; "
"waiting for it to exit...
\n
"
);
}
wait_time
=
*
wait_interval
;
select
(
0
,
NULL
,
NULL
,
NULL
,
&
wait_time
);
if
(
wait
==
-
1
)
continue
;
timeradd
(
&
waited_time
,
wait_interval
,
&
waited_time
);
timersub
(
&
time_left
,
wait_interval
,
&
time_left
);
if
(
!
timerisset
(
&
time_left
))
return
false
;
}
}
void
parse_wait_interval
(
const
char
*
str
,
struct
timeval
*
wait_interval
)
void
xtables_unlock
(
int
lock
)
{
if
(
lock
>=
0
)
close
(
lock
);
}
int
xtables_lock_or_exit
(
int
wait
,
struct
timeval
*
wait_interval
)
{
int
lock
=
xtables_lock
(
wait
,
wait_interval
);
if
(
lock
==
XT_LOCK_FAILED
)
{
xtables_free_opts
(
1
);
exit
(
RESOURCE_PROBLEM
);
}
if
(
lock
==
XT_LOCK_BUSY
)
{
fprintf
(
stderr
,
"Another app is currently holding the xtables lock. "
);
if
(
wait
==
0
)
fprintf
(
stderr
,
"Perhaps you want to use the -w option?
\n
"
);
else
fprintf
(
stderr
,
"Stopped waiting after %ds.
\n
"
,
wait
);
xtables_free_opts
(
1
);
exit
(
RESOURCE_PROBLEM
);
}
return
lock
;
}
int
parse_wait_time
(
int
argc
,
char
*
argv
[])
{
int
wait
=
-
1
;
if
(
optarg
)
{
if
(
sscanf
(
optarg
,
"%i"
,
&
wait
)
!=
1
)
xtables_error
(
PARAMETER_PROBLEM
,
"wait seconds not numeric"
);
}
else
if
(
xs_has_arg
(
argc
,
argv
))
if
(
sscanf
(
argv
[
optind
++
],
"%i"
,
&
wait
)
!=
1
)
xtables_error
(
PARAMETER_PROBLEM
,
"wait seconds not numeric"
);
return
wait
;
}
void
parse_wait_interval
(
int
argc
,
char
*
argv
[],
struct
timeval
*
wait_interval
)
{
const
char
*
arg
;
unsigned
int
usec
;
int
ret
;
ret
=
sscanf
(
str
,
"%u"
,
&
usec
);
if
(
optarg
)
arg
=
optarg
;
else
if
(
xs_has_arg
(
argc
,
argv
))
arg
=
argv
[
optind
++
];
else
xtables_error
(
PARAMETER_PROBLEM
,
"wait interval value required"
);
ret
=
sscanf
(
arg
,
"%u"
,
&
usec
);
if
(
ret
==
1
)
{
if
(
usec
>
999999
)
xtables_error
(
PARAMETER_PROBLEM
,
...
...
@@ -304,3 +359,338 @@ void parse_wait_interval(const char *str, struct timeval *wait_interval)
}
xtables_error
(
PARAMETER_PROBLEM
,
"wait interval not numeric"
);
}
int
parse_counters
(
const
char
*
string
,
struct
xt_counters
*
ctr
)
{
int
ret
;
if
(
!
string
)
return
0
;
ret
=
sscanf
(
string
,
"[%llu:%llu]"
,
(
unsigned
long
long
*
)
&
ctr
->
pcnt
,
(
unsigned
long
long
*
)
&
ctr
->
bcnt
);
return
ret
==
2
;
}
inline
bool
xs_has_arg
(
int
argc
,
char
*
argv
[])
{
return
optind
<
argc
&&
argv
[
optind
][
0
]
!=
'-'
&&
argv
[
optind
][
0
]
!=
'!'
;
}
/* global new argv and argc */
char
*
newargv
[
255
];
int
newargc
=
0
;
/* saved newargv and newargc from save_argv() */
char
*
oldargv
[
255
];
int
oldargc
=
0
;
/* arg meta data, were they quoted, frinstance */
int
newargvattr
[
255
];
/* function adding one argument to newargv, updating newargc
* returns true if argument added, false otherwise */
int
add_argv
(
const
char
*
what
,
int
quoted
)
{
DEBUGP
(
"add_argv: %s
\n
"
,
what
);
if
(
what
&&
newargc
+
1
<
ARRAY_SIZE
(
newargv
))
{
newargv
[
newargc
]
=
strdup
(
what
);
newargvattr
[
newargc
]
=
quoted
;
newargv
[
++
newargc
]
=
NULL
;
return
1
;
}
else
{
xtables_error
(
PARAMETER_PROBLEM
,
"Parser cannot handle more arguments
\n
"
);
}
}
void
free_argv
(
void
)
{
while
(
newargc
)
free
(
newargv
[
--
newargc
]);
while
(
oldargc
)
free
(
oldargv
[
--
oldargc
]);
}
/* Save parsed rule for comparison with next rule to perform action aggregation
* on duplicate conditions.
*/
void
save_argv
(
void
)
{
unsigned
int
i
;
while
(
oldargc
)
free
(
oldargv
[
--
oldargc
]);
oldargc
=
newargc
;
newargc
=
0
;
for
(
i
=
0
;
i
<
oldargc
;
i
++
)
{
oldargv
[
i
]
=
newargv
[
i
];
}
}
void
add_param_to_argv
(
char
*
parsestart
,
int
line
)
{
int
quote_open
=
0
,
escaped
=
0
,
param_len
=
0
;
char
param_buffer
[
1024
],
*
curchar
;
/* After fighting with strtok enough, here's now
* a 'real' parser. According to Rusty I'm now no
* longer a real hacker, but I can live with that */
for
(
curchar
=
parsestart
;
*
curchar
;
curchar
++
)
{
if
(
quote_open
)
{
if
(
escaped
)
{
param_buffer
[
param_len
++
]
=
*
curchar
;
escaped
=
0
;
continue
;
}
else
if
(
*
curchar
==
'\\'
)
{
escaped
=
1
;
continue
;
}
else
if
(
*
curchar
==
'"'
)
{
quote_open
=
0
;
*
curchar
=
'"'
;
}
else
{
param_buffer
[
param_len
++
]
=
*
curchar
;
continue
;
}
}
else
{
if
(
*
curchar
==
'"'
)
{
quote_open
=
1
;
continue
;
}
}
switch
(
*
curchar
)
{
case
'"'
:
break
;
case
' '
:
case
'\t'
:
case
'\n'
:
if
(
!
param_len
)
{
/* two spaces? */
continue
;
}
break
;
default:
/* regular character, copy to buffer */
param_buffer
[
param_len
++
]
=
*
curchar
;
if
(
param_len
>=
sizeof
(
param_buffer
))
xtables_error
(
PARAMETER_PROBLEM
,
"Parameter too long!"
);
continue
;
}
param_buffer
[
param_len
]
=
'\0'
;
/* check if table name specified */
if
((
param_buffer
[
0
]
==
'-'
&&
param_buffer
[
1
]
!=
'-'
&&
strchr
(
param_buffer
,
't'
))
||
(
!
strncmp
(
param_buffer
,
"--t"
,
3
)
&&
!
strncmp
(
param_buffer
,
"--table"
,
strlen
(
param_buffer
))))
{
xtables_error
(
PARAMETER_PROBLEM
,
"The -t option (seen in line %u) cannot be used in %s.
\n
"
,
line
,
xt_params
->
program_name
);
}
add_argv
(
param_buffer
,
0
);
param_len
=
0
;
}
}
static
const
char
*
ipv4_addr_to_string
(
const
struct
in_addr
*
addr
,
const
struct
in_addr
*
mask
,
unsigned
int
format
)
{
static
char
buf
[
BUFSIZ
];
if
(
!
mask
->
s_addr
&&
!
(
format
&
FMT_NUMERIC
))
return
"anywhere"
;
if
(
format
&
FMT_NUMERIC
)
strncpy
(
buf
,
xtables_ipaddr_to_numeric
(
addr
),
BUFSIZ
-
1
);
else
strncpy
(
buf
,
xtables_ipaddr_to_anyname
(
addr
),
BUFSIZ
-
1
);
buf
[
BUFSIZ
-
1
]
=
'\0'
;
strncat
(
buf
,
xtables_ipmask_to_numeric
(
mask
),
BUFSIZ
-
strlen
(
buf
)
-
1
);
return
buf
;
}
void
print_ipv4_addresses
(
const
struct
ipt_entry
*
fw
,
unsigned
int
format
)
{
fputc
(
fw
->
ip
.
invflags
&
IPT_INV_SRCIP
?
'!'
:
' '
,
stdout
);
printf
(
FMT
(
"%-19s "
,
"%s "
),
ipv4_addr_to_string
(
&
fw
->
ip
.
src
,
&
fw
->
ip
.
smsk
,
format
));
fputc
(
fw
->
ip
.
invflags
&
IPT_INV_DSTIP
?
'!'
:
' '
,
stdout
);
printf
(
FMT
(
"%-19s "
,
"-> %s"
),
ipv4_addr_to_string
(
&
fw
->
ip
.
dst
,
&
fw
->
ip
.
dmsk
,
format
));
}
static
const
char
*
ipv6_addr_to_string
(
const
struct
in6_addr
*
addr
,
const
struct
in6_addr
*
mask
,
unsigned
int
format
)
{
static
char
buf
[
BUFSIZ
];
if
(
IN6_IS_ADDR_UNSPECIFIED
(
addr
)
&&
!
(
format
&
FMT_NUMERIC
))
return
"anywhere"
;
if
(
format
&
FMT_NUMERIC
)
strncpy
(
buf
,
xtables_ip6addr_to_numeric
(
addr
),
BUFSIZ
-
1
);
else
strncpy
(
buf
,
xtables_ip6addr_to_anyname
(
addr
),
BUFSIZ
-
1
);
buf
[
BUFSIZ
-
1
]
=
'\0'
;
strncat
(
buf
,
xtables_ip6mask_to_numeric
(
mask
),
BUFSIZ
-
strlen
(
buf
)
-
1
);
return
buf
;
}
void
print_ipv6_addresses
(
const
struct
ip6t_entry
*
fw6
,
unsigned
int
format
)
{
fputc
(
fw6
->
ipv6
.
invflags
&
IP6T_INV_SRCIP
?
'!'
:
' '
,
stdout
);
printf
(
FMT
(
"%-19s "
,
"%s "
),
ipv6_addr_to_string
(
&
fw6
->
ipv6
.
src
,
&
fw6
->
ipv6
.
smsk
,
format
));
fputc
(
fw6
->
ipv6
.
invflags
&
IP6T_INV_DSTIP
?
'!'
:
' '
,
stdout
);
printf
(
FMT
(
"%-19s "
,
"-> %s"
),
ipv6_addr_to_string
(
&
fw6
->
ipv6
.
dst
,
&
fw6
->
ipv6
.
dmsk
,
format
));
}
/* Luckily, IPT_INV_VIA_IN and IPT_INV_VIA_OUT
* have the same values as IP6T_INV_VIA_IN and IP6T_INV_VIA_OUT
* so this function serves for both iptables and ip6tables */
void
print_ifaces
(
const
char
*
iniface
,
const
char
*
outiface
,
uint8_t
invflags
,
unsigned
int
format
)
{
const
char
*
anyname
=
format
&
FMT_NUMERIC
?
"*"
:
"any"
;
char
iface
[
IFNAMSIZ
+
2
];
if
(
!
(
format
&
FMT_VIA
))
return
;
snprintf
(
iface
,
IFNAMSIZ
+
2
,
"%s%s"
,
invflags
&
IPT_INV_VIA_IN
?
"!"
:
""
,
iniface
[
0
]
!=
'\0'
?
iniface
:
anyname
);
printf
(
FMT
(
" %-6s "
,
"in %s "
),
iface
);
snprintf
(
iface
,
IFNAMSIZ
+
2
,
"%s%s"
,
invflags
&
IPT_INV_VIA_OUT
?
"!"
:
""
,
outiface
[
0
]
!=
'\0'
?
outiface
:
anyname
);
printf
(
FMT
(
"%-6s "
,
"out %s "
),
iface
);
}
void
command_match
(
struct
iptables_command_state
*
cs
)
{
struct
option
*
opts
=
xt_params
->
opts
;
struct
xtables_match
*
m
;
size_t
size
;
if
(
cs
->
invert
)
xtables_error
(
PARAMETER_PROBLEM
,
"unexpected ! flag before --match"
);
m
=
xtables_find_match
(
optarg
,
XTF_LOAD_MUST_SUCCEED
,
&
cs
->
matches
);
size
=
XT_ALIGN
(
sizeof
(
struct
xt_entry_match
))
+
m
->
size
;
m
->
m
=
xtables_calloc
(
1
,
size
);
m
->
m
->
u
.
match_size
=
size
;
if
(
m
->
real_name
==
NULL
)
{
strcpy
(
m
->
m
->
u
.
user
.
name
,
m
->
name
);
}
else
{
strcpy
(
m
->
m
->
u
.
user
.
name
,
m
->
real_name
);
if
(
!
(
m
->
ext_flags
&
XTABLES_EXT_ALIAS
))
fprintf
(
stderr
,
"Notice: the %s match is converted into %s match "
"in rule listing and saving.
\n
"
,
m
->
name
,
m
->
real_name
);
}
m
->
m
->
u
.
user
.
revision
=
m
->
revision
;
xs_init_match
(
m
);
if
(
m
==
m
->
next
)
return
;
/* Merge options for non-cloned matches */
if
(
m
->
x6_options
!=
NULL
)
opts
=
xtables_options_xfrm
(
xt_params
->
orig_opts
,
opts
,
m
->
x6_options
,
&
m
->
option_offset
);
else
if
(
m
->
extra_opts
!=
NULL
)
opts
=
xtables_merge_options
(
xt_params
->
orig_opts
,
opts
,
m
->
extra_opts
,
&
m
->
option_offset
);
if
(
opts
==
NULL
)
xtables_error
(
OTHER_PROBLEM
,
"can't alloc memory!"
);
xt_params
->
opts
=
opts
;
}
const
char
*
xt_parse_target
(
const
char
*
targetname
)
{
const
char
*
ptr
;
if
(
strlen
(
targetname
)
<
1
)
xtables_error
(
PARAMETER_PROBLEM
,
"Invalid target name (too short)"
);
if
(
strlen
(
targetname
)
>=
XT_EXTENSION_MAXNAMELEN
)
xtables_error
(
PARAMETER_PROBLEM
,
"Invalid target name `%s' (%u chars max)"
,
targetname
,
XT_EXTENSION_MAXNAMELEN
-
1
);
for
(
ptr
=
targetname
;
*
ptr
;
ptr
++
)
if
(
isspace
(
*
ptr
))
xtables_error
(
PARAMETER_PROBLEM
,
"Invalid target name `%s'"
,
targetname
);
return
targetname
;
}
void
command_jump
(
struct
iptables_command_state
*
cs
)
{
struct
option
*
opts
=
xt_params
->
opts
;
size_t
size
;
cs
->
jumpto
=
xt_parse_target
(
optarg
);
/* TRY_LOAD (may be chain name) */
cs
->
target
=
xtables_find_target
(
cs
->
jumpto
,
XTF_TRY_LOAD
);
if
(
cs
->
target
==
NULL
)
return
;
size
=
XT_ALIGN
(
sizeof
(
struct
xt_entry_target
))
+
cs
->
target
->
size
;
cs
->
target
->
t
=
xtables_calloc
(
1
,
size
);
cs
->
target
->
t
->
u
.
target_size
=
size
;
if
(
cs
->
target
->
real_name
==
NULL
)
{
strcpy
(
cs
->
target
->
t
->
u
.
user
.
name
,
cs
->
jumpto
);
}
else
{
/* Alias support for userspace side */
strcpy
(
cs
->
target
->
t
->
u
.
user
.
name
,
cs
->
target
->
real_name
);
if
(
!
(
cs
->
target
->
ext_flags
&
XTABLES_EXT_ALIAS
))
fprintf
(
stderr
,
"Notice: The %s target is converted into %s target "
"in rule listing and saving.
\n
"
,
cs
->
jumpto
,
cs
->
target
->
real_name
);
}
cs
->
target
->
t
->
u
.
user
.
revision
=
cs
->
target
->
revision
;
xs_init_target
(
cs
->
target
);
if
(
cs
->
target
->
x6_options
!=
NULL
)
opts
=
xtables_options_xfrm
(
xt_params
->
orig_opts
,
opts
,
cs
->
target
->
x6_options
,
&
cs
->
target
->
option_offset
);
else
opts
=
xtables_merge_options
(
xt_params
->
orig_opts
,
opts
,
cs
->
target
->
extra_opts
,
&
cs
->
target
->
option_offset
);
if
(
opts
==
NULL
)
xtables_error
(
OTHER_PROBLEM
,
"can't alloc memory!"
);
xt_params
->
opts
=
opts
;
}
iptables/xshared.h
View file @
dab1e98e
...
...
@@ -6,9 +6,16 @@
#include <stdint.h>
#include <netinet/in.h>
#include <net/if.h>
#include <linux/netfilter_arp/arp_tables.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv6/ip6_tables.h>
#ifdef DEBUG
#define DEBUGP(x, args...) fprintf(stdout, x, ## args)
#else
#define DEBUGP(x, args...)
#endif
enum
{
OPT_NONE
=
0
,
OPT_NUMERIC
=
1
<<
0
,
...
...
@@ -48,15 +55,48 @@ struct xtables_afinfo {
int
so_rev_target
;
};
/* trick for ebtables-compat, since watchers are targets */
struct
ebt_match
{
struct
ebt_match
*
next
;
union
{
struct
xtables_match
*
match
;
struct
xtables_target
*
watcher
;
}
u
;
bool
ismatch
;
};
/* Fake ebt_entry */
struct
ebt_entry
{
/* this needs to be the first field */
unsigned
int
bitmask
;
unsigned
int
invflags
;
uint16_t
ethproto
;
/* the physical in-dev */
char
in
[
IFNAMSIZ
];
/* the logical in-dev */
char
logical_in
[
IFNAMSIZ
];
/* the physical out-dev */
char
out
[
IFNAMSIZ
];
/* the logical out-dev */
char
logical_out
[
IFNAMSIZ
];
unsigned
char
sourcemac
[
6
];
unsigned
char
sourcemsk
[
6
];
unsigned
char
destmac
[
6
];
unsigned
char
destmsk
[
6
];
};
struct
iptables_command_state
{
union
{
struct
ebt_entry
eb
;
struct
ipt_entry
fw
;
struct
ip6t_entry
fw6
;
struct
arpt_entry
arp
;
};
int
invert
;
int
c
;
unsigned
int
options
;
struct
xtables_rule_match
*
matches
;
struct
ebt_match
*
match_list
;
struct
xtables_target
*
target
;
struct
xt_counters
counters
;
char
*
protocol
;
...
...
@@ -86,10 +126,56 @@ extern struct xtables_match *load_proto(struct iptables_command_state *);
extern
int
subcmd_main
(
int
,
char
**
,
const
struct
subcommand
*
);
extern
void
xs_init_target
(
struct
xtables_target
*
);
extern
void
xs_init_match
(
struct
xtables_match
*
);
bool
xtables_lock
(
int
wait
,
struct
timeval
*
wait_interval
);
void
parse_wait_interval
(
const
char
*
str
,
struct
timeval
*
wait_interval
);
/**
* Values for the iptables lock.
*
* A value >= 0 indicates the lock filedescriptor. Other values are:
*
* XT_LOCK_FAILED : The lock could not be acquired.
*
* XT_LOCK_BUSY : The lock was held by another process. xtables_lock only
* returns this value when |wait| == false. If |wait| == true, xtables_lock
* will not return unless the lock has been acquired.
*
* XT_LOCK_NOT_ACQUIRED : We have not yet attempted to acquire the lock.
*/
enum
{
XT_LOCK_BUSY
=
-
1
,
XT_LOCK_FAILED
=
-
2
,
XT_LOCK_NOT_ACQUIRED
=
-
3
,
};
extern
void
xtables_unlock
(
int
lock
);
extern
int
xtables_lock_or_exit
(
int
wait
,
struct
timeval
*
tv
);
int
parse_wait_time
(
int
argc
,
char
*
argv
[]);
void
parse_wait_interval
(
int
argc
,
char
*
argv
[],
struct
timeval
*
wait_interval
);
int
parse_counters
(
const
char
*
string
,
struct
xt_counters
*
ctr
);
bool
xs_has_arg
(
int
argc
,
char
*
argv
[]);
extern
const
struct
xtables_afinfo
*
afinfo
;
extern
char
*
newargv
[];
extern
int
newargc
;
extern
char
*
oldargv
[];
extern
int
oldargc
;
extern
int
newargvattr
[];
int
add_argv
(
const
char
*
what
,
int
quoted
);
void
free_argv
(
void
);
void
save_argv
(
void
);
void
add_param_to_argv
(
char
*
parsestart
,
int
line
);
void
print_ipv4_addresses
(
const
struct
ipt_entry
*
fw
,
unsigned
int
format
);
void
print_ipv6_addresses
(
const
struct
ip6t_entry
*
fw6
,
unsigned
int
format
);
void
print_ifaces
(
const
char
*
iniface
,
const
char
*
outiface
,
uint8_t
invflags
,
unsigned
int
format
);
void
command_match
(
struct
iptables_command_state
*
cs
);
const
char
*
xt_parse_target
(
const
char
*
targetname
);
void
command_jump
(
struct
iptables_command_state
*
cs
);
#endif
/* IPTABLES_XSHARED_H */
iptables/xtables-arp-standalone.c
View file @
dab1e98e
...
...
@@ -47,24 +47,11 @@ int xtables_arp_main(int argc, char *argv[])
{
int
ret
;
char
*
table
=
"filter"
;
struct
nft_handle
h
=
{
.
family
=
NFPROTO_ARP
,
};
struct
nft_handle
h
;
arptables_globals
.
program_name
=
"arptables"
;
ret
=
xtables_init_all
(
&
arptables_globals
,
NFPROTO_ARP
);
if
(
ret
<
0
)
{
fprintf
(
stderr
,
"%s/%s Failed to initialize arptables-compat
\n
"
,
arptables_globals
.
program_name
,
arptables_globals
.
program_version
);
exit
(
1
);
}
nft_init_arp
(
&
h
,
"arptables"
);
#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
init_extensionsa
();
#endif
ret
=
do_commandarp
(
&
h
,
argc
,
argv
,
&
table
);
ret
=
do_commandarp
(
&
h
,
argc
,
argv
,
&
table
,
false
);
if
(
ret
)
ret
=
nft_commit
(
&
h
);
...
...
iptables/xtables-arp.c
View file @
dab1e98e
...
...
@@ -149,8 +149,7 @@ static struct option original_opts[] = {
int
RUNTIME_NF_ARP_NUMHOOKS
=
3
;
static
struct
option
*
opts
=
original_opts
;
static
unsigned
int
global_option_offset
=
0
;
#define opts xt_params->opts
extern
void
xtables_exit_error
(
enum
xtables_exittype
status
,
const
char
*
msg
,
...)
__attribute__
((
noreturn
,
format
(
printf
,
2
,
3
)));
struct
xtables_globals
arptables_globals
=
{
...
...
@@ -588,16 +587,15 @@ static struct in_addr *
host_to_addr
(
const
char
*
name
,
unsigned
int
*
naddr
)
{
struct
in_addr
*
addr
;
struct
addrinfo
hints
;
struct
addrinfo
hints
=
{
.
ai_flags
=
AI_CANONNAME
,
.
ai_family
=
AF_INET
,
.
ai_socktype
=
SOCK_RAW
,
};;
struct
addrinfo
*
res
,
*
p
;
int
err
;
unsigned
int
i
;
memset
(
&
hints
,
0
,
sizeof
(
hints
));
hints
.
ai_flags
=
AI_CANONNAME
;
hints
.
ai_family
=
AF_INET
;
hints
.
ai_socktype
=
SOCK_RAW
;
*
naddr
=
0
;
err
=
getaddrinfo
(
name
,
NULL
,
&
hints
,
&
res
);
if
(
err
!=
0
)
...
...
@@ -757,27 +755,6 @@ parse_rulenumber(const char *rule)
return
rulenum
;
}
static
const
char
*
parse_target
(
const
char
*
targetname
)
{
const
char
*
ptr
;
if
(
strlen
(
targetname
)
<
1
)
xtables_error
(
PARAMETER_PROBLEM
,
"Invalid target name (too short)"
);
if
(
strlen
(
targetname
)
+
1
>
sizeof
(
arpt_chainlabel
))
xtables_error
(
PARAMETER_PROBLEM
,
"Invalid target name `%s' (%zu chars max)"
,
targetname
,
sizeof
(
arpt_chainlabel
)
-
1
);
for
(
ptr
=
targetname
;
*
ptr
;
ptr
++
)
if
(
isspace
(
*
ptr
))
xtables_error
(
PARAMETER_PROBLEM
,
"Invalid target name `%s'"
,
targetname
);
return
targetname
;
}
static
void
set_option
(
unsigned
int
*
options
,
unsigned
int
option
,
u_int16_t
*
invflg
,
int
invert
)
...
...
@@ -824,46 +801,11 @@ list_entries(struct nft_handle *h, const char *chain, const char *table,
return
nft_rule_list
(
h
,
chain
,
table
,
rulenum
,
format
);
}
static
struct
xtables_target
*
command_jump
(
struct
arpt_entry
*
fw
,
const
char
*
jumpto
)
{
struct
xtables_target
*
target
;
size_t
size
;
/* XTF_TRY_LOAD (may be chain name) */
target
=
xtables_find_target
(
jumpto
,
XTF_TRY_LOAD
);
if
(
!
target
)
return
NULL
;
size
=
XT_ALIGN
(
sizeof
(
struct
xt_entry_target
))
+
target
->
size
;
target
->
t
=
xtables_calloc
(
1
,
size
);
target
->
t
->
u
.
target_size
=
size
;
strncpy
(
target
->
t
->
u
.
user
.
name
,
jumpto
,
sizeof
(
target
->
t
->
u
.
user
.
name
));
target
->
t
->
u
.
user
.
name
[
sizeof
(
target
->
t
->
u
.
user
.
name
)
-
1
]
=
'\0'
;
target
->
t
->
u
.
user
.
revision
=
target
->
revision
;
xs_init_target
(
target
);
if
(
target
->
x6_options
!=
NULL
)
opts
=
xtables_options_xfrm
(
arptables_globals
.
orig_opts
,
opts
,
target
->
x6_options
,
&
target
->
option_offset
);
else
opts
=
xtables_merge_options
(
arptables_globals
.
orig_opts
,
opts
,
target
->
extra_opts
,
&
target
->
option_offset
);
return
target
;
}
static
int
append_entry
(
struct
nft_handle
*
h
,
const
char
*
chain
,
const
char
*
table
,
struct
ar
ptables_command_state
*
cs
,
struct
i
ptables_command_state
*
cs
,
int
rulenum
,
unsigned
int
nsaddrs
,
const
struct
in_addr
saddrs
[],
...
...
@@ -875,9 +817,9 @@ append_entry(struct nft_handle *h,
int
ret
=
1
;
for
(
i
=
0
;
i
<
nsaddrs
;
i
++
)
{
cs
->
fw
.
arp
.
src
.
s_addr
=
saddrs
[
i
].
s_addr
;
cs
->
arp
.
arp
.
src
.
s_addr
=
saddrs
[
i
].
s_addr
;
for
(
j
=
0
;
j
<
ndaddrs
;
j
++
)
{
cs
->
fw
.
arp
.
tgt
.
s_addr
=
daddrs
[
j
].
s_addr
;
cs
->
arp
.
arp
.
tgt
.
s_addr
=
daddrs
[
j
].
s_addr
;
if
(
append
)
{
ret
=
nft_rule_append
(
h
,
chain
,
table
,
cs
,
0
,
verbose
);
...
...
@@ -894,14 +836,14 @@ append_entry(struct nft_handle *h,
static
int
replace_entry
(
const
char
*
chain
,
const
char
*
table
,
struct
ar
ptables_command_state
*
cs
,
struct
i
ptables_command_state
*
cs
,
unsigned
int
rulenum
,
const
struct
in_addr
*
saddr
,
const
struct
in_addr
*
daddr
,
bool
verbose
,
struct
nft_handle
*
h
)
{
cs
->
fw
.
arp
.
src
.
s_addr
=
saddr
->
s_addr
;
cs
->
fw
.
arp
.
tgt
.
s_addr
=
daddr
->
s_addr
;
cs
->
arp
.
arp
.
src
.
s_addr
=
saddr
->
s_addr
;
cs
->
arp
.
arp
.
tgt
.
s_addr
=
daddr
->
s_addr
;
return
nft_rule_replace
(
h
,
chain
,
table
,
cs
,
rulenum
,
verbose
);
}
...
...
@@ -909,7 +851,7 @@ replace_entry(const char *chain,
static
int
delete_entry
(
const
char
*
chain
,
const
char
*
table
,
struct
ar
ptables_command_state
*
cs
,
struct
i
ptables_command_state
*
cs
,
unsigned
int
nsaddrs
,
const
struct
in_addr
saddrs
[],
unsigned
int
ndaddrs
,
...
...
@@ -920,9 +862,9 @@ delete_entry(const char *chain,
int
ret
=
1
;
for
(
i
=
0
;
i
<
nsaddrs
;
i
++
)
{
cs
->
fw
.
arp
.
src
.
s_addr
=
saddrs
[
i
].
s_addr
;
cs
->
arp
.
arp
.
src
.
s_addr
=
saddrs
[
i
].
s_addr
;
for
(
j
=
0
;
j
<
ndaddrs
;
j
++
)
{
cs
->
fw
.
arp
.
tgt
.
s_addr
=
daddrs
[
j
].
s_addr
;
cs
->
arp
.
arp
.
tgt
.
s_addr
=
daddrs
[
j
].
s_addr
;
ret
=
nft_rule_delete
(
h
,
chain
,
table
,
cs
,
verbose
);
}
}
...
...
@@ -930,9 +872,40 @@ delete_entry(const char *chain,
return
ret
;
}
int
do_commandarp
(
struct
nft_handle
*
h
,
int
argc
,
char
*
argv
[],
char
**
table
)
int
nft_init_arp
(
struct
nft_handle
*
h
,
const
char
*
pname
)
{
arptables_globals
.
program_name
=
pname
;
if
(
xtables_init_all
(
&
arptables_globals
,
NFPROTO_ARP
)
<
0
)
{
fprintf
(
stderr
,
"%s/%s Failed to initialize arptables-compat
\n
"
,
arptables_globals
.
program_name
,
arptables_globals
.
program_version
);
exit
(
1
);
}
#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
init_extensionsa
();
#endif
memset
(
h
,
0
,
sizeof
(
*
h
));
h
->
family
=
NFPROTO_ARP
;
if
(
nft_init
(
h
,
xtables_arp
)
<
0
)
xtables_error
(
OTHER_PROBLEM
,
"Could not initialize nftables layer."
);
h
->
ops
=
nft_family_ops_lookup
(
h
->
family
);
if
(
h
->
ops
==
NULL
)
xtables_error
(
PARAMETER_PROBLEM
,
"Unknown family"
);
return
0
;
}
int
do_commandarp
(
struct
nft_handle
*
h
,
int
argc
,
char
*
argv
[],
char
**
table
,
bool
restore
)
{
struct
arptables_command_state
cs
;
struct
iptables_command_state
cs
=
{
.
jumpto
=
""
,
};
int
invert
=
0
;
unsigned
int
nsaddrs
=
0
,
ndaddrs
=
0
;
struct
in_addr
*
saddrs
=
NULL
,
*
daddrs
=
NULL
;
...
...
@@ -946,14 +919,6 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table)
int
ret
=
1
;
struct
xtables_target
*
t
;
memset
(
&
cs
,
0
,
sizeof
(
cs
));
cs
.
jumpto
=
""
;
opts
=
original_opts
;
global_option_offset
=
0
;
xtables_globals
.
orig_opts
=
original_opts
;
/* re-set optind to 0 in case do_command gets called
* a second time */
optind
=
0
;
...
...
@@ -967,6 +932,7 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table)
demand-load a protocol. */
opterr
=
0
;
opts
=
xt_params
->
orig_opts
;
while
((
c
=
getopt_long
(
argc
,
argv
,
"-A:D:R:I:L::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:l:i:vnt:m:c:"
,
opts
,
NULL
))
!=
-
1
)
{
...
...
@@ -984,8 +950,7 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table)
add_command
(
&
command
,
CMD_DELETE
,
CMD_NONE
,
invert
);
chain
=
optarg
;
if
(
optind
<
argc
&&
argv
[
optind
][
0
]
!=
'-'
&&
argv
[
optind
][
0
]
!=
'!'
)
{
if
(
xs_has_arg
(
argc
,
argv
))
{
rulenum
=
parse_rulenumber
(
argv
[
optind
++
]);
command
=
CMD_DELETE_NUM
;
}
...
...
@@ -995,8 +960,7 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table)
add_command
(
&
command
,
CMD_REPLACE
,
CMD_NONE
,
invert
);
chain
=
optarg
;
if
(
optind
<
argc
&&
argv
[
optind
][
0
]
!=
'-'
&&
argv
[
optind
][
0
]
!=
'!'
)
if
(
xs_has_arg
(
argc
,
argv
))
rulenum
=
parse_rulenumber
(
argv
[
optind
++
]);
else
xtables_error
(
PARAMETER_PROBLEM
,
...
...
@@ -1008,8 +972,7 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table)
add_command
(
&
command
,
CMD_INSERT
,
CMD_NONE
,
invert
);
chain
=
optarg
;
if
(
optind
<
argc
&&
argv
[
optind
][
0
]
!=
'-'
&&
argv
[
optind
][
0
]
!=
'!'
)
if
(
xs_has_arg
(
argc
,
argv
))
rulenum
=
parse_rulenumber
(
argv
[
optind
++
]);
else
rulenum
=
1
;
break
;
...
...
@@ -1018,8 +981,7 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table)
add_command
(
&
command
,
CMD_LIST
,
CMD_ZERO
,
invert
);
if
(
optarg
)
chain
=
optarg
;
else
if
(
optind
<
argc
&&
argv
[
optind
][
0
]
!=
'-'
&&
argv
[
optind
][
0
]
!=
'!'
)
else
if
(
xs_has_arg
(
argc
,
argv
))
chain
=
argv
[
optind
++
];
break
;
...
...
@@ -1027,8 +989,7 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table)
add_command
(
&
command
,
CMD_FLUSH
,
CMD_NONE
,
invert
);
if
(
optarg
)
chain
=
optarg
;
else
if
(
optind
<
argc
&&
argv
[
optind
][
0
]
!=
'-'
&&
argv
[
optind
][
0
]
!=
'!'
)
else
if
(
xs_has_arg
(
argc
,
argv
))
chain
=
argv
[
optind
++
];
break
;
...
...
@@ -1036,8 +997,7 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table)
add_command
(
&
command
,
CMD_ZERO
,
CMD_LIST
,
invert
);
if
(
optarg
)
chain
=
optarg
;
else
if
(
optind
<
argc
&&
argv
[
optind
][
0
]
!=
'-'
&&
argv
[
optind
][
0
]
!=
'!'
)
else
if
(
xs_has_arg
(
argc
,
argv
))
chain
=
argv
[
optind
++
];
break
;
...
...
@@ -1059,8 +1019,7 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table)
add_command
(
&
command
,
CMD_DELETE_CHAIN
,
CMD_NONE
,
invert
);
if
(
optarg
)
chain
=
optarg
;
else
if
(
optind
<
argc
&&
argv
[
optind
][
0
]
!=
'-'
&&
argv
[
optind
][
0
]
!=
'!'
)
else
if
(
xs_has_arg
(
argc
,
argv
))
chain
=
argv
[
optind
++
];
break
;
...
...
@@ -1068,8 +1027,7 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table)
add_command
(
&
command
,
CMD_RENAME_CHAIN
,
CMD_NONE
,
invert
);
chain
=
optarg
;
if
(
optind
<
argc
&&
argv
[
optind
][
0
]
!=
'-'
&&
argv
[
optind
][
0
]
!=
'!'
)
if
(
xs_has_arg
(
argc
,
argv
))
newname
=
argv
[
optind
++
];
else
xtables_error
(
PARAMETER_PROBLEM
,
...
...
@@ -1082,8 +1040,7 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table)
add_command
(
&
command
,
CMD_SET_POLICY
,
CMD_NONE
,
invert
);
chain
=
optarg
;
if
(
optind
<
argc
&&
argv
[
optind
][
0
]
!=
'-'
&&
argv
[
optind
][
0
]
!=
'!'
)
if
(
xs_has_arg
(
argc
,
argv
))
policy
=
argv
[
optind
++
];
else
xtables_error
(
PARAMETER_PROBLEM
,
...
...
@@ -1099,47 +1056,47 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table)
break
;
case
's'
:
check_inverse
(
optarg
,
&
invert
,
&
optind
,
argc
);
set_option
(
&
options
,
OPT_S_IP
,
&
cs
.
fw
.
arp
.
invflags
,
set_option
(
&
options
,
OPT_S_IP
,
&
cs
.
arp
.
arp
.
invflags
,
invert
);
shostnetworkmask
=
argv
[
optind
-
1
];
break
;
case
'd'
:
check_inverse
(
optarg
,
&
invert
,
&
optind
,
argc
);
set_option
(
&
options
,
OPT_D_IP
,
&
cs
.
fw
.
arp
.
invflags
,
set_option
(
&
options
,
OPT_D_IP
,
&
cs
.
arp
.
arp
.
invflags
,
invert
);
dhostnetworkmask
=
argv
[
optind
-
1
];
break
;
case
2
:
/* src-mac */
check_inverse
(
optarg
,
&
invert
,
&
optind
,
argc
);
set_option
(
&
options
,
OPT_S_MAC
,
&
cs
.
fw
.
arp
.
invflags
,
set_option
(
&
options
,
OPT_S_MAC
,
&
cs
.
arp
.
arp
.
invflags
,
invert
);
if
(
getmac_and_mask
(
argv
[
optind
-
1
],
cs
.
fw
.
arp
.
src_devaddr
.
addr
,
cs
.
fw
.
arp
.
src_devaddr
.
mask
))
cs
.
arp
.
arp
.
src_devaddr
.
addr
,
cs
.
arp
.
arp
.
src_devaddr
.
mask
))
xtables_error
(
PARAMETER_PROBLEM
,
"Problem with specified "
"source mac"
);
break
;
case
3
:
/* dst-mac */
check_inverse
(
optarg
,
&
invert
,
&
optind
,
argc
);
set_option
(
&
options
,
OPT_D_MAC
,
&
cs
.
fw
.
arp
.
invflags
,
set_option
(
&
options
,
OPT_D_MAC
,
&
cs
.
arp
.
arp
.
invflags
,
invert
);
if
(
getmac_and_mask
(
argv
[
optind
-
1
],
cs
.
fw
.
arp
.
tgt_devaddr
.
addr
,
cs
.
fw
.
arp
.
tgt_devaddr
.
mask
))
cs
.
arp
.
arp
.
tgt_devaddr
.
addr
,
cs
.
arp
.
arp
.
tgt_devaddr
.
mask
))
xtables_error
(
PARAMETER_PROBLEM
,
"Problem with specified "
"destination mac"
);
break
;
case
'l'
:
/* hardware length */
check_inverse
(
optarg
,
&
invert
,
&
optind
,
argc
);
set_option
(
&
options
,
OPT_H_LENGTH
,
&
cs
.
fw
.
arp
.
invflags
,
set_option
(
&
options
,
OPT_H_LENGTH
,
&
cs
.
arp
.
arp
.
invflags
,
invert
);
getlength_and_mask
(
argv
[
optind
-
1
],
&
cs
.
fw
.
arp
.
arhln
,
&
cs
.
fw
.
arp
.
arhln_mask
);
getlength_and_mask
(
argv
[
optind
-
1
],
&
cs
.
arp
.
arp
.
arhln
,
&
cs
.
arp
.
arp
.
arhln_mask
);
if
(
cs
.
fw
.
arp
.
arhln
!=
6
)
{
if
(
cs
.
arp
.
arp
.
arhln
!=
6
)
{
xtables_error
(
PARAMETER_PROBLEM
,
"Only harware address length of"
" 6 is supported currently."
);
...
...
@@ -1151,20 +1108,20 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table)
xtables_error
(
PARAMETER_PROBLEM
,
"not supported"
);
/*
check_inverse(optarg, &invert, &optind, argc);
set_option(&options, OPT_P_LENGTH, &cs.
fw
.arp.invflags,
set_option(&options, OPT_P_LENGTH, &cs.
arp
.arp.invflags,
invert);
getlength_and_mask(argv[optind - 1], &cs.
fw
.arp.arpln,
&cs.
fw
.arp.arpln_mask);
getlength_and_mask(argv[optind - 1], &cs.
arp
.arp.arpln,
&cs.
arp
.arp.arpln_mask);
break;
*/
case
4
:
/* opcode */
check_inverse
(
optarg
,
&
invert
,
&
optind
,
argc
);
set_option
(
&
options
,
OPT_OPCODE
,
&
cs
.
fw
.
arp
.
invflags
,
set_option
(
&
options
,
OPT_OPCODE
,
&
cs
.
arp
.
arp
.
invflags
,
invert
);
if
(
get16_and_mask
(
argv
[
optind
-
1
],
&
cs
.
fw
.
arp
.
arpop
,
&
cs
.
fw
.
arp
.
arpop_mask
,
10
))
{
if
(
get16_and_mask
(
argv
[
optind
-
1
],
&
cs
.
arp
.
arp
.
arpop
,
&
cs
.
arp
.
arp
.
arpop_mask
,
10
))
{
int
i
;
for
(
i
=
0
;
i
<
NUMOPCODES
;
i
++
)
...
...
@@ -1172,65 +1129,64 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table)
break
;
if
(
i
==
NUMOPCODES
)
xtables_error
(
PARAMETER_PROBLEM
,
"Problem with specified opcode"
);
cs
.
fw
.
arp
.
arpop
=
htons
(
i
+
1
);
cs
.
arp
.
arp
.
arpop
=
htons
(
i
+
1
);
}
break
;
case
5
:
/* h-type */
check_inverse
(
optarg
,
&
invert
,
&
optind
,
argc
);
set_option
(
&
options
,
OPT_H_TYPE
,
&
cs
.
fw
.
arp
.
invflags
,
set_option
(
&
options
,
OPT_H_TYPE
,
&
cs
.
arp
.
arp
.
invflags
,
invert
);
if
(
get16_and_mask
(
argv
[
optind
-
1
],
&
cs
.
fw
.
arp
.
arhrd
,
&
cs
.
fw
.
arp
.
arhrd_mask
,
16
))
{
if
(
get16_and_mask
(
argv
[
optind
-
1
],
&
cs
.
arp
.
arp
.
arhrd
,
&
cs
.
arp
.
arp
.
arhrd_mask
,
16
))
{
if
(
strcasecmp
(
argv
[
optind
-
1
],
"Ethernet"
))
xtables_error
(
PARAMETER_PROBLEM
,
"Problem with specified hardware type"
);
cs
.
fw
.
arp
.
arhrd
=
htons
(
1
);
cs
.
arp
.
arp
.
arhrd
=
htons
(
1
);
}
break
;
case
6
:
/* proto-type */
check_inverse
(
optarg
,
&
invert
,
&
optind
,
argc
);
set_option
(
&
options
,
OPT_P_TYPE
,
&
cs
.
fw
.
arp
.
invflags
,
set_option
(
&
options
,
OPT_P_TYPE
,
&
cs
.
arp
.
arp
.
invflags
,
invert
);
if
(
get16_and_mask
(
argv
[
optind
-
1
],
&
cs
.
fw
.
arp
.
arpro
,
&
cs
.
fw
.
arp
.
arpro_mask
,
0
))
{
if
(
get16_and_mask
(
argv
[
optind
-
1
],
&
cs
.
arp
.
arp
.
arpro
,
&
cs
.
arp
.
arp
.
arpro_mask
,
0
))
{
if
(
strcasecmp
(
argv
[
optind
-
1
],
"ipv4"
))
xtables_error
(
PARAMETER_PROBLEM
,
"Problem with specified protocol type"
);
cs
.
fw
.
arp
.
arpro
=
htons
(
0x800
);
cs
.
arp
.
arp
.
arpro
=
htons
(
0x800
);
}
break
;
case
'j'
:
set_option
(
&
options
,
OPT_JUMP
,
&
cs
.
fw
.
arp
.
invflags
,
set_option
(
&
options
,
OPT_JUMP
,
&
cs
.
arp
.
arp
.
invflags
,
invert
);
cs
.
jumpto
=
parse_target
(
optarg
);
cs
.
target
=
command_jump
(
&
cs
.
fw
,
cs
.
jumpto
);
command_jump
(
&
cs
);
break
;
case
'i'
:
check_inverse
(
optarg
,
&
invert
,
&
optind
,
argc
);
set_option
(
&
options
,
OPT_VIANAMEIN
,
&
cs
.
fw
.
arp
.
invflags
,
set_option
(
&
options
,
OPT_VIANAMEIN
,
&
cs
.
arp
.
arp
.
invflags
,
invert
);
parse_interface
(
argv
[
optind
-
1
],
cs
.
fw
.
arp
.
iniface
,
cs
.
fw
.
arp
.
iniface_mask
);
/* cs.
fw
.nfcache |= NFC_IP_IF_IN; */
cs
.
arp
.
arp
.
iniface
,
cs
.
arp
.
arp
.
iniface_mask
);
/* cs.
arp
.nfcache |= NFC_IP_IF_IN; */
break
;
case
'o'
:
check_inverse
(
optarg
,
&
invert
,
&
optind
,
argc
);
set_option
(
&
options
,
OPT_VIANAMEOUT
,
&
cs
.
fw
.
arp
.
invflags
,
set_option
(
&
options
,
OPT_VIANAMEOUT
,
&
cs
.
arp
.
arp
.
invflags
,
invert
);
parse_interface
(
argv
[
optind
-
1
],
cs
.
fw
.
arp
.
outiface
,
cs
.
fw
.
arp
.
outiface_mask
);
/* cs.
fw
.nfcache |= NFC_IP_IF_OUT; */
cs
.
arp
.
arp
.
outiface
,
cs
.
arp
.
arp
.
outiface_mask
);
/* cs.
arp
.nfcache |= NFC_IP_IF_OUT; */
break
;
case
'v'
:
if
(
!
verbose
)
set_option
(
&
options
,
OPT_VERBOSE
,
&
cs
.
fw
.
arp
.
invflags
,
invert
);
&
cs
.
arp
.
arp
.
invflags
,
invert
);
verbose
++
;
break
;
...
...
@@ -1253,7 +1209,7 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table)
break
;
case
'n'
:
set_option
(
&
options
,
OPT_NUMERIC
,
&
cs
.
fw
.
arp
.
invflags
,
set_option
(
&
options
,
OPT_NUMERIC
,
&
cs
.
arp
.
arp
.
invflags
,
invert
);
break
;
...
...
@@ -1268,12 +1224,12 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table)
if
(
invert
)
printf
(
"Not %s ;-)
\n
"
,
program_version
);
else
printf
(
"%s v%s
\n
"
,
printf
(
"%s v%s
(nf_tables)
\n
"
,
program_name
,
program_version
);
exit
(
0
);
case
'0'
:
set_option
(
&
options
,
OPT_LINENUMBERS
,
&
cs
.
fw
.
arp
.
invflags
,
set_option
(
&
options
,
OPT_LINENUMBERS
,
&
cs
.
arp
.
arp
.
invflags
,
invert
);
break
;
...
...
@@ -1283,23 +1239,22 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table)
case
'c'
:
set_option
(
&
options
,
OPT_COUNTERS
,
&
cs
.
fw
.
arp
.
invflags
,
set_option
(
&
options
,
OPT_COUNTERS
,
&
cs
.
arp
.
arp
.
invflags
,
invert
);
pcnt
=
optarg
;
if
(
optind
<
argc
&&
argv
[
optind
][
0
]
!=
'-'
&&
argv
[
optind
][
0
]
!=
'!'
)
if
(
xs_has_arg
(
argc
,
argv
))
bcnt
=
argv
[
optind
++
];
else
xtables_error
(
PARAMETER_PROBLEM
,
"-%c requires packet and byte counter"
,
opt2char
(
OPT_COUNTERS
));
if
(
sscanf
(
pcnt
,
"%llu"
,
&
cs
.
fw
.
counters
.
pcnt
)
!=
1
)
if
(
sscanf
(
pcnt
,
"%llu"
,
&
cs
.
arp
.
counters
.
pcnt
)
!=
1
)
xtables_error
(
PARAMETER_PROBLEM
,
"-%c packet counter not numeric"
,
opt2char
(
OPT_COUNTERS
));
if
(
sscanf
(
bcnt
,
"%llu"
,
&
cs
.
fw
.
counters
.
bcnt
)
!=
1
)
if
(
sscanf
(
bcnt
,
"%llu"
,
&
cs
.
arp
.
counters
.
bcnt
)
!=
1
)
xtables_error
(
PARAMETER_PROBLEM
,
"-%c byte counter not numeric"
,
opt2char
(
OPT_COUNTERS
));
...
...
@@ -1323,7 +1278,7 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table)
default:
if
(
cs
.
target
)
{
xtables_option_tpcall
(
c
,
argv
,
invert
,
cs
.
target
,
&
cs
.
fw
);
invert
,
cs
.
target
,
&
cs
.
arp
);
}
break
;
}
...
...
@@ -1351,14 +1306,14 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table)
if
(
shostnetworkmask
)
parse_hostnetworkmask
(
shostnetworkmask
,
&
saddrs
,
&
(
cs
.
fw
.
arp
.
smsk
),
&
nsaddrs
);
&
(
cs
.
arp
.
arp
.
smsk
),
&
nsaddrs
);
if
(
dhostnetworkmask
)
parse_hostnetworkmask
(
dhostnetworkmask
,
&
daddrs
,
&
(
cs
.
fw
.
arp
.
tmsk
),
&
ndaddrs
);
&
(
cs
.
arp
.
arp
.
tmsk
),
&
ndaddrs
);
if
((
nsaddrs
>
1
||
ndaddrs
>
1
)
&&
(
cs
.
fw
.
arp
.
invflags
&
(
ARPT_INV_SRCIP
|
ARPT_INV_TGTIP
)))
(
cs
.
arp
.
arp
.
invflags
&
(
ARPT_INV_SRCIP
|
ARPT_INV_TGTIP
)))
xtables_error
(
PARAMETER_PROBLEM
,
"! not allowed with multiple"
" source or destination IP addresses"
);
...
...
@@ -1373,14 +1328,6 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table)
"chain name `%s' too long (must be under %i chars)"
,
chain
,
ARPT_FUNCTION_MAXNAMELEN
);
if
(
nft_init
(
h
,
xtables_arp
)
<
0
)
xtables_error
(
OTHER_PROBLEM
,
"Could not initialize nftables layer."
);
h
->
ops
=
nft_family_ops_lookup
(
h
->
family
);
if
(
h
->
ops
==
NULL
)
xtables_error
(
PARAMETER_PROBLEM
,
"Unknown family"
);
if
(
command
==
CMD_APPEND
||
command
==
CMD_DELETE
||
command
==
CMD_INSERT
...
...
@@ -1404,17 +1351,6 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table)
opt2char
(
OPT_VIANAMEIN
),
chain
);
}
if
(
!
cs
.
target
&&
strlen
(
cs
.
jumpto
)
!=
0
)
{
size_t
size
;
cs
.
target
=
xtables_find_target
(
XT_STANDARD_TARGET
,
XTF_LOAD_MUST_SUCCEED
);
size
=
sizeof
(
struct
arpt_entry_target
)
+
cs
.
target
->
size
;
cs
.
target
->
t
=
xtables_calloc
(
1
,
size
);
cs
.
target
->
t
->
u
.
target_size
=
size
;
strcpy
(
cs
.
target
->
t
->
u
.
user
.
name
,
cs
.
jumpto
);
}
}
switch
(
command
)
{
...
...
@@ -1449,10 +1385,11 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table)
options
&
OPT_LINENUMBERS
);
break
;
case
CMD_FLUSH
:
ret
=
nft_rule_flush
(
h
,
chain
,
*
table
);
ret
=
nft_rule_flush
(
h
,
chain
,
*
table
,
options
&
OPT_VERBOSE
);
break
;
case
CMD_ZERO
:
ret
=
nft_chain_zero_counters
(
h
,
chain
,
*
table
);
ret
=
nft_chain_zero_counters
(
h
,
chain
,
*
table
,
options
&
OPT_VERBOSE
);
break
;
case
CMD_LIST
|
CMD_ZERO
:
ret
=
list_entries
(
h
,
chain
,
*
table
,
rulenum
,
...
...
@@ -1461,13 +1398,15 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table)
/*options&OPT_EXPANDED*/
0
,
options
&
OPT_LINENUMBERS
);
if
(
ret
)
ret
=
nft_chain_zero_counters
(
h
,
chain
,
*
table
);
ret
=
nft_chain_zero_counters
(
h
,
chain
,
*
table
,
options
&
OPT_VERBOSE
);
break
;
case
CMD_NEW_CHAIN
:
ret
=
nft_chain_user_add
(
h
,
chain
,
*
table
);
break
;
case
CMD_DELETE_CHAIN
:
ret
=
nft_chain_user_del
(
h
,
chain
,
*
table
);
ret
=
nft_chain_user_del
(
h
,
chain
,
*
table
,
options
&
OPT_VERBOSE
);
break
;
case
CMD_RENAME_CHAIN
:
ret
=
nft_chain_user_rename
(
h
,
chain
,
*
table
,
newname
);
...
...
@@ -1483,6 +1422,16 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table)
exit_tryhelp
(
2
);
}
if
(
nsaddrs
)
free
(
saddrs
);
if
(
ndaddrs
)
free
(
daddrs
);
if
(
cs
.
target
)
free
(
cs
.
target
->
t
);
xtables_free_opts
(
1
);
/* if (verbose > 1)
dump_entries(*handle);*/
...
...
iptables/xtables-eb-standalone.c
View file @
dab1e98e
...
...
@@ -41,29 +41,15 @@
#include "xtables-multi.h"
extern
struct
xtables_globals
ebtables_globals
;
int
xtables_eb_main
(
int
argc
,
char
*
argv
[])
{
int
ret
;
char
*
table
=
"filter"
;
struct
nft_handle
h
=
{
.
family
=
NFPROTO_BRIDGE
,
};
struct
nft_handle
h
;
ebtables_globals
.
program_name
=
"ebtables"
;
ret
=
xtables_init_all
(
&
ebtables_globals
,
NFPROTO_BRIDGE
);
if
(
ret
<
0
)
{
fprintf
(
stderr
,
"%s/%s Failed to initialize ebtables-compat
\n
"
,
ebtables_globals
.
program_name
,
ebtables_globals
.
program_version
);
exit
(
1
);
}
nft_init_eb
(
&
h
,
"ebtables"
);
#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
init_extensionsb
();
#endif
ret
=
do_commandeb
(
&
h
,
argc
,
argv
,
&
table
);
ret
=
do_commandeb
(
&
h
,
argc
,
argv
,
&
table
,
false
);
if
(
ret
)
ret
=
nft_commit
(
&
h
);
...
...
iptables/xtables-eb-translate.c
0 → 100644
View file @
dab1e98e
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdarg.h>
#include <string.h>
#include <fcntl.h>
#include <getopt.h>
#include <iptables.h>
#include <xtables.h>
#include <netinet/ether.h>
#include <linux/netfilter_bridge.h>
#include <linux/netfilter/nf_tables.h>
#include <libiptc/libxtc.h>
#include "xshared.h"
#include "xtables-multi.h"
#include "nft-bridge.h"
#include "nft.h"
#include "nft-shared.h"
/*
* From include/ebtables_u.h
*/
#define EXEC_STYLE_PRG 0
#define EXEC_STYLE_DAEMON 1
#define ebt_check_option2(flags, mask) EBT_CHECK_OPTION(flags, mask)
extern
int
ebt_invert
;
static
int
ebt_check_inverse2
(
const
char
option
[],
int
argc
,
char
**
argv
)
{
if
(
!
option
)
return
ebt_invert
;
if
(
strcmp
(
option
,
"!"
)
==
0
)
{
if
(
ebt_invert
==
1
)
xtables_error
(
PARAMETER_PROBLEM
,
"Double use of '!' not allowed"
);
if
(
optind
>=
argc
)
optarg
=
NULL
;
else
optarg
=
argv
[
optind
];
optind
++
;
ebt_invert
=
1
;
return
1
;
}
return
ebt_invert
;
}
/*
* Glue code to use libxtables
*/
static
int
parse_rule_number
(
const
char
*
rule
)
{
unsigned
int
rule_nr
;
if
(
!
xtables_strtoui
(
rule
,
NULL
,
&
rule_nr
,
1
,
INT_MAX
))
xtables_error
(
PARAMETER_PROBLEM
,
"Invalid rule number `%s'"
,
rule
);
return
rule_nr
;
}
static
const
char
*
parse_target
(
const
char
*
targetname
)
{
const
char
*
ptr
;
if
(
strlen
(
targetname
)
<
1
)
xtables_error
(
PARAMETER_PROBLEM
,
"Invalid target name (too short)"
);
if
(
strlen
(
targetname
)
+
1
>
EBT_CHAIN_MAXNAMELEN
)
xtables_error
(
PARAMETER_PROBLEM
,
"Invalid target '%s' (%d chars max)"
,
targetname
,
EBT_CHAIN_MAXNAMELEN
);
for
(
ptr
=
targetname
;
*
ptr
;
ptr
++
)
if
(
isspace
(
*
ptr
))
xtables_error
(
PARAMETER_PROBLEM
,
"Invalid target name `%s'"
,
targetname
);
return
targetname
;
}
static
int
get_current_chain
(
const
char
*
chain
)
{
if
(
strcmp
(
chain
,
"PREROUTING"
)
==
0
)
return
NF_BR_PRE_ROUTING
;
else
if
(
strcmp
(
chain
,
"INPUT"
)
==
0
)
return
NF_BR_LOCAL_IN
;
else
if
(
strcmp
(
chain
,
"FORWARD"
)
==
0
)
return
NF_BR_FORWARD
;
else
if
(
strcmp
(
chain
,
"OUTPUT"
)
==
0
)
return
NF_BR_LOCAL_OUT
;
else
if
(
strcmp
(
chain
,
"POSTROUTING"
)
==
0
)
return
NF_BR_POST_ROUTING
;
return
-
1
;
}
/*
* The original ebtables parser
*/
/* Checks whether a command has already been specified */
#define OPT_COMMANDS (flags & OPT_COMMAND || flags & OPT_ZERO)
#define OPT_COMMAND 0x01
#define OPT_TABLE 0x02
#define OPT_IN 0x04
#define OPT_OUT 0x08
#define OPT_JUMP 0x10
#define OPT_PROTOCOL 0x20
#define OPT_SOURCE 0x40
#define OPT_DEST 0x80
#define OPT_ZERO 0x100
#define OPT_LOGICALIN 0x200
#define OPT_LOGICALOUT 0x400
#define OPT_COUNT 0x1000
/* This value is also defined in libebtc.c */
/* Default command line options. Do not mess around with the already
* assigned numbers unless you know what you are doing */
extern
struct
option
ebt_original_options
[];
extern
struct
xtables_globals
ebtables_globals
;
#define opts ebtables_globals.opts
#define prog_name ebtables_globals.program_name
#define prog_vers ebtables_globals.program_version
static
void
print_help
(
void
)
{
fprintf
(
stderr
,
"%s: Translate ebtables command to nft syntax
\n
"
"no side effects occur, the translated command is written "
"to standard output.
\n
"
"A '#' followed by input means no translation "
"is available.
\n
"
,
prog_name
);
exit
(
0
);
}
static
int
parse_rule_range
(
const
char
*
argv
,
int
*
rule_nr
,
int
*
rule_nr_end
)
{
char
*
colon
=
strchr
(
argv
,
':'
),
*
buffer
;
if
(
colon
)
{
*
colon
=
'\0'
;
if
(
*
(
colon
+
1
)
==
'\0'
)
*
rule_nr_end
=
-
1
;
/* Until the last rule */
else
{
*
rule_nr_end
=
strtol
(
colon
+
1
,
&
buffer
,
10
);
if
(
*
buffer
!=
'\0'
||
*
rule_nr_end
==
0
)
return
-
1
;
}
}
if
(
colon
==
argv
)
*
rule_nr
=
1
;
/* Beginning with the first rule */
else
{
*
rule_nr
=
strtol
(
argv
,
&
buffer
,
10
);
if
(
*
buffer
!=
'\0'
||
*
rule_nr
==
0
)
return
-
1
;
}
if
(
!
colon
)
*
rule_nr_end
=
*
rule_nr
;
return
0
;
}
static
void
ebtables_parse_interface
(
const
char
*
arg
,
char
*
vianame
)
{
unsigned
char
mask
[
IFNAMSIZ
];
char
*
c
;
xtables_parse_interface
(
arg
,
vianame
,
mask
);
if
((
c
=
strchr
(
vianame
,
'+'
)))
{
if
(
*
(
c
+
1
)
!=
'\0'
)
xtables_error
(
PARAMETER_PROBLEM
,
"Spurious characters after '+' wildcard"
);
}
}
static
void
print_ebt_cmd
(
int
argc
,
char
*
argv
[])
{
int
i
;
printf
(
"# "
);
for
(
i
=
1
;
i
<
argc
;
i
++
)
printf
(
"%s "
,
argv
[
i
]);
printf
(
"
\n
"
);
}
static
int
nft_rule_eb_xlate_add
(
struct
nft_handle
*
h
,
const
struct
nft_xt_cmd_parse
*
p
,
const
struct
iptables_command_state
*
cs
,
bool
append
)
{
struct
xt_xlate
*
xl
=
xt_xlate_alloc
(
10240
);
int
ret
;
if
(
append
)
{
xt_xlate_add
(
xl
,
"add rule bridge %s %s "
,
p
->
table
,
p
->
chain
);
}
else
{
xt_xlate_add
(
xl
,
"insert rule bridge %s %s "
,
p
->
table
,
p
->
chain
);
}
ret
=
h
->
ops
->
xlate
(
cs
,
xl
);
if
(
ret
)
printf
(
"%s
\n
"
,
xt_xlate_get
(
xl
));
xt_xlate_free
(
xl
);
return
ret
;
}
/* We use exec_style instead of #ifdef's because ebtables.so is a shared object. */
static
int
do_commandeb_xlate
(
struct
nft_handle
*
h
,
int
argc
,
char
*
argv
[],
char
**
table
)
{
char
*
buffer
;
int
c
,
i
;
int
rule_nr
=
0
;
int
rule_nr_end
=
0
;
int
ret
=
0
;
unsigned
int
flags
=
0
;
struct
iptables_command_state
cs
=
{
.
argv
=
argv
,
.
eb
.
bitmask
=
EBT_NOPROTO
,
};
char
command
=
'h'
;
const
char
*
chain
=
NULL
;
int
exec_style
=
EXEC_STYLE_PRG
;
int
selected_chain
=
-
1
;
struct
xtables_rule_match
*
xtrm_i
;
struct
ebt_match
*
match
;
struct
nft_xt_cmd_parse
p
=
{
.
table
=
*
table
,
};
/* prevent getopt to spoil our error reporting */
opterr
=
false
;
printf
(
"nft "
);
/* Getopt saves the day */
while
((
c
=
getopt_long
(
argc
,
argv
,
"-A:D:I:N:E:X::L::Z::F::P:Vhi:o:j:c:p:s:d:t:M:"
,
opts
,
NULL
))
!=
-
1
)
{
cs
.
c
=
c
;
cs
.
invert
=
ebt_invert
;
switch
(
c
)
{
case
'A'
:
/* Add a rule */
case
'D'
:
/* Delete a rule */
case
'P'
:
/* Define policy */
case
'I'
:
/* Insert a rule */
case
'N'
:
/* Make a user defined chain */
case
'E'
:
/* Rename chain */
case
'X'
:
/* Delete chain */
/* We allow -N chainname -P policy */
/* XXX: Not in ebtables-compat */
if
(
command
==
'N'
&&
c
==
'P'
)
{
command
=
c
;
optind
--
;
/* No table specified */
break
;
}
if
(
OPT_COMMANDS
)
xtables_error
(
PARAMETER_PROBLEM
,
"Multiple commands are not allowed"
);
command
=
c
;
chain
=
optarg
;
selected_chain
=
get_current_chain
(
chain
);
p
.
chain
=
chain
;
flags
|=
OPT_COMMAND
;
if
(
c
==
'N'
)
{
printf
(
"add chain bridge %s %s
\n
"
,
p
.
table
,
p
.
chain
);
ret
=
1
;
break
;
}
else
if
(
c
==
'X'
)
{
printf
(
"delete chain bridge %s %s
\n
"
,
p
.
table
,
p
.
chain
);
ret
=
1
;
break
;
}
if
(
c
==
'E'
)
{
break
;
}
else
if
(
c
==
'D'
&&
optind
<
argc
&&
(
argv
[
optind
][
0
]
!=
'-'
||
(
argv
[
optind
][
1
]
>=
'0'
&&
argv
[
optind
][
1
]
<=
'9'
)))
{
if
(
optind
!=
argc
-
1
)
xtables_error
(
PARAMETER_PROBLEM
,
"No extra options allowed with -D start_nr[:end_nr]"
);
if
(
parse_rule_range
(
argv
[
optind
],
&
rule_nr
,
&
rule_nr_end
))
xtables_error
(
PARAMETER_PROBLEM
,
"Problem with the specified rule number(s) '%s'"
,
argv
[
optind
]);
optind
++
;
}
else
if
(
c
==
'I'
)
{
if
(
optind
>=
argc
||
(
argv
[
optind
][
0
]
==
'-'
&&
(
argv
[
optind
][
1
]
<
'0'
||
argv
[
optind
][
1
]
>
'9'
)))
rule_nr
=
1
;
else
{
rule_nr
=
parse_rule_number
(
argv
[
optind
]);
optind
++
;
}
p
.
rulenum
=
rule_nr
;
}
else
if
(
c
==
'P'
)
{
break
;
}
break
;
case
'L'
:
/* List */
printf
(
"list table bridge %s
\n
"
,
p
.
table
);
ret
=
1
;
break
;
case
'F'
:
/* Flush */
if
(
p
.
chain
)
{
printf
(
"flush chain bridge %s %s
\n
"
,
p
.
table
,
p
.
chain
);
}
else
{
printf
(
"flush table bridge %s
\n
"
,
p
.
table
);
}
ret
=
1
;
break
;
case
'Z'
:
/* Zero counters */
if
(
c
==
'Z'
)
{
if
((
flags
&
OPT_ZERO
)
||
(
flags
&
OPT_COMMAND
&&
command
!=
'L'
))
print_zero:
xtables_error
(
PARAMETER_PROBLEM
,
"Command -Z only allowed together with command -L"
);
flags
|=
OPT_ZERO
;
}
else
{
if
(
flags
&
OPT_COMMAND
)
xtables_error
(
PARAMETER_PROBLEM
,
"Multiple commands are not allowed"
);
command
=
c
;
flags
|=
OPT_COMMAND
;
if
(
flags
&
OPT_ZERO
&&
c
!=
'L'
)
goto
print_zero
;
}
break
;
case
'V'
:
/* Version */
if
(
OPT_COMMANDS
)
xtables_error
(
PARAMETER_PROBLEM
,
"Multiple commands are not allowed"
);
if
(
exec_style
==
EXEC_STYLE_DAEMON
)
xtables_error
(
PARAMETER_PROBLEM
,
"%s %s
\n
"
,
prog_name
,
prog_vers
);
printf
(
"%s %s
\n
"
,
prog_name
,
prog_vers
);
exit
(
0
);
case
'h'
:
if
(
OPT_COMMANDS
)
xtables_error
(
PARAMETER_PROBLEM
,
"Multiple commands are not allowed"
);
print_help
();
break
;
case
't'
:
/* Table */
if
(
OPT_COMMANDS
)
xtables_error
(
PARAMETER_PROBLEM
,
"Please put the -t option first"
);
ebt_check_option2
(
&
flags
,
OPT_TABLE
);
if
(
strlen
(
optarg
)
>
EBT_TABLE_MAXNAMELEN
-
1
)
xtables_error
(
PARAMETER_PROBLEM
,
"Table name length cannot exceed %d characters"
,
EBT_TABLE_MAXNAMELEN
-
1
);
*
table
=
optarg
;
p
.
table
=
optarg
;
break
;
case
'i'
:
/* Input interface */
case
2
:
/* Logical input interface */
case
'o'
:
/* Output interface */
case
3
:
/* Logical output interface */
case
'j'
:
/* Target */
case
'p'
:
/* Net family protocol */
case
's'
:
/* Source mac */
case
'd'
:
/* Destination mac */
case
'c'
:
/* Set counters */
if
(
!
OPT_COMMANDS
)
xtables_error
(
PARAMETER_PROBLEM
,
"No command specified"
);
if
(
command
!=
'A'
&&
command
!=
'D'
&&
command
!=
'I'
)
xtables_error
(
PARAMETER_PROBLEM
,
"Command and option do not match"
);
if
(
c
==
'i'
)
{
ebt_check_option2
(
&
flags
,
OPT_IN
);
if
(
selected_chain
>
2
&&
selected_chain
<
NF_BR_BROUTING
)
xtables_error
(
PARAMETER_PROBLEM
,
"Use -i only in INPUT, FORWARD, PREROUTING and BROUTING chains"
);
if
(
ebt_check_inverse2
(
optarg
,
argc
,
argv
))
cs
.
eb
.
invflags
|=
EBT_IIN
;
ebtables_parse_interface
(
optarg
,
cs
.
eb
.
in
);
break
;
}
else
if
(
c
==
2
)
{
ebt_check_option2
(
&
flags
,
OPT_LOGICALIN
);
if
(
selected_chain
>
2
&&
selected_chain
<
NF_BR_BROUTING
)
xtables_error
(
PARAMETER_PROBLEM
,
"Use --logical-in only in INPUT, FORWARD, PREROUTING and BROUTING chains"
);
if
(
ebt_check_inverse2
(
optarg
,
argc
,
argv
))
cs
.
eb
.
invflags
|=
EBT_ILOGICALIN
;
ebtables_parse_interface
(
optarg
,
cs
.
eb
.
logical_in
);
break
;
}
else
if
(
c
==
'o'
)
{
ebt_check_option2
(
&
flags
,
OPT_OUT
);
if
(
selected_chain
<
2
||
selected_chain
==
NF_BR_BROUTING
)
xtables_error
(
PARAMETER_PROBLEM
,
"Use -o only in OUTPUT, FORWARD and POSTROUTING chains"
);
if
(
ebt_check_inverse2
(
optarg
,
argc
,
argv
))
cs
.
eb
.
invflags
|=
EBT_IOUT
;
ebtables_parse_interface
(
optarg
,
cs
.
eb
.
out
);
break
;
}
else
if
(
c
==
3
)
{
ebt_check_option2
(
&
flags
,
OPT_LOGICALOUT
);
if
(
selected_chain
<
2
||
selected_chain
==
NF_BR_BROUTING
)
xtables_error
(
PARAMETER_PROBLEM
,
"Use --logical-out only in OUTPUT, FORWARD and POSTROUTING chains"
);
if
(
ebt_check_inverse2
(
optarg
,
argc
,
argv
))
cs
.
eb
.
invflags
|=
EBT_ILOGICALOUT
;
ebtables_parse_interface
(
optarg
,
cs
.
eb
.
logical_out
);
break
;
}
else
if
(
c
==
'j'
)
{
ebt_check_option2
(
&
flags
,
OPT_JUMP
);
cs
.
jumpto
=
parse_target
(
optarg
);
cs
.
target
=
ebt_command_jump
(
cs
.
jumpto
);
break
;
}
else
if
(
c
==
's'
)
{
ebt_check_option2
(
&
flags
,
OPT_SOURCE
);
if
(
ebt_check_inverse2
(
optarg
,
argc
,
argv
))
cs
.
eb
.
invflags
|=
EBT_ISOURCE
;
if
(
ebt_get_mac_and_mask
(
optarg
,
cs
.
eb
.
sourcemac
,
cs
.
eb
.
sourcemsk
))
xtables_error
(
PARAMETER_PROBLEM
,
"Problem with specified source mac '%s'"
,
optarg
);
cs
.
eb
.
bitmask
|=
EBT_SOURCEMAC
;
break
;
}
else
if
(
c
==
'd'
)
{
ebt_check_option2
(
&
flags
,
OPT_DEST
);
if
(
ebt_check_inverse2
(
optarg
,
argc
,
argv
))
cs
.
eb
.
invflags
|=
EBT_IDEST
;
if
(
ebt_get_mac_and_mask
(
optarg
,
cs
.
eb
.
destmac
,
cs
.
eb
.
destmsk
))
xtables_error
(
PARAMETER_PROBLEM
,
"Problem with specified destination mac '%s'"
,
optarg
);
cs
.
eb
.
bitmask
|=
EBT_DESTMAC
;
break
;
}
else
if
(
c
==
'c'
)
{
ebt_check_option2
(
&
flags
,
OPT_COUNT
);
if
(
ebt_check_inverse2
(
optarg
,
argc
,
argv
))
xtables_error
(
PARAMETER_PROBLEM
,
"Unexpected '!' after -c"
);
if
(
optind
>=
argc
||
optarg
[
0
]
==
'-'
||
argv
[
optind
][
0
]
==
'-'
)
xtables_error
(
PARAMETER_PROBLEM
,
"Option -c needs 2 arguments"
);
cs
.
counters
.
pcnt
=
strtoull
(
optarg
,
&
buffer
,
10
);
if
(
*
buffer
!=
'\0'
)
xtables_error
(
PARAMETER_PROBLEM
,
"Packet counter '%s' invalid"
,
optarg
);
cs
.
counters
.
bcnt
=
strtoull
(
argv
[
optind
],
&
buffer
,
10
);
if
(
*
buffer
!=
'\0'
)
xtables_error
(
PARAMETER_PROBLEM
,
"Packet counter '%s' invalid"
,
argv
[
optind
]);
optind
++
;
break
;
}
ebt_check_option2
(
&
flags
,
OPT_PROTOCOL
);
if
(
ebt_check_inverse2
(
optarg
,
argc
,
argv
))
cs
.
eb
.
invflags
|=
EBT_IPROTO
;
cs
.
eb
.
bitmask
&=
~
((
unsigned
int
)
EBT_NOPROTO
);
i
=
strtol
(
optarg
,
&
buffer
,
16
);
if
(
*
buffer
==
'\0'
&&
(
i
<
0
||
i
>
0xFFFF
))
xtables_error
(
PARAMETER_PROBLEM
,
"Problem with the specified protocol"
);
if
(
*
buffer
!=
'\0'
)
{
struct
xt_ethertypeent
*
ent
;
if
(
!
strcasecmp
(
optarg
,
"LENGTH"
))
{
cs
.
eb
.
bitmask
|=
EBT_802_3
;
break
;
}
ent
=
xtables_getethertypebyname
(
optarg
);
if
(
!
ent
)
xtables_error
(
PARAMETER_PROBLEM
,
"Problem with the specified Ethernet protocol '%s', perhaps "
XT_PATH_ETHERTYPES
" is missing"
,
optarg
);
cs
.
eb
.
ethproto
=
ent
->
e_ethertype
;
}
else
cs
.
eb
.
ethproto
=
i
;
if
(
cs
.
eb
.
ethproto
<
0x0600
)
xtables_error
(
PARAMETER_PROBLEM
,
"Sorry, protocols have values above or equal to 0x0600"
);
break
;
case
4
:
/* Lc */
ebt_check_option2
(
&
flags
,
LIST_C
);
if
(
command
!=
'L'
)
xtables_error
(
PARAMETER_PROBLEM
,
"Use --Lc with -L"
);
flags
|=
LIST_C
;
break
;
case
5
:
/* Ln */
ebt_check_option2
(
&
flags
,
LIST_N
);
if
(
command
!=
'L'
)
xtables_error
(
PARAMETER_PROBLEM
,
"Use --Ln with -L"
);
if
(
flags
&
LIST_X
)
xtables_error
(
PARAMETER_PROBLEM
,
"--Lx is not compatible with --Ln"
);
flags
|=
LIST_N
;
break
;
case
6
:
/* Lx */
ebt_check_option2
(
&
flags
,
LIST_X
);
if
(
command
!=
'L'
)
xtables_error
(
PARAMETER_PROBLEM
,
"Use --Lx with -L"
);
if
(
flags
&
LIST_N
)
xtables_error
(
PARAMETER_PROBLEM
,
"--Lx is not compatible with --Ln"
);
flags
|=
LIST_X
;
break
;
case
12
:
/* Lmac2 */
ebt_check_option2
(
&
flags
,
LIST_MAC2
);
if
(
command
!=
'L'
)
xtables_error
(
PARAMETER_PROBLEM
,
"Use --Lmac2 with -L"
);
flags
|=
LIST_MAC2
;
break
;
case
1
:
if
(
!
strcmp
(
optarg
,
"!"
))
ebt_check_inverse2
(
optarg
,
argc
,
argv
);
else
xtables_error
(
PARAMETER_PROBLEM
,
"Bad argument : '%s'"
,
optarg
);
/* ebt_ebt_check_inverse2() did optind++ */
optind
--
;
continue
;
default:
ebt_check_inverse2
(
optarg
,
argc
,
argv
);
if
(
ebt_command_default
(
&
cs
))
xtables_error
(
PARAMETER_PROBLEM
,
"Unknown argument: '%s'"
,
argv
[
optind
-
1
]);
if
(
command
!=
'A'
&&
command
!=
'I'
&&
command
!=
'D'
)
xtables_error
(
PARAMETER_PROBLEM
,
"Extensions only for -A, -I, -D"
);
}
ebt_invert
=
0
;
}
/* Do the final checks */
if
(
command
==
'A'
||
command
==
'I'
||
command
==
'D'
)
{
for
(
xtrm_i
=
cs
.
matches
;
xtrm_i
;
xtrm_i
=
xtrm_i
->
next
)
xtables_option_mfcall
(
xtrm_i
->
match
);
for
(
match
=
cs
.
match_list
;
match
;
match
=
match
->
next
)
{
if
(
match
->
ismatch
)
continue
;
xtables_option_tfcall
(
match
->
u
.
watcher
);
}
if
(
cs
.
target
!=
NULL
)
xtables_option_tfcall
(
cs
.
target
);
}
cs
.
eb
.
ethproto
=
htons
(
cs
.
eb
.
ethproto
);
if
(
command
==
'P'
)
{
return
0
;
}
else
if
(
command
==
'A'
)
{
ret
=
nft_rule_eb_xlate_add
(
h
,
&
p
,
&
cs
,
true
);
if
(
!
ret
)
print_ebt_cmd
(
argc
,
argv
);
}
else
if
(
command
==
'I'
)
{
ret
=
nft_rule_eb_xlate_add
(
h
,
&
p
,
&
cs
,
false
);
if
(
!
ret
)
print_ebt_cmd
(
argc
,
argv
);
}
ebt_cs_clean
(
&
cs
);
return
ret
;
}
static
int
dummy_compat_rev
(
const
char
*
name
,
uint8_t
rev
,
int
opt
)
{
return
1
;
}
int
xtables_eb_xlate_main
(
int
argc
,
char
*
argv
[])
{
int
ret
;
char
*
table
=
"filter"
;
struct
nft_handle
h
;
nft_init_eb
(
&
h
,
argv
[
0
]);
ebtables_globals
.
compat_rev
=
dummy_compat_rev
;
ret
=
do_commandeb_xlate
(
&
h
,
argc
,
argv
,
&
table
);
if
(
!
ret
)
fprintf
(
stderr
,
"Translation not implemented
\n
"
);
exit
(
!
ret
);
}
iptables/xtables-eb.c
View file @
dab1e98e
...
...
@@ -37,7 +37,6 @@
#include <linux/netfilter_bridge.h>
#include <linux/netfilter/nf_tables.h>
#include <ebtables/ethernetdb.h>
#include <libiptc/libxtc.h>
#include "xshared.h"
#include "nft.h"
...
...
@@ -46,9 +45,6 @@
/*
* From include/ebtables_u.h
*/
#define EXEC_STYLE_PRG 0
#define EXEC_STYLE_DAEMON 1
#define ebt_check_option2(flags, mask) EBT_CHECK_OPTION(flags, mask)
/*
...
...
@@ -168,7 +164,7 @@ static int
append_entry
(
struct
nft_handle
*
h
,
const
char
*
chain
,
const
char
*
table
,
struct
eb
tables_command_state
*
cs
,
struct
ip
tables_command_state
*
cs
,
int
rule_nr
,
bool
verbose
,
bool
append
)
{
...
...
@@ -186,7 +182,7 @@ static int
delete_entry
(
struct
nft_handle
*
h
,
const
char
*
chain
,
const
char
*
table
,
struct
eb
tables_command_state
*
cs
,
struct
ip
tables_command_state
*
cs
,
int
rule_nr
,
int
rule_nr_end
,
bool
verbose
)
...
...
@@ -206,8 +202,11 @@ delete_entry(struct nft_handle *h,
return
ret
;
}
static
int
get_current_chain
(
const
char
*
chain
)
int
ebt_
get_current_chain
(
const
char
*
chain
)
{
if
(
!
chain
)
return
-
1
;
if
(
strcmp
(
chain
,
"PREROUTING"
)
==
0
)
return
NF_BR_PRE_ROUTING
;
else
if
(
strcmp
(
chain
,
"INPUT"
)
==
0
)
...
...
@@ -247,7 +246,7 @@ static int get_current_chain(const char *chain)
/* Default command line options. Do not mess around with the already
* assigned numbers unless you know what you are doing */
static
struct
option
ebt_original_options
[]
=
struct
option
ebt_original_options
[]
=
{
{
"append"
,
required_argument
,
0
,
'A'
},
{
"insert"
,
required_argument
,
0
,
'I'
},
...
...
@@ -380,32 +379,22 @@ static struct option *merge_options(struct option *oldopts,
/*
* More glue code.
*/
static
struct
xtables_target
*
command_jump
(
struct
ebtables_command_state
*
cs
,
const
char
*
jumpto
)
struct
xtables_target
*
ebt_command_jump
(
const
char
*
jumpto
)
{
struct
xtables_target
*
target
;
size_t
size
;
/* XTF_TRY_LOAD (may be chain name) */
target
=
xtables_find_target
(
jumpto
,
XTF_TRY_LOAD
);
unsigned
int
verdict
;
if
(
!
target
)
return
NULL
;
/* Standard target? */
if
(
!
ebt_fill_target
(
jumpto
,
&
verdict
))
jumpto
=
"standard"
;
size
=
XT_ALIGN
(
sizeof
(
struct
xt_entry_target
))
+
target
->
size
;
target
->
t
=
xtables_calloc
(
1
,
size
);
target
->
t
->
u
.
target_size
=
size
;
strncpy
(
target
->
t
->
u
.
user
.
name
,
jumpto
,
sizeof
(
target
->
t
->
u
.
user
.
name
));
target
->
t
->
u
.
user
.
name
[
sizeof
(
target
->
t
->
u
.
user
.
name
)
-
1
]
=
'\0'
;
target
->
t
->
u
.
user
.
revision
=
target
->
revision
;
xs_init_target
(
target
);
opts
=
merge_options
(
opts
,
target
->
extra_opts
,
&
target
->
option_offset
);
if
(
opts
==
NULL
)
xtables_error
(
OTHER_PROBLEM
,
"Can't alloc memory"
);
/* For ebtables, all targets are preloaded. Hence it is either in
* xtables_targets or a custom chain to jump to, in which case
* returning NULL is fine. */
for
(
target
=
xtables_targets
;
target
;
target
=
target
->
next
)
{
if
(
!
strcmp
(
target
->
name
,
jumpto
))
break
;
}
return
target
;
}
...
...
@@ -524,13 +513,12 @@ static int parse_rule_range(const char *argv, int *rule_nr, int *rule_nr_end)
/* Incrementing or decrementing rules in daemon mode is not supported as the
* involved code overload is not worth it (too annoying to take the increased
* counters in the kernel into account). */
static
int
parse_change_counters_rule
(
int
argc
,
char
**
argv
,
int
*
rule_nr
,
int
*
rule_nr_end
,
int
exec_style
,
struct
eb
tables_command_state
*
cs
)
static
int
parse_change_counters_rule
(
int
argc
,
char
**
argv
,
int
*
rule_nr
,
int
*
rule_nr_end
,
struct
ip
tables_command_state
*
cs
)
{
char
*
buffer
;
int
ret
=
0
;
if
(
optind
+
1
>=
argc
||
(
argv
[
optind
][
0
]
==
'-'
&&
(
argv
[
optind
][
1
]
<
'0'
||
argv
[
optind
][
1
]
>
'9'
))
||
(
argv
[
optind
+
1
][
0
]
==
'-'
&&
(
argv
[
optind
+
1
][
1
]
<
'0'
&&
argv
[
optind
+
1
][
1
]
>
'9'
)))
if
(
optind
+
1
>=
argc
||
argv
[
optind
][
0
]
==
'-'
||
argv
[
optind
+
1
][
0
]
==
'-'
)
xtables_error
(
PARAMETER_PROBLEM
,
"The command -C needs at least 2 arguments"
);
if
(
optind
+
2
<
argc
&&
(
argv
[
optind
+
2
][
0
]
!=
'-'
||
(
argv
[
optind
+
2
][
1
]
>=
'0'
&&
argv
[
optind
+
2
][
1
]
<=
'9'
)))
{
...
...
@@ -544,17 +532,9 @@ static int parse_change_counters_rule(int argc, char **argv, int *rule_nr, int *
}
if
(
argv
[
optind
][
0
]
==
'+'
)
{
if
(
exec_style
==
EXEC_STYLE_DAEMON
)
daemon_incr:
xtables_error
(
PARAMETER_PROBLEM
,
"Incrementing rule counters (%s) not allowed in daemon mode"
,
argv
[
optind
]);
ret
+=
1
;
cs
->
counters
.
pcnt
=
strtoull
(
argv
[
optind
]
+
1
,
&
buffer
,
10
);
}
else
if
(
argv
[
optind
][
0
]
==
'-'
)
{
if
(
exec_style
==
EXEC_STYLE_DAEMON
)
daemon_decr:
xtables_error
(
PARAMETER_PROBLEM
,
"Decrementing rule counters (%s) not allowed in daemon mode"
,
argv
[
optind
]);
ret
+=
2
;
cs
->
counters
.
pcnt
=
strtoull
(
argv
[
optind
]
+
1
,
&
buffer
,
10
);
}
else
...
...
@@ -564,13 +544,9 @@ daemon_decr:
goto
invalid
;
optind
++
;
if
(
argv
[
optind
][
0
]
==
'+'
)
{
if
(
exec_style
==
EXEC_STYLE_DAEMON
)
goto
daemon_incr
;
ret
+=
3
;
cs
->
counters
.
bcnt
=
strtoull
(
argv
[
optind
]
+
1
,
&
buffer
,
10
);
}
else
if
(
argv
[
optind
][
0
]
==
'-'
)
{
if
(
exec_style
==
EXEC_STYLE_DAEMON
)
goto
daemon_decr
;
ret
+=
6
;
cs
->
counters
.
bcnt
=
strtoull
(
argv
[
optind
]
+
1
,
&
buffer
,
10
);
}
else
...
...
@@ -584,19 +560,18 @@ invalid:
xtables_error
(
PARAMETER_PROBLEM
,
"Packet counter '%s' invalid"
,
argv
[
optind
]);
}
static
int
parse_iface
(
c
har
*
iface
,
char
*
option
)
static
void
ebtables_
parse_i
nter
face
(
c
onst
char
*
arg
,
char
*
vianame
)
{
unsigned
char
mask
[
IFNAMSIZ
];
char
*
c
;
if
((
c
=
strchr
(
iface
,
'+'
)))
{
if
(
*
(
c
+
1
)
!=
'\0'
)
{
xtables_parse_interface
(
arg
,
vianame
,
mask
);
if
((
c
=
strchr
(
vianame
,
'+'
)))
{
if
(
*
(
c
+
1
)
!=
'\0'
)
xtables_error
(
PARAMETER_PROBLEM
,
"Spurious characters after '+' wildcard for '%s'"
,
option
);
return
-
1
;
}
else
*
c
=
IF_WILDCARD
;
"Spurious characters after '+' wildcard"
);
}
return
0
;
}
/* This code is very similar to iptables/xtables.c:command_match() */
...
...
@@ -605,9 +580,11 @@ static void ebt_load_match(const char *name)
struct
xtables_match
*
m
;
size_t
size
;
m
=
xtables_find_match
(
name
,
XTF_LOAD_MUST_SUCCEED
,
NULL
);
if
(
m
==
NULL
)
xtables_error
(
OTHER_PROBLEM
,
"Unable to load %s match"
,
name
);
m
=
xtables_find_match
(
name
,
XTF_TRY_LOAD
,
NULL
);
if
(
m
==
NULL
)
{
fprintf
(
stderr
,
"Unable to load %s match
\n
"
,
name
);
return
;
}
size
=
XT_ALIGN
(
sizeof
(
struct
xt_entry_match
))
+
m
->
size
;
m
->
m
=
xtables_calloc
(
1
,
size
);
...
...
@@ -621,22 +598,23 @@ static void ebt_load_match(const char *name)
xtables_error
(
OTHER_PROBLEM
,
"Can't alloc memory"
);
}
static
void
ebt_load_watcher
(
const
char
*
name
)
static
void
__
ebt_load_watcher
(
const
char
*
name
,
const
char
*
typename
)
{
struct
xtables_target
*
watcher
;
size_t
size
;
watcher
=
xtables_find_target
(
name
,
XTF_LOAD_MUST_SUCCEED
);
if
(
!
watcher
)
xtables_error
(
OTHER_PROBLEM
,
"Unable to load %s watcher"
,
name
);
watcher
=
xtables_find_target
(
name
,
XTF_TRY_LOAD
);
if
(
!
watcher
)
{
fprintf
(
stderr
,
"Unable to load %s %s
\n
"
,
name
,
typename
);
return
;
}
size
=
XT_ALIGN
(
sizeof
(
struct
xt_entry_target
))
+
watcher
->
size
;
watcher
->
t
=
xtables_calloc
(
1
,
size
);
watcher
->
t
->
u
.
target_size
=
size
;
s
trncpy
(
watcher
->
t
->
u
.
user
.
name
,
name
,
sizeof
(
watcher
->
t
->
u
.
user
.
name
));
s
nprintf
(
watcher
->
t
->
u
.
user
.
name
,
sizeof
(
watcher
->
t
->
u
.
user
.
name
)
,
"%s"
,
name
);
watcher
->
t
->
u
.
user
.
name
[
sizeof
(
watcher
->
t
->
u
.
user
.
name
)
-
1
]
=
'\0'
;
watcher
->
t
->
u
.
user
.
revision
=
watcher
->
revision
;
...
...
@@ -648,39 +626,60 @@ static void ebt_load_watcher(const char *name)
xtables_error
(
OTHER_PROBLEM
,
"Can't alloc memory"
);
}
static
void
ebt_load_match_extensions
(
void
)
static
void
ebt_load_watcher
(
const
char
*
name
)
{
return
__ebt_load_watcher
(
name
,
"watcher"
);
}
static
void
ebt_load_target
(
const
char
*
name
)
{
return
__ebt_load_watcher
(
name
,
"target"
);
}
void
ebt_load_match_extensions
(
void
)
{
opts
=
ebt_original_options
;
ebt_load_match
(
"802_3"
);
ebt_load_match
(
"arp"
);
ebt_load_match
(
"ip"
);
ebt_load_match
(
"ip6"
);
ebt_load_match
(
"mark_m"
);
ebt_load_match
(
"limit"
);
ebt_load_match
(
"pkttype"
);
ebt_load_match
(
"vlan"
);
ebt_load_match
(
"stp"
);
ebt_load_watcher
(
"log"
);
ebt_load_watcher
(
"nflog"
);
ebt_load_target
(
"mark"
);
ebt_load_target
(
"dnat"
);
ebt_load_target
(
"snat"
);
ebt_load_target
(
"redirect"
);
ebt_load_target
(
"standard"
);
}
static
void
ebt_add_match
(
struct
xtables_match
*
m
,
struct
eb
tables_command_state
*
cs
)
void
ebt_add_match
(
struct
xtables_match
*
m
,
struct
ip
tables_command_state
*
cs
)
{
struct
xtables_rule_match
*
i
,
**
rule_matches
=
&
cs
->
matches
;
struct
xtables_rule_match
**
rule_matches
=
&
cs
->
matches
;
struct
xtables_match
*
newm
;
struct
ebt_match
*
newnode
;
/* match already in rule_matches, skip inclusion */
for
(
i
=
*
rule_matches
;
i
;
i
=
i
->
next
)
{
if
(
strcmp
(
m
->
name
,
i
->
match
->
name
)
==
0
)
{
i
->
match
->
mflags
|=
m
->
mflags
;
return
;
}
}
struct
ebt_match
*
newnode
,
**
matchp
;
struct
xt_entry_match
*
m2
;
newm
=
xtables_find_match
(
m
->
name
,
XTF_LOAD_MUST_SUCCEED
,
rule_matches
);
if
(
newm
==
NULL
)
xtables_error
(
OTHER_PROBLEM
,
"Unable to add match %s"
,
m
->
name
);
m2
=
xtables_calloc
(
1
,
newm
->
m
->
u
.
match_size
);
memcpy
(
m2
,
newm
->
m
,
newm
->
m
->
u
.
match_size
);
memset
(
newm
->
m
->
data
,
0
,
newm
->
size
);
xs_init_match
(
newm
);
newm
->
m
=
m2
;
newm
->
mflags
=
m
->
mflags
;
m
->
mflags
=
0
;
/* glue code for watchers */
newnode
=
calloc
(
1
,
sizeof
(
struct
ebt_match
));
...
...
@@ -690,88 +689,152 @@ static void ebt_add_match(struct xtables_match *m,
newnode
->
ismatch
=
true
;
newnode
->
u
.
match
=
newm
;
if
(
cs
->
match_list
==
NULL
)
cs
->
match_list
=
newnode
;
else
cs
->
match_list
->
next
=
newnode
;
for
(
matchp
=
&
cs
->
match_list
;
*
matchp
;
matchp
=
&
(
*
matchp
)
->
next
)
;
*
matchp
=
newnode
;
}
static
void
ebt_add_watcher
(
struct
xtables_target
*
watcher
,
struct
eb
tables_command_state
*
cs
)
void
ebt_add_watcher
(
struct
xtables_target
*
watcher
,
struct
ip
tables_command_state
*
cs
)
{
struct
ebt_match
*
i
,
*
newnode
;
struct
ebt_match
*
newnode
,
**
matchp
;
struct
xtables_target
*
clone
;
clone
=
xtables_malloc
(
sizeof
(
struct
xtables_target
));
memcpy
(
clone
,
watcher
,
sizeof
(
struct
xtables_target
));
clone
->
udata
=
NULL
;
clone
->
tflags
=
watcher
->
tflags
;
clone
->
next
=
clone
;
clone
->
t
=
xtables_calloc
(
1
,
watcher
->
t
->
u
.
target_size
);
memcpy
(
clone
->
t
,
watcher
->
t
,
watcher
->
t
->
u
.
target_size
);
memset
(
watcher
->
t
->
data
,
0
,
watcher
->
size
);
xs_init_target
(
watcher
);
watcher
->
tflags
=
0
;
for
(
i
=
cs
->
match_list
;
i
;
i
=
i
->
next
)
{
if
(
i
->
ismatch
)
continue
;
if
(
strcmp
(
i
->
u
.
watcher
->
name
,
watcher
->
name
)
==
0
)
{
i
->
u
.
watcher
->
tflags
|=
watcher
->
tflags
;
return
;
}
}
newnode
=
calloc
(
1
,
sizeof
(
struct
ebt_match
));
if
(
newnode
==
NULL
)
xtables_error
(
OTHER_PROBLEM
,
"Unable to alloc memory"
);
newnode
->
u
.
watcher
=
watcher
;
newnode
->
u
.
watcher
=
clone
;
if
(
cs
->
match_list
==
NULL
)
cs
->
match_list
=
newnode
;
else
cs
->
match_list
->
next
=
newnode
;
for
(
matchp
=
&
cs
->
match_list
;
*
matchp
;
matchp
=
&
(
*
matchp
)
->
next
)
;
*
matchp
=
newnode
;
}
/* We use exec_style instead of #ifdef's because ebtables.so is a shared object. */
int
do_commandeb
(
struct
nft_handle
*
h
,
int
argc
,
char
*
argv
[],
char
**
table
)
int
ebt_command_default
(
struct
iptables_command_state
*
cs
)
{
char
*
buffer
;
int
c
,
i
;
int
zerochain
=
-
1
;
/* Needed for the -Z option (we can have -Z <this> -L <that>) */
int
chcounter
=
0
;
/* Needed for -C */
int
rule_nr
=
0
;
int
rule_nr_end
=
0
;
int
ret
=
0
;
unsigned
int
flags
=
0
;
struct
xtables_target
*
t
,
*
w
;
struct
xtables_target
*
t
=
cs
->
target
;
struct
xtables_match
*
m
;
struct
ebtables_command_state
cs
;
char
command
=
'h'
;
const
char
*
chain
=
NULL
;
const
char
*
policy
=
NULL
;
int
exec_style
=
EXEC_STYLE_PRG
;
int
selected_chain
=
-
1
;
struct
xtables_rule_match
*
xtrm_i
;
struct
ebt_match
*
match
;
struct
ebt_match
*
matchp
;
/* Is it a target option? */
if
(
t
&&
t
->
parse
)
{
if
(
t
->
parse
(
cs
->
c
-
t
->
option_offset
,
cs
->
argv
,
ebt_invert
,
&
t
->
tflags
,
NULL
,
&
t
->
t
))
return
0
;
}
/* check previously added matches/watchers to this rule first */
for
(
matchp
=
cs
->
match_list
;
matchp
;
matchp
=
matchp
->
next
)
{
if
(
matchp
->
ismatch
)
{
m
=
matchp
->
u
.
match
;
if
(
m
->
parse
&&
m
->
parse
(
cs
->
c
-
m
->
option_offset
,
cs
->
argv
,
ebt_invert
,
&
m
->
mflags
,
NULL
,
&
m
->
m
))
return
0
;
}
else
{
t
=
matchp
->
u
.
watcher
;
if
(
t
->
parse
&&
t
->
parse
(
cs
->
c
-
t
->
option_offset
,
cs
->
argv
,
ebt_invert
,
&
t
->
tflags
,
NULL
,
&
t
->
t
))
return
0
;
}
}
/* Is it a match_option? */
for
(
m
=
xtables_matches
;
m
;
m
=
m
->
next
)
{
if
(
m
->
parse
&&
m
->
parse
(
cs
->
c
-
m
->
option_offset
,
cs
->
argv
,
ebt_invert
,
&
m
->
mflags
,
NULL
,
&
m
->
m
))
{
ebt_add_match
(
m
,
cs
);
return
0
;
}
}
/* Is it a watcher option? */
for
(
t
=
xtables_targets
;
t
;
t
=
t
->
next
)
{
if
(
t
->
parse
&&
t
->
parse
(
cs
->
c
-
t
->
option_offset
,
cs
->
argv
,
ebt_invert
,
&
t
->
tflags
,
NULL
,
&
t
->
t
))
{
ebt_add_watcher
(
t
,
cs
);
return
0
;
}
}
return
1
;
}
memset
(
&
cs
,
0
,
sizeof
(
cs
));
cs
.
argv
=
argv
;
int
nft_init_eb
(
struct
nft_handle
*
h
,
const
char
*
pname
)
{
ebtables_globals
.
program_name
=
pname
;
if
(
xtables_init_all
(
&
ebtables_globals
,
NFPROTO_BRIDGE
)
<
0
)
{
fprintf
(
stderr
,
"%s/%s Failed to initialize ebtables-compat
\n
"
,
ebtables_globals
.
program_name
,
ebtables_globals
.
program_version
);
exit
(
1
);
}
#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
init_extensionsb
();
#endif
memset
(
h
,
0
,
sizeof
(
*
h
));
h
->
family
=
NFPROTO_BRIDGE
;
if
(
nft_init
(
h
,
xtables_bridge
)
<
0
)
xtables_error
(
OTHER_PROBLEM
,
"Could not initialize nftables layer."
);
h
->
ops
=
nft_family_ops_lookup
(
h
->
family
);
if
(
h
->
ops
==
NULL
)
if
(
!
h
->
ops
)
xtables_error
(
PARAMETER_PROBLEM
,
"Unknown family"
);
/* manually registering ebt matches, given the original ebtables parser
* don't use '-m matchname' and the match can't loaded d
i
namically when
* don't use '-m matchname' and the match can't
be
loaded d
y
namically when
* the user calls it.
*/
ebt_load_match_extensions
();
/* clear mflags in case do_commandeb gets called a second time
* (we clear the global list of all matches for security)*/
for
(
m
=
xtables_matches
;
m
;
m
=
m
->
next
)
m
->
mflags
=
0
;
return
0
;
}
for
(
t
=
xtables_targets
;
t
;
t
=
t
->
next
)
{
t
->
tflags
=
0
;
t
->
used
=
0
;
}
int
do_commandeb
(
struct
nft_handle
*
h
,
int
argc
,
char
*
argv
[],
char
**
table
,
bool
restore
)
{
char
*
buffer
;
int
c
,
i
;
int
chcounter
=
0
;
/* Needed for -C */
int
rule_nr
=
0
;
int
rule_nr_end
=
0
;
int
ret
=
0
;
unsigned
int
flags
=
0
;
struct
xtables_target
*
t
;
struct
iptables_command_state
cs
=
{
.
argv
=
argv
,
.
eb
.
bitmask
=
EBT_NOPROTO
,
};
char
command
=
'h'
;
const
char
*
chain
=
NULL
;
const
char
*
policy
=
NULL
;
int
selected_chain
=
-
1
;
struct
xtables_rule_match
*
xtrm_i
;
struct
ebt_match
*
match
;
/* prevent getopt to spoil our error reporting */
optind
=
0
;
opterr
=
false
;
/* Getopt saves the day */
...
...
@@ -801,18 +864,22 @@ int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table)
"Multiple commands are not allowed"
);
command
=
c
;
if
(
optarg
&&
(
optarg
[
0
]
==
'-'
||
!
strcmp
(
optarg
,
"!"
)))
xtables_error
(
PARAMETER_PROBLEM
,
"No chain name specified"
);
chain
=
optarg
;
selected_chain
=
get_current_chain
(
chain
);
selected_chain
=
ebt_
get_current_chain
(
chain
);
flags
|=
OPT_COMMAND
;
/*if (!(replace->flags & OPT_KERNELDATA))
ebt_get_kernel_table(replace, 0);*/
/*if (optarg && (optarg[0] == '-' || !strcmp(optarg, "!")))
ebt_print_error2("No chain name specified");*/
if
(
c
==
'N'
)
{
ret
=
nft_chain_user_add
(
h
,
chain
,
*
table
);
break
;
}
else
if
(
c
==
'X'
)
{
ret
=
nft_chain_user_del
(
h
,
chain
,
*
table
);
/* X arg is optional, optarg is NULL */
if
(
!
chain
&&
optind
<
argc
&&
argv
[
optind
][
0
]
!=
'-'
)
{
chain
=
argv
[
optind
];
optind
++
;
}
ret
=
nft_chain_user_del
(
h
,
chain
,
*
table
,
0
);
break
;
}
...
...
@@ -842,7 +909,7 @@ int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table)
"Problem with the specified rule number(s) '%s'"
,
argv
[
optind
]);
optind
++
;
}
else
if
(
c
==
'C'
)
{
if
((
chcounter
=
parse_change_counters_rule
(
argc
,
argv
,
&
rule_nr
,
&
rule_nr_end
,
exec_style
,
&
cs
))
==
-
1
)
if
((
chcounter
=
parse_change_counters_rule
(
argc
,
argv
,
&
rule_nr
,
&
rule_nr_end
,
&
cs
))
==
-
1
)
return
-
1
;
}
else
if
(
c
==
'I'
)
{
if
(
optind
>=
argc
||
(
argv
[
optind
][
0
]
==
'-'
&&
(
argv
[
optind
][
1
]
<
'0'
||
argv
[
optind
][
1
]
>
'9'
)))
...
...
@@ -890,43 +957,18 @@ print_zero:
goto
print_zero
;
}
#ifdef SILENT_DAEMON
if
(
c
==
'L'
&&
exec_style
==
EXEC_STYLE_DAEMON
)
xtables_error
(
PARAMETER_PROBLEM
,
"-L not supported in daemon mode"
);
#endif
/*if (!(replace->flags & OPT_KERNELDATA))
ebt_get_kernel_table(replace, 0);
i = -1;
if
(
optind
<
argc
&&
argv
[
optind
][
0
]
!=
'-'
)
{
if ((i = ebt_get_chainnr(replace, argv[optind])) == -1)
ebt_print_error2("Chain '%s' doesn't exist", argv[optind]);
chain
=
argv
[
optind
];
optind
++
;
}
if (i != -1) {
if (c == 'Z')
zerochain = i;
else
replace->selected_chain = i;
}*/
break
;
case
'V'
:
/* Version */
if
(
OPT_COMMANDS
)
xtables_error
(
PARAMETER_PROBLEM
,
"Multiple commands are not allowed"
);
command
=
'V'
;
if
(
exec_style
==
EXEC_STYLE_DAEMON
)
xtables_error
(
PARAMETER_PROBLEM
,
"%s %s
\n
"
,
prog_name
,
prog_vers
);
printf
(
"%s %s
\n
"
,
prog_name
,
prog_vers
);
printf
(
"%s %s (nf_tables)
\n
"
,
prog_name
,
prog_vers
);
exit
(
0
);
case
'h'
:
/* Help */
#ifdef SILENT_DAEMON
if
(
exec_style
==
EXEC_STYLE_DAEMON
)
xtables_error
(
PARAMETER_PROBLEM
,
"-h not supported in daemon mode"
);
#endif
if
(
OPT_COMMANDS
)
xtables_error
(
PARAMETER_PROBLEM
,
"Multiple commands are not allowed"
);
...
...
@@ -988,14 +1030,9 @@ print_zero:
xtables_error
(
PARAMETER_PROBLEM
,
"Use -i only in INPUT, FORWARD, PREROUTING and BROUTING chains"
);
if
(
ebt_check_inverse2
(
optarg
,
argc
,
argv
))
cs
.
fw
.
invflags
|=
EBT_IIN
;
cs
.
eb
.
invflags
|=
EBT_IIN
;
if
(
strlen
(
optarg
)
>=
IFNAMSIZ
)
big_iface_length:
xtables_error
(
PARAMETER_PROBLEM
,
"Interface name length cannot exceed %d characters"
,
IFNAMSIZ
-
1
);
xtables_parse_interface
(
optarg
,
cs
.
fw
.
in
,
cs
.
fw
.
in_mask
);
ebtables_parse_interface
(
optarg
,
cs
.
eb
.
in
);
break
;
}
else
if
(
c
==
2
)
{
ebt_check_option2
(
&
flags
,
OPT_LOGICALIN
);
...
...
@@ -1003,13 +1040,9 @@ big_iface_length:
xtables_error
(
PARAMETER_PROBLEM
,
"Use --logical-in only in INPUT, FORWARD, PREROUTING and BROUTING chains"
);
if
(
ebt_check_inverse2
(
optarg
,
argc
,
argv
))
cs
.
fw
.
invflags
|=
EBT_ILOGICALIN
;
cs
.
eb
.
invflags
|=
EBT_ILOGICALIN
;
if
(
strlen
(
optarg
)
>=
IFNAMSIZ
)
goto
big_iface_length
;
strcpy
(
cs
.
fw
.
logical_in
,
optarg
);
if
(
parse_iface
(
cs
.
fw
.
logical_in
,
"--logical-in"
))
return
-
1
;
ebtables_parse_interface
(
optarg
,
cs
.
eb
.
logical_in
);
break
;
}
else
if
(
c
==
'o'
)
{
ebt_check_option2
(
&
flags
,
OPT_OUT
);
...
...
@@ -1017,12 +1050,9 @@ big_iface_length:
xtables_error
(
PARAMETER_PROBLEM
,
"Use -o only in OUTPUT, FORWARD and POSTROUTING chains"
);
if
(
ebt_check_inverse2
(
optarg
,
argc
,
argv
))
cs
.
fw
.
invflags
|=
EBT_IOUT
;
if
(
strlen
(
optarg
)
>=
IFNAMSIZ
)
goto
big_iface_length
;
cs
.
eb
.
invflags
|=
EBT_IOUT
;
x
tables_parse_interface
(
optarg
,
cs
.
fw
.
out
,
cs
.
fw
.
out_mask
);
eb
tables_parse_interface
(
optarg
,
cs
.
eb
.
out
);
break
;
}
else
if
(
c
==
3
)
{
ebt_check_option2
(
&
flags
,
OPT_LOGICALOUT
);
...
...
@@ -1030,36 +1060,32 @@ big_iface_length:
xtables_error
(
PARAMETER_PROBLEM
,
"Use --logical-out only in OUTPUT, FORWARD and POSTROUTING chains"
);
if
(
ebt_check_inverse2
(
optarg
,
argc
,
argv
))
cs
.
fw
.
invflags
|=
EBT_ILOGICALOUT
;
cs
.
eb
.
invflags
|=
EBT_ILOGICALOUT
;
if
(
strlen
(
optarg
)
>=
IFNAMSIZ
)
goto
big_iface_length
;
strcpy
(
cs
.
fw
.
logical_out
,
optarg
);
if
(
parse_iface
(
cs
.
fw
.
logical_out
,
"--logical-out"
))
return
-
1
;
ebtables_parse_interface
(
optarg
,
cs
.
eb
.
logical_out
);
break
;
}
else
if
(
c
==
'j'
)
{
ebt_check_option2
(
&
flags
,
OPT_JUMP
);
cs
.
jumpto
=
parse_target
(
optarg
);
cs
.
target
=
command_jump
(
&
cs
,
cs
.
jumpto
);
cs
.
target
=
ebt_
command_jump
(
cs
.
jumpto
);
break
;
}
else
if
(
c
==
's'
)
{
ebt_check_option2
(
&
flags
,
OPT_SOURCE
);
if
(
ebt_check_inverse2
(
optarg
,
argc
,
argv
))
cs
.
fw
.
invflags
|=
EBT_ISOURCE
;
cs
.
eb
.
invflags
|=
EBT_ISOURCE
;
if
(
ebt_get_mac_and_mask
(
optarg
,
cs
.
fw
.
sourcemac
,
cs
.
fw
.
sourcemsk
))
if
(
ebt_get_mac_and_mask
(
optarg
,
cs
.
eb
.
sourcemac
,
cs
.
eb
.
sourcemsk
))
xtables_error
(
PARAMETER_PROBLEM
,
"Problem with specified source mac '%s'"
,
optarg
);
cs
.
fw
.
bitmask
|=
EBT_SOURCEMAC
;
cs
.
eb
.
bitmask
|=
EBT_SOURCEMAC
;
break
;
}
else
if
(
c
==
'd'
)
{
ebt_check_option2
(
&
flags
,
OPT_DEST
);
if
(
ebt_check_inverse2
(
optarg
,
argc
,
argv
))
cs
.
fw
.
invflags
|=
EBT_IDEST
;
cs
.
eb
.
invflags
|=
EBT_IDEST
;
if
(
ebt_get_mac_and_mask
(
optarg
,
cs
.
fw
.
destmac
,
cs
.
fw
.
destmsk
))
if
(
ebt_get_mac_and_mask
(
optarg
,
cs
.
eb
.
destmac
,
cs
.
eb
.
destmsk
))
xtables_error
(
PARAMETER_PROBLEM
,
"Problem with specified destination mac '%s'"
,
optarg
);
cs
.
fw
.
bitmask
|=
EBT_DESTMAC
;
cs
.
eb
.
bitmask
|=
EBT_DESTMAC
;
break
;
}
else
if
(
c
==
'c'
)
{
ebt_check_option2
(
&
flags
,
OPT_COUNT
);
...
...
@@ -1085,38 +1111,33 @@ big_iface_length:
}
ebt_check_option2
(
&
flags
,
OPT_PROTOCOL
);
if
(
ebt_check_inverse2
(
optarg
,
argc
,
argv
))
cs
.
fw
.
invflags
|=
EBT_IPROTO
;
cs
.
eb
.
invflags
|=
EBT_IPROTO
;
cs
.
fw
.
bitmask
&=
~
((
unsigned
int
)
EBT_NOPROTO
);
cs
.
eb
.
bitmask
&=
~
((
unsigned
int
)
EBT_NOPROTO
);
i
=
strtol
(
optarg
,
&
buffer
,
16
);
if
(
*
buffer
==
'\0'
&&
(
i
<
0
||
i
>
0xFFFF
))
xtables_error
(
PARAMETER_PROBLEM
,
"Problem with the specified protocol"
);
if
(
*
buffer
!=
'\0'
)
{
struct
ethertypeent
*
ent
;
struct
xt_
ethertypeent
*
ent
;
if
(
!
strcasecmp
(
optarg
,
"LENGTH"
))
{
cs
.
fw
.
bitmask
|=
EBT_802_3
;
cs
.
eb
.
bitmask
|=
EBT_802_3
;
break
;
}
ent
=
getethertypebyname
(
optarg
);
ent
=
xtables_
getethertypebyname
(
optarg
);
if
(
!
ent
)
xtables_error
(
PARAMETER_PROBLEM
,
"Problem with the specified Ethernet protocol '%s', perhaps "
_PATH_ETHERTYPES
" is missing"
,
optarg
);
cs
.
fw
.
ethproto
=
ent
->
e_ethertype
;
"Problem with the specified Ethernet protocol '%s', perhaps "
XT
_PATH_ETHERTYPES
" is missing"
,
optarg
);
cs
.
eb
.
ethproto
=
ent
->
e_ethertype
;
}
else
cs
.
fw
.
ethproto
=
i
;
cs
.
eb
.
ethproto
=
i
;
if
(
cs
.
fw
.
ethproto
<
0x0600
)
if
(
cs
.
eb
.
ethproto
<
0x0600
)
xtables_error
(
PARAMETER_PROBLEM
,
"Sorry, protocols have values above or equal to 0x0600"
);
break
;
case
4
:
/* Lc */
#ifdef SILENT_DAEMON
if
(
exec_style
==
EXEC_STYLE_DAEMON
)
xtables_error
(
PARAMETER_PROBLEM
,
"--Lc is not supported in daemon mode"
);
#endif
ebt_check_option2
(
&
flags
,
LIST_C
);
if
(
command
!=
'L'
)
xtables_error
(
PARAMETER_PROBLEM
,
...
...
@@ -1124,11 +1145,6 @@ big_iface_length:
flags
|=
LIST_C
;
break
;
case
5
:
/* Ln */
#ifdef SILENT_DAEMON
if
(
exec_style
==
EXEC_STYLE_DAEMON
)
xtables_error
(
PARAMETER_PROBLEM
,
"--Ln is not supported in daemon mode"
);
#endif
ebt_check_option2
(
&
flags
,
LIST_N
);
if
(
command
!=
'L'
)
xtables_error
(
PARAMETER_PROBLEM
,
...
...
@@ -1139,11 +1155,6 @@ big_iface_length:
flags
|=
LIST_N
;
break
;
case
6
:
/* Lx */
#ifdef SILENT_DAEMON
if
(
exec_style
==
EXEC_STYLE_DAEMON
)
xtables_error
(
PARAMETER_PROBLEM
,
"--Lx is not supported in daemon mode"
);
#endif
ebt_check_option2
(
&
flags
,
LIST_X
);
if
(
command
!=
'L'
)
xtables_error
(
PARAMETER_PROBLEM
,
...
...
@@ -1154,11 +1165,6 @@ big_iface_length:
flags
|=
LIST_X
;
break
;
case
12
:
/* Lmac2 */
#ifdef SILENT_DAEMON
if
(
exec_style
==
EXEC_STYLE_DAEMON
)
xtables_error
(
PARAMETER_PROBLEM
,
"--Lmac2 is not supported in daemon mode"
);
#endif
ebt_check_option2
(
&
flags
,
LIST_MAC2
);
if
(
command
!=
'L'
)
xtables_error
(
PARAMETER_PROBLEM
,
...
...
@@ -1166,8 +1172,7 @@ big_iface_length:
flags
|=
LIST_MAC2
;
break
;
case
8
:
/* atomic-commit */
/* if (exec_style == EXEC_STYLE_DAEMON)
ebt_print_error2("--atomic-commit is not supported in daemon mode");
/*
replace->command = c;
if (OPT_COMMANDS)
ebt_print_error2("Multiple commands are not allowed");
...
...
@@ -1186,14 +1191,10 @@ big_iface_length:
break;*/
/*case 7 :*/
/* atomic-init */
/*case 10:*/
/* atomic-save */
/*case 11:*/
/* init-table */
/* if (exec_style == EXEC_STYLE_DAEMON) {
if (c == 7) {
ebt_print_error2("--atomic-init is not supported in daemon mode");
} else if (c == 10)
ebt_print_error2("--atomic-save is not supported in daemon mode");
ebt_print_error2("--init-table is not supported in daemon mode");
}
case
11
:
/* init-table */
nft_table_flush
(
h
,
*
table
);
return
1
;
/*
replace->command = c;
if (OPT_COMMANDS)
ebt_print_error2("Multiple commands are not allowed");
...
...
@@ -1210,20 +1211,16 @@ big_iface_length:
}
break;
case 9 :*/
/* atomic */
/*if (exec_style == EXEC_STYLE_DAEMON)
ebt_print_error2("--atomic is not supported in daemon mode");
/*
if (OPT_COMMANDS)
ebt_print_error2("--atomic has to come before the command");*/
/* A possible memory leak here, but this is not
* executed in daemon mode */
/*replace->filename = (char *)malloc(strlen(optarg) + 1);
strcpy(replace->filename, optarg);
break; */
case
13
:
break
;
case 13 : *//* concurrent */
/*signal(SIGINT, sighandler);
signal(SIGTERM, sighandler);
use_lockfd = 1;
break;*/
case
1
:
if
(
!
strcmp
(
optarg
,
"!"
))
ebt_check_inverse2
(
optarg
,
argc
,
argv
);
...
...
@@ -1234,49 +1231,13 @@ big_iface_length:
optind
--
;
continue
;
default:
/* Is it a target option? */
if
(
cs
.
target
!=
NULL
&&
cs
.
target
->
parse
!=
NULL
)
{
int
opt_offset
=
cs
.
target
->
option_offset
;
if
(
cs
.
target
->
parse
(
c
-
opt_offset
,
argv
,
ebt_invert
,
&
cs
.
target
->
tflags
,
NULL
,
&
cs
.
target
->
t
))
goto
check_extension
;
}
ebt_check_inverse2
(
optarg
,
argc
,
argv
);
/* Is it a match_option? */
for
(
m
=
xtables_matches
;
m
;
m
=
m
->
next
)
{
if
(
m
->
parse
(
c
-
m
->
option_offset
,
argv
,
ebt_invert
,
&
m
->
mflags
,
NULL
,
&
m
->
m
))
{
ebt_add_match
(
m
,
&
cs
);
goto
check_extension
;
}
}
if
(
ebt_command_default
(
&
cs
))
xtables_error
(
PARAMETER_PROBLEM
,
"Unknown argument: '%s'"
,
argv
[
optind
-
1
]);
/* Is it a watcher option? */
for
(
w
=
xtables_targets
;
w
;
w
=
w
->
next
)
{
if
(
w
->
parse
(
c
-
w
->
option_offset
,
argv
,
ebt_invert
,
&
w
->
tflags
,
NULL
,
&
w
->
t
))
{
ebt_add_watcher
(
w
,
&
cs
);
goto
check_extension
;
}
}
/*
if (w == NULL && c == '?')
ebt_print_error2("Unknown argument: '%s'", argv[optind - 1], (char)optopt, (char)c);
else if (w == NULL) {
if (!strcmp(t->name, "standard"))
ebt_print_error2("Unknown argument: don't forget the -t option");
else
ebt_print_error2("Target-specific option does not correspond with specified target");
}
if (ebt_errormsg[0] != '\0')
return -1;
if (w->used == 0) {
ebt_add_watcher(new_entry, w);
w->used = 1;
}*/
check_extension:
if
(
command
!=
'A'
&&
command
!=
'I'
&&
command
!=
'D'
&&
command
!=
'C'
)
xtables_error
(
PARAMETER_PROBLEM
,
...
...
@@ -1294,7 +1255,6 @@ check_extension:
if
(
command
==
'h'
&&
!
(
flags
&
OPT_ZERO
))
{
print_help
(
cs
.
target
,
cs
.
matches
,
*
table
);
if
(
exec_style
==
EXEC_STYLE_PRG
)
exit
(
0
);
}
...
...
@@ -1316,7 +1276,7 @@ check_extension:
}
/* So, the extensions can work with the host endian.
* The kernel does not have to do this of course */
cs
.
fw
.
ethproto
=
htons
(
cs
.
fw
.
ethproto
);
cs
.
eb
.
ethproto
=
htons
(
cs
.
eb
.
ethproto
);
if
(
command
==
'P'
)
{
if
(
selected_chain
<
0
)
{
...
...
@@ -1333,46 +1293,29 @@ check_extension:
xtables_error
(
PARAMETER_PROBLEM
,
"Wrong policy"
);
}
else
if
(
command
==
'L'
)
{
ret
=
list_rules
(
h
,
chain
,
*
table
,
rule_nr
,
flags
&
OPT_VERBOSE
,
flags
&
OPT_NUMERIC
,
0
,
0
,
/*flags&OPT_EXPANDED*/
0
,
flags
&
LIST_N
,
flags
&
LIST_C
);
if
(
!
(
flags
&
OPT_ZERO
)
&&
exec_style
==
EXEC_STYLE_PRG
)
exit
(
0
);
}
if
(
flags
&
OPT_ZERO
)
{
selected_chain
=
zerochain
;
ret
=
nft_chain_zero_counters
(
h
,
chain
,
*
table
);
ret
=
nft_chain_zero_counters
(
h
,
chain
,
*
table
,
0
);
}
else
if
(
command
==
'F'
)
{
ret
=
nft_rule_flush
(
h
,
chain
,
*
table
);
ret
=
nft_rule_flush
(
h
,
chain
,
*
table
,
0
);
}
else
if
(
command
==
'A'
)
{
ret
=
append_entry
(
h
,
chain
,
*
table
,
&
cs
,
0
,
flags
&
OPT_VERBOSE
,
true
);
ret
=
append_entry
(
h
,
chain
,
*
table
,
&
cs
,
0
,
0
,
true
);
}
else
if
(
command
==
'I'
)
{
ret
=
append_entry
(
h
,
chain
,
*
table
,
&
cs
,
rule_nr
-
1
,
flags
&
OPT_VERBOSE
,
false
);
0
,
false
);
}
else
if
(
command
==
'D'
)
{
ret
=
delete_entry
(
h
,
chain
,
*
table
,
&
cs
,
rule_nr
-
1
,
rule_nr_end
,
flags
&
OPT_VERBOSE
);
rule_nr_end
,
0
);
}
/*else if (replace->command == 'C') {
ebt_change_counters(replace, new_entry, rule_nr, rule_nr_end, &(new_entry->cnt_surplus), chcounter);
if (ebt_errormsg[0] != '\0')
return -1;
}*/
/* Commands -N, -E, -X, --atomic-commit, --atomic-commit, --atomic-save,
* --init-table fall through */
/*if (ebt_errormsg[0] != '\0')
return -1;
if (table->check)
table->check(replace);
if (exec_style == EXEC_STYLE_PRG) {*//* Implies ebt_errormsg[0] == '\0' */
/*ebt_deliver_table(replace);
if (replace->nentries)
ebt_deliver_counters(replace);*/
ebt_cs_clean
(
&
cs
);
return
ret
;
...
...
iptables/xtables-multi.c
→
iptables/xtables-
legacy-
multi.c
View file @
dab1e98e
...
...
@@ -25,6 +25,11 @@ static const struct subcommand multi_subcommands[] = {
{
"save4"
,
iptables_save_main
},
{
"iptables-restore"
,
iptables_restore_main
},
{
"restore4"
,
iptables_restore_main
},
{
"iptables-legacy"
,
iptables_main
},
{
"iptables-legacy-save"
,
iptables_save_main
},
{
"iptables-legacy-restore"
,
iptables_restore_main
},
#endif
{
"iptables-xml"
,
iptables_xml_main
},
{
"xml"
,
iptables_xml_main
},
...
...
@@ -35,15 +40,9 @@ static const struct subcommand multi_subcommands[] = {
{
"save6"
,
ip6tables_save_main
},
{
"ip6tables-restore"
,
ip6tables_restore_main
},
{
"restore6"
,
ip6tables_restore_main
},
#endif
#ifdef ENABLE_NFTABLES
{
"xtables"
,
xtables_main
},
{
"xtables-save"
,
xtables_save_main
},
{
"xtables-restore"
,
xtables_restore_main
},
{
"xtables-config"
,
xtables_config_main
},
{
"xtables-events"
,
xtables_events_main
},
{
"xtables-arp"
,
xtables_arp_main
},
{
"xtables-ebtables"
,
xtables_eb_main
},
{
"ip6tables-legacy"
,
ip6tables_main
},
{
"ip6tables-legacy-save"
,
ip6tables_save_main
},
{
"ip6tables-legacy-restore"
,
ip6tables_restore_main
},
#endif
{
NULL
},
};
...
...
iptables/xtables-legacy.8
0 → 100644
View file @
dab1e98e
.\"
.\" (C) Copyright 2016-2017, Arturo Borrero Gonzalez <arturo@netfilter.org>
.\"
.\" %%%LICENSE_START(GPLv2+_DOC_FULL)
.\" This is free documentation; you can redistribute it and/or
.\" modify it under the terms of the GNU General Public License as
.\" published by the Free Software Foundation; either version 2 of
.\" the License, or (at your option) any later version.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual 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 General Public License for more details.
.\"
.\" You should have received a copy of the GNU General Public
.\" License along with this manual; if not, see
.\" <http://www.gnu.org/licenses/>.
.\" %%%LICENSE_END
.\"
.TH XTABLES-LEGACY 8 "June 2018"
.SH NAME
xtables-legacy \(em iptables using old getsockopt/setsockopt-based kernel api
.SH DESCRIPTION
\fBxtables-legacy\fP are the original versions of iptables that use
old getsockopt/setsockopt-based kernel interface.
This kernel interface has some limitations, therefore iptables can also
be used with the newer nf_tables based API.
See
.B xtables\-nft(8)
for information about the xtables-nft variants of iptables.
.SH USAGE
The xtables-legacy-multi binary can be linked to the traditional names:
.nf
/sbin/iptables -> /sbin/iptables\-legacy\-multi
/sbin/ip6tables -> /sbin/ip6tables\-legacy\-multi
/sbin/iptables\-save -> /sbin/ip6tables\-legacy\-multi
/sbin/iptables\-restore -> /sbin/ip6tables\-legacy\-multi
.fi
The iptables version string will indicate whether the legacy API (get/setsockopt) or
the new nf_tables API is used:
.nf
iptables \-V
iptables v1.7 (legacy)
.fi
.SH LIMITATIONS
When inserting a rule using
iptables \-A or iptables \-I, iptables first needs to retrieve the current active
ruleset, change it to include the new rule, and then commit back the result.
This means that if two instances of iptables are running concurrently, one of the
updates might be lost. This can be worked around partially with the \-\-wait option.
There is also no method to monitor changes to the ruleset, except periodically calling
iptables-legacy-save and checking for any differences in output.
.B xtables\-monitor(8)
will need the
.B xtables\-nft(8)
versions to work, it cannot display changes made using the.
.B iptables-legacy
tools.
.SH SEE ALSO
\fBxtables\-nft(8)\fP, \fBxtables\-translate(8)\fP
.SH AUTHORS
Rusty Russell originally wrote iptables, in early consultation with Michael Neuling.
iptables/xtables-monitor.8.in
0 → 100644
View file @
dab1e98e
.TH XTABLES\-MONITOR 8 "" "@PACKAGE_STRING@" "@PACKAGE_STRING@"
.SH NAME
xtables-monitor \(em show changes to rule set and trace-events
.SH SYNOPSIS
\fBxtables\-monitor\fP [\fB\-t\fP] [\fB\-e\fP] [\fB\-4\fP|\fB|\-6\fB]
.PP
\
.SH DESCRIPTION
.PP
.B xtables-monitor
is used to monitor changes to the ruleset or to show rule evaluation events
for packets tagged using the TRACE target.
.B xtables-monitor
will run until the user aborts execution, typically by using CTRL-C.
.RE
.SH OPTIONS
\fB\-e\fP, \fB\-\-event\fP
.TP
Watch for updates to the rule set.
Updates include creation of new tables, chains and rules and
the name of the program that caused the rule update.
.TP
\fB\-t\fP, \fB\-\-trace\fP
Watch for trace events generated by packets that have been tagged
using the TRACE target.
.TP
\fB\-4\fP
Restrict output to IPv4.
.TP
\fB\-6\fP
Restrict output to IPv6.
.SH EXAMPLE OUTPUT
.TP
.B xtables-monitor \-\-trace
1 TRACE: 2 fc475095 raw:PREROUTING:rule:0x3:CONTINUE \-4 \-t raw \-A PREROUTING \-p icmp \-j TRACE
2 PACKET: 0 fc475095 IN=lo LL=0x304 0000000000000000000000000800 SRC=127.0.0.1 DST=127.0.0.1 LEN=84 TOS=0x0 TTL=64 ID=38349DF
3 TRACE: 2 fc475095 raw:PREROUTING:return:
4 TRACE: 2 fc475095 raw:PREROUTING:policy:ACCEPT
5 TRACE: 2 fc475095 filter:INPUT:return:
6 TRACE: 2 fc475095 filter:INPUT:policy:DROP
7 TRACE: 2 0df9d3d8 raw:PREROUTING:rule:0x3:CONTINUE \-4 \-t raw \-A PREROUTING \-p icmp \-j TRACE
.PP
The first line shows a packet entering rule set evaluation.
The protocol number is shown (AF_INET in this case), then a packet
identifier number that allows to correlate messages coming from rule set evaluation of
this packet. After this, the rule that was matched by the packet is shown.
This is the TRACE rule that turns on tracing events for this packet.
The second line dumps information about the packet. Incoming interface
and packet headers such as source and destination addresses are shown.
The third line shows that the packet completed traversal of the raw table
PREROUTING chain, and is returning, followed by use the chain policy to make accept/drop
decision (the example shows accept being applied).
The fifth line shows that the packet leaves the filter INPUT chain, i.e., no rules in the filter tables
INPUT chain matched the packet.
It then got DROPPED by the policy of the INPUT table, as shown by line six.
The last line shows another packet arriving \-\- the packet id is different.
When using the TRACE target, it is usually a good idea to only select packets
that are relevant, for example via
.nf
iptables \-t raw \-A PREROUTING \-p tcp \-\-dport 80 \-\-syn \-m limit \-\-limit 1/s \-j TRACE
.fi
.TP
.B xtables-monitor \-\-event
1 EVENT: nft: NEW table: table filter ip flags 0 use 4 handle 444
2 EVENT: # nft: ip filter INPUT use 2 type filter hook input prio 0 policy drop packets 0 bytes 0
3 EVENT: # nft: ip filter FORWARD use 0 type filter hook forward prio 0 policy accept packets 0 bytes 0
4 EVENT: # nft: ip filter OUTPUT use 0 type filter hook output prio 0 policy accept packets 0 bytes 0
5 EVENT: \-4 \-t filter \-N TCP
6 EVENT: \-4 \-t filter \-A TCP \-s 192.168.0.0/16 \-p tcp \-m tcp \-\-dport 22 \-j ACCEPT
7 EVENT: \-4 \-t filter \-A TCP \-p tcp \-m multiport \-\-dports 80,443 \-j ACCEPT
8 EVENT: \-4 \-t filter \-A INPUT \-p tcp \-j TCP
9 EVENT: \-4 \-t filter \-A INPUT \-m conntrack \-\-ctstate RELATED,ESTABLISHED \-j ACCEPT
10 NEWGEN: GENID=13904 PID=25167 NAME=iptables-nftables-restore
.PP
This example shows event monitoring. Line one shows creation of a table (filter in this case), followed
by three base hooks INPUT, FORWARD and OUTPUT. The iptables-nftables tools all create tables and base
chains automatically when needed, so this is expected when a table was not yet initialized or when it is
re-created from scratch by iptables-nftables-restore. Line five shows a new user-defined chain (TCP)
being added, followed by addition a few rules. the last line shows that a new ruleset generation has
become active, i.e., the rule set changes are now active. This also lists the process id and the programs name.
.SH LIMITATIONS
.B xtables-monitor
only works with rules added using iptables-nftables, rules added using
iptables-legacy cannot be monitored.
.SH BUGS
Should be reported or by sending email to netfilter-devel@vger.kernel.org or
by filing a report on https://bugzilla.netfilter.org/.
.SH SEE ALSO
\fBiptables\fP(8), \fBxtables\fP(8), \fBnft\fP(8)
iptables/xtables-monitor.c
0 → 100644
View file @
dab1e98e
/*
* (C) 2012-2013 by Pablo Neira Ayuso <pablo@netfilter.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software has been sponsored by Sophos Astaro <http://www.sophos.com>
*/
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <netinet/ether.h>
#include <netinet/in.h>
#include <netinet/ip6.h>
#include <net/if_arp.h>
#include <getopt.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/nf_tables.h>
#include <libmnl/libmnl.h>
#include <libnftnl/table.h>
#include <libnftnl/trace.h>
#include <libnftnl/chain.h>
#include <libnftnl/rule.h>
#include <include/xtables.h>
#include "iptables.h"
/* for xtables_globals */
#include "xtables-multi.h"
#include "nft.h"
#include "nft-arp.h"
struct
cb_arg
{
uint32_t
nfproto
;
bool
is_event
;
};
static
int
table_cb
(
const
struct
nlmsghdr
*
nlh
,
void
*
data
)
{
uint32_t
type
=
nlh
->
nlmsg_type
&
0xFF
;
const
struct
cb_arg
*
arg
=
data
;
struct
nftnl_table
*
t
;
char
buf
[
4096
];
t
=
nftnl_table_alloc
();
if
(
t
==
NULL
)
goto
err
;
if
(
nftnl_table_nlmsg_parse
(
nlh
,
t
)
<
0
)
goto
err_free
;
if
(
arg
->
nfproto
&&
arg
->
nfproto
!=
nftnl_table_get_u32
(
t
,
NFTNL_TABLE_FAMILY
))
goto
err_free
;
nftnl_table_snprintf
(
buf
,
sizeof
(
buf
),
t
,
NFTNL_OUTPUT_DEFAULT
,
0
);
printf
(
" EVENT: "
);
printf
(
"nft: %s table: %s
\n
"
,
type
==
NFT_MSG_NEWTABLE
?
"NEW"
:
"DEL"
,
buf
);
err_free:
nftnl_table_free
(
t
);
err:
return
MNL_CB_OK
;
}
static
bool
counters
;
static
bool
trace
;
static
bool
events
;
static
int
rule_cb
(
const
struct
nlmsghdr
*
nlh
,
void
*
data
)
{
uint32_t
type
=
nlh
->
nlmsg_type
&
0xFF
;
const
struct
cb_arg
*
arg
=
data
;
struct
nftnl_rule
*
r
;
uint8_t
family
;
r
=
nftnl_rule_alloc
();
if
(
r
==
NULL
)
goto
err
;
if
(
nftnl_rule_nlmsg_parse
(
nlh
,
r
)
<
0
)
goto
err_free
;
family
=
nftnl_rule_get_u32
(
r
,
NFTNL_RULE_FAMILY
);
if
(
arg
->
nfproto
&&
arg
->
nfproto
!=
family
)
goto
err_free
;
if
(
arg
->
is_event
)
printf
(
" EVENT: "
);
switch
(
family
)
{
case
AF_INET
:
case
AF_INET6
:
printf
(
"-%c "
,
family
==
AF_INET
?
'4'
:
'6'
);
break
;
case
NFPROTO_ARP
:
printf
(
"-0 "
);
break
;
default:
goto
err_free
;
}
printf
(
"-t %s "
,
nftnl_rule_get_str
(
r
,
NFTNL_RULE_TABLE
));
nft_rule_print_save
(
r
,
type
==
NFT_MSG_NEWRULE
?
NFT_RULE_APPEND
:
NFT_RULE_DEL
,
counters
?
0
:
FMT_NOCOUNTS
);
err_free:
nftnl_rule_free
(
r
);
err:
return
MNL_CB_OK
;
}
static
int
chain_cb
(
const
struct
nlmsghdr
*
nlh
,
void
*
data
)
{
uint32_t
type
=
nlh
->
nlmsg_type
&
0xFF
;
const
struct
cb_arg
*
arg
=
data
;
struct
nftnl_chain
*
c
;
char
buf
[
4096
];
int
family
;
c
=
nftnl_chain_alloc
();
if
(
c
==
NULL
)
goto
err
;
if
(
nftnl_chain_nlmsg_parse
(
nlh
,
c
)
<
0
)
goto
err_free
;
family
=
nftnl_chain_get_u32
(
c
,
NFTNL_CHAIN_FAMILY
);
if
(
arg
->
nfproto
&&
arg
->
nfproto
!=
family
)
goto
err_free
;
if
(
nftnl_chain_is_set
(
c
,
NFTNL_CHAIN_PRIO
))
family
=
-
1
;
printf
(
" EVENT: "
);
switch
(
family
)
{
case
NFPROTO_IPV4
:
family
=
4
;
break
;
case
NFPROTO_IPV6
:
family
=
6
;
break
;
default:
nftnl_chain_snprintf
(
buf
,
sizeof
(
buf
),
c
,
NFTNL_OUTPUT_DEFAULT
,
0
);
printf
(
"# nft: %s
\n
"
,
buf
);
goto
err_free
;
}
printf
(
"-%d -t %s -%c %s
\n
"
,
family
,
nftnl_chain_get_str
(
c
,
NFTNL_CHAIN_TABLE
),
type
==
NFT_MSG_NEWCHAIN
?
'N'
:
'X'
,
nftnl_chain_get_str
(
c
,
NFTNL_CHAIN_NAME
));
err_free:
nftnl_chain_free
(
c
);
err:
return
MNL_CB_OK
;
}
static
int
newgen_cb
(
const
struct
nlmsghdr
*
nlh
,
void
*
data
)
{
uint32_t
genid
=
0
,
pid
=
0
;
const
struct
nlattr
*
attr
;
const
char
*
name
=
NULL
;
mnl_attr_for_each
(
attr
,
nlh
,
sizeof
(
struct
nfgenmsg
))
{
switch
(
mnl_attr_get_type
(
attr
))
{
case
NFTA_GEN_ID
:
if
(
mnl_attr_validate
(
attr
,
MNL_TYPE_U32
)
<
0
)
break
;
genid
=
ntohl
(
mnl_attr_get_u32
(
attr
));
break
;
case
NFTA_GEN_PROC_NAME
:
if
(
mnl_attr_validate
(
attr
,
MNL_TYPE_NUL_STRING
)
<
0
)
break
;
name
=
mnl_attr_get_str
(
attr
);
break
;
case
NFTA_GEN_PROC_PID
:
if
(
mnl_attr_validate
(
attr
,
MNL_TYPE_U32
)
<
0
)
break
;
pid
=
ntohl
(
mnl_attr_get_u32
(
attr
));
break
;
}
}
if
(
name
)
printf
(
"NEWGEN: GENID=%u PID=%u NAME=%s
\n
"
,
genid
,
pid
,
name
);
return
MNL_CB_OK
;
}
static
void
trace_print_return
(
const
struct
nftnl_trace
*
nlt
)
{
const
char
*
chain
=
NULL
;
if
(
nftnl_trace_is_set
(
nlt
,
NFTNL_TRACE_JUMP_TARGET
))
{
chain
=
nftnl_trace_get_str
(
nlt
,
NFTNL_TRACE_JUMP_TARGET
);
printf
(
"%s"
,
chain
);
}
}
static
void
trace_print_rule
(
const
struct
nftnl_trace
*
nlt
,
struct
cb_arg
*
args
)
{
uint64_t
handle
=
nftnl_trace_get_u64
(
nlt
,
NFTNL_TRACE_RULE_HANDLE
);
uint32_t
family
=
nftnl_trace_get_u32
(
nlt
,
NFTNL_TRACE_FAMILY
);
const
char
*
table
=
nftnl_trace_get_str
(
nlt
,
NFTNL_TRACE_TABLE
);
const
char
*
chain
=
nftnl_trace_get_str
(
nlt
,
NFTNL_TRACE_CHAIN
);
struct
nftnl_rule
*
r
;
struct
mnl_socket
*
nl
;
struct
nlmsghdr
*
nlh
;
uint32_t
portid
;
char
buf
[
16536
];
int
ret
;
r
=
nftnl_rule_alloc
();
if
(
r
==
NULL
)
{
perror
(
"OOM"
);
exit
(
EXIT_FAILURE
);
}
nlh
=
nftnl_chain_nlmsg_build_hdr
(
buf
,
NFT_MSG_GETRULE
,
family
,
NLM_F_DUMP
,
0
);
nftnl_rule_set_u32
(
r
,
NFTNL_RULE_FAMILY
,
family
);
nftnl_rule_set_str
(
r
,
NFTNL_RULE_CHAIN
,
chain
);
nftnl_rule_set_str
(
r
,
NFTNL_RULE_TABLE
,
table
);
nftnl_rule_set_u64
(
r
,
NFTNL_RULE_POSITION
,
handle
);
nftnl_rule_nlmsg_build_payload
(
nlh
,
r
);
nftnl_rule_free
(
r
);
nl
=
mnl_socket_open
(
NETLINK_NETFILTER
);
if
(
nl
==
NULL
)
{
perror
(
"mnl_socket_open"
);
exit
(
EXIT_FAILURE
);
}
if
(
mnl_socket_bind
(
nl
,
0
,
MNL_SOCKET_AUTOPID
)
<
0
)
{
perror
(
"mnl_socket_bind"
);
exit
(
EXIT_FAILURE
);
}
portid
=
mnl_socket_get_portid
(
nl
);
if
(
mnl_socket_sendto
(
nl
,
nlh
,
nlh
->
nlmsg_len
)
<
0
)
{
perror
(
"mnl_socket_send"
);
exit
(
EXIT_FAILURE
);
}
ret
=
mnl_socket_recvfrom
(
nl
,
buf
,
sizeof
(
buf
));
while
(
ret
>
0
)
{
args
->
is_event
=
false
;
ret
=
mnl_cb_run
(
buf
,
ret
,
0
,
portid
,
rule_cb
,
args
);
if
(
ret
<=
0
)
break
;
ret
=
mnl_socket_recvfrom
(
nl
,
buf
,
sizeof
(
buf
));
}
if
(
ret
==
-
1
)
{
perror
(
"error"
);
exit
(
EXIT_FAILURE
);
}
mnl_socket_close
(
nl
);
}
static
void
trace_print_packet
(
const
struct
nftnl_trace
*
nlt
,
struct
cb_arg
*
args
)
{
struct
list_head
stmts
=
LIST_HEAD_INIT
(
stmts
);
uint32_t
nfproto
,
family
;
uint16_t
l4proto
=
0
;
uint32_t
mark
;
char
name
[
IFNAMSIZ
];
printf
(
"PACKET: %d %08x "
,
args
->
nfproto
,
nftnl_trace_get_u32
(
nlt
,
NFTNL_TRACE_ID
));
if
(
nftnl_trace_is_set
(
nlt
,
NFTNL_TRACE_IIF
))
printf
(
"IN=%s "
,
if_indextoname
(
nftnl_trace_get_u32
(
nlt
,
NFTNL_TRACE_IIF
),
name
));
if
(
nftnl_trace_is_set
(
nlt
,
NFTNL_TRACE_OIF
))
printf
(
"OUT=%s "
,
if_indextoname
(
nftnl_trace_get_u32
(
nlt
,
NFTNL_TRACE_OIF
),
name
));
family
=
nftnl_trace_get_u32
(
nlt
,
NFTNL_TRACE_FAMILY
);
nfproto
=
family
;
if
(
nftnl_trace_is_set
(
nlt
,
NFTNL_TRACE_NFPROTO
))
{
nfproto
=
nftnl_trace_get_u32
(
nlt
,
NFTNL_TRACE_NFPROTO
);
if
(
family
!=
nfproto
)
printf
(
"NFPROTO=%d "
,
nfproto
);
}
if
(
nftnl_trace_is_set
(
nlt
,
NFTNL_TRACE_LL_HEADER
))
{
const
struct
ethhdr
*
eh
;
const
char
*
linklayer
;
uint32_t
i
,
len
;
uint16_t
type
=
nftnl_trace_get_u16
(
nlt
,
NFTNL_TRACE_IIFTYPE
);
linklayer
=
nftnl_trace_get_data
(
nlt
,
NFTNL_TRACE_LL_HEADER
,
&
len
);
switch
(
type
)
{
case
ARPHRD_ETHER
:
if
(
len
<
sizeof
(
*
eh
))
break
;
eh
=
(
const
void
*
)
linklayer
;
printf
(
"MACSRC=%s "
,
ether_ntoa
((
const
void
*
)
eh
->
h_source
));
printf
(
"MACDST=%s "
,
ether_ntoa
((
const
void
*
)
eh
->
h_dest
));
printf
(
"MACPROTO=%04x "
,
ntohs
(
eh
->
h_proto
));
break
;
default:
printf
(
"LL=0x%x "
,
type
);
for
(
i
=
0
;
i
<
len
;
i
++
)
printf
(
"%02x"
,
linklayer
[
i
]);
printf
(
" "
);
break
;
}
}
if
(
nftnl_trace_is_set
(
nlt
,
NFTNL_TRACE_NETWORK_HEADER
))
{
const
struct
ip6_hdr
*
ip6h
;
const
struct
iphdr
*
iph
;
uint32_t
i
,
len
;
const
char
*
nh
;
ip6h
=
nftnl_trace_get_data
(
nlt
,
NFTNL_TRACE_NETWORK_HEADER
,
&
len
);
switch
(
nfproto
)
{
case
NFPROTO_IPV4
:
{
char
addrbuf
[
INET_ADDRSTRLEN
];
if
(
len
<
sizeof
(
*
iph
))
break
;
iph
=
(
const
void
*
)
ip6h
;
inet_ntop
(
AF_INET
,
&
iph
->
saddr
,
addrbuf
,
sizeof
(
addrbuf
));
printf
(
"SRC=%s "
,
addrbuf
);
inet_ntop
(
AF_INET
,
&
iph
->
daddr
,
addrbuf
,
sizeof
(
addrbuf
));
printf
(
"DST=%s "
,
addrbuf
);
printf
(
"LEN=%d TOS=0x%x TTL=%d ID=%d"
,
ntohs
(
iph
->
tot_len
),
iph
->
tos
,
iph
->
ttl
,
ntohs
(
iph
->
id
));
if
(
iph
->
frag_off
&
htons
(
0x8000
))
printf
(
"CE "
);
if
(
iph
->
frag_off
&
htons
(
IP_DF
))
printf
(
"DF "
);
if
(
iph
->
frag_off
&
htons
(
IP_MF
))
printf
(
"MF "
);
if
(
ntohs
(
iph
->
frag_off
)
&
0x1fff
)
printf
(
"FRAG:%u "
,
ntohs
(
iph
->
frag_off
)
&
0x1fff
);
l4proto
=
iph
->
protocol
;
if
(
iph
->
ihl
*
4
>
sizeof
(
*
iph
))
{
unsigned
int
optsize
;
const
char
*
op
;
optsize
=
iph
->
ihl
*
4
-
sizeof
(
*
iph
);
op
=
(
const
char
*
)
iph
;
op
+=
sizeof
(
*
iph
);
printf
(
"OPT ("
);
for
(
i
=
0
;
i
<
optsize
;
i
++
)
printf
(
"%02X"
,
op
[
i
]);
printf
(
")"
);
}
break
;
}
case
NFPROTO_IPV6
:
{
uint32_t
flowlabel
=
ntohl
(
*
(
uint32_t
*
)
ip6h
);
char
addrbuf
[
INET6_ADDRSTRLEN
];
if
(
len
<
sizeof
(
*
ip6h
))
break
;
inet_ntop
(
AF_INET6
,
&
ip6h
->
ip6_src
,
addrbuf
,
sizeof
(
addrbuf
));
printf
(
"SRC=%s "
,
addrbuf
);
inet_ntop
(
AF_INET6
,
&
ip6h
->
ip6_dst
,
addrbuf
,
sizeof
(
addrbuf
));
printf
(
"DST=%s "
,
addrbuf
);
printf
(
"LEN=%zu TC=%u HOPLIMIT=%u FLOWLBL=%u "
,
ntohs
(
ip6h
->
ip6_plen
)
+
sizeof
(
*
iph
),
(
flowlabel
&
0x0ff00000
)
>>
20
,
ip6h
->
ip6_hops
,
flowlabel
&
0x000fffff
);
l4proto
=
ip6h
->
ip6_nxt
;
break
;
}
default:
nh
=
(
const
char
*
)
ip6h
;
printf
(
"NH="
);
for
(
i
=
0
;
i
<
len
;
i
++
)
printf
(
"%02x"
,
nh
[
i
]);
printf
(
" "
);
}
}
if
(
nftnl_trace_is_set
(
nlt
,
NFTNL_TRACE_TRANSPORT_HEADER
))
{
const
struct
tcphdr
*
tcph
;
uint32_t
len
;
tcph
=
nftnl_trace_get_data
(
nlt
,
NFTNL_TRACE_TRANSPORT_HEADER
,
&
len
);
switch
(
l4proto
)
{
case
IPPROTO_DCCP
:
case
IPPROTO_SCTP
:
case
IPPROTO_UDPLITE
:
case
IPPROTO_UDP
:
if
(
len
<
4
)
break
;
printf
(
"SPORT=%d DPORT=%d "
,
ntohs
(
tcph
->
th_sport
),
ntohs
(
tcph
->
th_dport
));
break
;
case
IPPROTO_TCP
:
if
(
len
<
sizeof
(
*
tcph
))
break
;
printf
(
"SPORT=%d DPORT=%d "
,
ntohs
(
tcph
->
th_sport
),
ntohs
(
tcph
->
th_dport
));
if
(
tcph
->
th_flags
&
(
TH_FIN
|
TH_SYN
|
TH_RST
|
TH_PUSH
|
TH_ACK
|
TH_URG
))
{
if
(
tcph
->
th_flags
&
TH_SYN
)
printf
(
"SYN "
);
if
(
tcph
->
th_flags
&
TH_ACK
)
printf
(
"ACK "
);
if
(
tcph
->
th_flags
&
TH_FIN
)
printf
(
"FIN "
);
if
(
tcph
->
th_flags
&
TH_RST
)
printf
(
"RST "
);
if
(
tcph
->
th_flags
&
TH_PUSH
)
printf
(
"PSH "
);
if
(
tcph
->
th_flags
&
TH_URG
)
printf
(
"URG "
);
}
break
;
default:
break
;
}
}
mark
=
nftnl_trace_get_u32
(
nlt
,
NFTNL_TRACE_MARK
);
if
(
mark
)
printf
(
"MARK=0x%x "
,
mark
);
}
static
void
print_verdict
(
struct
nftnl_trace
*
nlt
,
uint32_t
verdict
)
{
const
char
*
chain
;
switch
(
verdict
)
{
case
NF_ACCEPT
:
printf
(
"ACCEPT"
);
break
;
case
NF_DROP
:
printf
(
"DROP"
);
break
;
case
NF_QUEUE
:
printf
(
"QUEUE"
);
break
;
case
NF_STOLEN
:
printf
(
"STOLEN"
);
break
;
case
NFT_BREAK
:
printf
(
"BREAK"
);
break
;
case
NFT_CONTINUE
:
printf
(
"CONTINUE"
);
break
;
case
NFT_GOTO
:
printf
(
"GOTO"
);
if
(
nftnl_trace_is_set
(
nlt
,
NFTNL_TRACE_JUMP_TARGET
))
{
chain
=
nftnl_trace_get_str
(
nlt
,
NFTNL_TRACE_JUMP_TARGET
);
printf
(
":%s"
,
chain
);
}
break
;
case
NFT_JUMP
:
printf
(
"JUMP"
);
if
(
nftnl_trace_is_set
(
nlt
,
NFTNL_TRACE_JUMP_TARGET
))
{
chain
=
nftnl_trace_get_str
(
nlt
,
NFTNL_TRACE_JUMP_TARGET
);
printf
(
":%s"
,
chain
);
}
break
;
default:
printf
(
"0x%x"
,
verdict
);
break
;
}
printf
(
" "
);
}
static
int
trace_cb
(
const
struct
nlmsghdr
*
nlh
,
struct
cb_arg
*
arg
)
{
struct
nftnl_trace
*
nlt
;
uint32_t
verdict
;
nlt
=
nftnl_trace_alloc
();
if
(
nlt
==
NULL
)
goto
err
;
if
(
nftnl_trace_nlmsg_parse
(
nlh
,
nlt
)
<
0
)
goto
err_free
;
if
(
arg
->
nfproto
&&
arg
->
nfproto
!=
nftnl_trace_get_u32
(
nlt
,
NFTNL_TABLE_FAMILY
))
goto
err_free
;
printf
(
" TRACE: %d %08x %s:%s"
,
nftnl_trace_get_u32
(
nlt
,
NFTNL_TABLE_FAMILY
),
nftnl_trace_get_u32
(
nlt
,
NFTNL_TRACE_ID
),
nftnl_trace_get_str
(
nlt
,
NFTNL_TRACE_TABLE
),
nftnl_trace_get_str
(
nlt
,
NFTNL_TRACE_CHAIN
));
switch
(
nftnl_trace_get_u32
(
nlt
,
NFTNL_TRACE_TYPE
))
{
case
NFT_TRACETYPE_RULE
:
verdict
=
nftnl_trace_get_u32
(
nlt
,
NFTNL_TRACE_VERDICT
);
printf
(
":rule:0x%llx:"
,
(
unsigned
long
long
)
nftnl_trace_get_u64
(
nlt
,
NFTNL_TRACE_RULE_HANDLE
));
print_verdict
(
nlt
,
verdict
);
if
(
nftnl_trace_is_set
(
nlt
,
NFTNL_TRACE_RULE_HANDLE
))
trace_print_rule
(
nlt
,
arg
);
if
(
nftnl_trace_is_set
(
nlt
,
NFTNL_TRACE_LL_HEADER
)
||
nftnl_trace_is_set
(
nlt
,
NFTNL_TRACE_NETWORK_HEADER
))
trace_print_packet
(
nlt
,
arg
);
break
;
case
NFT_TRACETYPE_POLICY
:
printf
(
":policy:"
);
verdict
=
nftnl_trace_get_u32
(
nlt
,
NFTNL_TRACE_POLICY
);
print_verdict
(
nlt
,
verdict
);
break
;
case
NFT_TRACETYPE_RETURN
:
printf
(
":return:"
);
trace_print_return
(
nlt
);
break
;
}
puts
(
""
);
err_free:
nftnl_trace_free
(
nlt
);
err:
return
MNL_CB_OK
;
}
static
int
monitor_cb
(
const
struct
nlmsghdr
*
nlh
,
void
*
data
)
{
uint32_t
type
=
nlh
->
nlmsg_type
&
0xFF
;
struct
cb_arg
*
arg
=
data
;
int
ret
=
MNL_CB_OK
;
switch
(
type
)
{
case
NFT_MSG_NEWTABLE
:
case
NFT_MSG_DELTABLE
:
ret
=
table_cb
(
nlh
,
data
);
break
;
case
NFT_MSG_NEWCHAIN
:
case
NFT_MSG_DELCHAIN
:
ret
=
chain_cb
(
nlh
,
data
);
break
;
case
NFT_MSG_NEWRULE
:
case
NFT_MSG_DELRULE
:
arg
->
is_event
=
true
;
ret
=
rule_cb
(
nlh
,
data
);
break
;
case
NFT_MSG_NEWGEN
:
ret
=
newgen_cb
(
nlh
,
data
);
break
;
case
NFT_MSG_TRACE
:
ret
=
trace_cb
(
nlh
,
data
);
break
;
}
return
ret
;
}
static
const
struct
option
options
[]
=
{
{.
name
=
"counters"
,
.
has_arg
=
false
,
.
val
=
'c'
},
{.
name
=
"trace"
,
.
has_arg
=
false
,
.
val
=
't'
},
{.
name
=
"event"
,
.
has_arg
=
false
,
.
val
=
'e'
},
{.
name
=
"ipv4"
,
.
has_arg
=
false
,
.
val
=
'4'
},
{.
name
=
"ipv6"
,
.
has_arg
=
false
,
.
val
=
'6'
},
{.
name
=
"version"
,
.
has_arg
=
false
,
.
val
=
'V'
},
{.
name
=
"help"
,
.
has_arg
=
false
,
.
val
=
'h'
},
{
NULL
},
};
static
void
print_usage
(
void
)
{
printf
(
"%s %s
\n
"
,
xtables_globals
.
program_name
,
xtables_globals
.
program_version
);
printf
(
"Usage: %s [ -t | -e ]
\n
"
" --trace -t trace ruleset traversal of packets tagged via -j TRACE rule
\n
"
" --event -e show events that modify the ruleset
\n
"
"Optional arguments:
\n
"
" --ipv4 -4 only monitor IPv4
\n
"
" --ipv6 -6 only monitor IPv6
\n
"
" --counters -c show counters in rules
\n
"
,
xtables_globals
.
program_name
);
exit
(
EXIT_FAILURE
);
}
int
xtables_monitor_main
(
int
argc
,
char
*
argv
[])
{
struct
mnl_socket
*
nl
;
char
buf
[
MNL_SOCKET_BUFFER_SIZE
];
uint32_t
nfgroup
=
0
;
struct
cb_arg
cb_arg
=
{};
int
ret
,
c
;
xtables_globals
.
program_name
=
"xtables-monitor"
;
/* XXX xtables_init_all does several things we don't want */
c
=
xtables_init_all
(
&
xtables_globals
,
NFPROTO_IPV4
);
if
(
c
<
0
)
{
fprintf
(
stderr
,
"%s/%s Failed to initialize xtables
\n
"
,
xtables_globals
.
program_name
,
xtables_globals
.
program_version
);
exit
(
1
);
}
#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
init_extensions
();
init_extensions4
();
#endif
opterr
=
0
;
while
((
c
=
getopt_long
(
argc
,
argv
,
"ceht46V"
,
options
,
NULL
))
!=
-
1
)
{
switch
(
c
)
{
case
'c'
:
counters
=
true
;
break
;
case
't'
:
trace
=
true
;
break
;
case
'e'
:
events
=
true
;
break
;
case
'h'
:
print_usage
();
exit
(
0
);
case
'4'
:
cb_arg
.
nfproto
=
NFPROTO_IPV4
;
break
;
case
'6'
:
cb_arg
.
nfproto
=
NFPROTO_IPV6
;
break
;
case
'V'
:
printf
(
"xtables-monitor %s
\n
"
,
IPTABLES_VERSION
);
exit
(
0
);
default:
fprintf
(
stderr
,
"xtables-monitor %s: Bad argument.
\n
"
,
IPTABLES_VERSION
);
fprintf
(
stderr
,
"Try `xtables-monitor -h' for more information.
\n
"
);
exit
(
PARAMETER_PROBLEM
);
}
}
if
(
trace
)
nfgroup
|=
1
<<
(
NFNLGRP_NFTRACE
-
1
);
if
(
events
)
nfgroup
|=
1
<<
(
NFNLGRP_NFTABLES
-
1
);
if
(
nfgroup
==
0
)
{
print_usage
();
exit
(
EXIT_FAILURE
);
}
nl
=
mnl_socket_open
(
NETLINK_NETFILTER
);
if
(
nl
==
NULL
)
{
perror
(
"cannot open nfnetlink socket"
);
exit
(
EXIT_FAILURE
);
}
if
(
mnl_socket_bind
(
nl
,
nfgroup
,
MNL_SOCKET_AUTOPID
)
<
0
)
{
perror
(
"cannot bind to nfnetlink socket"
);
exit
(
EXIT_FAILURE
);
}
ret
=
mnl_socket_recvfrom
(
nl
,
buf
,
sizeof
(
buf
));
while
(
ret
>
0
)
{
ret
=
mnl_cb_run
(
buf
,
ret
,
0
,
0
,
monitor_cb
,
&
cb_arg
);
if
(
ret
<=
0
)
break
;
ret
=
mnl_socket_recvfrom
(
nl
,
buf
,
sizeof
(
buf
));
}
if
(
ret
==
-
1
)
{
perror
(
"cannot receive from nfnetlink socket"
);
exit
(
EXIT_FAILURE
);
}
mnl_socket_close
(
nl
);
return
EXIT_SUCCESS
;
}
iptables/xtables-multi.h
View file @
dab1e98e
...
...
@@ -11,12 +11,17 @@ extern int xtables_ip6_save_main(int, char **);
extern
int
xtables_ip6_restore_main
(
int
,
char
**
);
extern
int
xtables_ip4_xlate_main
(
int
,
char
**
);
extern
int
xtables_ip6_xlate_main
(
int
,
char
**
);
extern
int
xtables_eb_xlate_main
(
int
,
char
**
);
extern
int
xtables_ip4_xlate_restore_main
(
int
,
char
**
);
extern
int
xtables_ip6_xlate_restore_main
(
int
,
char
**
);
extern
int
xtables_arp_main
(
int
,
char
**
);
extern
int
xtables_arp_restore_main
(
int
,
char
**
);
extern
int
xtables_arp_save_main
(
int
,
char
**
);
extern
int
xtables_eb_main
(
int
,
char
**
);
extern
int
xtables_eb_restore_main
(
int
,
char
**
);
extern
int
xtables_eb_save_main
(
int
,
char
**
);
extern
int
xtables_config_main
(
int
,
char
**
);
extern
int
xtables_
events
_main
(
int
,
char
**
);
extern
int
xtables_
monitor
_main
(
int
,
char
**
);
#endif
#endif
/* _XTABLES_MULTI_H */
iptables/xtables-
compa
t-multi.c
→
iptables/xtables-
nf
t-multi.c
View file @
dab1e98e
...
...
@@ -9,30 +9,41 @@ static const struct subcommand multi_subcommands[] = {
{
"iptables-xml"
,
iptables_xml_main
},
{
"xml"
,
iptables_xml_main
},
{
"iptables"
,
xtables_ip4_main
},
{
"iptables-
compa
t"
,
xtables_ip4_main
},
{
"iptables-
nf
t"
,
xtables_ip4_main
},
{
"main4"
,
xtables_ip4_main
},
{
"save4"
,
xtables_ip4_save_main
},
{
"restore4"
,
xtables_ip4_restore_main
},
{
"iptables-save"
,
xtables_ip4_save_main
},
{
"iptables-restore"
,
xtables_ip4_restore_main
},
{
"iptables-
compa
t-save"
,
xtables_ip4_save_main
},
{
"iptables-
compa
t-restore"
,
xtables_ip4_restore_main
},
{
"iptables-
nf
t-save"
,
xtables_ip4_save_main
},
{
"iptables-
nf
t-restore"
,
xtables_ip4_restore_main
},
{
"ip6tables"
,
xtables_ip6_main
},
{
"ip6tables-
compa
t"
,
xtables_ip6_main
},
{
"ip6tables-
nf
t"
,
xtables_ip6_main
},
{
"main6"
,
xtables_ip6_main
},
{
"save6"
,
xtables_ip6_save_main
},
{
"restore6"
,
xtables_ip6_restore_main
},
{
"ip6tables-save"
,
xtables_ip6_save_main
},
{
"ip6tables-restore"
,
xtables_ip6_restore_main
},
{
"ip6tables-
compa
t-save"
,
xtables_ip6_save_main
},
{
"ip6tables-
compa
t-restore"
,
xtables_ip6_restore_main
},
{
"ip6tables-
nf
t-save"
,
xtables_ip6_save_main
},
{
"ip6tables-
nf
t-restore"
,
xtables_ip6_restore_main
},
{
"iptables-translate"
,
xtables_ip4_xlate_main
},
{
"ip6tables-translate"
,
xtables_ip6_xlate_main
},
{
"iptables-restore-translate"
,
xtables_ip4_xlate_restore_main
},
{
"ip6tables-restore-translate"
,
xtables_ip6_xlate_restore_main
},
{
"arptables"
,
xtables_arp_main
},
{
"arptables-compat"
,
xtables_arp_main
},
{
"ebtables-compat"
,
xtables_eb_main
},
{
"arptables-nft"
,
xtables_arp_main
},
{
"arptables-restore"
,
xtables_arp_restore_main
},
{
"arptables-nft-restore"
,
xtables_arp_restore_main
},
{
"arptables-save"
,
xtables_arp_save_main
},
{
"arptables-nft-save"
,
xtables_arp_save_main
},
{
"ebtables-translate"
,
xtables_eb_xlate_main
},
{
"ebtables"
,
xtables_eb_main
},
{
"ebtables-restore"
,
xtables_eb_restore_main
},
{
"ebtables-save"
,
xtables_eb_save_main
},
{
"ebtables-nft"
,
xtables_eb_main
},
{
"ebtables-nft-restore"
,
xtables_eb_restore_main
},
{
"ebtables-nft-save"
,
xtables_eb_save_main
},
{
"xtables-monitor"
,
xtables_monitor_main
},
{
NULL
},
};
...
...
Prev
1
…
8
9
10
11
12
13
14
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment