iproute2/ip/xfrm_policy.c
<<
>>
Prefs
   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, see <http://www.gnu.org/licenses>.
  18 */
  19/*
  20 * based on iproute.c
  21 */
  22/*
  23 * Authors:
  24 *      Masahide NAKAMURA @USAGI
  25 */
  26
  27#include <stdio.h>
  28#include <stdlib.h>
  29#include <string.h>
  30#include <netdb.h>
  31#include <linux/netlink.h>
  32#include "utils.h"
  33#include "xfrm.h"
  34#include "ip_common.h"
  35
  36/* #define NLMSG_DELETEALL_BUF_SIZE (4096-512) */
  37#define NLMSG_DELETEALL_BUF_SIZE 8192
  38
  39/*
  40 * Receiving buffer defines:
  41 * nlmsg
  42 *   data = struct xfrm_userpolicy_info
  43 *   rtattr
  44 *     data = struct xfrm_user_tmpl[]
  45 */
  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
  50
  51static void usage(void) __attribute__((noreturn));
  52
  53static void usage(void)
  54{
  55        fprintf(stderr,
  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"
  62                "       [ if_id IF_ID ]\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"
  84                "XFRM-PROTO := ");
  85        fprintf(stderr,
  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));
  92        fprintf(stderr,
  93                "MODE := transport | tunnel | beet | ro | in_trigger\n"
  94                "LEVEL := required | use\n");
  95
  96        exit(-1);
  97}
  98
  99static int xfrm_policy_dir_parse(__u8 *dir, int *argcp, char ***argvp)
 100{
 101        int argc = *argcp;
 102        char **argv = *argvp;
 103
 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;
 110        else
 111                invarg("DIR value is invalid", *argv);
 112
 113        *argcp = argc;
 114        *argvp = argv;
 115
 116        return 0;
 117}
 118
 119static int xfrm_policy_ptype_parse(__u8 *ptype, int *argcp, char ***argvp)
 120{
 121        int argc = *argcp;
 122        char **argv = *argvp;
 123
 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;
 128        else
 129                invarg("PTYPE value is invalid", *argv);
 130
 131        *argcp = argc;
 132        *argvp = argv;
 133
 134        return 0;
 135}
 136
 137static int xfrm_policy_flag_parse(__u8 *flags, int *argcp, char ***argvp)
 138{
 139        int argc = *argcp;
 140        char **argv = *argvp;
 141        int len = strlen(*argv);
 142
 143        if (len > 2 && strncmp(*argv, "0x", 2) == 0) {
 144                __u8 val = 0;
 145
 146                if (get_u8(&val, *argv, 16))
 147                        invarg("FLAG value is invalid", *argv);
 148                *flags = val;
 149        } else {
 150                while (1) {
 151                        if (strcmp(*argv, "localok") == 0)
 152                                *flags |= XFRM_POLICY_LOCALOK;
 153                        else if (strcmp(*argv, "icmp") == 0)
 154                                *flags |= XFRM_POLICY_ICMP;
 155                        else {
 156                                PREV_ARG(); /* back track */
 157                                break;
 158                        }
 159
 160                        if (!NEXT_ARG_OK())
 161                                break;
 162                        NEXT_ARG();
 163                }
 164        }
 165
 166        *argcp = argc;
 167        *argvp = argv;
 168
 169        return 0;
 170}
 171
 172static int xfrm_tmpl_parse(struct xfrm_user_tmpl *tmpl,
 173                           int *argcp, char ***argvp)
 174{
 175        int argc = *argcp;
 176        char **argv = *argvp;
 177        char *idp = NULL;
 178
 179        while (1) {
 180                if (strcmp(*argv, "mode") == 0) {
 181                        NEXT_ARG();
 182                        xfrm_mode_parse(&tmpl->mode,  &argc, &argv);
 183                } else if (strcmp(*argv, "reqid") == 0) {
 184                        NEXT_ARG();
 185                        xfrm_reqid_parse(&tmpl->reqid, &argc, &argv);
 186                } else if (strcmp(*argv, "level") == 0) {
 187                        NEXT_ARG();
 188
 189                        if (strcmp(*argv, "required") == 0)
 190                                tmpl->optional = 0;
 191                        else if (strcmp(*argv, "use") == 0)
 192                                tmpl->optional = 1;
 193                        else
 194                                invarg("LEVEL value is invalid\n", *argv);
 195
 196                } else {
 197                        if (idp) {
 198                                PREV_ARG(); /* back track */
 199                                break;
 200                        }
 201                        idp = *argv;
 202                        preferred_family = AF_UNSPEC;
 203                        xfrm_id_parse(&tmpl->saddr, &tmpl->id, &tmpl->family,
 204                                      0, &argc, &argv);
 205                        preferred_family = tmpl->family;
 206                }
 207
 208                if (!NEXT_ARG_OK())
 209                        break;
 210
 211                NEXT_ARG();
 212        }
 213        if (argc == *argcp)
 214                missarg("TMPL");
 215
 216        *argcp = argc;
 217        *argvp = argv;
 218
 219        return 0;
 220}
 221
 222int xfrm_sctx_parse(char *ctxstr, char *s,
 223                           struct xfrm_user_sec_ctx *sctx)
 224{
 225        int slen;
 226
 227        slen = strlen(s) + 1;
 228
 229        sctx->exttype = XFRMA_SEC_CTX;
 230        sctx->ctx_doi = 1;
 231        sctx->ctx_alg = 1;
 232        sctx->ctx_len = slen;
 233        sctx->len = sizeof(struct xfrm_user_sec_ctx) + slen;
 234        memcpy(ctxstr, s, slen);
 235
 236        return 0;
 237}
 238
 239static int xfrm_policy_modify(int cmd, unsigned int flags, int argc, char **argv)
 240{
 241        struct rtnl_handle rth;
 242        struct {
 243                struct nlmsghdr                 n;
 244                struct xfrm_userpolicy_info     xpinfo;
 245                char                            buf[RTA_BUF_SIZE];
 246        } req = {
 247                .n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xpinfo)),
 248                .n.nlmsg_flags = NLM_F_REQUEST | flags,
 249                .n.nlmsg_type = cmd,
 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,
 255        };
 256        char *dirp = NULL;
 257        char *selp = NULL;
 258        char *ptypep = NULL;
 259        char *sctxp = NULL;
 260        struct xfrm_userpolicy_type upt = {};
 261        char tmpls_buf[XFRM_TMPLS_BUF_SIZE] = {};
 262        int tmpls_len = 0;
 263        struct xfrm_mark mark = {0, 0};
 264        struct {
 265                struct xfrm_user_sec_ctx sctx;
 266                char    str[CTX_BUF_SIZE];
 267        } ctx = {};
 268        bool is_if_id_set = false;
 269        __u32 if_id = 0;
 270
 271        while (argc > 0) {
 272                if (strcmp(*argv, "dir") == 0) {
 273                        if (dirp)
 274                                duparg("dir", *argv);
 275                        dirp = *argv;
 276
 277                        NEXT_ARG();
 278                        xfrm_policy_dir_parse(&req.xpinfo.dir, &argc, &argv);
 279                } else if (strcmp(*argv, "ctx") == 0) {
 280                        char *context;
 281
 282                        if (sctxp)
 283                                duparg("ctx", *argv);
 284                        sctxp = *argv;
 285                        NEXT_ARG();
 286                        context = *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) {
 291                        NEXT_ARG();
 292                        if (get_u32(&req.xpinfo.index, *argv, 0))
 293                                invarg("INDEX value is invalid", *argv);
 294                } else if (strcmp(*argv, "ptype") == 0) {
 295                        if (ptypep)
 296                                duparg("ptype", *argv);
 297                        ptypep = *argv;
 298
 299                        NEXT_ARG();
 300                        xfrm_policy_ptype_parse(&upt.type, &argc, &argv);
 301                } else if (strcmp(*argv, "action") == 0) {
 302                        NEXT_ARG();
 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;
 307                        else
 308                                invarg("ACTION value is invalid\n", *argv);
 309                } else if (strcmp(*argv, "priority") == 0) {
 310                        NEXT_ARG();
 311                        if (get_u32(&req.xpinfo.priority, *argv, 0))
 312                                invarg("PRIORITY value is invalid", *argv);
 313                } else if (strcmp(*argv, "flag") == 0) {
 314                        NEXT_ARG();
 315                        xfrm_policy_flag_parse(&req.xpinfo.flags, &argc,
 316                                               &argv);
 317                } else if (strcmp(*argv, "limit") == 0) {
 318                        NEXT_ARG();
 319                        xfrm_lifetime_cfg_parse(&req.xpinfo.lft, &argc, &argv);
 320                } else if (strcmp(*argv, "tmpl") == 0) {
 321                        struct xfrm_user_tmpl *tmpl;
 322
 323                        if (tmpls_len + sizeof(*tmpl) > sizeof(tmpls_buf)) {
 324                                fprintf(stderr, "Too many tmpls: buffer overflow\n");
 325                                exit(1);
 326                        }
 327                        tmpl = (struct xfrm_user_tmpl *)((char *)tmpls_buf + tmpls_len);
 328
 329                        tmpl->family = preferred_family;
 330                        tmpl->aalgos = (~(__u32)0);
 331                        tmpl->ealgos = (~(__u32)0);
 332                        tmpl->calgos = (~(__u32)0);
 333
 334                        NEXT_ARG();
 335                        xfrm_tmpl_parse(tmpl, &argc, &argv);
 336
 337                        tmpls_len += sizeof(*tmpl);
 338                } else if (strcmp(*argv, "if_id") == 0) {
 339                        NEXT_ARG();
 340                        if (get_u32(&if_id, *argv, 0))
 341                                invarg("IF_ID value is invalid", *argv);
 342                        is_if_id_set = true;
 343                } else {
 344                        if (selp)
 345                                duparg("unknown", *argv);
 346                        selp = *argv;
 347
 348                        xfrm_selector_parse(&req.xpinfo.sel, &argc, &argv);
 349                        if (preferred_family == AF_UNSPEC)
 350                                preferred_family = req.xpinfo.sel.family;
 351                }
 352
 353                argc--; argv++;
 354        }
 355
 356        if (!dirp) {
 357                fprintf(stderr, "Not enough information: DIR is required.\n");
 358                exit(1);
 359        }
 360
 361        if (ptypep) {
 362                addattr_l(&req.n, sizeof(req), XFRMA_POLICY_TYPE,
 363                          (void *)&upt, sizeof(upt));
 364        }
 365
 366        if (tmpls_len > 0) {
 367                addattr_l(&req.n, sizeof(req), XFRMA_TMPL,
 368                          (void *)tmpls_buf, tmpls_len);
 369        }
 370
 371        if (mark.m) {
 372                int r = addattr_l(&req.n, sizeof(req.buf), XFRMA_MARK,
 373                                  (void *)&mark, sizeof(mark));
 374                if (r < 0) {
 375                        fprintf(stderr, "%s: XFRMA_MARK failed\n", __func__);
 376                        exit(1);
 377                }
 378        }
 379
 380        if (sctxp) {
 381                addattr_l(&req.n, sizeof(req), XFRMA_SEC_CTX,
 382                          (void *)&ctx, ctx.sctx.len);
 383        }
 384
 385        if (is_if_id_set)
 386                addattr32(&req.n, sizeof(req.buf), XFRMA_IF_ID, if_id);
 387
 388        if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
 389                exit(1);
 390
 391        if (req.xpinfo.sel.family == AF_UNSPEC)
 392                req.xpinfo.sel.family = AF_INET;
 393
 394        if (rtnl_talk(&rth, &req.n, NULL) < 0)
 395                exit(2);
 396
 397        rtnl_close(&rth);
 398
 399        return 0;
 400}
 401
 402static int xfrm_policy_filter_match(struct xfrm_userpolicy_info *xpinfo,
 403                                    __u8 ptype)
 404{
 405        if (!filter.use)
 406                return 1;
 407
 408        if (filter.xpinfo.sel.family != AF_UNSPEC &&
 409            filter.xpinfo.sel.family != xpinfo->sel.family)
 410                return 0;
 411
 412        if ((xpinfo->dir^filter.xpinfo.dir)&filter.dir_mask)
 413                return 0;
 414
 415        if (filter.filter_socket && (xpinfo->dir >= XFRM_POLICY_MAX))
 416                return 0;
 417
 418        if ((ptype^filter.ptype)&filter.ptype_mask)
 419                return 0;
 420
 421        if (filter.sel_src_mask) {
 422                if (xfrm_addr_match(&xpinfo->sel.saddr, &filter.xpinfo.sel.saddr,
 423                                    filter.sel_src_mask))
 424                        return 0;
 425        }
 426
 427        if (filter.sel_dst_mask) {
 428                if (xfrm_addr_match(&xpinfo->sel.daddr, &filter.xpinfo.sel.daddr,
 429                                    filter.sel_dst_mask))
 430                        return 0;
 431        }
 432
 433        if ((xpinfo->sel.ifindex^filter.xpinfo.sel.ifindex)&filter.sel_dev_mask)
 434                return 0;
 435
 436        if ((xpinfo->sel.proto^filter.xpinfo.sel.proto)&filter.upspec_proto_mask)
 437                return 0;
 438
 439        if (filter.upspec_sport_mask) {
 440                if ((xpinfo->sel.sport^filter.xpinfo.sel.sport)&filter.upspec_sport_mask)
 441                        return 0;
 442        }
 443
 444        if (filter.upspec_dport_mask) {
 445                if ((xpinfo->sel.dport^filter.xpinfo.sel.dport)&filter.upspec_dport_mask)
 446                        return 0;
 447        }
 448
 449        if ((xpinfo->index^filter.xpinfo.index)&filter.index_mask)
 450                return 0;
 451
 452        if ((xpinfo->action^filter.xpinfo.action)&filter.action_mask)
 453                return 0;
 454
 455        if ((xpinfo->priority^filter.xpinfo.priority)&filter.priority_mask)
 456                return 0;
 457
 458        if (filter.policy_flags_mask)
 459                if ((xpinfo->flags & filter.xpinfo.flags) == 0)
 460                        return 0;
 461
 462        return 1;
 463}
 464
 465int xfrm_policy_print(struct nlmsghdr *n, void *arg)
 466{
 467        struct rtattr *tb[XFRMA_MAX+1];
 468        struct rtattr *rta;
 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;
 475
 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);
 482                return 0;
 483        }
 484
 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));
 492        } else {
 493                xpexp = NULL;
 494                xpinfo = NLMSG_DATA(n);
 495                len -= NLMSG_SPACE(sizeof(*xpinfo));
 496        }
 497
 498        if (len < 0) {
 499                fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
 500                return -1;
 501        }
 502
 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);
 507        else
 508                rta = XFRMP_RTA(xpinfo);
 509
 510        parse_rtattr(tb, XFRMA_MAX, rta, len);
 511
 512        if (tb[XFRMA_POLICY_TYPE]) {
 513                struct xfrm_userpolicy_type *upt;
 514
 515                if (RTA_PAYLOAD(tb[XFRMA_POLICY_TYPE]) < sizeof(*upt)) {
 516                        fprintf(stderr, "too short XFRMA_POLICY_TYPE len\n");
 517                        return -1;
 518                }
 519                upt = RTA_DATA(tb[XFRMA_POLICY_TYPE]);
 520                ptype = upt->type;
 521        }
 522
 523        if (xpinfo && !xfrm_policy_filter_match(xpinfo, ptype))
 524                return 0;
 525
 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 ");
 532
 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");
 537                        return -1;
 538                }
 539                if (RTA_PAYLOAD(tb[XFRMA_POLICY]) < sizeof(*xpinfo)) {
 540                        fprintf(stderr, "Buggy XFRM_MSG_DELPOLICY: too short XFRMA_POLICY len\n");
 541                        return -1;
 542                }
 543                xpinfo = RTA_DATA(tb[XFRMA_POLICY]);
 544        }
 545
 546        xfrm_policy_info_print(xpinfo, tb, fp, NULL, NULL);
 547
 548        if (n->nlmsg_type == XFRM_MSG_POLEXPIRE) {
 549                fprintf(fp, "\t");
 550                fprintf(fp, "hard %u", xpexp->hard);
 551                fprintf(fp, "%s", _SL_);
 552        }
 553
 554        if (oneline)
 555                fprintf(fp, "\n");
 556        fflush(fp);
 557
 558        return 0;
 559}
 560
 561static int xfrm_policy_get_or_delete(int argc, char **argv, int delete,
 562                                     struct nlmsghdr **answer)
 563{
 564        struct rtnl_handle rth;
 565        struct {
 566                struct nlmsghdr                 n;
 567                struct xfrm_userpolicy_id       xpid;
 568                char                            buf[RTA_BUF_SIZE];
 569        } req = {
 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,
 574        };
 575        char *dirp = NULL;
 576        char *selp = NULL;
 577        char *indexp = NULL;
 578        char *ptypep = NULL;
 579        char *sctxp = NULL;
 580        struct xfrm_userpolicy_type upt = {};
 581        struct xfrm_mark mark = {0, 0};
 582        struct {
 583                struct xfrm_user_sec_ctx sctx;
 584                char    str[CTX_BUF_SIZE];
 585        } ctx = {};
 586        bool is_if_id_set = false;
 587        __u32 if_id = 0;
 588
 589        while (argc > 0) {
 590                if (strcmp(*argv, "dir") == 0) {
 591                        if (dirp)
 592                                duparg("dir", *argv);
 593                        dirp = *argv;
 594
 595                        NEXT_ARG();
 596                        xfrm_policy_dir_parse(&req.xpid.dir, &argc, &argv);
 597
 598                } else if (strcmp(*argv, "ctx") == 0) {
 599                        char *context;
 600
 601                        if (sctxp)
 602                                duparg("ctx", *argv);
 603                        sctxp = *argv;
 604                        NEXT_ARG();
 605                        context = *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) {
 610                        if (indexp)
 611                                duparg("index", *argv);
 612                        indexp = *argv;
 613
 614                        NEXT_ARG();
 615                        if (get_u32(&req.xpid.index, *argv, 0))
 616                                invarg("INDEX value is invalid", *argv);
 617
 618                } else if (strcmp(*argv, "ptype") == 0) {
 619                        if (ptypep)
 620                                duparg("ptype", *argv);
 621                        ptypep = *argv;
 622
 623                        NEXT_ARG();
 624                        xfrm_policy_ptype_parse(&upt.type, &argc, &argv);
 625                } else if (strcmp(*argv, "if_id") == 0) {
 626                        NEXT_ARG();
 627                        if (get_u32(&if_id, *argv, 0))
 628                                invarg("IF_ID value is invalid", *argv);
 629                        is_if_id_set = true;
 630                } else {
 631                        if (selp)
 632                                invarg("unknown", *argv);
 633                        selp = *argv;
 634
 635                        xfrm_selector_parse(&req.xpid.sel, &argc, &argv);
 636                        if (preferred_family == AF_UNSPEC)
 637                                preferred_family = req.xpid.sel.family;
 638
 639                }
 640
 641                argc--; argv++;
 642        }
 643
 644        if (!dirp) {
 645                fprintf(stderr, "Not enough information: DIR is required.\n");
 646                exit(1);
 647        }
 648        if (ptypep) {
 649                addattr_l(&req.n, sizeof(req), XFRMA_POLICY_TYPE,
 650                          (void *)&upt, sizeof(upt));
 651        }
 652        if (!selp && !indexp) {
 653                fprintf(stderr, "Not enough information: either SELECTOR or INDEX is required.\n");
 654                exit(1);
 655        }
 656        if (selp && indexp)
 657                duparg2("SELECTOR", "INDEX");
 658
 659        if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
 660                exit(1);
 661
 662        if (req.xpid.sel.family == AF_UNSPEC)
 663                req.xpid.sel.family = AF_INET;
 664
 665        if (mark.m & mark.v) {
 666                int r = addattr_l(&req.n, sizeof(req.buf), XFRMA_MARK,
 667                                  (void *)&mark, sizeof(mark));
 668                if (r < 0) {
 669                        fprintf(stderr, "%s: XFRMA_MARK failed\n", __func__);
 670                        exit(1);
 671                }
 672        }
 673
 674        if (sctxp) {
 675                addattr_l(&req.n, sizeof(req), XFRMA_SEC_CTX,
 676                          (void *)&ctx, ctx.sctx.len);
 677        }
 678
 679        if (is_if_id_set)
 680                addattr32(&req.n, sizeof(req.buf), XFRMA_IF_ID, if_id);
 681
 682        if (rtnl_talk(&rth, &req.n, answer) < 0)
 683                exit(2);
 684
 685        rtnl_close(&rth);
 686
 687        return 0;
 688}
 689
 690static int xfrm_policy_delete(int argc, char **argv)
 691{
 692        return xfrm_policy_get_or_delete(argc, argv, 1, NULL);
 693}
 694
 695static int xfrm_policy_get(int argc, char **argv)
 696{
 697        struct nlmsghdr *n = NULL;
 698
 699        xfrm_policy_get_or_delete(argc, argv, 0, &n);
 700
 701        if (xfrm_policy_print(n, (void *)stdout) < 0) {
 702                fprintf(stderr, "An error :-)\n");
 703                exit(1);
 704        }
 705
 706        free(n);
 707        return 0;
 708}
 709
 710/*
 711 * With an existing policy of nlmsg, make new nlmsg for deleting the policy
 712 * and store it to buffer.
 713 */
 714static int xfrm_policy_keep(struct nlmsghdr *n, void *arg)
 715{
 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;
 724
 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);
 728                return 0;
 729        }
 730
 731        len -= NLMSG_LENGTH(sizeof(*xpinfo));
 732        if (len < 0) {
 733                fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
 734                return -1;
 735        }
 736
 737        parse_rtattr(tb, XFRMA_MAX, XFRMP_RTA(xpinfo), len);
 738
 739        if (tb[XFRMA_POLICY_TYPE]) {
 740                struct xfrm_userpolicy_type *upt;
 741
 742                if (RTA_PAYLOAD(tb[XFRMA_POLICY_TYPE]) < sizeof(*upt)) {
 743                        fprintf(stderr, "too short XFRMA_POLICY_TYPE len\n");
 744                        return -1;
 745                }
 746                upt = RTA_DATA(tb[XFRMA_POLICY_TYPE]);
 747                ptype = upt->type;
 748        }
 749
 750        if (!xfrm_policy_filter_match(xpinfo, ptype))
 751                return 0;
 752
 753        /* can't delete socket policies */
 754        if (xpinfo->dir >= XFRM_POLICY_MAX)
 755                return 0;
 756
 757        if (xb->offset + NLMSG_LENGTH(sizeof(*xpid)) > xb->size)
 758                return 0;
 759
 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;
 765
 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;
 770
 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);
 774                if (r < 0) {
 775                        fprintf(stderr, "%s: XFRMA_MARK failed\n", __func__);
 776                        exit(1);
 777                }
 778        }
 779
 780        if (tb[XFRMA_IF_ID]) {
 781                addattr32(new_n, xb->size, XFRMA_IF_ID,
 782                          rta_getattr_u32(tb[XFRMA_IF_ID]));
 783        }
 784
 785        xb->offset += new_n->nlmsg_len;
 786        xb->nlmsg_count++;
 787
 788        return 0;
 789}
 790
 791static int xfrm_policy_list_or_deleteall(int argc, char **argv, int deleteall)
 792{
 793        char *selp = NULL;
 794        struct rtnl_handle rth;
 795
 796        if (argc > 0 || preferred_family != AF_UNSPEC)
 797                filter.use = 1;
 798        filter.xpinfo.sel.family = preferred_family;
 799
 800        while (argc > 0) {
 801                if (strcmp(*argv, "dir") == 0) {
 802                        NEXT_ARG();
 803                        xfrm_policy_dir_parse(&filter.xpinfo.dir, &argc, &argv);
 804
 805                        filter.dir_mask = XFRM_FILTER_MASK_FULL;
 806
 807                } else if (strcmp(*argv, "index") == 0) {
 808                        NEXT_ARG();
 809                        if (get_u32(&filter.xpinfo.index, *argv, 0))
 810                                invarg("INDEX value is invalid", *argv);
 811
 812                        filter.index_mask = XFRM_FILTER_MASK_FULL;
 813
 814                } else if (strcmp(*argv, "ptype") == 0) {
 815                        NEXT_ARG();
 816                        xfrm_policy_ptype_parse(&filter.ptype, &argc, &argv);
 817
 818                        filter.ptype_mask = XFRM_FILTER_MASK_FULL;
 819
 820                } else if (strcmp(*argv, "action") == 0) {
 821                        NEXT_ARG();
 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;
 826                        else
 827                                invarg("ACTION value is invalid\n", *argv);
 828
 829                        filter.action_mask = XFRM_FILTER_MASK_FULL;
 830
 831                } else if (strcmp(*argv, "priority") == 0) {
 832                        NEXT_ARG();
 833                        if (get_u32(&filter.xpinfo.priority, *argv, 0))
 834                                invarg("PRIORITY value is invalid", *argv);
 835
 836                        filter.priority_mask = XFRM_FILTER_MASK_FULL;
 837
 838                } else if (strcmp(*argv, "flag") == 0) {
 839                        NEXT_ARG();
 840                        xfrm_policy_flag_parse(&filter.xpinfo.flags, &argc,
 841                                               &argv);
 842
 843                        filter.policy_flags_mask = XFRM_FILTER_MASK_FULL;
 844
 845                } else if (strcmp(*argv, "nosock") == 0) {
 846                        /* filter all socket-based policies */
 847                        filter.filter_socket = 1;
 848                } else {
 849                        if (selp)
 850                                invarg("unknown", *argv);
 851                        selp = *argv;
 852
 853                        xfrm_selector_parse(&filter.xpinfo.sel, &argc, &argv);
 854                        if (preferred_family == AF_UNSPEC)
 855                                preferred_family = filter.xpinfo.sel.family;
 856
 857                }
 858
 859                argc--; argv++;
 860        }
 861
 862        if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
 863                exit(1);
 864
 865        if (deleteall) {
 866                struct xfrm_buffer xb;
 867                char buf[NLMSG_DELETEALL_BUF_SIZE];
 868                int i;
 869
 870                xb.buf = buf;
 871                xb.size = sizeof(buf);
 872                xb.rth = &rth;
 873
 874                for (i = 0; ; i++) {
 875                        struct {
 876                                struct nlmsghdr n;
 877                                char buf[NLMSG_BUF_SIZE];
 878                        } req = {
 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,
 883                        };
 884
 885                        xb.offset = 0;
 886                        xb.nlmsg_count = 0;
 887
 888                        if (show_stats > 1)
 889                                fprintf(stderr, "Delete-all round = %d\n", i);
 890
 891                        if (rtnl_send(&rth, (void *)&req, req.n.nlmsg_len) < 0) {
 892                                perror("Cannot send dump request");
 893                                exit(1);
 894                        }
 895
 896                        if (rtnl_dump_filter(&rth, xfrm_policy_keep, &xb) < 0) {
 897                                fprintf(stderr, "Delete-all terminated\n");
 898                                exit(1);
 899                        }
 900                        if (xb.nlmsg_count == 0) {
 901                                if (show_stats > 1)
 902                                        fprintf(stderr, "Delete-all completed\n");
 903                                break;
 904                        }
 905
 906                        if (rtnl_send_check(&rth, xb.buf, xb.offset) < 0) {
 907                                perror("Failed to send delete-all request");
 908                                exit(1);
 909                        }
 910                        if (show_stats > 1)
 911                                fprintf(stderr, "Delete-all nlmsg count = %d\n", xb.nlmsg_count);
 912
 913                        xb.offset = 0;
 914                        xb.nlmsg_count = 0;
 915                }
 916        } else {
 917                struct {
 918                        struct nlmsghdr n;
 919                        char buf[NLMSG_BUF_SIZE];
 920                } req = {
 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,
 925                };
 926
 927                if (rtnl_send(&rth, (void *)&req, req.n.nlmsg_len) < 0) {
 928                        perror("Cannot send dump request");
 929                        exit(1);
 930                }
 931
 932                if (rtnl_dump_filter(&rth, xfrm_policy_print, stdout) < 0) {
 933                        fprintf(stderr, "Dump terminated\n");
 934                        exit(1);
 935                }
 936        }
 937
 938        rtnl_close(&rth);
 939
 940        exit(0);
 941}
 942
 943static int print_spdinfo(struct nlmsghdr *n, void *arg)
 944{
 945        FILE *fp = (FILE *)arg;
 946        __u32 *f = NLMSG_DATA(n);
 947        struct rtattr *tb[XFRMA_SPD_MAX+1];
 948        struct rtattr *rta;
 949
 950        int len = n->nlmsg_len;
 951
 952        len -= NLMSG_LENGTH(sizeof(__u32));
 953        if (len < 0) {
 954                fprintf(stderr, "SPDinfo: Wrong len %d\n", len);
 955                return -1;
 956        }
 957
 958        rta = XFRMSAPD_RTA(f);
 959        parse_rtattr(tb, XFRMA_SPD_MAX, rta, len);
 960
 961        fprintf(fp, "\t SPD");
 962        if (tb[XFRMA_SPD_INFO]) {
 963                struct xfrmu_spdinfo *si;
 964
 965                if (RTA_PAYLOAD(tb[XFRMA_SPD_INFO]) < sizeof(*si)) {
 966                        fprintf(stderr, "SPDinfo: Wrong len %d\n", len);
 967                        return -1;
 968                }
 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);
 973
 974                if (show_stats) {
 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);
 979                        fprintf(fp, ")");
 980                }
 981
 982                fprintf(fp, "%s", _SL_);
 983        }
 984        if (show_stats > 1) {
 985                struct xfrmu_spdhinfo *sh;
 986
 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);
 990                                return -1;
 991                        }
 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_);
 997                }
 998                if (tb[XFRMA_SPD_IPV4_HTHRESH]) {
 999                        struct xfrmu_spdhthresh *th;
1000
1001                        if (RTA_PAYLOAD(tb[XFRMA_SPD_IPV4_HTHRESH]) < sizeof(*th)) {
1002                                fprintf(stderr, "SPDinfo: Wrong len %d\n", len);
1003                                return -1;
1004                        }
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_);
1010
1011                }
1012                if (tb[XFRMA_SPD_IPV6_HTHRESH]) {
1013                        struct xfrmu_spdhthresh *th;
1014
1015                        if (RTA_PAYLOAD(tb[XFRMA_SPD_IPV6_HTHRESH]) < sizeof(*th)) {
1016                                fprintf(stderr, "SPDinfo: Wrong len %d\n", len);
1017                                return -1;
1018                        }
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_);
1024                }
1025        }
1026
1027        if (oneline)
1028                fprintf(fp, "\n");
1029
1030        return 0;
1031}
1032
1033static int xfrm_spd_setinfo(int argc, char **argv)
1034{
1035        struct rtnl_handle rth;
1036        struct {
1037                struct nlmsghdr                 n;
1038                __u32                           flags;
1039                char                            buf[RTA_BUF_SIZE];
1040        } req = {
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,
1045        };
1046
1047        char *thr4 = NULL;
1048        char *thr6 = NULL;
1049
1050        while (argc > 0) {
1051                if (strcmp(*argv, "hthresh4") == 0) {
1052                        struct xfrmu_spdhthresh thr;
1053
1054                        if (thr4)
1055                                duparg("hthresh4", *argv);
1056                        thr4 = *argv;
1057                        NEXT_ARG();
1058                        if (get_u8(&thr.lbits, *argv, 0) || thr.lbits > 32)
1059                                invarg("hthresh4 LBITS value is invalid", *argv);
1060                        NEXT_ARG();
1061                        if (get_u8(&thr.rbits, *argv, 0) || thr.rbits > 32)
1062                                invarg("hthresh4 RBITS value is invalid", *argv);
1063
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;
1068
1069                        if (thr6)
1070                                duparg("hthresh6", *argv);
1071                        thr6 = *argv;
1072                        NEXT_ARG();
1073                        if (get_u8(&thr.lbits, *argv, 0) || thr.lbits > 128)
1074                                invarg("hthresh6 LBITS value is invalid", *argv);
1075                        NEXT_ARG();
1076                        if (get_u8(&thr.rbits, *argv, 0) || thr.rbits > 128)
1077                                invarg("hthresh6 RBITS value is invalid", *argv);
1078
1079                        addattr_l(&req.n, sizeof(req), XFRMA_SPD_IPV6_HTHRESH,
1080                                  (void *)&thr, sizeof(thr));
1081                } else {
1082                        invarg("unknown", *argv);
1083                }
1084
1085                argc--; argv++;
1086        }
1087
1088        if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
1089                exit(1);
1090
1091        if (rtnl_talk(&rth, &req.n, NULL) < 0)
1092                exit(2);
1093
1094        rtnl_close(&rth);
1095
1096        return 0;
1097}
1098
1099static int xfrm_spd_getinfo(int argc, char **argv)
1100{
1101        struct rtnl_handle rth;
1102        struct {
1103                struct nlmsghdr                 n;
1104                __u32                           flags;
1105        } req = {
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,
1110        };
1111        struct nlmsghdr *answer;
1112
1113        if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
1114                exit(1);
1115
1116        if (rtnl_talk(&rth, &req.n, &answer) < 0)
1117                exit(2);
1118
1119        print_spdinfo(answer, (void *)stdout);
1120
1121        free(answer);
1122        rtnl_close(&rth);
1123
1124        return 0;
1125}
1126
1127static int xfrm_policy_flush(int argc, char **argv)
1128{
1129        struct rtnl_handle rth;
1130        struct {
1131                struct nlmsghdr n;
1132                char            buf[RTA_BUF_SIZE];
1133        } req = {
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,
1137        };
1138        char *ptypep = NULL;
1139        struct xfrm_userpolicy_type upt = {};
1140
1141        while (argc > 0) {
1142                if (strcmp(*argv, "ptype") == 0) {
1143                        if (ptypep)
1144                                duparg("ptype", *argv);
1145                        ptypep = *argv;
1146
1147                        NEXT_ARG();
1148                        xfrm_policy_ptype_parse(&upt.type, &argc, &argv);
1149                } else
1150                        invarg("unknown", *argv);
1151
1152                argc--; argv++;
1153        }
1154
1155        if (ptypep) {
1156                addattr_l(&req.n, sizeof(req), XFRMA_POLICY_TYPE,
1157                          (void *)&upt, sizeof(upt));
1158        }
1159
1160        if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
1161                exit(1);
1162
1163        if (show_stats > 1)
1164                fprintf(stderr, "Flush policy\n");
1165
1166        if (rtnl_talk(&rth, &req.n, NULL) < 0)
1167                exit(2);
1168
1169        rtnl_close(&rth);
1170
1171        return 0;
1172}
1173
1174int do_xfrm_policy(int argc, char **argv)
1175{
1176        if (argc < 1)
1177                return xfrm_policy_list_or_deleteall(0, NULL, 0);
1178
1179        if (matches(*argv, "add") == 0)
1180                return xfrm_policy_modify(XFRM_MSG_NEWPOLICY, 0,
1181                                          argc-1, argv+1);
1182        if (matches(*argv, "update") == 0)
1183                return xfrm_policy_modify(XFRM_MSG_UPDPOLICY, 0,
1184                                          argc-1, argv+1);
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)
1201                usage();
1202        fprintf(stderr, "Command \"%s\" is unknown, try \"ip xfrm policy help\".\n", *argv);
1203        exit(-1);
1204}
1205