4 * Copyright (C)2004 USAGI/WIDE Project
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.
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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses>.
24 * Masahide NAKAMURA @USAGI
31 #include <linux/netlink.h>
34 #include "ip_common.h"
36 /* #define NLMSG_DELETEALL_BUF_SIZE (4096-512) */
37 #define NLMSG_DELETEALL_BUF_SIZE 8192
40 * Receiving buffer defines:
42 * data = struct xfrm_userpolicy_info
44 * data = struct xfrm_user_tmpl[]
46 #define NLMSG_BUF_SIZE 4096
47 #define RTA_BUF_SIZE 2048
48 #define XFRM_TMPLS_BUF_SIZE 1024
49 #define CTX_BUF_SIZE 256
51 static void usage(void) __attribute__((noreturn
));
53 static void usage(void)
56 "Usage: ip xfrm policy { add | update } SELECTOR dir DIR [ ctx CTX ]\n"
57 " [ mark MARK [ mask MASK ] ] [ index INDEX ] [ ptype PTYPE ]\n"
58 " [ action ACTION ] [ priority PRIORITY ] [ flag FLAG-LIST ]\n"
59 " [ if_id IF_ID ] [ LIMIT-LIST ] [ TMPL-LIST ]\n"
60 "Usage: ip xfrm policy { delete | get } { SELECTOR | index INDEX } dir DIR\n"
61 " [ ctx CTX ] [ mark MARK [ mask MASK ] ] [ ptype PTYPE ]\n"
63 "Usage: ip xfrm policy { deleteall | list } [ nosock ] [ SELECTOR ] [ dir DIR ]\n"
64 " [ index INDEX ] [ ptype PTYPE ] [ action ACTION ] [ priority PRIORITY ]\n"
65 " [ flag FLAG-LIST ]\n"
66 "Usage: ip xfrm policy flush [ ptype PTYPE ]\n"
67 "Usage: ip xfrm policy count\n"
68 "Usage: ip xfrm policy set [ hthresh4 LBITS RBITS ] [ hthresh6 LBITS RBITS ]\n"
69 "SELECTOR := [ src ADDR[/PLEN] ] [ dst ADDR[/PLEN] ] [ dev DEV ] [ UPSPEC ]\n"
70 "UPSPEC := proto { { tcp | udp | sctp | dccp } [ sport PORT ] [ dport PORT ] |\n"
71 " { icmp | ipv6-icmp | mobility-header } [ type NUMBER ] [ code NUMBER ] |\n"
72 " gre [ key { DOTTED-QUAD | NUMBER } ] | PROTO }\n"
73 "DIR := in | out | fwd\n"
74 "PTYPE := main | sub\n"
75 "ACTION := allow | block\n"
76 "FLAG-LIST := [ FLAG-LIST ] FLAG\n"
77 "FLAG := localok | icmp\n"
78 "LIMIT-LIST := [ LIMIT-LIST ] limit LIMIT\n"
79 "LIMIT := { time-soft | time-hard | time-use-soft | time-use-hard } SECONDS |\n"
80 " { byte-soft | byte-hard } SIZE | { packet-soft | packet-hard } COUNT\n"
81 "TMPL-LIST := [ TMPL-LIST ] tmpl TMPL\n"
82 "TMPL := ID [ mode MODE ] [ reqid REQID ] [ level LEVEL ]\n"
83 "ID := [ src ADDR ] [ dst ADDR ] [ proto XFRM-PROTO ] [ spi SPI ]\n"
86 "%s | %s | %s | %s | %s\n",
87 strxf_xfrmproto(IPPROTO_ESP
),
88 strxf_xfrmproto(IPPROTO_AH
),
89 strxf_xfrmproto(IPPROTO_COMP
),
90 strxf_xfrmproto(IPPROTO_ROUTING
),
91 strxf_xfrmproto(IPPROTO_DSTOPTS
));
93 "MODE := transport | tunnel | beet | ro | in_trigger\n"
94 "LEVEL := required | use\n");
99 static int xfrm_policy_dir_parse(__u8
*dir
, int *argcp
, char ***argvp
)
102 char **argv
= *argvp
;
104 if (strcmp(*argv
, "in") == 0)
105 *dir
= XFRM_POLICY_IN
;
106 else if (strcmp(*argv
, "out") == 0)
107 *dir
= XFRM_POLICY_OUT
;
108 else if (strcmp(*argv
, "fwd") == 0)
109 *dir
= XFRM_POLICY_FWD
;
111 invarg("DIR value is invalid", *argv
);
119 static int xfrm_policy_ptype_parse(__u8
*ptype
, int *argcp
, char ***argvp
)
122 char **argv
= *argvp
;
124 if (strcmp(*argv
, "main") == 0)
125 *ptype
= XFRM_POLICY_TYPE_MAIN
;
126 else if (strcmp(*argv
, "sub") == 0)
127 *ptype
= XFRM_POLICY_TYPE_SUB
;
129 invarg("PTYPE value is invalid", *argv
);
137 static int xfrm_policy_flag_parse(__u8
*flags
, int *argcp
, char ***argvp
)
140 char **argv
= *argvp
;
141 int len
= strlen(*argv
);
143 if (len
> 2 && strncmp(*argv
, "0x", 2) == 0) {
146 if (get_u8(&val
, *argv
, 16))
147 invarg("FLAG value is invalid", *argv
);
151 if (strcmp(*argv
, "localok") == 0)
152 *flags
|= XFRM_POLICY_LOCALOK
;
153 else if (strcmp(*argv
, "icmp") == 0)
154 *flags
|= XFRM_POLICY_ICMP
;
156 PREV_ARG(); /* back track */
172 static int xfrm_tmpl_parse(struct xfrm_user_tmpl
*tmpl
,
173 int *argcp
, char ***argvp
)
176 char **argv
= *argvp
;
180 if (strcmp(*argv
, "mode") == 0) {
182 xfrm_mode_parse(&tmpl
->mode
, &argc
, &argv
);
183 } else if (strcmp(*argv
, "reqid") == 0) {
185 xfrm_reqid_parse(&tmpl
->reqid
, &argc
, &argv
);
186 } else if (strcmp(*argv
, "level") == 0) {
189 if (strcmp(*argv
, "required") == 0)
191 else if (strcmp(*argv
, "use") == 0)
194 invarg("LEVEL value is invalid\n", *argv
);
198 PREV_ARG(); /* back track */
202 preferred_family
= AF_UNSPEC
;
203 xfrm_id_parse(&tmpl
->saddr
, &tmpl
->id
, &tmpl
->family
,
205 preferred_family
= tmpl
->family
;
222 int xfrm_sctx_parse(char *ctxstr
, char *s
,
223 struct xfrm_user_sec_ctx
*sctx
)
227 slen
= strlen(s
) + 1;
229 sctx
->exttype
= XFRMA_SEC_CTX
;
232 sctx
->ctx_len
= slen
;
233 sctx
->len
= sizeof(struct xfrm_user_sec_ctx
) + slen
;
234 memcpy(ctxstr
, s
, slen
);
239 static int xfrm_policy_modify(int cmd
, unsigned int flags
, int argc
, char **argv
)
241 struct rtnl_handle rth
;
244 struct xfrm_userpolicy_info xpinfo
;
245 char buf
[RTA_BUF_SIZE
];
247 .n
.nlmsg_len
= NLMSG_LENGTH(sizeof(req
.xpinfo
)),
248 .n
.nlmsg_flags
= NLM_F_REQUEST
| flags
,
250 .xpinfo
.sel
.family
= preferred_family
,
251 .xpinfo
.lft
.soft_byte_limit
= XFRM_INF
,
252 .xpinfo
.lft
.hard_byte_limit
= XFRM_INF
,
253 .xpinfo
.lft
.soft_packet_limit
= XFRM_INF
,
254 .xpinfo
.lft
.hard_packet_limit
= XFRM_INF
,
260 struct xfrm_userpolicy_type upt
= {};
261 char tmpls_buf
[XFRM_TMPLS_BUF_SIZE
] = {};
263 struct xfrm_mark mark
= {0, 0};
265 struct xfrm_user_sec_ctx sctx
;
266 char str
[CTX_BUF_SIZE
];
268 bool is_if_id_set
= false;
272 if (strcmp(*argv
, "dir") == 0) {
274 duparg("dir", *argv
);
278 xfrm_policy_dir_parse(&req
.xpinfo
.dir
, &argc
, &argv
);
279 } else if (strcmp(*argv
, "ctx") == 0) {
283 duparg("ctx", *argv
);
287 xfrm_sctx_parse((char *)&ctx
.str
, context
, &ctx
.sctx
);
288 } else if (strcmp(*argv
, "mark") == 0) {
289 xfrm_parse_mark(&mark
, &argc
, &argv
);
290 } else if (strcmp(*argv
, "index") == 0) {
292 if (get_u32(&req
.xpinfo
.index
, *argv
, 0))
293 invarg("INDEX value is invalid", *argv
);
294 } else if (strcmp(*argv
, "ptype") == 0) {
296 duparg("ptype", *argv
);
300 xfrm_policy_ptype_parse(&upt
.type
, &argc
, &argv
);
301 } else if (strcmp(*argv
, "action") == 0) {
303 if (strcmp(*argv
, "allow") == 0)
304 req
.xpinfo
.action
= XFRM_POLICY_ALLOW
;
305 else if (strcmp(*argv
, "block") == 0)
306 req
.xpinfo
.action
= XFRM_POLICY_BLOCK
;
308 invarg("ACTION value is invalid\n", *argv
);
309 } else if (strcmp(*argv
, "priority") == 0) {
311 if (get_u32(&req
.xpinfo
.priority
, *argv
, 0))
312 invarg("PRIORITY value is invalid", *argv
);
313 } else if (strcmp(*argv
, "flag") == 0) {
315 xfrm_policy_flag_parse(&req
.xpinfo
.flags
, &argc
,
317 } else if (strcmp(*argv
, "limit") == 0) {
319 xfrm_lifetime_cfg_parse(&req
.xpinfo
.lft
, &argc
, &argv
);
320 } else if (strcmp(*argv
, "tmpl") == 0) {
321 struct xfrm_user_tmpl
*tmpl
;
323 if (tmpls_len
+ sizeof(*tmpl
) > sizeof(tmpls_buf
)) {
324 fprintf(stderr
, "Too many tmpls: buffer overflow\n");
327 tmpl
= (struct xfrm_user_tmpl
*)((char *)tmpls_buf
+ tmpls_len
);
329 tmpl
->family
= preferred_family
;
330 tmpl
->aalgos
= (~(__u32
)0);
331 tmpl
->ealgos
= (~(__u32
)0);
332 tmpl
->calgos
= (~(__u32
)0);
335 xfrm_tmpl_parse(tmpl
, &argc
, &argv
);
337 tmpls_len
+= sizeof(*tmpl
);
338 } else if (strcmp(*argv
, "if_id") == 0) {
340 if (get_u32(&if_id
, *argv
, 0))
341 invarg("IF_ID value is invalid", *argv
);
345 duparg("unknown", *argv
);
348 xfrm_selector_parse(&req
.xpinfo
.sel
, &argc
, &argv
);
349 if (preferred_family
== AF_UNSPEC
)
350 preferred_family
= req
.xpinfo
.sel
.family
;
357 fprintf(stderr
, "Not enough information: DIR is required.\n");
362 addattr_l(&req
.n
, sizeof(req
), XFRMA_POLICY_TYPE
,
363 (void *)&upt
, sizeof(upt
));
367 addattr_l(&req
.n
, sizeof(req
), XFRMA_TMPL
,
368 (void *)tmpls_buf
, tmpls_len
);
372 int r
= addattr_l(&req
.n
, sizeof(req
.buf
), XFRMA_MARK
,
373 (void *)&mark
, sizeof(mark
));
375 fprintf(stderr
, "%s: XFRMA_MARK failed\n", __func__
);
381 addattr_l(&req
.n
, sizeof(req
), XFRMA_SEC_CTX
,
382 (void *)&ctx
, ctx
.sctx
.len
);
386 addattr32(&req
.n
, sizeof(req
.buf
), XFRMA_IF_ID
, if_id
);
388 if (rtnl_open_byproto(&rth
, 0, NETLINK_XFRM
) < 0)
391 if (req
.xpinfo
.sel
.family
== AF_UNSPEC
)
392 req
.xpinfo
.sel
.family
= AF_INET
;
394 if (rtnl_talk(&rth
, &req
.n
, NULL
) < 0)
402 static int xfrm_policy_filter_match(struct xfrm_userpolicy_info
*xpinfo
,
408 if (filter
.xpinfo
.sel
.family
!= AF_UNSPEC
&&
409 filter
.xpinfo
.sel
.family
!= xpinfo
->sel
.family
)
412 if ((xpinfo
->dir
^filter
.xpinfo
.dir
)&filter
.dir_mask
)
415 if (filter
.filter_socket
&& (xpinfo
->dir
>= XFRM_POLICY_MAX
))
418 if ((ptype
^filter
.ptype
)&filter
.ptype_mask
)
421 if (filter
.sel_src_mask
) {
422 if (xfrm_addr_match(&xpinfo
->sel
.saddr
, &filter
.xpinfo
.sel
.saddr
,
423 filter
.sel_src_mask
))
427 if (filter
.sel_dst_mask
) {
428 if (xfrm_addr_match(&xpinfo
->sel
.daddr
, &filter
.xpinfo
.sel
.daddr
,
429 filter
.sel_dst_mask
))
433 if ((xpinfo
->sel
.ifindex
^filter
.xpinfo
.sel
.ifindex
)&filter
.sel_dev_mask
)
436 if ((xpinfo
->sel
.proto
^filter
.xpinfo
.sel
.proto
)&filter
.upspec_proto_mask
)
439 if (filter
.upspec_sport_mask
) {
440 if ((xpinfo
->sel
.sport
^filter
.xpinfo
.sel
.sport
)&filter
.upspec_sport_mask
)
444 if (filter
.upspec_dport_mask
) {
445 if ((xpinfo
->sel
.dport
^filter
.xpinfo
.sel
.dport
)&filter
.upspec_dport_mask
)
449 if ((xpinfo
->index
^filter
.xpinfo
.index
)&filter
.index_mask
)
452 if ((xpinfo
->action
^filter
.xpinfo
.action
)&filter
.action_mask
)
455 if ((xpinfo
->priority
^filter
.xpinfo
.priority
)&filter
.priority_mask
)
458 if (filter
.policy_flags_mask
)
459 if ((xpinfo
->flags
& filter
.xpinfo
.flags
) == 0)
465 int xfrm_policy_print(struct nlmsghdr
*n
, void *arg
)
467 struct rtattr
*tb
[XFRMA_MAX
+1];
469 struct xfrm_userpolicy_info
*xpinfo
= NULL
;
470 struct xfrm_user_polexpire
*xpexp
= NULL
;
471 struct xfrm_userpolicy_id
*xpid
= NULL
;
472 __u8 ptype
= XFRM_POLICY_TYPE_MAIN
;
473 FILE *fp
= (FILE *)arg
;
474 int len
= n
->nlmsg_len
;
476 if (n
->nlmsg_type
!= XFRM_MSG_NEWPOLICY
&&
477 n
->nlmsg_type
!= XFRM_MSG_DELPOLICY
&&
478 n
->nlmsg_type
!= XFRM_MSG_UPDPOLICY
&&
479 n
->nlmsg_type
!= XFRM_MSG_POLEXPIRE
) {
480 fprintf(stderr
, "Not a policy: %08x %08x %08x\n",
481 n
->nlmsg_len
, n
->nlmsg_type
, n
->nlmsg_flags
);
485 if (n
->nlmsg_type
== XFRM_MSG_DELPOLICY
) {
486 xpid
= NLMSG_DATA(n
);
487 len
-= NLMSG_SPACE(sizeof(*xpid
));
488 } else if (n
->nlmsg_type
== XFRM_MSG_POLEXPIRE
) {
489 xpexp
= NLMSG_DATA(n
);
490 xpinfo
= &xpexp
->pol
;
491 len
-= NLMSG_SPACE(sizeof(*xpexp
));
494 xpinfo
= NLMSG_DATA(n
);
495 len
-= NLMSG_SPACE(sizeof(*xpinfo
));
499 fprintf(stderr
, "BUG: wrong nlmsg len %d\n", len
);
503 if (n
->nlmsg_type
== XFRM_MSG_DELPOLICY
)
504 rta
= XFRMPID_RTA(xpid
);
505 else if (n
->nlmsg_type
== XFRM_MSG_POLEXPIRE
)
506 rta
= XFRMPEXP_RTA(xpexp
);
508 rta
= XFRMP_RTA(xpinfo
);
510 parse_rtattr(tb
, XFRMA_MAX
, rta
, len
);
512 if (tb
[XFRMA_POLICY_TYPE
]) {
513 struct xfrm_userpolicy_type
*upt
;
515 if (RTA_PAYLOAD(tb
[XFRMA_POLICY_TYPE
]) < sizeof(*upt
)) {
516 fprintf(stderr
, "too short XFRMA_POLICY_TYPE len\n");
519 upt
= RTA_DATA(tb
[XFRMA_POLICY_TYPE
]);
523 if (xpinfo
&& !xfrm_policy_filter_match(xpinfo
, ptype
))
526 if (n
->nlmsg_type
== XFRM_MSG_DELPOLICY
)
527 fprintf(fp
, "Deleted ");
528 else if (n
->nlmsg_type
== XFRM_MSG_UPDPOLICY
)
529 fprintf(fp
, "Updated ");
530 else if (n
->nlmsg_type
== XFRM_MSG_POLEXPIRE
)
531 fprintf(fp
, "Expired ");
533 if (n
->nlmsg_type
== XFRM_MSG_DELPOLICY
) {
534 /* xfrm_policy_id_print(); */
535 if (!tb
[XFRMA_POLICY
]) {
536 fprintf(stderr
, "Buggy XFRM_MSG_DELPOLICY: no XFRMA_POLICY\n");
539 if (RTA_PAYLOAD(tb
[XFRMA_POLICY
]) < sizeof(*xpinfo
)) {
540 fprintf(stderr
, "Buggy XFRM_MSG_DELPOLICY: too short XFRMA_POLICY len\n");
543 xpinfo
= RTA_DATA(tb
[XFRMA_POLICY
]);
546 xfrm_policy_info_print(xpinfo
, tb
, fp
, NULL
, NULL
);
548 if (n
->nlmsg_type
== XFRM_MSG_POLEXPIRE
) {
550 fprintf(fp
, "hard %u", xpexp
->hard
);
551 fprintf(fp
, "%s", _SL_
);
561 static int xfrm_policy_get_or_delete(int argc
, char **argv
, int delete,
562 struct nlmsghdr
**answer
)
564 struct rtnl_handle rth
;
567 struct xfrm_userpolicy_id xpid
;
568 char buf
[RTA_BUF_SIZE
];
570 .n
.nlmsg_len
= NLMSG_LENGTH(sizeof(req
.xpid
)),
571 .n
.nlmsg_flags
= NLM_F_REQUEST
,
572 .n
.nlmsg_type
= delete ? XFRM_MSG_DELPOLICY
573 : XFRM_MSG_GETPOLICY
,
580 struct xfrm_userpolicy_type upt
= {};
581 struct xfrm_mark mark
= {0, 0};
583 struct xfrm_user_sec_ctx sctx
;
584 char str
[CTX_BUF_SIZE
];
586 bool is_if_id_set
= false;
590 if (strcmp(*argv
, "dir") == 0) {
592 duparg("dir", *argv
);
596 xfrm_policy_dir_parse(&req
.xpid
.dir
, &argc
, &argv
);
598 } else if (strcmp(*argv
, "ctx") == 0) {
602 duparg("ctx", *argv
);
606 xfrm_sctx_parse((char *)&ctx
.str
, context
, &ctx
.sctx
);
607 } else if (strcmp(*argv
, "mark") == 0) {
608 xfrm_parse_mark(&mark
, &argc
, &argv
);
609 } else if (strcmp(*argv
, "index") == 0) {
611 duparg("index", *argv
);
615 if (get_u32(&req
.xpid
.index
, *argv
, 0))
616 invarg("INDEX value is invalid", *argv
);
618 } else if (strcmp(*argv
, "ptype") == 0) {
620 duparg("ptype", *argv
);
624 xfrm_policy_ptype_parse(&upt
.type
, &argc
, &argv
);
625 } else if (strcmp(*argv
, "if_id") == 0) {
627 if (get_u32(&if_id
, *argv
, 0))
628 invarg("IF_ID value is invalid", *argv
);
632 invarg("unknown", *argv
);
635 xfrm_selector_parse(&req
.xpid
.sel
, &argc
, &argv
);
636 if (preferred_family
== AF_UNSPEC
)
637 preferred_family
= req
.xpid
.sel
.family
;
645 fprintf(stderr
, "Not enough information: DIR is required.\n");
649 addattr_l(&req
.n
, sizeof(req
), XFRMA_POLICY_TYPE
,
650 (void *)&upt
, sizeof(upt
));
652 if (!selp
&& !indexp
) {
653 fprintf(stderr
, "Not enough information: either SELECTOR or INDEX is required.\n");
657 duparg2("SELECTOR", "INDEX");
659 if (rtnl_open_byproto(&rth
, 0, NETLINK_XFRM
) < 0)
662 if (req
.xpid
.sel
.family
== AF_UNSPEC
)
663 req
.xpid
.sel
.family
= AF_INET
;
665 if (mark
.m
& mark
.v
) {
666 int r
= addattr_l(&req
.n
, sizeof(req
.buf
), XFRMA_MARK
,
667 (void *)&mark
, sizeof(mark
));
669 fprintf(stderr
, "%s: XFRMA_MARK failed\n", __func__
);
675 addattr_l(&req
.n
, sizeof(req
), XFRMA_SEC_CTX
,
676 (void *)&ctx
, ctx
.sctx
.len
);
680 addattr32(&req
.n
, sizeof(req
.buf
), XFRMA_IF_ID
, if_id
);
682 if (rtnl_talk(&rth
, &req
.n
, answer
) < 0)
690 static int xfrm_policy_delete(int argc
, char **argv
)
692 return xfrm_policy_get_or_delete(argc
, argv
, 1, NULL
);
695 static int xfrm_policy_get(int argc
, char **argv
)
697 struct nlmsghdr
*n
= NULL
;
699 xfrm_policy_get_or_delete(argc
, argv
, 0, &n
);
701 if (xfrm_policy_print(n
, (void *)stdout
) < 0) {
702 fprintf(stderr
, "An error :-)\n");
711 * With an existing policy of nlmsg, make new nlmsg for deleting the policy
712 * and store it to buffer.
714 static int xfrm_policy_keep(struct nlmsghdr
*n
, void *arg
)
716 struct xfrm_buffer
*xb
= (struct xfrm_buffer
*)arg
;
717 struct rtnl_handle
*rth
= xb
->rth
;
718 struct xfrm_userpolicy_info
*xpinfo
= NLMSG_DATA(n
);
719 int len
= n
->nlmsg_len
;
720 struct rtattr
*tb
[XFRMA_MAX
+1];
721 __u8 ptype
= XFRM_POLICY_TYPE_MAIN
;
722 struct nlmsghdr
*new_n
;
723 struct xfrm_userpolicy_id
*xpid
;
725 if (n
->nlmsg_type
!= XFRM_MSG_NEWPOLICY
) {
726 fprintf(stderr
, "Not a policy: %08x %08x %08x\n",
727 n
->nlmsg_len
, n
->nlmsg_type
, n
->nlmsg_flags
);
731 len
-= NLMSG_LENGTH(sizeof(*xpinfo
));
733 fprintf(stderr
, "BUG: wrong nlmsg len %d\n", len
);
737 parse_rtattr(tb
, XFRMA_MAX
, XFRMP_RTA(xpinfo
), len
);
739 if (tb
[XFRMA_POLICY_TYPE
]) {
740 struct xfrm_userpolicy_type
*upt
;
742 if (RTA_PAYLOAD(tb
[XFRMA_POLICY_TYPE
]) < sizeof(*upt
)) {
743 fprintf(stderr
, "too short XFRMA_POLICY_TYPE len\n");
746 upt
= RTA_DATA(tb
[XFRMA_POLICY_TYPE
]);
750 if (!xfrm_policy_filter_match(xpinfo
, ptype
))
753 /* can't delete socket policies */
754 if (xpinfo
->dir
>= XFRM_POLICY_MAX
)
757 if (xb
->offset
+ NLMSG_LENGTH(sizeof(*xpid
)) > xb
->size
)
760 new_n
= (struct nlmsghdr
*)(xb
->buf
+ xb
->offset
);
761 new_n
->nlmsg_len
= NLMSG_LENGTH(sizeof(*xpid
));
762 new_n
->nlmsg_flags
= NLM_F_REQUEST
;
763 new_n
->nlmsg_type
= XFRM_MSG_DELPOLICY
;
764 new_n
->nlmsg_seq
= ++rth
->seq
;
766 xpid
= NLMSG_DATA(new_n
);
767 memcpy(&xpid
->sel
, &xpinfo
->sel
, sizeof(xpid
->sel
));
768 xpid
->dir
= xpinfo
->dir
;
769 xpid
->index
= xpinfo
->index
;
771 if (tb
[XFRMA_MARK
]) {
772 int r
= addattr_l(new_n
, xb
->size
, XFRMA_MARK
,
773 (void *)RTA_DATA(tb
[XFRMA_MARK
]), tb
[XFRMA_MARK
]->rta_len
);
775 fprintf(stderr
, "%s: XFRMA_MARK failed\n", __func__
);
780 if (tb
[XFRMA_IF_ID
]) {
781 addattr32(new_n
, xb
->size
, XFRMA_IF_ID
,
782 rta_getattr_u32(tb
[XFRMA_IF_ID
]));
785 xb
->offset
+= new_n
->nlmsg_len
;
791 static int xfrm_policy_list_or_deleteall(int argc
, char **argv
, int deleteall
)
794 struct rtnl_handle rth
;
796 if (argc
> 0 || preferred_family
!= AF_UNSPEC
)
798 filter
.xpinfo
.sel
.family
= preferred_family
;
801 if (strcmp(*argv
, "dir") == 0) {
803 xfrm_policy_dir_parse(&filter
.xpinfo
.dir
, &argc
, &argv
);
805 filter
.dir_mask
= XFRM_FILTER_MASK_FULL
;
807 } else if (strcmp(*argv
, "index") == 0) {
809 if (get_u32(&filter
.xpinfo
.index
, *argv
, 0))
810 invarg("INDEX value is invalid", *argv
);
812 filter
.index_mask
= XFRM_FILTER_MASK_FULL
;
814 } else if (strcmp(*argv
, "ptype") == 0) {
816 xfrm_policy_ptype_parse(&filter
.ptype
, &argc
, &argv
);
818 filter
.ptype_mask
= XFRM_FILTER_MASK_FULL
;
820 } else if (strcmp(*argv
, "action") == 0) {
822 if (strcmp(*argv
, "allow") == 0)
823 filter
.xpinfo
.action
= XFRM_POLICY_ALLOW
;
824 else if (strcmp(*argv
, "block") == 0)
825 filter
.xpinfo
.action
= XFRM_POLICY_BLOCK
;
827 invarg("ACTION value is invalid\n", *argv
);
829 filter
.action_mask
= XFRM_FILTER_MASK_FULL
;
831 } else if (strcmp(*argv
, "priority") == 0) {
833 if (get_u32(&filter
.xpinfo
.priority
, *argv
, 0))
834 invarg("PRIORITY value is invalid", *argv
);
836 filter
.priority_mask
= XFRM_FILTER_MASK_FULL
;
838 } else if (strcmp(*argv
, "flag") == 0) {
840 xfrm_policy_flag_parse(&filter
.xpinfo
.flags
, &argc
,
843 filter
.policy_flags_mask
= XFRM_FILTER_MASK_FULL
;
845 } else if (strcmp(*argv
, "nosock") == 0) {
846 /* filter all socket-based policies */
847 filter
.filter_socket
= 1;
850 invarg("unknown", *argv
);
853 xfrm_selector_parse(&filter
.xpinfo
.sel
, &argc
, &argv
);
854 if (preferred_family
== AF_UNSPEC
)
855 preferred_family
= filter
.xpinfo
.sel
.family
;
862 if (rtnl_open_byproto(&rth
, 0, NETLINK_XFRM
) < 0)
866 struct xfrm_buffer xb
;
867 char buf
[NLMSG_DELETEALL_BUF_SIZE
];
871 xb
.size
= sizeof(buf
);
877 char buf
[NLMSG_BUF_SIZE
];
879 .n
.nlmsg_len
= NLMSG_HDRLEN
,
880 .n
.nlmsg_flags
= NLM_F_DUMP
| NLM_F_REQUEST
,
881 .n
.nlmsg_type
= XFRM_MSG_GETPOLICY
,
882 .n
.nlmsg_seq
= rth
.dump
= ++rth
.seq
,
889 fprintf(stderr
, "Delete-all round = %d\n", i
);
891 if (rtnl_send(&rth
, (void *)&req
, req
.n
.nlmsg_len
) < 0) {
892 perror("Cannot send dump request");
896 if (rtnl_dump_filter(&rth
, xfrm_policy_keep
, &xb
) < 0) {
897 fprintf(stderr
, "Delete-all terminated\n");
900 if (xb
.nlmsg_count
== 0) {
902 fprintf(stderr
, "Delete-all completed\n");
906 if (rtnl_send_check(&rth
, xb
.buf
, xb
.offset
) < 0) {
907 perror("Failed to send delete-all request");
911 fprintf(stderr
, "Delete-all nlmsg count = %d\n", xb
.nlmsg_count
);
919 char buf
[NLMSG_BUF_SIZE
];
921 .n
.nlmsg_len
= NLMSG_HDRLEN
,
922 .n
.nlmsg_flags
= NLM_F_DUMP
| NLM_F_REQUEST
,
923 .n
.nlmsg_type
= XFRM_MSG_GETPOLICY
,
924 .n
.nlmsg_seq
= rth
.dump
= ++rth
.seq
,
927 if (rtnl_send(&rth
, (void *)&req
, req
.n
.nlmsg_len
) < 0) {
928 perror("Cannot send dump request");
932 if (rtnl_dump_filter(&rth
, xfrm_policy_print
, stdout
) < 0) {
933 fprintf(stderr
, "Dump terminated\n");
943 static int print_spdinfo(struct nlmsghdr
*n
, void *arg
)
945 FILE *fp
= (FILE *)arg
;
946 __u32
*f
= NLMSG_DATA(n
);
947 struct rtattr
*tb
[XFRMA_SPD_MAX
+1];
950 int len
= n
->nlmsg_len
;
952 len
-= NLMSG_LENGTH(sizeof(__u32
));
954 fprintf(stderr
, "SPDinfo: Wrong len %d\n", len
);
958 rta
= XFRMSAPD_RTA(f
);
959 parse_rtattr(tb
, XFRMA_SPD_MAX
, rta
, len
);
961 fprintf(fp
, "\t SPD");
962 if (tb
[XFRMA_SPD_INFO
]) {
963 struct xfrmu_spdinfo
*si
;
965 if (RTA_PAYLOAD(tb
[XFRMA_SPD_INFO
]) < sizeof(*si
)) {
966 fprintf(stderr
, "SPDinfo: Wrong len %d\n", len
);
969 si
= RTA_DATA(tb
[XFRMA_SPD_INFO
]);
970 fprintf(fp
, " IN %d", si
->incnt
);
971 fprintf(fp
, " OUT %d", si
->outcnt
);
972 fprintf(fp
, " FWD %d", si
->fwdcnt
);
975 fprintf(fp
, " (Sock:");
976 fprintf(fp
, " IN %d", si
->inscnt
);
977 fprintf(fp
, " OUT %d", si
->outscnt
);
978 fprintf(fp
, " FWD %d", si
->fwdscnt
);
982 fprintf(fp
, "%s", _SL_
);
984 if (show_stats
> 1) {
985 struct xfrmu_spdhinfo
*sh
;
987 if (tb
[XFRMA_SPD_HINFO
]) {
988 if (RTA_PAYLOAD(tb
[XFRMA_SPD_HINFO
]) < sizeof(*sh
)) {
989 fprintf(stderr
, "SPDinfo: Wrong len %d\n", len
);
992 sh
= RTA_DATA(tb
[XFRMA_SPD_HINFO
]);
993 fprintf(fp
, "\t SPD buckets:");
994 fprintf(fp
, " count %d", sh
->spdhcnt
);
995 fprintf(fp
, " Max %d", sh
->spdhmcnt
);
996 fprintf(fp
, "%s", _SL_
);
998 if (tb
[XFRMA_SPD_IPV4_HTHRESH
]) {
999 struct xfrmu_spdhthresh
*th
;
1001 if (RTA_PAYLOAD(tb
[XFRMA_SPD_IPV4_HTHRESH
]) < sizeof(*th
)) {
1002 fprintf(stderr
, "SPDinfo: Wrong len %d\n", len
);
1005 th
= RTA_DATA(tb
[XFRMA_SPD_IPV4_HTHRESH
]);
1006 fprintf(fp
, "\t SPD IPv4 thresholds:");
1007 fprintf(fp
, " local %d", th
->lbits
);
1008 fprintf(fp
, " remote %d", th
->rbits
);
1009 fprintf(fp
, "%s", _SL_
);
1012 if (tb
[XFRMA_SPD_IPV6_HTHRESH
]) {
1013 struct xfrmu_spdhthresh
*th
;
1015 if (RTA_PAYLOAD(tb
[XFRMA_SPD_IPV6_HTHRESH
]) < sizeof(*th
)) {
1016 fprintf(stderr
, "SPDinfo: Wrong len %d\n", len
);
1019 th
= RTA_DATA(tb
[XFRMA_SPD_IPV6_HTHRESH
]);
1020 fprintf(fp
, "\t SPD IPv6 thresholds:");
1021 fprintf(fp
, " local %d", th
->lbits
);
1022 fprintf(fp
, " remote %d", th
->rbits
);
1023 fprintf(fp
, "%s", _SL_
);
1033 static int xfrm_spd_setinfo(int argc
, char **argv
)
1035 struct rtnl_handle rth
;
1039 char buf
[RTA_BUF_SIZE
];
1041 .n
.nlmsg_len
= NLMSG_LENGTH(sizeof(__u32
)),
1042 .n
.nlmsg_flags
= NLM_F_REQUEST
,
1043 .n
.nlmsg_type
= XFRM_MSG_NEWSPDINFO
,
1044 .flags
= 0XFFFFFFFF,
1051 if (strcmp(*argv
, "hthresh4") == 0) {
1052 struct xfrmu_spdhthresh thr
;
1055 duparg("hthresh4", *argv
);
1058 if (get_u8(&thr
.lbits
, *argv
, 0) || thr
.lbits
> 32)
1059 invarg("hthresh4 LBITS value is invalid", *argv
);
1061 if (get_u8(&thr
.rbits
, *argv
, 0) || thr
.rbits
> 32)
1062 invarg("hthresh4 RBITS value is invalid", *argv
);
1064 addattr_l(&req
.n
, sizeof(req
), XFRMA_SPD_IPV4_HTHRESH
,
1065 (void *)&thr
, sizeof(thr
));
1066 } else if (strcmp(*argv
, "hthresh6") == 0) {
1067 struct xfrmu_spdhthresh thr
;
1070 duparg("hthresh6", *argv
);
1073 if (get_u8(&thr
.lbits
, *argv
, 0) || thr
.lbits
> 128)
1074 invarg("hthresh6 LBITS value is invalid", *argv
);
1076 if (get_u8(&thr
.rbits
, *argv
, 0) || thr
.rbits
> 128)
1077 invarg("hthresh6 RBITS value is invalid", *argv
);
1079 addattr_l(&req
.n
, sizeof(req
), XFRMA_SPD_IPV6_HTHRESH
,
1080 (void *)&thr
, sizeof(thr
));
1082 invarg("unknown", *argv
);
1088 if (rtnl_open_byproto(&rth
, 0, NETLINK_XFRM
) < 0)
1091 if (rtnl_talk(&rth
, &req
.n
, NULL
) < 0)
1099 static int xfrm_spd_getinfo(int argc
, char **argv
)
1101 struct rtnl_handle rth
;
1106 .n
.nlmsg_len
= NLMSG_LENGTH(sizeof(__u32
)),
1107 .n
.nlmsg_flags
= NLM_F_REQUEST
,
1108 .n
.nlmsg_type
= XFRM_MSG_GETSPDINFO
,
1109 .flags
= 0XFFFFFFFF,
1111 struct nlmsghdr
*answer
;
1113 if (rtnl_open_byproto(&rth
, 0, NETLINK_XFRM
) < 0)
1116 if (rtnl_talk(&rth
, &req
.n
, &answer
) < 0)
1119 print_spdinfo(answer
, (void *)stdout
);
1127 static int xfrm_policy_flush(int argc
, char **argv
)
1129 struct rtnl_handle rth
;
1132 char buf
[RTA_BUF_SIZE
];
1134 .n
.nlmsg_len
= NLMSG_LENGTH(0), /* nlmsg data is nothing */
1135 .n
.nlmsg_flags
= NLM_F_REQUEST
,
1136 .n
.nlmsg_type
= XFRM_MSG_FLUSHPOLICY
,
1138 char *ptypep
= NULL
;
1139 struct xfrm_userpolicy_type upt
= {};
1142 if (strcmp(*argv
, "ptype") == 0) {
1144 duparg("ptype", *argv
);
1148 xfrm_policy_ptype_parse(&upt
.type
, &argc
, &argv
);
1150 invarg("unknown", *argv
);
1156 addattr_l(&req
.n
, sizeof(req
), XFRMA_POLICY_TYPE
,
1157 (void *)&upt
, sizeof(upt
));
1160 if (rtnl_open_byproto(&rth
, 0, NETLINK_XFRM
) < 0)
1164 fprintf(stderr
, "Flush policy\n");
1166 if (rtnl_talk(&rth
, &req
.n
, NULL
) < 0)
1174 int do_xfrm_policy(int argc
, char **argv
)
1177 return xfrm_policy_list_or_deleteall(0, NULL
, 0);
1179 if (matches(*argv
, "add") == 0)
1180 return xfrm_policy_modify(XFRM_MSG_NEWPOLICY
, 0,
1182 if (matches(*argv
, "update") == 0)
1183 return xfrm_policy_modify(XFRM_MSG_UPDPOLICY
, 0,
1185 if (matches(*argv
, "delete") == 0)
1186 return xfrm_policy_delete(argc
-1, argv
+1);
1187 if (matches(*argv
, "deleteall") == 0 || matches(*argv
, "delall") == 0)
1188 return xfrm_policy_list_or_deleteall(argc
-1, argv
+1, 1);
1189 if (matches(*argv
, "list") == 0 || matches(*argv
, "show") == 0
1190 || matches(*argv
, "lst") == 0)
1191 return xfrm_policy_list_or_deleteall(argc
-1, argv
+1, 0);
1192 if (matches(*argv
, "get") == 0)
1193 return xfrm_policy_get(argc
-1, argv
+1);
1194 if (matches(*argv
, "flush") == 0)
1195 return xfrm_policy_flush(argc
-1, argv
+1);
1196 if (matches(*argv
, "count") == 0)
1197 return xfrm_spd_getinfo(argc
, argv
);
1198 if (matches(*argv
, "set") == 0)
1199 return xfrm_spd_setinfo(argc
-1, argv
+1);
1200 if (matches(*argv
, "help") == 0)
1202 fprintf(stderr
, "Command \"%s\" is unknown, try \"ip xfrm policy help\".\n", *argv
);