]> rtime.felk.cvut.cz Git - lisovros/iproute2_canprio.git/blob - ip/xfrm_state.c
iproute2: allow to specify truncation bits on auth algo
[lisovros/iproute2_canprio.git] / ip / xfrm_state.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/xfrm.h>
33 #include "utils.h"
34 #include "xfrm.h"
35 #include "ip_common.h"
36
37 //#define NLMSG_DELETEALL_BUF_SIZE (4096-512)
38 #define NLMSG_DELETEALL_BUF_SIZE 8192
39
40 /*
41  * Receiving buffer defines:
42  * nlmsg
43  *   data = struct xfrm_usersa_info
44  *   rtattr
45  *   rtattr
46  *   ... (max count of rtattr is XFRM_MAX+1
47  *
48  *  each rtattr data = struct xfrm_algo(dynamic size) or xfrm_address_t
49  */
50 #define NLMSG_BUF_SIZE 4096
51 #define RTA_BUF_SIZE 2048
52 #define XFRM_ALGO_KEY_BUF_SIZE 512
53 #define CTX_BUF_SIZE 256
54
55 static void usage(void) __attribute__((noreturn));
56
57 static void usage(void)
58 {
59         fprintf(stderr, "Usage: ip xfrm state { add | update } ID [ XFRM_OPT ] [ ctx SEC_CTX ] [ mode MODE ]\n");
60         fprintf(stderr, "        [ reqid REQID ] [ seq SEQ ] [ replay-window SIZE ] [ flag FLAG-LIST ]\n");
61         fprintf(stderr, "        [ encap ENCAP ] [ sel SELECTOR ] [ replay-seq SEQ ]\n");
62         fprintf(stderr, "        [ replay-oseq SEQ ] [ LIMIT-LIST ]\n");
63         fprintf(stderr, "Usage: ip xfrm state allocspi ID [ mode MODE ] [ reqid REQID ] [ seq SEQ ]\n");
64         fprintf(stderr, "        [ min SPI max SPI ]\n");
65         fprintf(stderr, "Usage: ip xfrm state { delete | get } ID\n");
66         fprintf(stderr, "Usage: ip xfrm state { deleteall | list } [ ID ] [ mode MODE ] [ reqid REQID ]\n");
67         fprintf(stderr, "        [ flag FLAG-LIST ]\n");
68         fprintf(stderr, "Usage: ip xfrm state flush [ proto XFRM_PROTO ]\n");
69         fprintf(stderr, "Usage: ip xfrm state count \n");
70
71         fprintf(stderr, "ID := [ src ADDR ] [ dst ADDR ] [ proto XFRM_PROTO ] [ spi SPI ] [mark MARK [mask MASK]]\n");
72         //fprintf(stderr, "XFRM_PROTO := [ esp | ah | comp ]\n");
73         fprintf(stderr, "XFRM_PROTO := [ ");
74         fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_ESP));
75         fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_AH));
76         fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_COMP));
77         fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_ROUTING));
78         fprintf(stderr, "%s ", strxf_xfrmproto(IPPROTO_DSTOPTS));
79         fprintf(stderr, "]\n");
80
81         //fprintf(stderr, "SPI - security parameter index(default=0)\n");
82
83         fprintf(stderr, "MODE := [ transport | tunnel | ro | beet ](default=transport)\n");
84         //fprintf(stderr, "REQID - number(default=0)\n");
85
86         fprintf(stderr, "FLAG-LIST := [ FLAG-LIST ] FLAG\n");
87         fprintf(stderr, "FLAG := [ noecn | decap-dscp | nopmtudisc | wildrecv | icmp | af-unspec ]\n");
88
89         fprintf(stderr, "ENCAP := ENCAP-TYPE SPORT DPORT OADDR\n");
90         fprintf(stderr, "ENCAP-TYPE := espinudp | espinudp-nonike\n");
91
92         fprintf(stderr, "ALGO-LIST := [ ALGO-LIST ] | [ ALGO ]\n");
93         fprintf(stderr, "ALGO := ALGO_TYPE ALGO_NAME ALGO_KEY "
94                         "[ ALGO_ICV_LEN | ALGO_TRUNC_LEN ]\n");
95         fprintf(stderr, "ALGO_TYPE := [ ");
96         fprintf(stderr, "%s | ", strxf_algotype(XFRMA_ALG_AEAD));
97         fprintf(stderr, "%s | ", strxf_algotype(XFRMA_ALG_CRYPT));
98         fprintf(stderr, "%s | ", strxf_algotype(XFRMA_ALG_AUTH));
99         fprintf(stderr, "%s | ", strxf_algotype(XFRMA_ALG_AUTH_TRUNC));
100         fprintf(stderr, "%s ", strxf_algotype(XFRMA_ALG_COMP));
101         fprintf(stderr, "]\n");
102
103         //fprintf(stderr, "ALGO_NAME - algorithm name\n");
104         //fprintf(stderr, "ALGO_KEY - algorithm key\n");
105
106         fprintf(stderr, "SELECTOR := src ADDR[/PLEN] dst ADDR[/PLEN] [ UPSPEC ] [ dev DEV ]\n");
107
108         fprintf(stderr, "UPSPEC := proto PROTO [ [ sport PORT ] [ dport PORT ] |\n");
109         fprintf(stderr, "                        [ type NUMBER ] [ code NUMBER ] ]\n");
110
111
112         //fprintf(stderr, "DEV - device name(default=none)\n");
113         fprintf(stderr, "LIMIT-LIST := [ LIMIT-LIST ] | [ limit LIMIT ]\n");
114         fprintf(stderr, "LIMIT := [ [time-soft|time-hard|time-use-soft|time-use-hard] SECONDS ] |\n");
115         fprintf(stderr, "         [ [byte-soft|byte-hard] SIZE ] | [ [packet-soft|packet-hard] COUNT ]\n");
116         exit(-1);
117 }
118
119 static int xfrm_algo_parse(struct xfrm_algo *alg, enum xfrm_attr_type_t type,
120                            char *name, char *key, char *buf, int max)
121 {
122         int len;
123         int slen = strlen(key);
124
125 #if 0
126         /* XXX: verifying both name and key is required! */
127         fprintf(stderr, "warning: ALGONAME/ALGOKEY will send to kernel promiscuously!(verifying them isn't implemented yet)\n");
128 #endif
129
130         strncpy(alg->alg_name, name, sizeof(alg->alg_name));
131
132         if (slen > 2 && strncmp(key, "0x", 2) == 0) {
133                 /* split two chars "0x" from the top */
134                 char *p = key + 2;
135                 int plen = slen - 2;
136                 int i;
137                 int j;
138
139                 /* Converting hexadecimal numbered string into real key;
140                  * Convert each two chars into one char(value). If number
141                  * of the length is odd, add zero on the top for rounding.
142                  */
143
144                 /* calculate length of the converted values(real key) */
145                 len = (plen + 1) / 2;
146                 if (len > max)
147                         invarg("\"ALGOKEY\" makes buffer overflow\n", key);
148
149                 for (i = - (plen % 2), j = 0; j < len; i += 2, j++) {
150                         char vbuf[3];
151                         __u8 val;
152
153                         vbuf[0] = i >= 0 ? p[i] : '0';
154                         vbuf[1] = p[i + 1];
155                         vbuf[2] = '\0';
156
157                         if (get_u8(&val, vbuf, 16))
158                                 invarg("\"ALGOKEY\" is invalid", key);
159
160                         buf[j] = val;
161                 }
162         } else {
163                 len = slen;
164                 if (len > 0) {
165                         if (len > max)
166                                 invarg("\"ALGOKEY\" makes buffer overflow\n", key);
167
168                         strncpy(buf, key, len);
169                 }
170         }
171
172         alg->alg_key_len = len * 8;
173
174         return 0;
175 }
176
177 static int xfrm_seq_parse(__u32 *seq, int *argcp, char ***argvp)
178 {
179         int argc = *argcp;
180         char **argv = *argvp;
181
182         if (get_u32(seq, *argv, 0))
183                 invarg("\"SEQ\" is invalid", *argv);
184
185         *seq = htonl(*seq);
186
187         *argcp = argc;
188         *argvp = argv;
189
190         return 0;
191 }
192
193 static int xfrm_state_flag_parse(__u8 *flags, int *argcp, char ***argvp)
194 {
195         int argc = *argcp;
196         char **argv = *argvp;
197         int len = strlen(*argv);
198
199         if (len > 2 && strncmp(*argv, "0x", 2) == 0) {
200                 __u8 val = 0;
201
202                 if (get_u8(&val, *argv, 16))
203                         invarg("\"FLAG\" is invalid", *argv);
204                 *flags = val;
205         } else {
206                 while (1) {
207                         if (strcmp(*argv, "noecn") == 0)
208                                 *flags |= XFRM_STATE_NOECN;
209                         else if (strcmp(*argv, "decap-dscp") == 0)
210                                 *flags |= XFRM_STATE_DECAP_DSCP;
211                         else if (strcmp(*argv, "nopmtudisc") == 0)
212                                 *flags |= XFRM_STATE_NOPMTUDISC;
213                         else if (strcmp(*argv, "wildrecv") == 0)
214                                 *flags |= XFRM_STATE_WILDRECV;
215                         else if (strcmp(*argv, "icmp") == 0)
216                                 *flags |= XFRM_STATE_ICMP;
217                         else if (strcmp(*argv, "af-unspec") == 0)
218                                 *flags |= XFRM_STATE_AF_UNSPEC;
219                         else {
220                                 PREV_ARG(); /* back track */
221                                 break;
222                         }
223
224                         if (!NEXT_ARG_OK())
225                                 break;
226                         NEXT_ARG();
227                 }
228         }
229
230         *argcp = argc;
231         *argvp = argv;
232
233         return 0;
234 }
235
236 static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv)
237 {
238         struct rtnl_handle rth;
239         struct {
240                 struct nlmsghdr         n;
241                 struct xfrm_usersa_info xsinfo;
242                 char                    buf[RTA_BUF_SIZE];
243         } req;
244         struct xfrm_replay_state replay;
245         char *idp = NULL;
246         char *aeadop = NULL;
247         char *ealgop = NULL;
248         char *aalgop = NULL;
249         char *calgop = NULL;
250         char *coap = NULL;
251         char *sctxp = NULL;
252         struct xfrm_mark mark = {0, 0};
253         struct {
254                 struct xfrm_user_sec_ctx sctx;
255                 char    str[CTX_BUF_SIZE];
256         } ctx;
257
258         memset(&req, 0, sizeof(req));
259         memset(&replay, 0, sizeof(replay));
260         memset(&ctx, 0, sizeof(ctx));
261
262         req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xsinfo));
263         req.n.nlmsg_flags = NLM_F_REQUEST|flags;
264         req.n.nlmsg_type = cmd;
265         req.xsinfo.family = preferred_family;
266
267         req.xsinfo.lft.soft_byte_limit = XFRM_INF;
268         req.xsinfo.lft.hard_byte_limit = XFRM_INF;
269         req.xsinfo.lft.soft_packet_limit = XFRM_INF;
270         req.xsinfo.lft.hard_packet_limit = XFRM_INF;
271
272         while (argc > 0) {
273                 if (strcmp(*argv, "mode") == 0) {
274                         NEXT_ARG();
275                         xfrm_mode_parse(&req.xsinfo.mode, &argc, &argv);
276                 } else if (strcmp(*argv, "mark") == 0) {
277                         xfrm_parse_mark(&mark, &argc, &argv);
278                 } else if (strcmp(*argv, "reqid") == 0) {
279                         NEXT_ARG();
280                         xfrm_reqid_parse(&req.xsinfo.reqid, &argc, &argv);
281                 } else if (strcmp(*argv, "seq") == 0) {
282                         NEXT_ARG();
283                         xfrm_seq_parse(&req.xsinfo.seq, &argc, &argv);
284                 } else if (strcmp(*argv, "replay-window") == 0) {
285                         NEXT_ARG();
286                         if (get_u8(&req.xsinfo.replay_window, *argv, 0))
287                                 invarg("\"replay-window\" value is invalid", *argv);
288                 } else if (strcmp(*argv, "replay-seq") == 0) {
289                         NEXT_ARG();
290                         if (get_u32(&replay.seq, *argv, 0))
291                                 invarg("\"replay-seq\" value is invalid", *argv);
292                 } else if (strcmp(*argv, "replay-oseq") == 0) {
293                         NEXT_ARG();
294                         if (get_u32(&replay.oseq, *argv, 0))
295                                 invarg("\"replay-oseq\" value is invalid", *argv);
296                 } else if (strcmp(*argv, "flag") == 0) {
297                         NEXT_ARG();
298                         xfrm_state_flag_parse(&req.xsinfo.flags, &argc, &argv);
299                 } else if (strcmp(*argv, "sel") == 0) {
300                         NEXT_ARG();
301                         xfrm_selector_parse(&req.xsinfo.sel, &argc, &argv);
302                 } else if (strcmp(*argv, "limit") == 0) {
303                         NEXT_ARG();
304                         xfrm_lifetime_cfg_parse(&req.xsinfo.lft, &argc, &argv);
305                 } else if (strcmp(*argv, "encap") == 0) {
306                         struct xfrm_encap_tmpl encap;
307                         inet_prefix oa;
308                         NEXT_ARG();
309                         xfrm_encap_type_parse(&encap.encap_type, &argc, &argv);
310                         NEXT_ARG();
311                         if (get_u16(&encap.encap_sport, *argv, 0))
312                                 invarg("\"encap\" sport value is invalid", *argv);
313                         encap.encap_sport = htons(encap.encap_sport);
314                         NEXT_ARG();
315                         if (get_u16(&encap.encap_dport, *argv, 0))
316                                 invarg("\"encap\" dport value is invalid", *argv);
317                         encap.encap_dport = htons(encap.encap_dport);
318                         NEXT_ARG();
319                         get_addr(&oa, *argv, AF_UNSPEC);
320                         memcpy(&encap.encap_oa, &oa.data, sizeof(encap.encap_oa));
321                         addattr_l(&req.n, sizeof(req.buf), XFRMA_ENCAP,
322                                   (void *)&encap, sizeof(encap));
323                 } else if (strcmp(*argv, "coa") == 0) {
324                         inet_prefix coa;
325                         xfrm_address_t xcoa;
326
327                         if (coap)
328                                 duparg("coa", *argv);
329                         coap = *argv;
330
331                         NEXT_ARG();
332
333                         get_prefix(&coa, *argv, preferred_family);
334                         if (coa.family == AF_UNSPEC)
335                                 invarg("\"coa\" address family is AF_UNSPEC", *argv);
336                         if (coa.bytelen > sizeof(xcoa))
337                                 invarg("\"coa\" address length is too large", *argv);
338
339                         memset(&xcoa, 0, sizeof(xcoa));
340                         memcpy(&xcoa, &coa.data, coa.bytelen);
341
342                         addattr_l(&req.n, sizeof(req.buf), XFRMA_COADDR,
343                                   (void *)&xcoa, sizeof(xcoa));
344                 } else if (strcmp(*argv, "ctx") == 0) {
345                         char *context;
346
347                         if (sctxp)
348                                 duparg("ctx", *argv);
349                         sctxp = *argv;
350
351                         NEXT_ARG();
352                         context = *argv;
353
354                         xfrm_sctx_parse((char *)&ctx.str, context, &ctx.sctx);
355                         addattr_l(&req.n, sizeof(req.buf), XFRMA_SEC_CTX,
356                                   (void *)&ctx, ctx.sctx.len);
357                 } else {
358                         /* try to assume ALGO */
359                         int type = xfrm_algotype_getbyname(*argv);
360                         switch (type) {
361                         case XFRMA_ALG_AEAD:
362                         case XFRMA_ALG_CRYPT:
363                         case XFRMA_ALG_AUTH:
364                         case XFRMA_ALG_AUTH_TRUNC:
365                         case XFRMA_ALG_COMP:
366                         {
367                                 /* ALGO */
368                                 struct {
369                                         union {
370                                                 struct xfrm_algo alg;
371                                                 struct xfrm_algo_aead aead;
372                                                 struct xfrm_algo_auth auth;
373                                         } u;
374                                         char buf[XFRM_ALGO_KEY_BUF_SIZE];
375                                 } alg = {};
376                                 int len;
377                                 __u32 icvlen, trunclen;
378                                 char *name;
379                                 char *key;
380                                 char *buf;
381
382                                 switch (type) {
383                                 case XFRMA_ALG_AEAD:
384                                         if (aeadop)
385                                                 duparg("ALGOTYPE", *argv);
386                                         aeadop = *argv;
387                                         break;
388                                 case XFRMA_ALG_CRYPT:
389                                         if (ealgop)
390                                                 duparg("ALGOTYPE", *argv);
391                                         ealgop = *argv;
392                                         break;
393                                 case XFRMA_ALG_AUTH:
394                                 case XFRMA_ALG_AUTH_TRUNC:
395                                         if (aalgop)
396                                                 duparg("ALGOTYPE", *argv);
397                                         aalgop = *argv;
398                                         break;
399                                 case XFRMA_ALG_COMP:
400                                         if (calgop)
401                                                 duparg("ALGOTYPE", *argv);
402                                         calgop = *argv;
403                                         break;
404                                 default:
405                                         /* not reached */
406                                         invarg("\"ALGOTYPE\" is invalid\n", *argv);
407                                 }
408
409                                 if (!NEXT_ARG_OK())
410                                         missarg("ALGONAME");
411                                 NEXT_ARG();
412                                 name = *argv;
413
414                                 if (!NEXT_ARG_OK())
415                                         missarg("ALGOKEY");
416                                 NEXT_ARG();
417                                 key = *argv;
418
419                                 buf = alg.u.alg.alg_key;
420                                 len = sizeof(alg.u.alg);
421
422                                 switch (type) {
423                                 case XFRMA_ALG_AEAD:
424                                         if (!NEXT_ARG_OK())
425                                                 missarg("ALGOICVLEN");
426                                         NEXT_ARG();
427                                         if (get_u32(&icvlen, *argv, 0))
428                                                 invarg("\"aead\" ICV length is invalid",
429                                                        *argv);
430                                         alg.u.aead.alg_icv_len = icvlen;
431
432                                         buf = alg.u.aead.alg_key;
433                                         len = sizeof(alg.u.aead);
434                                         break;
435                                 case XFRMA_ALG_AUTH_TRUNC:
436                                         if (!NEXT_ARG_OK())
437                                                 missarg("ALGOTRUNCLEN");
438                                         NEXT_ARG();
439                                         if (get_u32(&trunclen, *argv, 0))
440                                                 invarg("\"auth\" trunc length is invalid",
441                                                        *argv);
442                                         alg.u.auth.alg_trunc_len = trunclen;
443
444                                         buf = alg.u.auth.alg_key;
445                                         len = sizeof(alg.u.auth);
446                                         break;
447                                 }
448
449                                 xfrm_algo_parse((void *)&alg, type, name, key,
450                                                 buf, sizeof(alg.buf));
451                                 len += alg.u.alg.alg_key_len;
452
453                                 addattr_l(&req.n, sizeof(req.buf), type,
454                                           (void *)&alg, len);
455                                 break;
456                         }
457                         default:
458                                 /* try to assume ID */
459                                 if (idp)
460                                         invarg("unknown", *argv);
461                                 idp = *argv;
462
463                                 /* ID */
464                                 xfrm_id_parse(&req.xsinfo.saddr, &req.xsinfo.id,
465                                               &req.xsinfo.family, 0, &argc, &argv);
466                                 if (preferred_family == AF_UNSPEC)
467                                         preferred_family = req.xsinfo.family;
468                         }
469                 }
470                 argc--; argv++;
471         }
472
473         if (replay.seq || replay.oseq)
474                 addattr_l(&req.n, sizeof(req.buf), XFRMA_REPLAY_VAL,
475                           (void *)&replay, sizeof(replay));
476
477         if (!idp) {
478                 fprintf(stderr, "Not enough information: \"ID\" is required\n");
479                 exit(1);
480         }
481
482         if (mark.m & mark.v) {
483                 int r = addattr_l(&req.n, sizeof(req.buf), XFRMA_MARK,
484                                   (void *)&mark, sizeof(mark));
485                 if (r < 0) {
486                         fprintf(stderr, "XFRMA_MARK failed\n");
487                         exit(1);
488                 }
489         }
490
491         switch (req.xsinfo.mode) {
492         case XFRM_MODE_TRANSPORT:
493         case XFRM_MODE_TUNNEL:
494                 if (!xfrm_xfrmproto_is_ipsec(req.xsinfo.id.proto)) {
495                         fprintf(stderr, "\"mode\" is invalid with proto=%s\n",
496                                 strxf_xfrmproto(req.xsinfo.id.proto));
497                         exit(1);
498                 }
499                 break;
500         case XFRM_MODE_ROUTEOPTIMIZATION:
501         case XFRM_MODE_IN_TRIGGER:
502                 if (!xfrm_xfrmproto_is_ro(req.xsinfo.id.proto)) {
503                         fprintf(stderr, "\"mode\" is invalid with proto=%s\n",
504                                 strxf_xfrmproto(req.xsinfo.id.proto));
505                         exit(1);
506                 }
507                 if (req.xsinfo.id.spi != 0) {
508                         fprintf(stderr, "\"spi\" must be 0 with proto=%s\n",
509                                 strxf_xfrmproto(req.xsinfo.id.proto));
510                         exit(1);
511                 }
512                 break;
513         default:
514                 break;
515         }
516
517         if (aeadop || ealgop || aalgop || calgop) {
518                 if (!xfrm_xfrmproto_is_ipsec(req.xsinfo.id.proto)) {
519                         fprintf(stderr, "\"ALGO\" is invalid with proto=%s\n",
520                                 strxf_xfrmproto(req.xsinfo.id.proto));
521                         exit(1);
522                 }
523         } else {
524                 if (xfrm_xfrmproto_is_ipsec(req.xsinfo.id.proto)) {
525                         fprintf(stderr, "\"ALGO\" is required with proto=%s\n",
526                                 strxf_xfrmproto(req.xsinfo.id.proto));
527                         exit (1);
528                 }
529         }
530
531         if (coap) {
532                 if (!xfrm_xfrmproto_is_ro(req.xsinfo.id.proto)) {
533                         fprintf(stderr, "\"coa\" is invalid with proto=%s\n",
534                                 strxf_xfrmproto(req.xsinfo.id.proto));
535                         exit(1);
536                 }
537         } else {
538                 if (xfrm_xfrmproto_is_ro(req.xsinfo.id.proto)) {
539                         fprintf(stderr, "\"coa\" is required with proto=%s\n",
540                                 strxf_xfrmproto(req.xsinfo.id.proto));
541                         exit (1);
542                 }
543         }
544
545         if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
546                 exit(1);
547
548         if (req.xsinfo.family == AF_UNSPEC)
549                 req.xsinfo.family = AF_INET;
550
551         if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
552                 exit(2);
553
554         rtnl_close(&rth);
555
556         return 0;
557 }
558
559 static int xfrm_state_allocspi(int argc, char **argv)
560 {
561         struct rtnl_handle rth;
562         struct {
563                 struct nlmsghdr         n;
564                 struct xfrm_userspi_info xspi;
565                 char                    buf[RTA_BUF_SIZE];
566         } req;
567         char *idp = NULL;
568         char *minp = NULL;
569         char *maxp = NULL;
570         struct xfrm_mark mark = {0, 0};
571         char res_buf[NLMSG_BUF_SIZE];
572         struct nlmsghdr *res_n = (struct nlmsghdr *)res_buf;
573
574         memset(res_buf, 0, sizeof(res_buf));
575
576         memset(&req, 0, sizeof(req));
577
578         req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xspi));
579         req.n.nlmsg_flags = NLM_F_REQUEST;
580         req.n.nlmsg_type = XFRM_MSG_ALLOCSPI;
581         req.xspi.info.family = preferred_family;
582
583 #if 0
584         req.xsinfo.lft.soft_byte_limit = XFRM_INF;
585         req.xsinfo.lft.hard_byte_limit = XFRM_INF;
586         req.xsinfo.lft.soft_packet_limit = XFRM_INF;
587         req.xsinfo.lft.hard_packet_limit = XFRM_INF;
588 #endif
589
590         while (argc > 0) {
591                 if (strcmp(*argv, "mode") == 0) {
592                         NEXT_ARG();
593                         xfrm_mode_parse(&req.xspi.info.mode, &argc, &argv);
594                 } else if (strcmp(*argv, "mark") == 0) {
595                         xfrm_parse_mark(&mark, &argc, &argv);
596                 } else if (strcmp(*argv, "reqid") == 0) {
597                         NEXT_ARG();
598                         xfrm_reqid_parse(&req.xspi.info.reqid, &argc, &argv);
599                 } else if (strcmp(*argv, "seq") == 0) {
600                         NEXT_ARG();
601                         xfrm_seq_parse(&req.xspi.info.seq, &argc, &argv);
602                 } else if (strcmp(*argv, "min") == 0) {
603                         if (minp)
604                                 duparg("min", *argv);
605                         minp = *argv;
606
607                         NEXT_ARG();
608
609                         if (get_u32(&req.xspi.min, *argv, 0))
610                                 invarg("\"min\" value is invalid", *argv);
611                 } else if (strcmp(*argv, "max") == 0) {
612                         if (maxp)
613                                 duparg("max", *argv);
614                         maxp = *argv;
615
616                         NEXT_ARG();
617
618                         if (get_u32(&req.xspi.max, *argv, 0))
619                                 invarg("\"max\" value is invalid", *argv);
620                 } else {
621                         /* try to assume ID */
622                         if (idp)
623                                 invarg("unknown", *argv);
624                         idp = *argv;
625
626                         /* ID */
627                         xfrm_id_parse(&req.xspi.info.saddr, &req.xspi.info.id,
628                                       &req.xspi.info.family, 0, &argc, &argv);
629                         if (req.xspi.info.id.spi) {
630                                 fprintf(stderr, "\"SPI\" must be zero\n");
631                                 exit(1);
632                         }
633                         if (preferred_family == AF_UNSPEC)
634                                 preferred_family = req.xspi.info.family;
635                 }
636                 argc--; argv++;
637         }
638
639         if (!idp) {
640                 fprintf(stderr, "Not enough information: \"ID\" is required\n");
641                 exit(1);
642         }
643
644         if (minp) {
645                 if (!maxp) {
646                         fprintf(stderr, "\"max\" is missing\n");
647                         exit(1);
648                 }
649                 if (req.xspi.min > req.xspi.max) {
650                         fprintf(stderr, "\"min\" valie is larger than \"max\" one\n");
651                         exit(1);
652                 }
653         } else {
654                 if (maxp) {
655                         fprintf(stderr, "\"min\" is missing\n");
656                         exit(1);
657                 }
658
659                 /* XXX: Default value defined in PF_KEY;
660                  * See kernel's net/key/af_key.c(pfkey_getspi).
661                  */
662                 req.xspi.min = 0x100;
663                 req.xspi.max = 0x0fffffff;
664
665                 /* XXX: IPCOMP spi is 16-bits;
666                  * See kernel's net/xfrm/xfrm_user(verify_userspi_info).
667                  */
668                 if (req.xspi.info.id.proto == IPPROTO_COMP)
669                         req.xspi.max = 0xffff;
670         }
671
672         if (mark.m & mark.v) {
673                 int r = addattr_l(&req.n, sizeof(req.buf), XFRMA_MARK,
674                                   (void *)&mark, sizeof(mark));
675                 if (r < 0) {
676                         fprintf(stderr, "XFRMA_MARK failed\n");
677                         exit(1);
678                 }
679         }
680
681         if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
682                 exit(1);
683
684         if (req.xspi.info.family == AF_UNSPEC)
685                 req.xspi.info.family = AF_INET;
686
687
688         if (rtnl_talk(&rth, &req.n, 0, 0, res_n, NULL, NULL) < 0)
689                 exit(2);
690
691         if (xfrm_state_print(NULL, res_n, (void*)stdout) < 0) {
692                 fprintf(stderr, "An error :-)\n");
693                 exit(1);
694         }
695
696         rtnl_close(&rth);
697
698         return 0;
699 }
700
701 static int xfrm_state_filter_match(struct xfrm_usersa_info *xsinfo)
702 {
703         if (!filter.use)
704                 return 1;
705
706         if (filter.id_src_mask)
707                 if (xfrm_addr_match(&xsinfo->saddr, &filter.xsinfo.saddr,
708                                     filter.id_src_mask))
709                         return 0;
710         if (filter.id_dst_mask)
711                 if (xfrm_addr_match(&xsinfo->id.daddr, &filter.xsinfo.id.daddr,
712                                     filter.id_dst_mask))
713                         return 0;
714         if ((xsinfo->id.proto^filter.xsinfo.id.proto)&filter.id_proto_mask)
715                 return 0;
716         if ((xsinfo->id.spi^filter.xsinfo.id.spi)&filter.id_spi_mask)
717                 return 0;
718         if ((xsinfo->mode^filter.xsinfo.mode)&filter.mode_mask)
719                 return 0;
720         if ((xsinfo->reqid^filter.xsinfo.reqid)&filter.reqid_mask)
721                 return 0;
722         if (filter.state_flags_mask)
723                 if ((xsinfo->flags & filter.xsinfo.flags) == 0)
724                         return 0;
725
726         return 1;
727 }
728
729 int xfrm_state_print(const struct sockaddr_nl *who, struct nlmsghdr *n,
730                      void *arg)
731 {
732         FILE *fp = (FILE*)arg;
733         struct rtattr * tb[XFRMA_MAX+1];
734         struct rtattr * rta;
735         struct xfrm_usersa_info *xsinfo = NULL;
736         struct xfrm_user_expire *xexp = NULL;
737         struct xfrm_usersa_id   *xsid = NULL;
738         int len = n->nlmsg_len;
739
740         if (n->nlmsg_type != XFRM_MSG_NEWSA &&
741             n->nlmsg_type != XFRM_MSG_DELSA &&
742             n->nlmsg_type != XFRM_MSG_UPDSA &&
743             n->nlmsg_type != XFRM_MSG_EXPIRE) {
744                 fprintf(stderr, "Not a state: %08x %08x %08x\n",
745                         n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
746                 return 0;
747         }
748
749         if (n->nlmsg_type == XFRM_MSG_DELSA) {
750                 /* Dont blame me for this .. Herbert made me do it */
751                 xsid = NLMSG_DATA(n);
752                 len -= NLMSG_SPACE(sizeof(*xsid));
753         } else if (n->nlmsg_type == XFRM_MSG_EXPIRE) {
754                 xexp = NLMSG_DATA(n);
755                 xsinfo = &xexp->state;
756                 len -= NLMSG_SPACE(sizeof(*xexp));
757         } else {
758                 xexp = NULL;
759                 xsinfo = NLMSG_DATA(n);
760                 len -= NLMSG_SPACE(sizeof(*xsinfo));
761         }
762
763         if (len < 0) {
764                 fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
765                 return -1;
766         }
767
768         if (xsinfo && !xfrm_state_filter_match(xsinfo))
769                 return 0;
770
771         if (n->nlmsg_type == XFRM_MSG_DELSA)
772                 fprintf(fp, "Deleted ");
773         else if (n->nlmsg_type == XFRM_MSG_UPDSA)
774                 fprintf(fp, "Updated ");
775         else if (n->nlmsg_type == XFRM_MSG_EXPIRE)
776                 fprintf(fp, "Expired ");
777
778         if (n->nlmsg_type == XFRM_MSG_DELSA)
779                 rta = XFRMSID_RTA(xsid);
780         else if (n->nlmsg_type == XFRM_MSG_EXPIRE)
781                 rta = XFRMEXP_RTA(xexp);
782         else
783                 rta = XFRMS_RTA(xsinfo);
784
785         parse_rtattr(tb, XFRMA_MAX, rta, len);
786
787         if (n->nlmsg_type == XFRM_MSG_DELSA) {
788                 //xfrm_policy_id_print();
789
790                 if (!tb[XFRMA_SA]) {
791                         fprintf(stderr, "Buggy XFRM_MSG_DELSA: no XFRMA_SA\n");
792                         return -1;
793                 }
794                 if (RTA_PAYLOAD(tb[XFRMA_SA]) < sizeof(*xsinfo)) {
795                         fprintf(stderr, "Buggy XFRM_MSG_DELPOLICY: too short XFRMA_POLICY len\n");
796                         return -1;
797                 }
798                 xsinfo = RTA_DATA(tb[XFRMA_SA]);
799         }
800
801         xfrm_state_info_print(xsinfo, tb, fp, NULL, NULL);
802
803         if (n->nlmsg_type == XFRM_MSG_EXPIRE) {
804                 fprintf(fp, "\t");
805                 fprintf(fp, "hard %u", xexp->hard);
806                 fprintf(fp, "%s", _SL_);
807         }
808
809         if (oneline)
810                 fprintf(fp, "\n");
811         fflush(fp);
812
813         return 0;
814 }
815
816 static int xfrm_state_get_or_delete(int argc, char **argv, int delete)
817 {
818         struct rtnl_handle rth;
819         struct {
820                 struct nlmsghdr         n;
821                 struct xfrm_usersa_id   xsid;
822                 char                    buf[RTA_BUF_SIZE];
823         } req;
824         struct xfrm_id id;
825         char *idp = NULL;
826         struct xfrm_mark mark = {0, 0};
827
828         memset(&req, 0, sizeof(req));
829
830         req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xsid));
831         req.n.nlmsg_flags = NLM_F_REQUEST;
832         req.n.nlmsg_type = delete ? XFRM_MSG_DELSA : XFRM_MSG_GETSA;
833         req.xsid.family = preferred_family;
834
835         while (argc > 0) {
836                 xfrm_address_t saddr;
837
838                 if (strcmp(*argv, "mark") == 0) {
839                         xfrm_parse_mark(&mark, &argc, &argv);
840                 } else {
841                         if (idp)
842                                 invarg("unknown", *argv);
843                         idp = *argv;
844
845                         /* ID */
846                         memset(&id, 0, sizeof(id));
847                         memset(&saddr, 0, sizeof(saddr));
848                         xfrm_id_parse(&saddr, &id, &req.xsid.family, 0,
849                                       &argc, &argv);
850
851                         memcpy(&req.xsid.daddr, &id.daddr, sizeof(req.xsid.daddr));
852                         req.xsid.spi = id.spi;
853                         req.xsid.proto = id.proto;
854
855                         addattr_l(&req.n, sizeof(req.buf), XFRMA_SRCADDR,
856                                   (void *)&saddr, sizeof(saddr));
857                 }
858
859                 argc--; argv++;
860         }
861
862         if (mark.m & mark.v) {
863                 int r = addattr_l(&req.n, sizeof(req.buf), XFRMA_MARK,
864                                   (void *)&mark, sizeof(mark));
865                 if (r < 0) {
866                         fprintf(stderr, "XFRMA_MARK failed\n");
867                         exit(1);
868                 }
869         }
870
871         if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
872                 exit(1);
873
874         if (req.xsid.family == AF_UNSPEC)
875                 req.xsid.family = AF_INET;
876
877         if (delete) {
878                 if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
879                         exit(2);
880         } else {
881                 char buf[NLMSG_BUF_SIZE];
882                 struct nlmsghdr *res_n = (struct nlmsghdr *)buf;
883
884                 memset(buf, 0, sizeof(buf));
885
886                 if (rtnl_talk(&rth, &req.n, 0, 0, res_n, NULL, NULL) < 0)
887                         exit(2);
888
889                 if (xfrm_state_print(NULL, res_n, (void*)stdout) < 0) {
890                         fprintf(stderr, "An error :-)\n");
891                         exit(1);
892                 }
893         }
894
895         rtnl_close(&rth);
896
897         return 0;
898 }
899
900 /*
901  * With an existing state of nlmsg, make new nlmsg for deleting the state
902  * and store it to buffer.
903  */
904 static int xfrm_state_keep(const struct sockaddr_nl *who,
905                            struct nlmsghdr *n,
906                            void *arg)
907 {
908         struct xfrm_buffer *xb = (struct xfrm_buffer *)arg;
909         struct rtnl_handle *rth = xb->rth;
910         struct xfrm_usersa_info *xsinfo = NLMSG_DATA(n);
911         int len = n->nlmsg_len;
912         struct nlmsghdr *new_n;
913         struct xfrm_usersa_id *xsid;
914
915         if (n->nlmsg_type != XFRM_MSG_NEWSA) {
916                 fprintf(stderr, "Not a state: %08x %08x %08x\n",
917                         n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
918                 return 0;
919         }
920
921         len -= NLMSG_LENGTH(sizeof(*xsinfo));
922         if (len < 0) {
923                 fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
924                 return -1;
925         }
926
927         if (!xfrm_state_filter_match(xsinfo))
928                 return 0;
929
930         if (xb->offset > xb->size) {
931                 fprintf(stderr, "State buffer overflow\n");
932                 return -1;
933         }
934
935         new_n = (struct nlmsghdr *)(xb->buf + xb->offset);
936         new_n->nlmsg_len = NLMSG_LENGTH(sizeof(*xsid));
937         new_n->nlmsg_flags = NLM_F_REQUEST;
938         new_n->nlmsg_type = XFRM_MSG_DELSA;
939         new_n->nlmsg_seq = ++rth->seq;
940
941         xsid = NLMSG_DATA(new_n);
942         xsid->family = xsinfo->family;
943         memcpy(&xsid->daddr, &xsinfo->id.daddr, sizeof(xsid->daddr));
944         xsid->spi = xsinfo->id.spi;
945         xsid->proto = xsinfo->id.proto;
946
947         addattr_l(new_n, xb->size, XFRMA_SRCADDR, &xsinfo->saddr,
948                   sizeof(xsid->daddr));
949
950         xb->offset += new_n->nlmsg_len;
951         xb->nlmsg_count ++;
952
953         return 0;
954 }
955
956 static int xfrm_state_list_or_deleteall(int argc, char **argv, int deleteall)
957 {
958         char *idp = NULL;
959         struct rtnl_handle rth;
960
961         if(argc > 0)
962                 filter.use = 1;
963         filter.xsinfo.family = preferred_family;
964
965         while (argc > 0) {
966                 if (strcmp(*argv, "mode") == 0) {
967                         NEXT_ARG();
968                         xfrm_mode_parse(&filter.xsinfo.mode, &argc, &argv);
969
970                         filter.mode_mask = XFRM_FILTER_MASK_FULL;
971
972                 } else if (strcmp(*argv, "reqid") == 0) {
973                         NEXT_ARG();
974                         xfrm_reqid_parse(&filter.xsinfo.reqid, &argc, &argv);
975
976                         filter.reqid_mask = XFRM_FILTER_MASK_FULL;
977
978                 } else if (strcmp(*argv, "flag") == 0) {
979                         NEXT_ARG();
980                         xfrm_state_flag_parse(&filter.xsinfo.flags, &argc, &argv);
981
982                         filter.state_flags_mask = XFRM_FILTER_MASK_FULL;
983
984                 } else {
985                         if (idp)
986                                 invarg("unknown", *argv);
987                         idp = *argv;
988
989                         /* ID */
990                         xfrm_id_parse(&filter.xsinfo.saddr, &filter.xsinfo.id,
991                                       &filter.xsinfo.family, 1, &argc, &argv);
992                         if (preferred_family == AF_UNSPEC)
993                                 preferred_family = filter.xsinfo.family;
994                 }
995                 argc--; argv++;
996         }
997
998         if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
999                 exit(1);
1000
1001         if (deleteall) {
1002                 struct xfrm_buffer xb;
1003                 char buf[NLMSG_DELETEALL_BUF_SIZE];
1004                 int i;
1005
1006                 xb.buf = buf;
1007                 xb.size = sizeof(buf);
1008                 xb.rth = &rth;
1009
1010                 for (i = 0; ; i++) {
1011                         xb.offset = 0;
1012                         xb.nlmsg_count = 0;
1013
1014                         if (show_stats > 1)
1015                                 fprintf(stderr, "Delete-all round = %d\n", i);
1016
1017                         if (rtnl_wilddump_request(&rth, preferred_family, XFRM_MSG_GETSA) < 0) {
1018                                 perror("Cannot send dump request");
1019                                 exit(1);
1020                         }
1021
1022                         if (rtnl_dump_filter(&rth, xfrm_state_keep, &xb, NULL, NULL) < 0) {
1023                                 fprintf(stderr, "Delete-all terminated\n");
1024                                 exit(1);
1025                         }
1026                         if (xb.nlmsg_count == 0) {
1027                                 if (show_stats > 1)
1028                                         fprintf(stderr, "Delete-all completed\n");
1029                                 break;
1030                         }
1031
1032                         if (rtnl_send_check(&rth, xb.buf, xb.offset) < 0) {
1033                                 perror("Failed to send delete-all request\n");
1034                                 exit(1);
1035                         }
1036                         if (show_stats > 1)
1037                                 fprintf(stderr, "Delete-all nlmsg count = %d\n", xb.nlmsg_count);
1038
1039                         xb.offset = 0;
1040                         xb.nlmsg_count = 0;
1041                 }
1042
1043         } else {
1044                 if (rtnl_wilddump_request(&rth, preferred_family, XFRM_MSG_GETSA) < 0) {
1045                         perror("Cannot send dump request");
1046                         exit(1);
1047                 }
1048
1049                 if (rtnl_dump_filter(&rth, xfrm_state_print, stdout, NULL, NULL) < 0) {
1050                         fprintf(stderr, "Dump terminated\n");
1051                         exit(1);
1052                 }
1053         }
1054
1055         rtnl_close(&rth);
1056
1057         exit(0);
1058 }
1059
1060 int print_sadinfo(struct nlmsghdr *n, void *arg)
1061 {
1062         FILE *fp = (FILE*)arg;
1063         __u32 *f = NLMSG_DATA(n);
1064         struct rtattr *tb[XFRMA_SAD_MAX+1];
1065         struct rtattr *rta;
1066         __u32 *cnt;
1067
1068         int len = n->nlmsg_len;
1069
1070         len -= NLMSG_LENGTH(sizeof(__u32));
1071         if (len < 0) {
1072                 fprintf(stderr, "SADinfo: Wrong len %d\n", len);
1073                 return -1;
1074         }
1075
1076         rta = XFRMSAPD_RTA(f);
1077         parse_rtattr(tb, XFRMA_SAD_MAX, rta, len);
1078
1079         if (tb[XFRMA_SAD_CNT]) {
1080                 fprintf(fp,"\t SAD");
1081                 cnt = (__u32 *)RTA_DATA(tb[XFRMA_SAD_CNT]);
1082                 fprintf(fp," count %d", *cnt);
1083         } else {
1084                 fprintf(fp,"BAD SAD info returned\n");
1085                 return -1;
1086         }
1087
1088         if (show_stats) {
1089                 if (tb[XFRMA_SAD_HINFO]) {
1090                         struct xfrmu_sadhinfo *si;
1091
1092                         if (RTA_PAYLOAD(tb[XFRMA_SAD_HINFO]) < sizeof(*si)) {
1093                                 fprintf(fp,"BAD SAD length returned\n");
1094                                 return -1;
1095                         }
1096                                 
1097                         si = RTA_DATA(tb[XFRMA_SAD_HINFO]);
1098                         fprintf(fp," (buckets ");
1099                         fprintf(fp,"count %d", si->sadhcnt);
1100                         fprintf(fp," Max %d", si->sadhmcnt);
1101                         fprintf(fp,")");
1102                 }
1103         }
1104         fprintf(fp,"\n");
1105
1106         return 0;
1107 }
1108
1109 static int xfrm_sad_getinfo(int argc, char **argv)
1110 {
1111         struct rtnl_handle rth;
1112         struct {
1113                 struct nlmsghdr                 n;
1114                 __u32                           flags;
1115                 char                            ans[64];
1116         } req;
1117
1118         memset(&req, 0, sizeof(req));
1119         req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.flags));
1120         req.n.nlmsg_flags = NLM_F_REQUEST;
1121         req.n.nlmsg_type = XFRM_MSG_GETSADINFO;
1122         req.flags = 0XFFFFFFFF;
1123
1124         if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
1125                 exit(1);
1126
1127         if (rtnl_talk(&rth, &req.n, 0, 0, &req.n, NULL, NULL) < 0)
1128                 exit(2);
1129
1130         print_sadinfo(&req.n, (void*)stdout);
1131
1132         rtnl_close(&rth);
1133
1134         return 0;
1135 }
1136
1137 static int xfrm_state_flush(int argc, char **argv)
1138 {
1139         struct rtnl_handle rth;
1140         struct {
1141                 struct nlmsghdr                 n;
1142                 struct xfrm_usersa_flush        xsf;
1143         } req;
1144         char *protop = NULL;
1145
1146         memset(&req, 0, sizeof(req));
1147
1148         req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xsf));
1149         req.n.nlmsg_flags = NLM_F_REQUEST;
1150         req.n.nlmsg_type = XFRM_MSG_FLUSHSA;
1151         req.xsf.proto = 0;
1152
1153         while (argc > 0) {
1154                 if (strcmp(*argv, "proto") == 0) {
1155                         int ret;
1156
1157                         if (protop)
1158                                 duparg("proto", *argv);
1159                         protop = *argv;
1160
1161                         NEXT_ARG();
1162
1163                         ret = xfrm_xfrmproto_getbyname(*argv);
1164                         if (ret < 0)
1165                                 invarg("\"XFRM_PROTO\" is invalid", *argv);
1166
1167                         req.xsf.proto = (__u8)ret;
1168                 } else
1169                         invarg("unknown", *argv);
1170
1171                 argc--; argv++;
1172         }
1173
1174         if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
1175                 exit(1);
1176
1177         if (show_stats > 1)
1178                 fprintf(stderr, "Flush state proto=%s\n",
1179                         strxf_xfrmproto(req.xsf.proto));
1180
1181         if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
1182                 exit(2);
1183
1184         rtnl_close(&rth);
1185
1186         return 0;
1187 }
1188
1189 int do_xfrm_state(int argc, char **argv)
1190 {
1191         if (argc < 1)
1192                 return xfrm_state_list_or_deleteall(0, NULL, 0);
1193
1194         if (matches(*argv, "add") == 0)
1195                 return xfrm_state_modify(XFRM_MSG_NEWSA, 0,
1196                                          argc-1, argv+1);
1197         if (matches(*argv, "update") == 0)
1198                 return xfrm_state_modify(XFRM_MSG_UPDSA, 0,
1199                                          argc-1, argv+1);
1200         if (matches(*argv, "allocspi") == 0)
1201                 return xfrm_state_allocspi(argc-1, argv+1);
1202         if (matches(*argv, "delete") == 0)
1203                 return xfrm_state_get_or_delete(argc-1, argv+1, 1);
1204         if (matches(*argv, "deleteall") == 0 || matches(*argv, "delall") == 0)
1205                 return xfrm_state_list_or_deleteall(argc-1, argv+1, 1);
1206         if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0
1207             || matches(*argv, "lst") == 0)
1208                 return xfrm_state_list_or_deleteall(argc-1, argv+1, 0);
1209         if (matches(*argv, "get") == 0)
1210                 return xfrm_state_get_or_delete(argc-1, argv+1, 0);
1211         if (matches(*argv, "flush") == 0)
1212                 return xfrm_state_flush(argc-1, argv+1);
1213         if (matches(*argv, "count") == 0) {
1214                 return xfrm_sad_getinfo(argc, argv);
1215         }
1216         if (matches(*argv, "help") == 0)
1217                 usage();
1218         fprintf(stderr, "Command \"%s\" is unknown, try \"ip xfrm state help\".\n", *argv);
1219         exit(-1);
1220 }