]> git.proxmox.com Git - mirror_iproute2.git/blob - ip/xfrm_policy.c
Continue after errors in -batch
[mirror_iproute2.git] / ip / xfrm_policy.c
1 /* $USAGI: $ */
2
3 /*
4 * Copyright (C)2004 USAGI/WIDE Project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20 /*
21 * based on iproute.c
22 */
23 /*
24 * Authors:
25 * Masahide NAKAMURA @USAGI
26 */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <netdb.h>
32 #include <linux/netlink.h>
33 #include <linux/xfrm.h>
34 #include "utils.h"
35 #include "xfrm.h"
36 #include "ip_common.h"
37
38 //#define NLMSG_DELETEALL_BUF_SIZE (4096-512)
39 #define NLMSG_DELETEALL_BUF_SIZE 8192
40
41 /*
42 * Receiving buffer defines:
43 * nlmsg
44 * data = struct xfrm_userpolicy_info
45 * rtattr
46 * data = struct xfrm_user_tmpl[]
47 */
48 #define NLMSG_BUF_SIZE 4096
49 #define RTA_BUF_SIZE 2048
50 #define XFRM_TMPLS_BUF_SIZE 1024
51
52 static void usage(void) __attribute__((noreturn));
53
54 static void usage(void)
55 {
56 fprintf(stderr, "Usage: ip xfrm policy { add | update } dir DIR SELECTOR [ index INDEX ] [ ptype PTYPE ]\n");
57 fprintf(stderr, " [ action ACTION ] [ priority PRIORITY ] [ flag FLAG-LIST ] [ LIMIT-LIST ] [ TMPL-LIST ] [mark MARK [mask MASK]]\n");
58 fprintf(stderr, "Usage: ip xfrm policy { delete | get } dir DIR [ SELECTOR | index INDEX ] [ ptype PTYPE ] [mark MARK [mask MASK]]\n");
59 fprintf(stderr, "Usage: ip xfrm policy { deleteall | list } [ dir DIR ] [ SELECTOR ]\n");
60 fprintf(stderr, " [ index INDEX ] [ action ACTION ] [ priority PRIORITY ] [ flag FLAG-LIST ]\n");
61 fprintf(stderr, "Usage: ip xfrm policy flush [ ptype PTYPE ]\n");
62 fprintf(stderr, "Usage: ip xfrm count\n");
63 fprintf(stderr, "PTYPE := [ main | sub ](default=main)\n");
64 fprintf(stderr, "DIR := [ in | out | fwd ]\n");
65
66 fprintf(stderr, "SELECTOR := src ADDR[/PLEN] dst ADDR[/PLEN] [ UPSPEC ] [ dev DEV ]\n");
67
68 fprintf(stderr, "UPSPEC := proto PROTO [ [ sport PORT ] [ dport PORT ] |\n");
69 fprintf(stderr, " [ type NUMBER ] [ code NUMBER ] ]\n");
70
71 //fprintf(stderr, "DEV - device name(default=none)\n");
72
73 fprintf(stderr, "ACTION := [ allow | block ](default=allow)\n");
74
75 //fprintf(stderr, "PRIORITY - priority value(default=0)\n");
76
77 fprintf(stderr, "FLAG-LIST := [ FLAG-LIST ] FLAG\n");
78 fprintf(stderr, "FLAG := [ localok ]\n");
79
80 fprintf(stderr, "LIMIT-LIST := [ LIMIT-LIST ] | [ limit LIMIT ]\n");
81 fprintf(stderr, "LIMIT := [ [time-soft|time-hard|time-use-soft|time-use-hard] SECONDS ] |\n");
82 fprintf(stderr, " [ [byte-soft|byte-hard] SIZE ] | [ [packet-soft|packet-hard] NUMBER ]\n");
83
84 fprintf(stderr, "TMPL-LIST := [ TMPL-LIST ] | [ tmpl TMPL ]\n");
85 fprintf(stderr, "TMPL := ID [ mode MODE ] [ reqid REQID ] [ level LEVEL ]\n");
86 fprintf(stderr, "ID := [ src ADDR ] [ dst ADDR ] [ proto XFRM_PROTO ] [ spi SPI ]\n");
87
88 fprintf(stderr, "XFRM_PROTO := [ ");
89 fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_ESP));
90 fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_AH));
91 fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_COMP));
92 fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_ROUTING));
93 fprintf(stderr, "%s ", strxf_xfrmproto(IPPROTO_DSTOPTS));
94 fprintf(stderr, "]\n");
95
96 fprintf(stderr, "MODE := [ transport | tunnel | beet ](default=transport)\n");
97 //fprintf(stderr, "REQID - number(default=0)\n");
98 fprintf(stderr, "LEVEL := [ required | use ](default=required)\n");
99
100 exit(-1);
101 }
102
103 static int xfrm_policy_dir_parse(__u8 *dir, int *argcp, char ***argvp)
104 {
105 int argc = *argcp;
106 char **argv = *argvp;
107
108 if (strcmp(*argv, "in") == 0)
109 *dir = XFRM_POLICY_IN;
110 else if (strcmp(*argv, "out") == 0)
111 *dir = XFRM_POLICY_OUT;
112 else if (strcmp(*argv, "fwd") == 0)
113 *dir = XFRM_POLICY_FWD;
114 else
115 invarg("\"DIR\" is invalid", *argv);
116
117 *argcp = argc;
118 *argvp = argv;
119
120 return 0;
121 }
122
123 static int xfrm_policy_ptype_parse(__u8 *ptype, int *argcp, char ***argvp)
124 {
125 int argc = *argcp;
126 char **argv = *argvp;
127
128 if (strcmp(*argv, "main") == 0)
129 *ptype = XFRM_POLICY_TYPE_MAIN;
130 else if (strcmp(*argv, "sub") == 0)
131 *ptype = XFRM_POLICY_TYPE_SUB;
132 else
133 invarg("\"PTYPE\" is invalid", *argv);
134
135 *argcp = argc;
136 *argvp = argv;
137
138 return 0;
139 }
140
141 static int xfrm_policy_flag_parse(__u8 *flags, int *argcp, char ***argvp)
142 {
143 int argc = *argcp;
144 char **argv = *argvp;
145 int len = strlen(*argv);
146
147 if (len > 2 && strncmp(*argv, "0x", 2) == 0) {
148 __u8 val = 0;
149
150 if (get_u8(&val, *argv, 16))
151 invarg("\"FLAG\" is invalid", *argv);
152 *flags = val;
153 } else {
154 while (1) {
155 if (strcmp(*argv, "localok") == 0)
156 *flags |= XFRM_POLICY_LOCALOK;
157 else {
158 PREV_ARG(); /* back track */
159 break;
160 }
161
162 if (!NEXT_ARG_OK())
163 break;
164 NEXT_ARG();
165 }
166 }
167
168 *argcp = argc;
169 *argvp = argv;
170
171 return 0;
172 }
173
174 static int xfrm_tmpl_parse(struct xfrm_user_tmpl *tmpl,
175 int *argcp, char ***argvp)
176 {
177 int argc = *argcp;
178 char **argv = *argvp;
179 char *idp = NULL;
180
181 while (1) {
182 if (strcmp(*argv, "mode") == 0) {
183 NEXT_ARG();
184 xfrm_mode_parse(&tmpl->mode, &argc, &argv);
185 } else if (strcmp(*argv, "reqid") == 0) {
186 NEXT_ARG();
187 xfrm_reqid_parse(&tmpl->reqid, &argc, &argv);
188 } else if (strcmp(*argv, "level") == 0) {
189 NEXT_ARG();
190
191 if (strcmp(*argv, "required") == 0)
192 tmpl->optional = 0;
193 else if (strcmp(*argv, "use") == 0)
194 tmpl->optional = 1;
195 else
196 invarg("\"LEVEL\" is invalid\n", *argv);
197
198 } else {
199 if (idp) {
200 PREV_ARG(); /* back track */
201 break;
202 }
203 idp = *argv;
204 preferred_family = AF_UNSPEC;
205 xfrm_id_parse(&tmpl->saddr, &tmpl->id, &tmpl->family,
206 0, &argc, &argv);
207 preferred_family = tmpl->family;
208 }
209
210 if (!NEXT_ARG_OK())
211 break;
212
213 NEXT_ARG();
214 }
215 if (argc == *argcp)
216 missarg("TMPL");
217
218 *argcp = argc;
219 *argvp = argv;
220
221 return 0;
222 }
223
224 static int xfrm_policy_modify(int cmd, unsigned flags, int argc, char **argv)
225 {
226 struct rtnl_handle rth;
227 struct {
228 struct nlmsghdr n;
229 struct xfrm_userpolicy_info xpinfo;
230 char buf[RTA_BUF_SIZE];
231 } req;
232 char *dirp = NULL;
233 char *selp = NULL;
234 char *ptypep = NULL;
235 struct xfrm_userpolicy_type upt;
236 char tmpls_buf[XFRM_TMPLS_BUF_SIZE];
237 int tmpls_len = 0;
238 struct xfrm_mark mark = {0, 0};
239
240 memset(&req, 0, sizeof(req));
241 memset(&upt, 0, sizeof(upt));
242 memset(&tmpls_buf, 0, sizeof(tmpls_buf));
243
244 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xpinfo));
245 req.n.nlmsg_flags = NLM_F_REQUEST|flags;
246 req.n.nlmsg_type = cmd;
247 req.xpinfo.sel.family = preferred_family;
248
249 req.xpinfo.lft.soft_byte_limit = XFRM_INF;
250 req.xpinfo.lft.hard_byte_limit = XFRM_INF;
251 req.xpinfo.lft.soft_packet_limit = XFRM_INF;
252 req.xpinfo.lft.hard_packet_limit = XFRM_INF;
253
254 while (argc > 0) {
255 if (strcmp(*argv, "dir") == 0) {
256 if (dirp)
257 duparg("dir", *argv);
258 dirp = *argv;
259
260 NEXT_ARG();
261 xfrm_policy_dir_parse(&req.xpinfo.dir, &argc, &argv);
262 } else if (strcmp(*argv, "mark") == 0) {
263 xfrm_parse_mark(&mark, &argc, &argv);
264 } else if (strcmp(*argv, "index") == 0) {
265 NEXT_ARG();
266 if (get_u32(&req.xpinfo.index, *argv, 0))
267 invarg("\"INDEX\" is invalid", *argv);
268 } else if (strcmp(*argv, "ptype") == 0) {
269 if (ptypep)
270 duparg("ptype", *argv);
271 ptypep = *argv;
272
273 NEXT_ARG();
274 xfrm_policy_ptype_parse(&upt.type, &argc, &argv);
275 } else if (strcmp(*argv, "action") == 0) {
276 NEXT_ARG();
277 if (strcmp(*argv, "allow") == 0)
278 req.xpinfo.action = XFRM_POLICY_ALLOW;
279 else if (strcmp(*argv, "block") == 0)
280 req.xpinfo.action = XFRM_POLICY_BLOCK;
281 else
282 invarg("\"action\" value is invalid\n", *argv);
283 } else if (strcmp(*argv, "priority") == 0) {
284 NEXT_ARG();
285 if (get_u32(&req.xpinfo.priority, *argv, 0))
286 invarg("\"PRIORITY\" is invalid", *argv);
287 } else if (strcmp(*argv, "flag") == 0) {
288 NEXT_ARG();
289 xfrm_policy_flag_parse(&req.xpinfo.flags, &argc,
290 &argv);
291 } else if (strcmp(*argv, "limit") == 0) {
292 NEXT_ARG();
293 xfrm_lifetime_cfg_parse(&req.xpinfo.lft, &argc, &argv);
294 } else if (strcmp(*argv, "tmpl") == 0) {
295 struct xfrm_user_tmpl *tmpl;
296
297 if (tmpls_len + sizeof(*tmpl) > sizeof(tmpls_buf)) {
298 fprintf(stderr, "Too many tmpls: buffer overflow\n");
299 exit(1);
300 }
301 tmpl = (struct xfrm_user_tmpl *)((char *)tmpls_buf + tmpls_len);
302
303 tmpl->family = preferred_family;
304 tmpl->aalgos = (~(__u32)0);
305 tmpl->ealgos = (~(__u32)0);
306 tmpl->calgos = (~(__u32)0);
307
308 NEXT_ARG();
309 xfrm_tmpl_parse(tmpl, &argc, &argv);
310
311 tmpls_len += sizeof(*tmpl);
312 } else {
313 if (selp)
314 duparg("unknown", *argv);
315 selp = *argv;
316
317 xfrm_selector_parse(&req.xpinfo.sel, &argc, &argv);
318 if (preferred_family == AF_UNSPEC)
319 preferred_family = req.xpinfo.sel.family;
320 }
321
322 argc--; argv++;
323 }
324
325 if (!dirp) {
326 fprintf(stderr, "Not enough information: \"DIR\" is required.\n");
327 exit(1);
328 }
329
330 if (ptypep) {
331 addattr_l(&req.n, sizeof(req), XFRMA_POLICY_TYPE,
332 (void *)&upt, sizeof(upt));
333 }
334
335 if (tmpls_len > 0) {
336 addattr_l(&req.n, sizeof(req), XFRMA_TMPL,
337 (void *)tmpls_buf, tmpls_len);
338 }
339
340 if (mark.m & mark.v) {
341 int r = addattr_l(&req.n, sizeof(req.buf), XFRMA_MARK,
342 (void *)&mark, sizeof(mark));
343 if (r < 0) {
344 fprintf(stderr, "%s: XFRMA_MARK failed\n",__func__);
345 exit(1);
346 }
347 }
348
349
350 if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
351 exit(1);
352
353 if (req.xpinfo.sel.family == AF_UNSPEC)
354 req.xpinfo.sel.family = AF_INET;
355
356 if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
357 exit(2);
358
359 rtnl_close(&rth);
360
361 return 0;
362 }
363
364 static int xfrm_policy_filter_match(struct xfrm_userpolicy_info *xpinfo,
365 __u8 ptype)
366 {
367 if (!filter.use)
368 return 1;
369
370 if ((xpinfo->dir^filter.xpinfo.dir)&filter.dir_mask)
371 return 0;
372
373 if ((ptype^filter.ptype)&filter.ptype_mask)
374 return 0;
375
376 if (filter.sel_src_mask) {
377 if (xfrm_addr_match(&xpinfo->sel.saddr, &filter.xpinfo.sel.saddr,
378 filter.sel_src_mask))
379 return 0;
380 }
381
382 if (filter.sel_dst_mask) {
383 if (xfrm_addr_match(&xpinfo->sel.daddr, &filter.xpinfo.sel.daddr,
384 filter.sel_dst_mask))
385 return 0;
386 }
387
388 if ((xpinfo->sel.ifindex^filter.xpinfo.sel.ifindex)&filter.sel_dev_mask)
389 return 0;
390
391 if ((xpinfo->sel.proto^filter.xpinfo.sel.proto)&filter.upspec_proto_mask)
392 return 0;
393
394 if (filter.upspec_sport_mask) {
395 if ((xpinfo->sel.sport^filter.xpinfo.sel.sport)&filter.upspec_sport_mask)
396 return 0;
397 }
398
399 if (filter.upspec_dport_mask) {
400 if ((xpinfo->sel.dport^filter.xpinfo.sel.dport)&filter.upspec_dport_mask)
401 return 0;
402 }
403
404 if ((xpinfo->index^filter.xpinfo.index)&filter.index_mask)
405 return 0;
406
407 if ((xpinfo->action^filter.xpinfo.action)&filter.action_mask)
408 return 0;
409
410 if ((xpinfo->priority^filter.xpinfo.priority)&filter.priority_mask)
411 return 0;
412
413 if (filter.policy_flags_mask)
414 if ((xpinfo->flags & filter.xpinfo.flags) == 0)
415 return 0;
416
417 return 1;
418 }
419
420 int xfrm_policy_print(const struct sockaddr_nl *who, struct nlmsghdr *n,
421 void *arg)
422 {
423 struct rtattr * tb[XFRMA_MAX+1];
424 struct rtattr * rta;
425 struct xfrm_userpolicy_info *xpinfo = NULL;
426 struct xfrm_user_polexpire *xpexp = NULL;
427 struct xfrm_userpolicy_id *xpid = NULL;
428 __u8 ptype = XFRM_POLICY_TYPE_MAIN;
429 FILE *fp = (FILE*)arg;
430 int len = n->nlmsg_len;
431
432 if (n->nlmsg_type != XFRM_MSG_NEWPOLICY &&
433 n->nlmsg_type != XFRM_MSG_DELPOLICY &&
434 n->nlmsg_type != XFRM_MSG_UPDPOLICY &&
435 n->nlmsg_type != XFRM_MSG_POLEXPIRE) {
436 fprintf(stderr, "Not a policy: %08x %08x %08x\n",
437 n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
438 return 0;
439 }
440
441 if (n->nlmsg_type == XFRM_MSG_DELPOLICY) {
442 xpid = NLMSG_DATA(n);
443 len -= NLMSG_SPACE(sizeof(*xpid));
444 } else if (n->nlmsg_type == XFRM_MSG_POLEXPIRE) {
445 xpexp = NLMSG_DATA(n);
446 xpinfo = &xpexp->pol;
447 len -= NLMSG_SPACE(sizeof(*xpexp));
448 } else {
449 xpexp = NULL;
450 xpinfo = NLMSG_DATA(n);
451 len -= NLMSG_SPACE(sizeof(*xpinfo));
452 }
453
454 if (len < 0) {
455 fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
456 return -1;
457 }
458
459 if (n->nlmsg_type == XFRM_MSG_DELPOLICY)
460 rta = XFRMPID_RTA(xpid);
461 else if (n->nlmsg_type == XFRM_MSG_POLEXPIRE)
462 rta = XFRMPEXP_RTA(xpexp);
463 else
464 rta = XFRMP_RTA(xpinfo);
465
466 parse_rtattr(tb, XFRMA_MAX, rta, len);
467
468 if (tb[XFRMA_POLICY_TYPE]) {
469 struct xfrm_userpolicy_type *upt;
470
471 if (RTA_PAYLOAD(tb[XFRMA_POLICY_TYPE]) < sizeof(*upt)) {
472 fprintf(stderr, "too short XFRMA_POLICY_TYPE len\n");
473 return -1;
474 }
475 upt = (struct xfrm_userpolicy_type *)RTA_DATA(tb[XFRMA_POLICY_TYPE]);
476 ptype = upt->type;
477 }
478
479 if (xpinfo && !xfrm_policy_filter_match(xpinfo, ptype))
480 return 0;
481
482 if (n->nlmsg_type == XFRM_MSG_DELPOLICY)
483 fprintf(fp, "Deleted ");
484 else if (n->nlmsg_type == XFRM_MSG_UPDPOLICY)
485 fprintf(fp, "Updated ");
486 else if (n->nlmsg_type == XFRM_MSG_POLEXPIRE)
487 fprintf(fp, "Expired ");
488
489 if (n->nlmsg_type == XFRM_MSG_DELPOLICY) {
490 //xfrm_policy_id_print();
491 if (!tb[XFRMA_POLICY]) {
492 fprintf(stderr, "Buggy XFRM_MSG_DELPOLICY: no XFRMA_POLICY\n");
493 return -1;
494 }
495 if (RTA_PAYLOAD(tb[XFRMA_POLICY]) < sizeof(*xpinfo)) {
496 fprintf(stderr, "Buggy XFRM_MSG_DELPOLICY: too short XFRMA_POLICY len\n");
497 return -1;
498 }
499 xpinfo = (struct xfrm_userpolicy_info *)RTA_DATA(tb[XFRMA_POLICY]);
500 }
501
502 xfrm_policy_info_print(xpinfo, tb, fp, NULL, NULL);
503
504 if (n->nlmsg_type == XFRM_MSG_POLEXPIRE) {
505 fprintf(fp, "\t");
506 fprintf(fp, "hard %u", xpexp->hard);
507 fprintf(fp, "%s", _SL_);
508 }
509
510 if (oneline)
511 fprintf(fp, "\n");
512 fflush(fp);
513
514 return 0;
515 }
516
517 static int xfrm_policy_get_or_delete(int argc, char **argv, int delete,
518 void *res_nlbuf)
519 {
520 struct rtnl_handle rth;
521 struct {
522 struct nlmsghdr n;
523 struct xfrm_userpolicy_id xpid;
524 char buf[RTA_BUF_SIZE];
525 } req;
526 char *dirp = NULL;
527 char *selp = NULL;
528 char *indexp = NULL;
529 char *ptypep = NULL;
530 struct xfrm_userpolicy_type upt;
531 struct xfrm_mark mark = {0, 0};
532
533 memset(&req, 0, sizeof(req));
534 memset(&upt, 0, sizeof(upt));
535
536 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xpid));
537 req.n.nlmsg_flags = NLM_F_REQUEST;
538 req.n.nlmsg_type = delete ? XFRM_MSG_DELPOLICY : XFRM_MSG_GETPOLICY;
539
540 while (argc > 0) {
541 if (strcmp(*argv, "dir") == 0) {
542 if (dirp)
543 duparg("dir", *argv);
544 dirp = *argv;
545
546 NEXT_ARG();
547 xfrm_policy_dir_parse(&req.xpid.dir, &argc, &argv);
548
549 } else if (strcmp(*argv, "mark") == 0) {
550 xfrm_parse_mark(&mark, &argc, &argv);
551 } else if (strcmp(*argv, "index") == 0) {
552 if (indexp)
553 duparg("index", *argv);
554 indexp = *argv;
555
556 NEXT_ARG();
557 if (get_u32(&req.xpid.index, *argv, 0))
558 invarg("\"INDEX\" is invalid", *argv);
559
560 } else if (strcmp(*argv, "ptype") == 0) {
561 if (ptypep)
562 duparg("ptype", *argv);
563 ptypep = *argv;
564
565 NEXT_ARG();
566 xfrm_policy_ptype_parse(&upt.type, &argc, &argv);
567
568 } else {
569 if (selp)
570 invarg("unknown", *argv);
571 selp = *argv;
572
573 xfrm_selector_parse(&req.xpid.sel, &argc, &argv);
574 if (preferred_family == AF_UNSPEC)
575 preferred_family = req.xpid.sel.family;
576
577 }
578
579 argc--; argv++;
580 }
581
582 if (!dirp) {
583 fprintf(stderr, "Not enough information: \"DIR\" is required.\n");
584 exit(1);
585 }
586 if (ptypep) {
587 addattr_l(&req.n, sizeof(req), XFRMA_POLICY_TYPE,
588 (void *)&upt, sizeof(upt));
589 }
590 if (!selp && !indexp) {
591 fprintf(stderr, "Not enough information: either \"SELECTOR\" or \"INDEX\" is required.\n");
592 exit(1);
593 }
594 if (selp && indexp)
595 duparg2("SELECTOR", "INDEX");
596
597 if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
598 exit(1);
599
600 if (req.xpid.sel.family == AF_UNSPEC)
601 req.xpid.sel.family = AF_INET;
602
603 if (mark.m & mark.v) {
604 int r = addattr_l(&req.n, sizeof(req.buf), XFRMA_MARK,
605 (void *)&mark, sizeof(mark));
606 if (r < 0) {
607 fprintf(stderr, "%s: XFRMA_MARK failed\n",__func__);
608 exit(1);
609 }
610 }
611
612 if (rtnl_talk(&rth, &req.n, 0, 0, res_nlbuf, NULL, NULL) < 0)
613 exit(2);
614
615 rtnl_close(&rth);
616
617 return 0;
618 }
619
620 static int xfrm_policy_delete(int argc, char **argv)
621 {
622 return xfrm_policy_get_or_delete(argc, argv, 1, NULL);
623 }
624
625 static int xfrm_policy_get(int argc, char **argv)
626 {
627 char buf[NLMSG_BUF_SIZE];
628 struct nlmsghdr *n = (struct nlmsghdr *)buf;
629
630 memset(buf, 0, sizeof(buf));
631
632 xfrm_policy_get_or_delete(argc, argv, 0, n);
633
634 if (xfrm_policy_print(NULL, n, (void*)stdout) < 0) {
635 fprintf(stderr, "An error :-)\n");
636 exit(1);
637 }
638
639 return 0;
640 }
641
642 /*
643 * With an existing policy of nlmsg, make new nlmsg for deleting the policy
644 * and store it to buffer.
645 */
646 static int xfrm_policy_keep(const struct sockaddr_nl *who,
647 struct nlmsghdr *n,
648 void *arg)
649 {
650 struct xfrm_buffer *xb = (struct xfrm_buffer *)arg;
651 struct rtnl_handle *rth = xb->rth;
652 struct xfrm_userpolicy_info *xpinfo = NLMSG_DATA(n);
653 int len = n->nlmsg_len;
654 struct rtattr *tb[XFRMA_MAX+1];
655 __u8 ptype = XFRM_POLICY_TYPE_MAIN;
656 struct nlmsghdr *new_n;
657 struct xfrm_userpolicy_id *xpid;
658
659 if (n->nlmsg_type != XFRM_MSG_NEWPOLICY) {
660 fprintf(stderr, "Not a policy: %08x %08x %08x\n",
661 n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
662 return 0;
663 }
664
665 len -= NLMSG_LENGTH(sizeof(*xpinfo));
666 if (len < 0) {
667 fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
668 return -1;
669 }
670
671 parse_rtattr(tb, XFRMA_MAX, XFRMP_RTA(xpinfo), len);
672
673 if (tb[XFRMA_POLICY_TYPE]) {
674 struct xfrm_userpolicy_type *upt;
675
676 if (RTA_PAYLOAD(tb[XFRMA_POLICY_TYPE]) < sizeof(*upt)) {
677 fprintf(stderr, "too short XFRMA_POLICY_TYPE len\n");
678 return -1;
679 }
680 upt = (struct xfrm_userpolicy_type *)RTA_DATA(tb[XFRMA_POLICY_TYPE]);
681 ptype = upt->type;
682 }
683
684 if (!xfrm_policy_filter_match(xpinfo, ptype))
685 return 0;
686
687 if (xb->offset > xb->size) {
688 fprintf(stderr, "Policy buffer overflow\n");
689 return -1;
690 }
691
692 new_n = (struct nlmsghdr *)(xb->buf + xb->offset);
693 new_n->nlmsg_len = NLMSG_LENGTH(sizeof(*xpid));
694 new_n->nlmsg_flags = NLM_F_REQUEST;
695 new_n->nlmsg_type = XFRM_MSG_DELPOLICY;
696 new_n->nlmsg_seq = ++rth->seq;
697
698 xpid = NLMSG_DATA(new_n);
699 memcpy(&xpid->sel, &xpinfo->sel, sizeof(xpid->sel));
700 xpid->dir = xpinfo->dir;
701 xpid->index = xpinfo->index;
702
703 xb->offset += new_n->nlmsg_len;
704 xb->nlmsg_count ++;
705
706 return 0;
707 }
708
709 static int xfrm_policy_list_or_deleteall(int argc, char **argv, int deleteall)
710 {
711 char *selp = NULL;
712 struct rtnl_handle rth;
713
714 if (argc > 0)
715 filter.use = 1;
716 filter.xpinfo.sel.family = preferred_family;
717
718 while (argc > 0) {
719 if (strcmp(*argv, "dir") == 0) {
720 NEXT_ARG();
721 xfrm_policy_dir_parse(&filter.xpinfo.dir, &argc, &argv);
722
723 filter.dir_mask = XFRM_FILTER_MASK_FULL;
724
725 } else if (strcmp(*argv, "index") == 0) {
726 NEXT_ARG();
727 if (get_u32(&filter.xpinfo.index, *argv, 0))
728 invarg("\"INDEX\" is invalid", *argv);
729
730 filter.index_mask = XFRM_FILTER_MASK_FULL;
731
732 } else if (strcmp(*argv, "ptype") == 0) {
733 NEXT_ARG();
734 xfrm_policy_ptype_parse(&filter.ptype, &argc, &argv);
735
736 filter.ptype_mask = XFRM_FILTER_MASK_FULL;
737
738 } else if (strcmp(*argv, "action") == 0) {
739 NEXT_ARG();
740 if (strcmp(*argv, "allow") == 0)
741 filter.xpinfo.action = XFRM_POLICY_ALLOW;
742 else if (strcmp(*argv, "block") == 0)
743 filter.xpinfo.action = XFRM_POLICY_BLOCK;
744 else
745 invarg("\"ACTION\" is invalid\n", *argv);
746
747 filter.action_mask = XFRM_FILTER_MASK_FULL;
748
749 } else if (strcmp(*argv, "priority") == 0) {
750 NEXT_ARG();
751 if (get_u32(&filter.xpinfo.priority, *argv, 0))
752 invarg("\"PRIORITY\" is invalid", *argv);
753
754 filter.priority_mask = XFRM_FILTER_MASK_FULL;
755
756 } else if (strcmp(*argv, "flag") == 0) {
757 NEXT_ARG();
758 xfrm_policy_flag_parse(&filter.xpinfo.flags, &argc,
759 &argv);
760
761 filter.policy_flags_mask = XFRM_FILTER_MASK_FULL;
762
763 } else {
764 if (selp)
765 invarg("unknown", *argv);
766 selp = *argv;
767
768 xfrm_selector_parse(&filter.xpinfo.sel, &argc, &argv);
769 if (preferred_family == AF_UNSPEC)
770 preferred_family = filter.xpinfo.sel.family;
771
772 }
773
774 argc--; argv++;
775 }
776
777 if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
778 exit(1);
779
780 if (deleteall) {
781 struct xfrm_buffer xb;
782 char buf[NLMSG_DELETEALL_BUF_SIZE];
783 int i;
784
785 xb.buf = buf;
786 xb.size = sizeof(buf);
787 xb.rth = &rth;
788
789 for (i = 0; ; i++) {
790 xb.offset = 0;
791 xb.nlmsg_count = 0;
792
793 if (show_stats > 1)
794 fprintf(stderr, "Delete-all round = %d\n", i);
795
796 if (rtnl_wilddump_request(&rth, preferred_family, XFRM_MSG_GETPOLICY) < 0) {
797 perror("Cannot send dump request");
798 exit(1);
799 }
800
801 if (rtnl_dump_filter(&rth, xfrm_policy_keep, &xb, NULL, NULL) < 0) {
802 fprintf(stderr, "Delete-all terminated\n");
803 exit(1);
804 }
805 if (xb.nlmsg_count == 0) {
806 if (show_stats > 1)
807 fprintf(stderr, "Delete-all completed\n");
808 break;
809 }
810
811 if (rtnl_send_check(&rth, xb.buf, xb.offset) < 0) {
812 perror("Failed to send delete-all request");
813 exit(1);
814 }
815 if (show_stats > 1)
816 fprintf(stderr, "Delete-all nlmsg count = %d\n", xb.nlmsg_count);
817
818 xb.offset = 0;
819 xb.nlmsg_count = 0;
820 }
821 } else {
822 if (rtnl_wilddump_request(&rth, preferred_family, XFRM_MSG_GETPOLICY) < 0) {
823 perror("Cannot send dump request");
824 exit(1);
825 }
826
827 if (rtnl_dump_filter(&rth, xfrm_policy_print, stdout, NULL, NULL) < 0) {
828 fprintf(stderr, "Dump terminated\n");
829 exit(1);
830 }
831 }
832
833 rtnl_close(&rth);
834
835 exit(0);
836 }
837
838 int print_spdinfo( struct nlmsghdr *n, void *arg)
839 {
840 FILE *fp = (FILE*)arg;
841 __u32 *f = NLMSG_DATA(n);
842 struct rtattr * tb[XFRMA_SPD_MAX+1];
843 struct rtattr * rta;
844
845 int len = n->nlmsg_len;
846
847 len -= NLMSG_LENGTH(sizeof(__u32));
848 if (len < 0) {
849 fprintf(stderr, "SPDinfo: Wrong len %d\n", len);
850 return -1;
851 }
852
853 rta = XFRMSAPD_RTA(f);
854 parse_rtattr(tb, XFRMA_SPD_MAX, rta, len);
855
856 fprintf(fp,"\t SPD");
857 if (tb[XFRMA_SPD_INFO]) {
858 struct xfrmu_spdinfo *si;
859
860 if (RTA_PAYLOAD(tb[XFRMA_SPD_INFO]) < sizeof(*si)) {
861 fprintf(stderr, "SPDinfo: Wrong len %d\n", len);
862 return -1;
863 }
864 si = RTA_DATA(tb[XFRMA_SPD_INFO]);
865 fprintf(fp," IN %d", si->incnt);
866 fprintf(fp," OUT %d", si->outcnt);
867 fprintf(fp," FWD %d", si->fwdcnt);
868
869 if (show_stats) {
870 fprintf(fp," (Sock:");
871 fprintf(fp," IN %d", si->inscnt);
872 fprintf(fp," OUT %d", si->outscnt);
873 fprintf(fp," FWD %d", si->fwdscnt);
874 fprintf(fp,")");
875 }
876
877 fprintf(fp,"\n");
878 }
879 if (show_stats > 1) {
880 struct xfrmu_spdhinfo *sh;
881
882 if (tb[XFRMA_SPD_HINFO]) {
883 if (RTA_PAYLOAD(tb[XFRMA_SPD_HINFO]) < sizeof(*sh)) {
884 fprintf(stderr, "SPDinfo: Wrong len %d\n", len);
885 return -1;
886 }
887 sh = RTA_DATA(tb[XFRMA_SPD_HINFO]);
888 fprintf(fp,"\t SPD buckets:");
889 fprintf(fp," count %d", sh->spdhcnt);
890 fprintf(fp," Max %d", sh->spdhmcnt);
891 }
892 }
893 fprintf(fp,"\n");
894
895 return 0;
896 }
897
898 static int xfrm_spd_getinfo(int argc, char **argv)
899 {
900 struct rtnl_handle rth;
901 struct {
902 struct nlmsghdr n;
903 __u32 flags;
904 char ans[128];
905 } req;
906
907 memset(&req, 0, sizeof(req));
908
909 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(__u32));
910 req.n.nlmsg_flags = NLM_F_REQUEST;
911 req.n.nlmsg_type = XFRM_MSG_GETSPDINFO;
912 req.flags = 0XFFFFFFFF;
913
914 if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
915 exit(1);
916
917 if (rtnl_talk(&rth, &req.n, 0, 0, &req.n, NULL, NULL) < 0)
918 exit(2);
919
920 print_spdinfo(&req.n, (void*)stdout);
921
922 rtnl_close(&rth);
923
924 return 0;
925 }
926
927 static int xfrm_policy_flush(int argc, char **argv)
928 {
929 struct rtnl_handle rth;
930 struct {
931 struct nlmsghdr n;
932 char buf[RTA_BUF_SIZE];
933 } req;
934 char *ptypep = NULL;
935 struct xfrm_userpolicy_type upt;
936
937 memset(&req, 0, sizeof(req));
938 memset(&upt, 0, sizeof(upt));
939
940 req.n.nlmsg_len = NLMSG_LENGTH(0); /* nlmsg data is nothing */
941 req.n.nlmsg_flags = NLM_F_REQUEST;
942 req.n.nlmsg_type = XFRM_MSG_FLUSHPOLICY;
943
944 while (argc > 0) {
945 if (strcmp(*argv, "ptype") == 0) {
946 if (ptypep)
947 duparg("ptype", *argv);
948 ptypep = *argv;
949
950 NEXT_ARG();
951 xfrm_policy_ptype_parse(&upt.type, &argc, &argv);
952 } else
953 invarg("unknown", *argv);
954
955 argc--; argv++;
956 }
957
958 if (ptypep) {
959 addattr_l(&req.n, sizeof(req), XFRMA_POLICY_TYPE,
960 (void *)&upt, sizeof(upt));
961 }
962
963 if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
964 exit(1);
965
966 if (show_stats > 1)
967 fprintf(stderr, "Flush policy\n");
968
969 if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
970 exit(2);
971
972 rtnl_close(&rth);
973
974 return 0;
975 }
976
977 int do_xfrm_policy(int argc, char **argv)
978 {
979 if (argc < 1)
980 return xfrm_policy_list_or_deleteall(0, NULL, 0);
981
982 if (matches(*argv, "add") == 0)
983 return xfrm_policy_modify(XFRM_MSG_NEWPOLICY, 0,
984 argc-1, argv+1);
985 if (matches(*argv, "update") == 0)
986 return xfrm_policy_modify(XFRM_MSG_UPDPOLICY, 0,
987 argc-1, argv+1);
988 if (matches(*argv, "delete") == 0)
989 return xfrm_policy_delete(argc-1, argv+1);
990 if (matches(*argv, "deleteall") == 0 || matches(*argv, "delall") == 0)
991 return xfrm_policy_list_or_deleteall(argc-1, argv+1, 1);
992 if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0
993 || matches(*argv, "lst") == 0)
994 return xfrm_policy_list_or_deleteall(argc-1, argv+1, 0);
995 if (matches(*argv, "get") == 0)
996 return xfrm_policy_get(argc-1, argv+1);
997 if (matches(*argv, "flush") == 0)
998 return xfrm_policy_flush(argc-1, argv+1);
999 if (matches(*argv, "count") == 0)
1000 return xfrm_spd_getinfo(argc, argv);
1001 if (matches(*argv, "help") == 0)
1002 usage();
1003 fprintf(stderr, "Command \"%s\" is unknown, try \"ip xfrm policy help\".\n", *argv);
1004 exit(-1);
1005 }