]> git.proxmox.com Git - mirror_iproute2.git/blame - tc/m_tunnel_key.c
tc_filter: add support for chain index
[mirror_iproute2.git] / tc / m_tunnel_key.c
CommitLineData
d57639a4
AV
1/*
2 * m_tunnel_key.c ip tunnel manipulation module
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Authors: Amir Vadai <amir@vadai.me>
10 */
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <unistd.h>
15#include <string.h>
16#include <linux/if_ether.h>
17#include "utils.h"
18#include "rt_names.h"
19#include "tc_util.h"
20#include <linux/tc_act/tc_tunnel_key.h>
21
22static void explain(void)
23{
24 fprintf(stderr, "Usage: tunnel_key unset\n");
f6d3126e 25 fprintf(stderr, " tunnel_key set id TUNNELID src_ip IP dst_ip IP dst_port UDP_PORT\n");
d57639a4
AV
26}
27
28static void usage(void)
29{
30 explain();
31 exit(-1);
32}
33
34static int tunnel_key_parse_ip_addr(const char *str, int addr4_type,
35 int addr6_type, struct nlmsghdr *n)
36{
37 inet_prefix addr;
38 int ret;
39
40 ret = get_addr(&addr, str, AF_UNSPEC);
41 if (ret)
42 return ret;
43
44 addattr_l(n, MAX_MSG, addr.family == AF_INET ? addr4_type : addr6_type,
45 addr.data, addr.bytelen);
46
47 return 0;
48}
49
50static int tunnel_key_parse_key_id(const char *str, int type,
51 struct nlmsghdr *n)
52{
53 __be32 key_id;
54 int ret;
55
56 ret = get_be32(&key_id, str, 10);
57 if (!ret)
58 addattr32(n, MAX_MSG, type, key_id);
59
60 return ret;
61}
62
449c709c
HHZ
63static int tunnel_key_parse_dst_port(char *str, int type, struct nlmsghdr *n)
64{
65 int ret;
66 __be16 dst_port;
67
68 ret = get_be16(&dst_port, str, 10);
69 if (ret)
70 return -1;
71
72 addattr16(n, MAX_MSG, type, dst_port);
73
74 return 0;
75}
76
d57639a4
AV
77static int parse_tunnel_key(struct action_util *a, int *argc_p, char ***argv_p,
78 int tca_id, struct nlmsghdr *n)
79{
80 struct tc_tunnel_key parm = { .action = TC_ACT_PIPE };
81 char **argv = *argv_p;
82 int argc = *argc_p;
83 struct rtattr *tail;
84 int action = 0;
85 int ret;
86 int has_src_ip = 0;
87 int has_dst_ip = 0;
88 int has_key_id = 0;
89
90 if (matches(*argv, "tunnel_key") != 0)
91 return -1;
92
93 tail = NLMSG_TAIL(n);
94 addattr_l(n, MAX_MSG, tca_id, NULL, 0);
95
96 NEXT_ARG();
97
98 while (argc > 0) {
99 if (matches(*argv, "unset") == 0) {
100 if (action) {
101 fprintf(stderr, "unexpected \"%s\" - action already specified\n",
102 *argv);
103 explain();
104 return -1;
105 }
106 action = TCA_TUNNEL_KEY_ACT_RELEASE;
107 } else if (matches(*argv, "set") == 0) {
108 if (action) {
109 fprintf(stderr, "unexpected \"%s\" - action already specified\n",
110 *argv);
111 explain();
112 return -1;
113 }
114 action = TCA_TUNNEL_KEY_ACT_SET;
115 } else if (matches(*argv, "src_ip") == 0) {
116 NEXT_ARG();
117 ret = tunnel_key_parse_ip_addr(*argv,
118 TCA_TUNNEL_KEY_ENC_IPV4_SRC,
119 TCA_TUNNEL_KEY_ENC_IPV6_SRC,
120 n);
121 if (ret < 0) {
122 fprintf(stderr, "Illegal \"src_ip\"\n");
123 return -1;
124 }
125 has_src_ip = 1;
126 } else if (matches(*argv, "dst_ip") == 0) {
127 NEXT_ARG();
128 ret = tunnel_key_parse_ip_addr(*argv,
129 TCA_TUNNEL_KEY_ENC_IPV4_DST,
130 TCA_TUNNEL_KEY_ENC_IPV6_DST,
131 n);
132 if (ret < 0) {
133 fprintf(stderr, "Illegal \"dst_ip\"\n");
134 return -1;
135 }
136 has_dst_ip = 1;
137 } else if (matches(*argv, "id") == 0) {
138 NEXT_ARG();
139 ret = tunnel_key_parse_key_id(*argv, TCA_TUNNEL_KEY_ENC_KEY_ID, n);
140 if (ret < 0) {
141 fprintf(stderr, "Illegal \"id\"\n");
142 return -1;
143 }
144 has_key_id = 1;
449c709c
HHZ
145 } else if (matches(*argv, "dst_port") == 0) {
146 NEXT_ARG();
147 ret = tunnel_key_parse_dst_port(*argv,
148 TCA_TUNNEL_KEY_ENC_DST_PORT, n);
149 if (ret < 0) {
150 fprintf(stderr, "Illegal \"dst port\"\n");
151 return -1;
152 }
d57639a4
AV
153 } else if (matches(*argv, "help") == 0) {
154 usage();
155 } else {
156 break;
157 }
158 NEXT_ARG_FWD();
159 }
160
161 if (argc && !action_a2n(*argv, &parm.action, false))
162 NEXT_ARG_FWD();
163
164 if (argc) {
165 if (matches(*argv, "index") == 0) {
166 NEXT_ARG();
167 if (get_u32(&parm.index, *argv, 10)) {
168 fprintf(stderr, "tunnel_key: Illegal \"index\"\n");
169 return -1;
170 }
171
172 NEXT_ARG_FWD();
173 }
174 }
175
176 if (action == TCA_TUNNEL_KEY_ACT_SET &&
177 (!has_src_ip || !has_dst_ip || !has_key_id)) {
178 fprintf(stderr, "set needs tunnel_key parameters\n");
179 explain();
180 return -1;
181 }
182
183 parm.t_action = action;
184 addattr_l(n, MAX_MSG, TCA_TUNNEL_KEY_PARMS, &parm, sizeof(parm));
185 tail->rta_len = (char *)NLMSG_TAIL(n) - (char *)tail;
186
187 *argc_p = argc;
188 *argv_p = argv;
189
190 return 0;
191}
192
193static void tunnel_key_print_ip_addr(FILE *f, const char *name,
194 struct rtattr *attr)
195{
196 int family;
197 size_t len;
198
199 if (!attr)
200 return;
201
202 len = RTA_PAYLOAD(attr);
203
204 if (len == 4)
205 family = AF_INET;
206 else if (len == 16)
207 family = AF_INET6;
208 else
209 return;
210
211 fprintf(f, "\n\t%s %s", name, rt_addr_n2a_rta(family, attr));
212}
213
214static void tunnel_key_print_key_id(FILE *f, const char *name,
215 struct rtattr *attr)
216{
217 if (!attr)
218 return;
219 fprintf(f, "\n\t%s %d", name, rta_getattr_be32(attr));
220}
221
449c709c
HHZ
222static void tunnel_key_print_dst_port(FILE *f, char *name,
223 struct rtattr *attr)
224{
225 if (!attr)
226 return;
227 fprintf(f, "\n\t%s %d", name, rta_getattr_be16(attr));
228}
229
d57639a4
AV
230static int print_tunnel_key(struct action_util *au, FILE *f, struct rtattr *arg)
231{
232 struct rtattr *tb[TCA_TUNNEL_KEY_MAX + 1];
233 struct tc_tunnel_key *parm;
234
235 if (!arg)
236 return -1;
237
238 parse_rtattr_nested(tb, TCA_TUNNEL_KEY_MAX, arg);
239
240 if (!tb[TCA_TUNNEL_KEY_PARMS]) {
241 fprintf(f, "[NULL tunnel_key parameters]");
242 return -1;
243 }
244 parm = RTA_DATA(tb[TCA_TUNNEL_KEY_PARMS]);
245
246 fprintf(f, "tunnel_key");
247
248 switch (parm->t_action) {
249 case TCA_TUNNEL_KEY_ACT_RELEASE:
250 fprintf(f, " unset");
251 break;
252 case TCA_TUNNEL_KEY_ACT_SET:
253 fprintf(f, " set");
254 tunnel_key_print_ip_addr(f, "src_ip",
255 tb[TCA_TUNNEL_KEY_ENC_IPV4_SRC]);
256 tunnel_key_print_ip_addr(f, "dst_ip",
257 tb[TCA_TUNNEL_KEY_ENC_IPV4_DST]);
258 tunnel_key_print_ip_addr(f, "src_ip",
259 tb[TCA_TUNNEL_KEY_ENC_IPV6_SRC]);
260 tunnel_key_print_ip_addr(f, "dst_ip",
261 tb[TCA_TUNNEL_KEY_ENC_IPV6_DST]);
262 tunnel_key_print_key_id(f, "key_id",
263 tb[TCA_TUNNEL_KEY_ENC_KEY_ID]);
449c709c
HHZ
264 tunnel_key_print_dst_port(f, "dst_port",
265 tb[TCA_TUNNEL_KEY_ENC_DST_PORT]);
d57639a4
AV
266 break;
267 }
268 fprintf(f, " %s", action_n2a(parm->action));
269
270 fprintf(f, "\n\tindex %d ref %d bind %d", parm->index, parm->refcnt,
271 parm->bindcnt);
272
273 if (show_stats) {
274 if (tb[TCA_TUNNEL_KEY_TM]) {
275 struct tcf_t *tm = RTA_DATA(tb[TCA_TUNNEL_KEY_TM]);
276
277 print_tm(f, tm);
278 }
279 }
280
281 fprintf(f, "\n ");
282
283 return 0;
284}
285
286struct action_util tunnel_key_action_util = {
287 .id = "tunnel_key",
288 .parse_aopt = parse_tunnel_key,
289 .print_aopt = print_tunnel_key,
290};