593 lines
11 KiB
HTML
593 lines
11 KiB
HTML
|
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
<HTML><HEAD><TITLE>Man page of Generic packet editor action in tc</TITLE>
|
|
</HEAD><BODY>
|
|
<H1>Generic packet editor action in tc</H1>
|
|
Section: Linux (8)<BR>Updated: 12 Jan 2015<BR><A HREF="#index">Index</A>
|
|
<A HREF="/cgi-bin/man/man2html">Return to Main Contents</A><HR>
|
|
|
|
<P>
|
|
<A NAME="lbAB"> </A>
|
|
<H2>NAME</H2>
|
|
|
|
pedit - generic packet editor action
|
|
<A NAME="lbAC"> </A>
|
|
<H2>SYNOPSIS</H2>
|
|
|
|
|
|
<BR>
|
|
|
|
<B>tc</B> ... <B>action pedit [ex] munge </B>{
|
|
|
|
<I>RAW_OP</I> | <I>LAYERED_OP</I> | <I>EXTENDED_LAYERED_OP</I> } [ <I>CONTROL</I> ]
|
|
|
|
<P>
|
|
<BR>
|
|
|
|
<I>RAW_OP</I> :=
|
|
|
|
<B>offset</B><I> OFFSET</I>
|
|
|
|
{ <B>u8</B> | <B>u16</B> | <B>u32</B> } [
|
|
|
|
<I>AT_SPEC</I> ] <I>CMD_SPEC</I>
|
|
|
|
<P>
|
|
<BR>
|
|
|
|
<I>AT_SPEC</I> :=
|
|
|
|
<B>at</B><I> AT </I><B>offmask</B><I> MASK </I><B>shift</B><I> SHIFT</I>
|
|
|
|
<P>
|
|
<BR>
|
|
|
|
<I>LAYERED_OP</I> := {
|
|
|
|
<B>ip</B><I> IPHDR_FIELD</I>
|
|
|
|
|
|
|
<B>ip</B><I> BEYOND_IPHDR_FIELD</I>
|
|
|
|
}<I> CMD_SPEC</I>
|
|
|
|
<P>
|
|
<BR>
|
|
|
|
<I>EXTENDED_LAYERED_OP</I> := {
|
|
|
|
<B>eth</B><I> ETHHDR_FIELD</I>
|
|
|
|
|
|
|
<B>ip</B><I> IPHDR_FIELD</I>
|
|
|
|
|
|
|
<B>ip</B><I> EX_IPHDR_FIELD</I>
|
|
|
|
|
|
|
<B>ip6</B><I> IP6HDR_FIELD</I>
|
|
|
|
|
|
|
<B>tcp</B><I> TCPHDR_FIELD</I>
|
|
|
|
|
|
|
<B>udp</B><I> UDPHDR_FIELD</I>
|
|
|
|
}<I> CMD_SPEC</I>
|
|
|
|
<P>
|
|
<BR>
|
|
|
|
<I>ETHHDR_FIELD</I> := {
|
|
|
|
<B>src</B> | <B>dst</B> | <B>type</B> }
|
|
|
|
<P>
|
|
<BR>
|
|
|
|
<I>IPHDR_FIELD</I> := {
|
|
|
|
<B>src</B> | <B>dst</B> | <B>tos</B> | <B>dsfield</B> | <B>ihl</B> | <B>protocol</B> |
|
|
|
|
<B>precedence</B> | <B>nofrag</B> | <B>firstfrag</B> | <B>ce</B> | <B>df</B> }
|
|
|
|
<P>
|
|
<BR>
|
|
|
|
<I>BEYOND_IPHDR_FIELD</I> := {
|
|
|
|
<B>dport</B> | <B>sport</B> | <B>icmp_type</B> | <B>icmp_code</B> }
|
|
|
|
<P>
|
|
<BR>
|
|
|
|
<I>EX_IPHDR_FIELD</I> := {
|
|
|
|
<B>ttl</B> }
|
|
|
|
<P>
|
|
<P>
|
|
<BR>
|
|
|
|
<I>IP6HDR_FIELD</I> := {
|
|
|
|
<B>src</B> | <B>dst</B> | <B>flow_lbl</B> | <B>payload_len</B> | <B>nexthdr</B> |
|
|
|
|
<B>hoplimit</B> }
|
|
|
|
<P>
|
|
<BR>
|
|
|
|
<I>TCPHDR_FIELD</I> := {
|
|
|
|
<B>sport</B> | <B>dport</B> | <B>flags</B> }
|
|
|
|
<P>
|
|
<BR>
|
|
|
|
<I>UDPHDR_FIELD</I> := {
|
|
|
|
<B>sport</B> | <B>dport</B> }
|
|
|
|
<P>
|
|
<BR>
|
|
|
|
<I>CMD_SPEC</I> := {
|
|
|
|
<B>clear</B> | <B>invert</B> | <B>set</B>
|
|
|
|
<I>VAL</I> |
|
|
|
|
<B>add</B>
|
|
|
|
<I>VAL</I> |
|
|
|
|
<B>preserve</B> } [ <B>retain</B>
|
|
|
|
<I>RVAL</I> ]
|
|
|
|
<P>
|
|
<BR>
|
|
|
|
<I>CONTROL</I> := {
|
|
|
|
<B>reclassify</B> | <B>pipe</B> | <B>drop</B> | <B>shot</B> | <B>continue</B> | <B>pass</B> | <B>goto</B> <B>chain</B> <B>CHAIN_INDEX</B> }
|
|
|
|
<A NAME="lbAD"> </A>
|
|
<H2>DESCRIPTION</H2>
|
|
|
|
The
|
|
<B>pedit</B>
|
|
|
|
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
|
|
<I>RAW_OP</I>,
|
|
|
|
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.
|
|
<A NAME="lbAE"> </A>
|
|
<H2>OPTIONS</H2>
|
|
|
|
<DL COMPACT>
|
|
<DT id="1"><B>ex</B>
|
|
|
|
<DD>
|
|
Use extended pedit.
|
|
<I>EXTENDED_LAYERED_OP</I>
|
|
|
|
and the add
|
|
<I>CMD_SPEC</I>
|
|
|
|
are allowed only in this mode.
|
|
<DT id="2"><B>offset</B><I> OFFSET </I><B></B>{ <B>u32 </B>| <B>u16 </B>| <B>u8 </B>}
|
|
|
|
<DD>
|
|
Specify the offset at which to change data.
|
|
<I>OFFSET</I>
|
|
|
|
is a signed integer, it's base is automatically chosen (e.g. hex if prefixed by
|
|
<B>0x</B>
|
|
|
|
or octal if prefixed by
|
|
<B>0</B>).
|
|
|
|
The second argument specifies the length of data to change, that is four bytes
|
|
(<B>u32</B>),
|
|
|
|
two bytes
|
|
(<B>u16</B>)
|
|
|
|
or a single byte
|
|
(<B>u8</B>).
|
|
|
|
<DT id="3"><B>at</B><I> AT </I><B>offmask</B><I> MASK </I><B>shift</B><I> SHIFT</I>
|
|
|
|
<DD>
|
|
This is an optional part of
|
|
<I>RAW_OP</I>
|
|
|
|
which allows to have a variable
|
|
<I>OFFSET</I>
|
|
|
|
depending on packet data at offset
|
|
<I>AT</I>,
|
|
|
|
which is binary ANDed with
|
|
<I>MASK</I>
|
|
|
|
and right-shifted by
|
|
<I>SHIFT</I>
|
|
|
|
before adding it to
|
|
<I>OFFSET</I>.
|
|
|
|
<DT id="4"><B>eth</B><I> ETHHDR_FIELD</I>
|
|
|
|
<DD>
|
|
Change an ETH header field. The supported keywords for
|
|
<I>ETHHDR_FIELD</I>
|
|
|
|
are:
|
|
<DL COMPACT><DT id="5"><DD>
|
|
<DL COMPACT>
|
|
<DT id="6"><B>src</B>
|
|
|
|
<DD>
|
|
|
|
<B>dst</B>
|
|
|
|
Source or destination MAC address in the standard format: XX:XX:XX:XX:XX:XX
|
|
<DT id="7"><B>type</B>
|
|
|
|
<DD>
|
|
Ether-type in numeric value
|
|
</DL>
|
|
</DL>
|
|
|
|
<DT id="8"><B>ip</B><I> IPHDR_FIELD</I>
|
|
|
|
<DD>
|
|
Change an IPv4 header field. The supported keywords for
|
|
<I>IPHDR_FIELD</I>
|
|
|
|
are:
|
|
<DL COMPACT><DT id="9"><DD>
|
|
<DL COMPACT>
|
|
<DT id="10"><B>src</B>
|
|
|
|
<DD>
|
|
|
|
<B>dst</B>
|
|
|
|
Source or destination IP address, a four-byte value.
|
|
<DT id="11"><B>tos</B>
|
|
|
|
<DD>
|
|
|
|
<B>dsfield</B>
|
|
|
|
|
|
<B>precedence</B>
|
|
|
|
Type Of Service field, an eight-bit value.
|
|
<DT id="12"><B>ihl</B>
|
|
|
|
<DD>
|
|
Change the IP Header Length field, a four-bit value.
|
|
<DT id="13"><B>protocol</B>
|
|
|
|
<DD>
|
|
Next-layer Protocol field, an eight-bit value.
|
|
<DT id="14"><B>nofrag</B>
|
|
|
|
<DD>
|
|
|
|
<B>firstfrag</B>
|
|
|
|
|
|
<B>ce</B>
|
|
|
|
|
|
<B>df</B>
|
|
|
|
|
|
<B>mf</B>
|
|
|
|
Change IP header flags. Note that the value to pass to the
|
|
<B>set</B>
|
|
|
|
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.
|
|
</DL>
|
|
</DL>
|
|
|
|
<DT id="15"><B>ip</B><I> BEYOND_IPHDR_FIELD</I>
|
|
|
|
<DD>
|
|
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</I>
|
|
|
|
are:
|
|
<DL COMPACT><DT id="16"><DD>
|
|
<DL COMPACT>
|
|
<DT id="17"><B>dport</B>
|
|
|
|
<DD>
|
|
|
|
<B>sport</B>
|
|
|
|
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.
|
|
<DT id="18"><B>icmp_type</B>
|
|
|
|
<DD>
|
|
|
|
<B>icmp_code</B>
|
|
|
|
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.
|
|
</DL>
|
|
</DL>
|
|
|
|
<DT id="19"><B>ip</B><I> EX_IPHDR_FIELD</I>
|
|
|
|
<DD>
|
|
Supported only when
|
|
<I>ex</I>
|
|
|
|
is used. The supported keywords for
|
|
<I>EX_IPHDR_FIELD</I>
|
|
|
|
are:
|
|
<DL COMPACT><DT id="20"><DD>
|
|
<DL COMPACT>
|
|
<DT id="21"><B>ttl</B>
|
|
|
|
<DD>
|
|
</DL>
|
|
</DL>
|
|
|
|
<DT id="22"><B>ip6</B><I> IP6HDR_FIELD</I>
|
|
|
|
<DD>
|
|
The supported keywords for
|
|
<I>IP6HDR_FIELD</I>
|
|
|
|
are:
|
|
<DL COMPACT><DT id="23"><DD>
|
|
<DL COMPACT>
|
|
<DT id="24"><B>src</B>
|
|
|
|
<DD>
|
|
|
|
<B>dst</B>
|
|
|
|
|
|
<B>flow_lbl</B>
|
|
|
|
|
|
<B>payload_len</B>
|
|
|
|
|
|
<B>nexthdr</B>
|
|
|
|
|
|
<B>hoplimit</B>
|
|
|
|
</DL>
|
|
</DL>
|
|
|
|
<DT id="25"><B>tcp</B><I> TCPHDR_FIELD</I>
|
|
|
|
<DD>
|
|
The supported keywords for
|
|
<I>TCPHDR_FIELD</I>
|
|
|
|
are:
|
|
<DL COMPACT><DT id="26"><DD>
|
|
<DL COMPACT>
|
|
<DT id="27"><B>sport</B>
|
|
|
|
<DD>
|
|
|
|
<B>dport</B>
|
|
|
|
Source or destination TCP port number, a 16-bit value.
|
|
<DT id="28"><B>flags</B>
|
|
|
|
<DD>
|
|
</DL>
|
|
</DL>
|
|
|
|
<DT id="29"><B>udp</B><I> UDPHDR_FIELD</I>
|
|
|
|
<DD>
|
|
The supported keywords for
|
|
<I>UDPHDR_FIELD</I>
|
|
|
|
are:
|
|
<DL COMPACT><DT id="30"><DD>
|
|
<DL COMPACT>
|
|
<DT id="31"><B>sport</B>
|
|
|
|
<DD>
|
|
|
|
<B>dport</B>
|
|
|
|
Source or destination TCP port number, a 16-bit value.
|
|
</DL>
|
|
</DL>
|
|
|
|
<DT id="32"><B>clear</B>
|
|
|
|
<DD>
|
|
Clear the addressed data (i.e., set it to zero).
|
|
<DT id="33"><B>invert</B>
|
|
|
|
<DD>
|
|
Swap every bit in the addressed data.
|
|
<DT id="34"><B>set</B><I> VAL</I>
|
|
|
|
<DD>
|
|
Set the addressed data to a specific value. The size of
|
|
<I>VAL</I>
|
|
|
|
is defined by either one of the
|
|
<B>u32</B>, <B>u16</B> or <B>u8</B>
|
|
|
|
keywords in
|
|
<I>RAW_OP</I>,
|
|
|
|
or the size of the addressed header field in
|
|
<I>LAYERED_OP</I>.
|
|
|
|
<DT id="35"><B>add</B><I> VAL</I>
|
|
|
|
<DD>
|
|
Add the addressed data by a specific value. The size of
|
|
<I>VAL</I>
|
|
|
|
is defined by the size of the addressed header field in
|
|
<I>EXTENDED_LAYERED_OP</I>.
|
|
|
|
This operation is supported only for extended layered op.
|
|
<DT id="36"><B>preserve</B>
|
|
|
|
<DD>
|
|
Keep the addressed data as is.
|
|
<DT id="37"><B>retain</B><I> RVAL</I>
|
|
|
|
<DD>
|
|
This optional extra part of
|
|
<I>CMD_SPEC</I>
|
|
|
|
allows to exclude bits from being changed. Supported only for 32 bits fields
|
|
or smaller.
|
|
<DT id="38"><I>CONTROL</I>
|
|
|
|
<DD>
|
|
The following keywords allow to control how the tree of qdisc, classes,
|
|
filters and actions is further traversed after this action.
|
|
<DL COMPACT><DT id="39"><DD>
|
|
<DL COMPACT>
|
|
<DT id="40"><B>reclassify</B>
|
|
|
|
<DD>
|
|
Restart with the first filter in the current list.
|
|
<DT id="41"><B>pipe</B>
|
|
|
|
<DD>
|
|
Continue with the next action attached to the same filter.
|
|
<DT id="42"><B>drop</B>
|
|
|
|
<DD>
|
|
|
|
<B>shot</B>
|
|
|
|
Drop the packet.
|
|
<DT id="43"><B>continue</B>
|
|
|
|
<DD>
|
|
Continue classification with the next filter in line.
|
|
<DT id="44"><B>pass</B>
|
|
|
|
<DD>
|
|
Finish classification process and return to calling qdisc for further packet
|
|
processing. This is the default.
|
|
</DL>
|
|
</DL>
|
|
|
|
</DL>
|
|
<A NAME="lbAF"> </A>
|
|
<H2>EXAMPLES</H2>
|
|
|
|
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:
|
|
<P>
|
|
First, qdiscs need to be set up to attach filters to. For the receive path, a simple
|
|
<B>ingress</B>
|
|
|
|
qdisc will do, for transmit path a classful qdisc
|
|
(<B>HTB</B>
|
|
|
|
in this case) is necessary:
|
|
<P>
|
|
<DL COMPACT><DT id="45"><DD>
|
|
|
|
tc qdisc replace dev eth0 root handle 1: htb
|
|
tc qdisc add dev eth0 ingress handle ffff:
|
|
|
|
</DL>
|
|
|
|
<P>
|
|
Finally, a filter with
|
|
<B>pedit</B>
|
|
|
|
action can be added for each direction. In this case,
|
|
<B>u32</B>
|
|
|
|
is used matching on the port number to redirect from, while
|
|
<B>pedit</B>
|
|
|
|
then does the actual rewriting:
|
|
<P>
|
|
<DL COMPACT><DT id="46"><DD>
|
|
|
|
tc filter add dev eth0 parent 1: u32 \
|
|
<TT> </TT>match ip dport 23 0xffff \<BR>
|
|
<TT> </TT>action pedit pedit munge ip dport set 22<BR>
|
|
tc filter add dev eth0 parent ffff: u32 \
|
|
<TT> </TT>match ip sport 22 0xffff \<BR>
|
|
<TT> </TT>action pedit pedit munge ip sport set 23<BR>
|
|
tc filter add dev eth0 parent ffff: u32 \
|
|
<TT> </TT>match ip sport 22 0xffff \<BR>
|
|
<TT> </TT>action pedit ex munge ip dst set 192.168.1.199<BR>
|
|
tc filter add dev eth0 parent ffff: u32 \
|
|
<TT> </TT>match ip sport 22 0xffff \<BR>
|
|
<TT> </TT>action pedit ex munge ip6 dst set fe80::dacb:8aff:fec7:320e<BR>
|
|
tc filter add dev eth0 parent ffff: u32 \
|
|
<TT> </TT>match ip sport 22 0xffff \<BR>
|
|
<TT> </TT>action pedit ex munge eth dst set 11:22:33:44:55:66<BR>
|
|
tc filter add dev eth0 parent ffff: u32 \
|
|
<TT> </TT>match ip dport 23 0xffff \<BR>
|
|
<TT> </TT>action pedit ex munge tcp dport set 22<BR>
|
|
|
|
</DL>
|
|
|
|
<A NAME="lbAG"> </A>
|
|
<H2>SEE ALSO</H2>
|
|
|
|
<B><A HREF="/cgi-bin/man/man2html?8+tc">tc</A></B>(8),
|
|
|
|
<B><A HREF="/cgi-bin/man/man2html?8+tc-htb">tc-htb</A></B>(8),
|
|
|
|
<B><A HREF="/cgi-bin/man/man2html?8+tc-u32">tc-u32</A></B>(8)
|
|
|
|
<P>
|
|
|
|
<HR>
|
|
<A NAME="index"> </A><H2>Index</H2>
|
|
<DL>
|
|
<DT id="47"><A HREF="#lbAB">NAME</A><DD>
|
|
<DT id="48"><A HREF="#lbAC">SYNOPSIS</A><DD>
|
|
<DT id="49"><A HREF="#lbAD">DESCRIPTION</A><DD>
|
|
<DT id="50"><A HREF="#lbAE">OPTIONS</A><DD>
|
|
<DT id="51"><A HREF="#lbAF">EXAMPLES</A><DD>
|
|
<DT id="52"><A HREF="#lbAG">SEE ALSO</A><DD>
|
|
</DL>
|
|
<HR>
|
|
This document was created by
|
|
<A HREF="/cgi-bin/man/man2html">man2html</A>,
|
|
using the manual pages.<BR>
|
|
Time: 00:06:17 GMT, March 31, 2021
|
|
</BODY>
|
|
</HTML>
|