]> git.proxmox.com Git - mirror_iproute2.git/blame - tc/m_tunnel_key.c
man: tc-csum.8: Fix inconsistency in example description
[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");
50907a82
JB
25 fprintf(stderr, " tunnel_key set <TUNNEL_KEY>\n");
26 fprintf(stderr,
27 "Where TUNNEL_KEY is a combination of:\n"
28 "id <TUNNELID> (mandatory)\n"
29 "src_ip <IP> (mandatory)\n"
30 "dst_ip <IP> (mandatory)\n"
59eb271d
JB
31 "dst_port <UDP_PORT>\n"
32 "csum | nocsum (default is \"csum\")\n");
d57639a4
AV
33}
34
35static void usage(void)
36{
37 explain();
38 exit(-1);
39}
40
41static int tunnel_key_parse_ip_addr(const char *str, int addr4_type,
42 int addr6_type, struct nlmsghdr *n)
43{
44 inet_prefix addr;
45 int ret;
46
47 ret = get_addr(&addr, str, AF_UNSPEC);
48 if (ret)
49 return ret;
50
51 addattr_l(n, MAX_MSG, addr.family == AF_INET ? addr4_type : addr6_type,
52 addr.data, addr.bytelen);
53
54 return 0;
55}
56
57static int tunnel_key_parse_key_id(const char *str, int type,
58 struct nlmsghdr *n)
59{
60 __be32 key_id;
61 int ret;
62
63 ret = get_be32(&key_id, str, 10);
64 if (!ret)
65 addattr32(n, MAX_MSG, type, key_id);
66
67 return ret;
68}
69
449c709c
HHZ
70static int tunnel_key_parse_dst_port(char *str, int type, struct nlmsghdr *n)
71{
72 int ret;
73 __be16 dst_port;
74
75 ret = get_be16(&dst_port, str, 10);
76 if (ret)
77 return -1;
78
79 addattr16(n, MAX_MSG, type, dst_port);
80
81 return 0;
82}
83
d57639a4
AV
84static int parse_tunnel_key(struct action_util *a, int *argc_p, char ***argv_p,
85 int tca_id, struct nlmsghdr *n)
86{
e67aba55 87 struct tc_tunnel_key parm = {};
d57639a4
AV
88 char **argv = *argv_p;
89 int argc = *argc_p;
90 struct rtattr *tail;
91 int action = 0;
92 int ret;
93 int has_src_ip = 0;
94 int has_dst_ip = 0;
95 int has_key_id = 0;
59eb271d 96 int csum = 1;
d57639a4
AV
97
98 if (matches(*argv, "tunnel_key") != 0)
99 return -1;
100
101 tail = NLMSG_TAIL(n);
102 addattr_l(n, MAX_MSG, tca_id, NULL, 0);
103
104 NEXT_ARG();
105
106 while (argc > 0) {
107 if (matches(*argv, "unset") == 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_RELEASE;
115 } else if (matches(*argv, "set") == 0) {
116 if (action) {
117 fprintf(stderr, "unexpected \"%s\" - action already specified\n",
118 *argv);
119 explain();
120 return -1;
121 }
122 action = TCA_TUNNEL_KEY_ACT_SET;
123 } else if (matches(*argv, "src_ip") == 0) {
124 NEXT_ARG();
125 ret = tunnel_key_parse_ip_addr(*argv,
126 TCA_TUNNEL_KEY_ENC_IPV4_SRC,
127 TCA_TUNNEL_KEY_ENC_IPV6_SRC,
128 n);
129 if (ret < 0) {
130 fprintf(stderr, "Illegal \"src_ip\"\n");
131 return -1;
132 }
133 has_src_ip = 1;
134 } else if (matches(*argv, "dst_ip") == 0) {
135 NEXT_ARG();
136 ret = tunnel_key_parse_ip_addr(*argv,
137 TCA_TUNNEL_KEY_ENC_IPV4_DST,
138 TCA_TUNNEL_KEY_ENC_IPV6_DST,
139 n);
140 if (ret < 0) {
141 fprintf(stderr, "Illegal \"dst_ip\"\n");
142 return -1;
143 }
144 has_dst_ip = 1;
145 } else if (matches(*argv, "id") == 0) {
146 NEXT_ARG();
147 ret = tunnel_key_parse_key_id(*argv, TCA_TUNNEL_KEY_ENC_KEY_ID, n);
148 if (ret < 0) {
149 fprintf(stderr, "Illegal \"id\"\n");
150 return -1;
151 }
152 has_key_id = 1;
449c709c
HHZ
153 } else if (matches(*argv, "dst_port") == 0) {
154 NEXT_ARG();
155 ret = tunnel_key_parse_dst_port(*argv,
156 TCA_TUNNEL_KEY_ENC_DST_PORT, n);
157 if (ret < 0) {
158 fprintf(stderr, "Illegal \"dst port\"\n");
159 return -1;
160 }
59eb271d
JB
161 } else if (matches(*argv, "csum") == 0) {
162 csum = 1;
163 } else if (matches(*argv, "nocsum") == 0) {
164 csum = 0;
d57639a4
AV
165 } else if (matches(*argv, "help") == 0) {
166 usage();
167 } else {
168 break;
169 }
170 NEXT_ARG_FWD();
171 }
172
59eb271d
JB
173 addattr8(n, MAX_MSG, TCA_TUNNEL_KEY_NO_CSUM, !csum);
174
e67aba55
JP
175 parse_action_control_dflt(&argc, &argv, &parm.action,
176 false, TC_ACT_PIPE);
d57639a4
AV
177
178 if (argc) {
179 if (matches(*argv, "index") == 0) {
180 NEXT_ARG();
181 if (get_u32(&parm.index, *argv, 10)) {
182 fprintf(stderr, "tunnel_key: Illegal \"index\"\n");
183 return -1;
184 }
185
186 NEXT_ARG_FWD();
187 }
188 }
189
190 if (action == TCA_TUNNEL_KEY_ACT_SET &&
191 (!has_src_ip || !has_dst_ip || !has_key_id)) {
192 fprintf(stderr, "set needs tunnel_key parameters\n");
193 explain();
194 return -1;
195 }
196
197 parm.t_action = action;
198 addattr_l(n, MAX_MSG, TCA_TUNNEL_KEY_PARMS, &parm, sizeof(parm));
199 tail->rta_len = (char *)NLMSG_TAIL(n) - (char *)tail;
200
201 *argc_p = argc;
202 *argv_p = argv;
203
204 return 0;
205}
206
207static void tunnel_key_print_ip_addr(FILE *f, const char *name,
208 struct rtattr *attr)
209{
210 int family;
211 size_t len;
212
213 if (!attr)
214 return;
215
216 len = RTA_PAYLOAD(attr);
217
218 if (len == 4)
219 family = AF_INET;
220 else if (len == 16)
221 family = AF_INET6;
222 else
223 return;
224
225 fprintf(f, "\n\t%s %s", name, rt_addr_n2a_rta(family, attr));
226}
227
228static void tunnel_key_print_key_id(FILE *f, const char *name,
229 struct rtattr *attr)
230{
231 if (!attr)
232 return;
233 fprintf(f, "\n\t%s %d", name, rta_getattr_be32(attr));
234}
235
449c709c
HHZ
236static void tunnel_key_print_dst_port(FILE *f, char *name,
237 struct rtattr *attr)
238{
239 if (!attr)
240 return;
241 fprintf(f, "\n\t%s %d", name, rta_getattr_be16(attr));
242}
243
59eb271d
JB
244static void tunnel_key_print_flag(FILE *f, const char *name_on,
245 const char *name_off,
246 struct rtattr *attr)
247{
248 if (!attr)
249 return;
250 fprintf(f, "\n\t%s", rta_getattr_u8(attr) ? name_on : name_off);
251}
252
d57639a4
AV
253static int print_tunnel_key(struct action_util *au, FILE *f, struct rtattr *arg)
254{
255 struct rtattr *tb[TCA_TUNNEL_KEY_MAX + 1];
256 struct tc_tunnel_key *parm;
257
258 if (!arg)
259 return -1;
260
261 parse_rtattr_nested(tb, TCA_TUNNEL_KEY_MAX, arg);
262
263 if (!tb[TCA_TUNNEL_KEY_PARMS]) {
264 fprintf(f, "[NULL tunnel_key parameters]");
265 return -1;
266 }
267 parm = RTA_DATA(tb[TCA_TUNNEL_KEY_PARMS]);
268
269 fprintf(f, "tunnel_key");
270
271 switch (parm->t_action) {
272 case TCA_TUNNEL_KEY_ACT_RELEASE:
273 fprintf(f, " unset");
274 break;
275 case TCA_TUNNEL_KEY_ACT_SET:
276 fprintf(f, " set");
277 tunnel_key_print_ip_addr(f, "src_ip",
278 tb[TCA_TUNNEL_KEY_ENC_IPV4_SRC]);
279 tunnel_key_print_ip_addr(f, "dst_ip",
280 tb[TCA_TUNNEL_KEY_ENC_IPV4_DST]);
281 tunnel_key_print_ip_addr(f, "src_ip",
282 tb[TCA_TUNNEL_KEY_ENC_IPV6_SRC]);
283 tunnel_key_print_ip_addr(f, "dst_ip",
284 tb[TCA_TUNNEL_KEY_ENC_IPV6_DST]);
285 tunnel_key_print_key_id(f, "key_id",
286 tb[TCA_TUNNEL_KEY_ENC_KEY_ID]);
449c709c
HHZ
287 tunnel_key_print_dst_port(f, "dst_port",
288 tb[TCA_TUNNEL_KEY_ENC_DST_PORT]);
59eb271d
JB
289 tunnel_key_print_flag(f, "nocsum", "csum",
290 tb[TCA_TUNNEL_KEY_NO_CSUM]);
d57639a4
AV
291 break;
292 }
e67aba55 293 print_action_control(f, " ", parm->action, "");
d57639a4
AV
294
295 fprintf(f, "\n\tindex %d ref %d bind %d", parm->index, parm->refcnt,
296 parm->bindcnt);
297
298 if (show_stats) {
299 if (tb[TCA_TUNNEL_KEY_TM]) {
300 struct tcf_t *tm = RTA_DATA(tb[TCA_TUNNEL_KEY_TM]);
301
302 print_tm(f, tm);
303 }
304 }
305
306 fprintf(f, "\n ");
307
308 return 0;
309}
310
311struct action_util tunnel_key_action_util = {
312 .id = "tunnel_key",
313 .parse_aopt = parse_tunnel_key,
314 .print_aopt = print_tunnel_key,
315};