You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
374 lines
7.9 KiB
374 lines
7.9 KiB
.TH "Generic packet editor action in tc" 8 "12 Jan 2015" "iproute2" "Linux"
|
|
|
|
.SH NAME
|
|
pedit - generic packet editor action
|
|
.SH SYNOPSIS
|
|
.in +8
|
|
.ti -8
|
|
.BR tc " ... " "action pedit [ex] munge " {
|
|
.IR RAW_OP " | " LAYERED_OP " | " EXTENDED_LAYERED_OP " } [ " CONTROL " ]"
|
|
|
|
.ti -8
|
|
.IR RAW_OP " := "
|
|
.BI offset " OFFSET"
|
|
.RB "{ " u8 " | " u16 " | " u32 " } ["
|
|
.IR AT_SPEC " ] " CMD_SPEC
|
|
|
|
.ti -8
|
|
.IR AT_SPEC " := "
|
|
.BI at " AT " offmask " MASK " shift " SHIFT"
|
|
|
|
.ti -8
|
|
.IR LAYERED_OP " := { "
|
|
.BI ip " IPHDR_FIELD"
|
|
|
|
|
.BI ip " BEYOND_IPHDR_FIELD"
|
|
.RI } " CMD_SPEC"
|
|
|
|
.ti -8
|
|
.IR EXTENDED_LAYERED_OP " := { "
|
|
.BI eth " ETHHDR_FIELD"
|
|
|
|
|
.BI ip " IPHDR_FIELD"
|
|
|
|
|
.BI ip " EX_IPHDR_FIELD"
|
|
|
|
|
.BI ip6 " IP6HDR_FIELD"
|
|
|
|
|
.BI tcp " TCPHDR_FIELD"
|
|
|
|
|
.BI udp " UDPHDR_FIELD"
|
|
.RI } " CMD_SPEC"
|
|
|
|
.ti -8
|
|
.IR ETHHDR_FIELD " := { "
|
|
.BR src " | " dst " | " type " }"
|
|
|
|
.ti -8
|
|
.IR IPHDR_FIELD " := { "
|
|
.BR src " | " dst " | " tos " | " dsfield " | " ihl " | " protocol " |"
|
|
.BR precedence " | " nofrag " | " firstfrag " | " ce " | " df " }"
|
|
|
|
.ti -8
|
|
.IR BEYOND_IPHDR_FIELD " := { "
|
|
.BR dport " | " sport " | " icmp_type " | " icmp_code " }"
|
|
|
|
.ti -8
|
|
.IR EX_IPHDR_FIELD " := { "
|
|
.BR ttl " }"
|
|
|
|
|
|
.ti -8
|
|
.IR IP6HDR_FIELD " := { "
|
|
.BR src " | " dst " | " flow_lbl " | " payload_len " | " nexthdr " |"
|
|
.BR hoplimit " }"
|
|
|
|
.ti -8
|
|
.IR TCPHDR_FIELD " := { "
|
|
.BR sport " | " dport " | " flags " }"
|
|
|
|
.ti -8
|
|
.IR UDPHDR_FIELD " := { "
|
|
.BR sport " | " dport " }"
|
|
|
|
.ti -8
|
|
.IR CMD_SPEC " := {"
|
|
.BR clear " | " invert " | " set
|
|
.IR VAL " | "
|
|
.BR add
|
|
.IR VAL " | "
|
|
.BR preserve " } [ " retain
|
|
.IR RVAL " ]"
|
|
|
|
.ti -8
|
|
.IR CONTROL " := {"
|
|
.BR reclassify " | " pipe " | " drop " | " shot " | " continue " | " pass " | " goto " " chain " " CHAIN_INDEX " }"
|
|
.SH DESCRIPTION
|
|
The
|
|
.B pedit
|
|
action can be used to change arbitrary packet data. The location of data to
|
|
change can either be specified by giving an offset and size as in
|
|
.IR RAW_OP ,
|
|
or for header values by naming the header and field to edit the size is then
|
|
chosen automatically based on the header field size. Currently this is supported
|
|
only for IPv4 headers.
|
|
.SH OPTIONS
|
|
.TP
|
|
.B ex
|
|
Use extended pedit.
|
|
.I EXTENDED_LAYERED_OP
|
|
and the add
|
|
.I CMD_SPEC
|
|
are allowed only in this mode.
|
|
.TP
|
|
.BI offset " OFFSET " "\fR{ \fBu32 \fR| \fBu16 \fR| \fBu8 \fR}"
|
|
Specify the offset at which to change data.
|
|
.I OFFSET
|
|
is a signed integer, it's base is automatically chosen (e.g. hex if prefixed by
|
|
.B 0x
|
|
or octal if prefixed by
|
|
.BR 0 ).
|
|
The second argument specifies the length of data to change, that is four bytes
|
|
.RB ( u32 ),
|
|
two bytes
|
|
.RB ( u16 )
|
|
or a single byte
|
|
.RB ( u8 ).
|
|
.TP
|
|
.BI at " AT " offmask " MASK " shift " SHIFT"
|
|
This is an optional part of
|
|
.IR RAW_OP
|
|
which allows to have a variable
|
|
.I OFFSET
|
|
depending on packet data at offset
|
|
.IR AT ,
|
|
which is binary ANDed with
|
|
.I MASK
|
|
and right-shifted by
|
|
.I SHIFT
|
|
before adding it to
|
|
.IR OFFSET .
|
|
.TP
|
|
.BI eth " ETHHDR_FIELD"
|
|
Change an ETH header field. The supported keywords for
|
|
.I ETHHDR_FIELD
|
|
are:
|
|
.RS
|
|
.TP
|
|
.B src
|
|
.TQ
|
|
.B dst
|
|
Source or destination MAC address in the standard format: XX:XX:XX:XX:XX:XX
|
|
.TP
|
|
.B type
|
|
Ether-type in numeric value
|
|
.RE
|
|
.TP
|
|
.BI ip " IPHDR_FIELD"
|
|
Change an IPv4 header field. The supported keywords for
|
|
.I IPHDR_FIELD
|
|
are:
|
|
.RS
|
|
.TP
|
|
.B src
|
|
.TQ
|
|
.B dst
|
|
Source or destination IP address, a four-byte value.
|
|
.TP
|
|
.B tos
|
|
.TQ
|
|
.B dsfield
|
|
.TQ
|
|
.B precedence
|
|
Type Of Service field, an eight-bit value.
|
|
.TP
|
|
.B ihl
|
|
Change the IP Header Length field, a four-bit value.
|
|
.TP
|
|
.B protocol
|
|
Next-layer Protocol field, an eight-bit value.
|
|
.TP
|
|
.B nofrag
|
|
.TQ
|
|
.B firstfrag
|
|
.TQ
|
|
.B ce
|
|
.TQ
|
|
.B df
|
|
.TQ
|
|
.B mf
|
|
Change IP header flags. Note that the value to pass to the
|
|
.B set
|
|
command is not just a bit value, but the full byte including the flags field.
|
|
Though only the relevant bits of that value are respected, the rest ignored.
|
|
.RE
|
|
.TP
|
|
.BI ip " BEYOND_IPHDR_FIELD"
|
|
Supported only for non-extended layered op. It is passed to the kernel as
|
|
offsets relative to the beginning of the IP header and assumes the IP header is
|
|
of minimum size (20 bytes). The supported keywords for
|
|
.I BEYOND_IPHDR_FIELD
|
|
are:
|
|
.RS
|
|
.TP
|
|
.B dport
|
|
.TQ
|
|
.B sport
|
|
Destination or source port numbers, a 16-bit value. Indeed, IPv4 headers don't
|
|
contain this information. Instead, this will set an offset which suits at least
|
|
TCP and UDP if the IP header is of minimum size (20 bytes). If not, this will do
|
|
unexpected things.
|
|
.TP
|
|
.B icmp_type
|
|
.TQ
|
|
.B icmp_code
|
|
Again, this allows to change data past the actual IP header itself. It assumes
|
|
an ICMP header is present immediately following the (minimal sized) IP header.
|
|
If it is not or the latter is bigger than the minimum of 20 bytes, this will do
|
|
unexpected things. These fields are eight-bit values.
|
|
.RE
|
|
.TP
|
|
.BI ip " EX_IPHDR_FIELD"
|
|
Supported only when
|
|
.I ex
|
|
is used. The supported keywords for
|
|
.I EX_IPHDR_FIELD
|
|
are:
|
|
.RS
|
|
.TP
|
|
.B ttl
|
|
.RE
|
|
.TP
|
|
.BI ip6 " IP6HDR_FIELD"
|
|
The supported keywords for
|
|
.I IP6HDR_FIELD
|
|
are:
|
|
.RS
|
|
.TP
|
|
.B src
|
|
.TQ
|
|
.B dst
|
|
.TQ
|
|
.B flow_lbl
|
|
.TQ
|
|
.B payload_len
|
|
.TQ
|
|
.B nexthdr
|
|
.TQ
|
|
.B hoplimit
|
|
.RE
|
|
.TP
|
|
.BI tcp " TCPHDR_FIELD"
|
|
The supported keywords for
|
|
.I TCPHDR_FIELD
|
|
are:
|
|
.RS
|
|
.TP
|
|
.B sport
|
|
.TQ
|
|
.B dport
|
|
Source or destination TCP port number, a 16-bit value.
|
|
.TP
|
|
.B flags
|
|
.RE
|
|
.TP
|
|
.BI udp " UDPHDR_FIELD"
|
|
The supported keywords for
|
|
.I UDPHDR_FIELD
|
|
are:
|
|
.RS
|
|
.TP
|
|
.B sport
|
|
.TQ
|
|
.B dport
|
|
Source or destination TCP port number, a 16-bit value.
|
|
.RE
|
|
.TP
|
|
.B clear
|
|
Clear the addressed data (i.e., set it to zero).
|
|
.TP
|
|
.B invert
|
|
Swap every bit in the addressed data.
|
|
.TP
|
|
.BI set " VAL"
|
|
Set the addressed data to a specific value. The size of
|
|
.I VAL
|
|
is defined by either one of the
|
|
.BR u32 ", " u16 " or " u8
|
|
keywords in
|
|
.IR RAW_OP ,
|
|
or the size of the addressed header field in
|
|
.IR LAYERED_OP .
|
|
.TP
|
|
.BI add " VAL"
|
|
Add the addressed data by a specific value. The size of
|
|
.I VAL
|
|
is defined by the size of the addressed header field in
|
|
.IR EXTENDED_LAYERED_OP .
|
|
This operation is supported only for extended layered op.
|
|
.TP
|
|
.B preserve
|
|
Keep the addressed data as is.
|
|
.TP
|
|
.BI retain " RVAL"
|
|
This optional extra part of
|
|
.I CMD_SPEC
|
|
allows to exclude bits from being changed. Supported only for 32 bits fields
|
|
or smaller.
|
|
.TP
|
|
.I CONTROL
|
|
The following keywords allow to control how the tree of qdisc, classes,
|
|
filters and actions is further traversed after this action.
|
|
.RS
|
|
.TP
|
|
.B reclassify
|
|
Restart with the first filter in the current list.
|
|
.TP
|
|
.B pipe
|
|
Continue with the next action attached to the same filter.
|
|
.TP
|
|
.B drop
|
|
.TQ
|
|
.B shot
|
|
Drop the packet.
|
|
.TP
|
|
.B continue
|
|
Continue classification with the next filter in line.
|
|
.TP
|
|
.B pass
|
|
Finish classification process and return to calling qdisc for further packet
|
|
processing. This is the default.
|
|
.RE
|
|
.SH EXAMPLES
|
|
Being able to edit packet data, one could do all kinds of things, such as e.g.
|
|
implementing port redirection. Certainly not the most useful application, but
|
|
as an example it should do:
|
|
|
|
First, qdiscs need to be set up to attach filters to. For the receive path, a simple
|
|
.B ingress
|
|
qdisc will do, for transmit path a classful qdisc
|
|
.RB ( HTB
|
|
in this case) is necessary:
|
|
|
|
.RS
|
|
.EX
|
|
tc qdisc replace dev eth0 root handle 1: htb
|
|
tc qdisc add dev eth0 ingress handle ffff:
|
|
.EE
|
|
.RE
|
|
|
|
Finally, a filter with
|
|
.B pedit
|
|
action can be added for each direction. In this case,
|
|
.B u32
|
|
is used matching on the port number to redirect from, while
|
|
.B pedit
|
|
then does the actual rewriting:
|
|
|
|
.RS
|
|
.EX
|
|
tc filter add dev eth0 parent 1: u32 \\
|
|
match ip dport 23 0xffff \\
|
|
action pedit pedit munge ip dport set 22
|
|
tc filter add dev eth0 parent ffff: u32 \\
|
|
match ip sport 22 0xffff \\
|
|
action pedit pedit munge ip sport set 23
|
|
tc filter add dev eth0 parent ffff: u32 \\
|
|
match ip sport 22 0xffff \\
|
|
action pedit ex munge ip dst set 192.168.1.199
|
|
tc filter add dev eth0 parent ffff: u32 \\
|
|
match ip sport 22 0xffff \\
|
|
action pedit ex munge ip6 dst set fe80::dacb:8aff:fec7:320e
|
|
tc filter add dev eth0 parent ffff: u32 \\
|
|
match ip sport 22 0xffff \\
|
|
action pedit ex munge eth dst set 11:22:33:44:55:66
|
|
tc filter add dev eth0 parent ffff: u32 \\
|
|
match ip dport 23 0xffff \\
|
|
action pedit ex munge tcp dport set 22
|
|
.EE
|
|
.RE
|
|
.SH SEE ALSO
|
|
.BR tc (8),
|
|
.BR tc-htb (8),
|
|
.BR tc-u32 (8)
|