]> git.proxmox.com Git - mirror_iproute2.git/blob - tc/m_tunnel_key.c
2dc91879c237566a376bd28b8b3221fabc3de5ad
[mirror_iproute2.git] / tc / m_tunnel_key.c
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
22 static void explain(void)
23 {
24 fprintf(stderr, "Usage: tunnel_key unset\n");
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"
31 "dst_port <UDP_PORT>\n"
32 "csum | nocsum (default is \"csum\")\n");
33 }
34
35 static void usage(void)
36 {
37 explain();
38 exit(-1);
39 }
40
41 static 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
57 static 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
70 static 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
84 static int parse_tunnel_key(struct action_util *a, int *argc_p, char ***argv_p,
85 int tca_id, struct nlmsghdr *n)
86 {
87 struct tc_tunnel_key parm = {};
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;
96 int csum = 1;
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;
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 }
161 } else if (matches(*argv, "csum") == 0) {
162 csum = 1;
163 } else if (matches(*argv, "nocsum") == 0) {
164 csum = 0;
165 } else if (matches(*argv, "help") == 0) {
166 usage();
167 } else {
168 break;
169 }
170 NEXT_ARG_FWD();
171 }
172
173 addattr8(n, MAX_MSG, TCA_TUNNEL_KEY_NO_CSUM, !csum);
174
175 parse_action_control_dflt(&argc, &argv, &parm.action,
176 false, TC_ACT_PIPE);
177
178 NEXT_ARG_FWD();
179 if (argc) {
180 if (matches(*argv, "index") == 0) {
181 NEXT_ARG();
182 if (get_u32(&parm.index, *argv, 10)) {
183 fprintf(stderr, "tunnel_key: Illegal \"index\"\n");
184 return -1;
185 }
186
187 NEXT_ARG_FWD();
188 }
189 }
190
191 if (action == TCA_TUNNEL_KEY_ACT_SET &&
192 (!has_src_ip || !has_dst_ip || !has_key_id)) {
193 fprintf(stderr, "set needs tunnel_key parameters\n");
194 explain();
195 return -1;
196 }
197
198 parm.t_action = action;
199 addattr_l(n, MAX_MSG, TCA_TUNNEL_KEY_PARMS, &parm, sizeof(parm));
200 tail->rta_len = (char *)NLMSG_TAIL(n) - (char *)tail;
201
202 *argc_p = argc;
203 *argv_p = argv;
204
205 return 0;
206 }
207
208 static void tunnel_key_print_ip_addr(FILE *f, const char *name,
209 struct rtattr *attr)
210 {
211 int family;
212 size_t len;
213
214 if (!attr)
215 return;
216
217 len = RTA_PAYLOAD(attr);
218
219 if (len == 4)
220 family = AF_INET;
221 else if (len == 16)
222 family = AF_INET6;
223 else
224 return;
225
226 fprintf(f, "\n\t%s %s", name, rt_addr_n2a_rta(family, attr));
227 }
228
229 static void tunnel_key_print_key_id(FILE *f, const char *name,
230 struct rtattr *attr)
231 {
232 if (!attr)
233 return;
234 fprintf(f, "\n\t%s %d", name, rta_getattr_be32(attr));
235 }
236
237 static void tunnel_key_print_dst_port(FILE *f, char *name,
238 struct rtattr *attr)
239 {
240 if (!attr)
241 return;
242 fprintf(f, "\n\t%s %d", name, rta_getattr_be16(attr));
243 }
244
245 static void tunnel_key_print_flag(FILE *f, const char *name_on,
246 const char *name_off,
247 struct rtattr *attr)
248 {
249 if (!attr)
250 return;
251 fprintf(f, "\n\t%s", rta_getattr_u8(attr) ? name_on : name_off);
252 }
253
254 static int print_tunnel_key(struct action_util *au, FILE *f, struct rtattr *arg)
255 {
256 struct rtattr *tb[TCA_TUNNEL_KEY_MAX + 1];
257 struct tc_tunnel_key *parm;
258
259 if (!arg)
260 return -1;
261
262 parse_rtattr_nested(tb, TCA_TUNNEL_KEY_MAX, arg);
263
264 if (!tb[TCA_TUNNEL_KEY_PARMS]) {
265 fprintf(f, "[NULL tunnel_key parameters]");
266 return -1;
267 }
268 parm = RTA_DATA(tb[TCA_TUNNEL_KEY_PARMS]);
269
270 fprintf(f, "tunnel_key");
271
272 switch (parm->t_action) {
273 case TCA_TUNNEL_KEY_ACT_RELEASE:
274 fprintf(f, " unset");
275 break;
276 case TCA_TUNNEL_KEY_ACT_SET:
277 fprintf(f, " set");
278 tunnel_key_print_ip_addr(f, "src_ip",
279 tb[TCA_TUNNEL_KEY_ENC_IPV4_SRC]);
280 tunnel_key_print_ip_addr(f, "dst_ip",
281 tb[TCA_TUNNEL_KEY_ENC_IPV4_DST]);
282 tunnel_key_print_ip_addr(f, "src_ip",
283 tb[TCA_TUNNEL_KEY_ENC_IPV6_SRC]);
284 tunnel_key_print_ip_addr(f, "dst_ip",
285 tb[TCA_TUNNEL_KEY_ENC_IPV6_DST]);
286 tunnel_key_print_key_id(f, "key_id",
287 tb[TCA_TUNNEL_KEY_ENC_KEY_ID]);
288 tunnel_key_print_dst_port(f, "dst_port",
289 tb[TCA_TUNNEL_KEY_ENC_DST_PORT]);
290 tunnel_key_print_flag(f, "nocsum", "csum",
291 tb[TCA_TUNNEL_KEY_NO_CSUM]);
292 break;
293 }
294 print_action_control(f, " ", parm->action, "");
295
296 fprintf(f, "\n\tindex %d ref %d bind %d", parm->index, parm->refcnt,
297 parm->bindcnt);
298
299 if (show_stats) {
300 if (tb[TCA_TUNNEL_KEY_TM]) {
301 struct tcf_t *tm = RTA_DATA(tb[TCA_TUNNEL_KEY_TM]);
302
303 print_tm(f, tm);
304 }
305 }
306
307 fprintf(f, "\n ");
308
309 return 0;
310 }
311
312 struct action_util tunnel_key_action_util = {
313 .id = "tunnel_key",
314 .parse_aopt = parse_tunnel_key,
315 .print_aopt = print_tunnel_key,
316 };