mirror of
https://git.proxmox.com/git/mirror_iproute2
synced 2025-10-05 22:35:10 +00:00

As Jamal suggested, BRANCH is the wrong name, as these keywords go beyond simple branch control - e.g. loops are possible, too. Therefore rename the non-terminal to CONTROL instead which should be more appropriate. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
231 lines
5.3 KiB
Groff
231 lines
5.3 KiB
Groff
.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 munge " {
|
|
.IR RAW_OP " | " 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 ip6 " IP6HDR_FIELD"
|
|
|
|
|
.BI udp " UDPHDR_FIELD"
|
|
|
|
|
.BI tcp " TCPHDR_FIELD"
|
|
|
|
|
.BI icmp " ICMPHDR_FIELD"
|
|
.RI } " CMD_SPEC"
|
|
|
|
.ti -8
|
|
.IR IPHDR_FIELD " := { "
|
|
.BR src " | " dst " | " tos " | " dsfield " | " ihl " | " protocol " |"
|
|
.BR precedence " | " nofrag " | " firstfrag " | " ce " | " df " |"
|
|
.BR mf " | " dport " | " sport " | " icmp_type " | " icmp_code " }"
|
|
|
|
.ti -8
|
|
.IR CMD_SPEC " := {"
|
|
.BR clear " | " invert " | " set
|
|
.IR VAL " | "
|
|
.BR preserve " } [ " retain
|
|
.IR RVAL " ]"
|
|
|
|
.ti -8
|
|
.IR CONTROL " := {"
|
|
.BR reclassify " | " pipe " | " drop " | " shot " | " continue " | " pass " }"
|
|
.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
|
|
.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 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.
|
|
.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
|
|
.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
|
|
.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.
|
|
.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
|
|
.EE
|
|
.RE
|
|
.SH SEE ALSO
|
|
.BR tc (8),
|
|
.BR tc-htb (8),
|
|
.BR tc-u32 (8)
|