pedit: Introduce ipv6 support

Add support for modifying IPv6 headers using pedit.

Signed-off-by: Amir Vadai <amir@vadai.me>
This commit is contained in:
Amir Vadai 2017-05-14 11:17:46 +03:00 committed by Stephen Hemminger
parent a13426fe1a
commit f3e1b2448a
5 changed files with 164 additions and 18 deletions

View File

@ -33,6 +33,8 @@ pedit - generic packet editor action
| |
.BI ip " EX_IPHDR_FIELD" .BI ip " EX_IPHDR_FIELD"
| |
.BI ip6 " IP6HDR_FIELD"
|
.BI tcp " TCPHDR_FIELD" .BI tcp " TCPHDR_FIELD"
| |
.BI udp " UDPHDR_FIELD" .BI udp " UDPHDR_FIELD"
@ -55,6 +57,12 @@ pedit - generic packet editor action
.IR EX_IPHDR_FIELD " := { " .IR EX_IPHDR_FIELD " := { "
.BR ttl " }" .BR ttl " }"
.ti -8
.IR IP6HDR_FIELD " := { "
.BR src " | " dst " | " flow_lbl " | " payload_len " | " nexthdr " |"
.BR hoplimit " }"
.ti -8 .ti -8
.IR TCPHDR_FIELD " := { " .IR TCPHDR_FIELD " := { "
.BR sport " | " dport " | " flags " }" .BR sport " | " dport " | " flags " }"
@ -211,6 +219,25 @@ are:
.B ttl .B ttl
.RE .RE
.TP .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" .BI tcp " TCPHDR_FIELD"
The supported keywords for The supported keywords for
.I TCPHDR_FIELD .I TCPHDR_FIELD
@ -329,6 +356,9 @@ tc filter add dev eth0 parent ffff: u32 \\
tc filter add dev eth0 parent ffff: u32 \\ tc filter add dev eth0 parent ffff: u32 \\
match ip sport 22 0xffff \\ match ip sport 22 0xffff \\
action pedit ex munge ip dst set 192.168.1.199 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 \\ tc filter add dev eth0 parent ffff: u32 \\
match ip sport 22 0xffff \\ match ip sport 22 0xffff \\
action pedit ex munge eth dst set 11:22:33:44:55:66 action pedit ex munge eth dst set 11:22:33:44:55:66

View File

@ -53,6 +53,7 @@ TCMODULES += m_bpf.o
TCMODULES += m_tunnel_key.o TCMODULES += m_tunnel_key.o
TCMODULES += m_sample.o TCMODULES += m_sample.o
TCMODULES += p_ip.o TCMODULES += p_ip.o
TCMODULES += p_ip6.o
TCMODULES += p_icmp.o TCMODULES += p_icmp.o
TCMODULES += p_eth.o TCMODULES += p_eth.o
TCMODULES += p_tcp.o TCMODULES += p_tcp.o

View File

@ -257,6 +257,32 @@ static int pack_mac(struct m_pedit_sel *sel, struct m_pedit_key *tkey,
return ret; return ret;
} }
static int pack_ipv6(struct m_pedit_sel *sel, struct m_pedit_key *tkey,
__u32 *ipv6)
{
int ret = 0;
int i;
if (tkey->off & 0x3) {
fprintf(stderr,
"pack_ipv6: IPv6 offsets must begin in 32bit boundaries\n");
return -1;
}
for (i = 0; i < 4; i++) {
tkey->mask = 0;
tkey->val = ntohl(ipv6[i]);
ret = pack_key32(~0, sel, tkey);
if (ret)
return ret;
tkey->off += 4;
}
return 0;
}
int parse_val(int *argc_p, char ***argv_p, __u32 *val, int type) int parse_val(int *argc_p, char ***argv_p, __u32 *val, int type)
{ {
int argc = *argc_p; int argc = *argc_p;
@ -281,8 +307,16 @@ int parse_val(int *argc_p, char ***argv_p, __u32 *val, int type)
return 0; return 0;
} }
if (type == TIPV6) if (type == TIPV6) {
return -1; /* not implemented yet */ inet_prefix addr;
if (get_prefix_1(&addr, *argv, AF_INET6))
return -1;
memcpy(val, addr.data, addr.bytelen);
return 0;
}
if (type == TMAC) { if (type == TMAC) {
#define MAC_ALEN 6 #define MAC_ALEN 6
@ -364,6 +398,11 @@ int parse_cmd(int *argc_p, char ***argv_p, __u32 len, int type, __u32 retain,
goto done; goto done;
} }
if (type == TIPV6) {
res = pack_ipv6(sel, tkey, val);
goto done;
}
tkey->val = *v; tkey->val = *v;
tkey->mask = *m; tkey->mask = *m;

View File

@ -1,5 +1,5 @@
/* /*
* m_pedit.c packet editor: IPV4/6 header * p_ip.c packet editor: IPV4 header
* *
* This program is free software; you can distribute it and/or * This program is free software; you can distribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -156,23 +156,8 @@ done:
return res; return res;
} }
static int
parse_ip6(int *argc_p, char ***argv_p,
struct m_pedit_sel *sel, struct m_pedit_key *tkey)
{
int res = -1;
return res;
}
struct m_pedit_util p_pedit_ip = { struct m_pedit_util p_pedit_ip = {
NULL, NULL,
"ip", "ip",
parse_ip, parse_ip,
}; };
struct m_pedit_util p_pedit_ip6 = {
NULL,
"ip6",
parse_ip6,
};

91
tc/p_ip6.c Normal file
View File

@ -0,0 +1,91 @@
/*
* p_ip6.c packet editor: IPV6 header
*
* This program is free software; you can distribute 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.
*
* Authors: Amir Vadai <amir@vadai.me>
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <syslog.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include "utils.h"
#include "tc_util.h"
#include "m_pedit.h"
static int
parse_ip6(int *argc_p, char ***argv_p,
struct m_pedit_sel *sel, struct m_pedit_key *tkey)
{
int res = -1;
int argc = *argc_p;
char **argv = *argv_p;
if (argc < 2)
return -1;
if (!sel->extended)
return -1;
tkey->htype = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6;
if (strcmp(*argv, "src") == 0) {
NEXT_ARG();
tkey->off = 8;
res = parse_cmd(&argc, &argv, 16, TIPV6, RU32, sel, tkey);
goto done;
}
if (strcmp(*argv, "dst") == 0) {
NEXT_ARG();
tkey->off = 24;
res = parse_cmd(&argc, &argv, 16, TIPV6, RU32, sel, tkey);
goto done;
}
if (strcmp(*argv, "flow_lbl") == 0) {
NEXT_ARG();
tkey->off = 0;
res = parse_cmd(&argc, &argv, 4, TU32, 0x0007ffff, sel, tkey);
goto done;
}
if (strcmp(*argv, "payload_len") == 0) {
NEXT_ARG();
tkey->off = 4;
res = parse_cmd(&argc, &argv, 2, TU32, RU16, sel, tkey);
goto done;
}
if (strcmp(*argv, "nexthdr") == 0) {
NEXT_ARG();
tkey->off = 6;
res = parse_cmd(&argc, &argv, 1, TU32, RU8, sel, tkey);
goto done;
}
if (strcmp(*argv, "hoplimit") == 0) {
NEXT_ARG();
tkey->off = 7;
res = parse_cmd(&argc, &argv, 1, TU32, RU8, sel, tkey);
goto done;
}
return -1;
done:
*argc_p = argc;
*argv_p = argv;
return res;
}
struct m_pedit_util p_pedit_ip6 = {
NULL,
"ipv6",
parse_ip6,
};