1*de1e4e89SAndroid Build Coastguard Worker /* $USAGI: $ */
2*de1e4e89SAndroid Build Coastguard Worker
3*de1e4e89SAndroid Build Coastguard Worker /*
4*de1e4e89SAndroid Build Coastguard Worker * Copyright (C)2004 USAGI/WIDE Project
5*de1e4e89SAndroid Build Coastguard Worker *
6*de1e4e89SAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or modify
7*de1e4e89SAndroid Build Coastguard Worker * it under the terms of the GNU General Public License as published by
8*de1e4e89SAndroid Build Coastguard Worker * the Free Software Foundation; either version 2 of the License, or
9*de1e4e89SAndroid Build Coastguard Worker * (at your option) any later version.
10*de1e4e89SAndroid Build Coastguard Worker *
11*de1e4e89SAndroid Build Coastguard Worker * This program is distributed in the hope that it will be useful,
12*de1e4e89SAndroid Build Coastguard Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*de1e4e89SAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14*de1e4e89SAndroid Build Coastguard Worker * GNU General Public License for more details.
15*de1e4e89SAndroid Build Coastguard Worker *
16*de1e4e89SAndroid Build Coastguard Worker * You should have received a copy of the GNU General Public License
17*de1e4e89SAndroid Build Coastguard Worker * along with this program; if not, see <http://www.gnu.org/licenses>.
18*de1e4e89SAndroid Build Coastguard Worker */
19*de1e4e89SAndroid Build Coastguard Worker /*
20*de1e4e89SAndroid Build Coastguard Worker * based on iproute.c
21*de1e4e89SAndroid Build Coastguard Worker */
22*de1e4e89SAndroid Build Coastguard Worker /*
23*de1e4e89SAndroid Build Coastguard Worker * Authors:
24*de1e4e89SAndroid Build Coastguard Worker * Masahide NAKAMURA @USAGI
25*de1e4e89SAndroid Build Coastguard Worker */
26*de1e4e89SAndroid Build Coastguard Worker
27*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
28*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
29*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
30*de1e4e89SAndroid Build Coastguard Worker #include <netdb.h>
31*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
32*de1e4e89SAndroid Build Coastguard Worker #include "xfrm.h"
33*de1e4e89SAndroid Build Coastguard Worker #include "ip_common.h"
34*de1e4e89SAndroid Build Coastguard Worker
35*de1e4e89SAndroid Build Coastguard Worker /* #define NLMSG_DELETEALL_BUF_SIZE (4096-512) */
36*de1e4e89SAndroid Build Coastguard Worker #define NLMSG_DELETEALL_BUF_SIZE 8192
37*de1e4e89SAndroid Build Coastguard Worker
38*de1e4e89SAndroid Build Coastguard Worker /*
39*de1e4e89SAndroid Build Coastguard Worker * Receiving buffer defines:
40*de1e4e89SAndroid Build Coastguard Worker * nlmsg
41*de1e4e89SAndroid Build Coastguard Worker * data = struct xfrm_usersa_info
42*de1e4e89SAndroid Build Coastguard Worker * rtattr
43*de1e4e89SAndroid Build Coastguard Worker * rtattr
44*de1e4e89SAndroid Build Coastguard Worker * ... (max count of rtattr is XFRM_MAX+1
45*de1e4e89SAndroid Build Coastguard Worker *
46*de1e4e89SAndroid Build Coastguard Worker * each rtattr data = struct xfrm_algo(dynamic size) or xfrm_address_t
47*de1e4e89SAndroid Build Coastguard Worker */
48*de1e4e89SAndroid Build Coastguard Worker #define NLMSG_BUF_SIZE 4096
49*de1e4e89SAndroid Build Coastguard Worker #define RTA_BUF_SIZE 2048
50*de1e4e89SAndroid Build Coastguard Worker #define XFRM_ALGO_KEY_BUF_SIZE 512
51*de1e4e89SAndroid Build Coastguard Worker #define CTX_BUF_SIZE 256
52*de1e4e89SAndroid Build Coastguard Worker
53*de1e4e89SAndroid Build Coastguard Worker static void usage(void) __attribute__((noreturn));
54*de1e4e89SAndroid Build Coastguard Worker
usage(void)55*de1e4e89SAndroid Build Coastguard Worker static void usage(void)
56*de1e4e89SAndroid Build Coastguard Worker {
57*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Usage: ip xfrm state { add | update } ID [ ALGO-LIST ] [ mode MODE ]\n");
58*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " [ mark MARK [ mask MASK ] ] [ reqid REQID ] [ seq SEQ ]\n");
59*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " [ replay-window SIZE ] [ replay-seq SEQ ] [ replay-oseq SEQ ]\n");
60*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " [ replay-seq-hi SEQ ] [ replay-oseq-hi SEQ ]\n");
61*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " [ flag FLAG-LIST ] [ sel SELECTOR ] [ LIMIT-LIST ] [ encap ENCAP ]\n");
62*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " [ coa ADDR[/PLEN] ] [ ctx CTX ] [ extra-flag EXTRA-FLAG-LIST ]\n");
63*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " [ offload [dev DEV] dir DIR ]\n");
64*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " [ output-mark OUTPUT-MARK ]\n");
65*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Usage: ip xfrm state allocspi ID [ mode MODE ] [ mark MARK [ mask MASK ] ]\n");
66*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " [ reqid REQID ] [ seq SEQ ] [ min SPI max SPI ]\n");
67*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Usage: ip xfrm state { delete | get } ID [ mark MARK [ mask MASK ] ]\n");
68*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Usage: ip xfrm state { deleteall | list } [ ID ] [ mode MODE ] [ reqid REQID ]\n");
69*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " [ flag FLAG-LIST ]\n");
70*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Usage: ip xfrm state flush [ proto XFRM-PROTO ]\n");
71*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Usage: ip xfrm state count\n");
72*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "ID := [ src ADDR ] [ dst ADDR ] [ proto XFRM-PROTO ] [ spi SPI ]\n");
73*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "XFRM-PROTO := ");
74*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_ESP));
75*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_AH));
76*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_COMP));
77*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "%s | ", strxf_xfrmproto(IPPROTO_ROUTING));
78*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "%s\n", strxf_xfrmproto(IPPROTO_DSTOPTS));
79*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "ALGO-LIST := [ ALGO-LIST ] ALGO\n");
80*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "ALGO := { ");
81*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "%s | ", strxf_algotype(XFRMA_ALG_CRYPT));
82*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "%s", strxf_algotype(XFRMA_ALG_AUTH));
83*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " } ALGO-NAME ALGO-KEYMAT |\n");
84*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " %s", strxf_algotype(XFRMA_ALG_AUTH_TRUNC));
85*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " ALGO-NAME ALGO-KEYMAT ALGO-TRUNC-LEN |\n");
86*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " %s", strxf_algotype(XFRMA_ALG_AEAD));
87*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " ALGO-NAME ALGO-KEYMAT ALGO-ICV-LEN |\n");
88*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " %s", strxf_algotype(XFRMA_ALG_COMP));
89*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " ALGO-NAME\n");
90*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "MODE := transport | tunnel | beet | ro | in_trigger\n");
91*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "FLAG-LIST := [ FLAG-LIST ] FLAG\n");
92*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "FLAG := noecn | decap-dscp | nopmtudisc | wildrecv | icmp | af-unspec | align4 | esn\n");
93*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "EXTRA-FLAG-LIST := [ EXTRA-FLAG-LIST ] EXTRA-FLAG\n");
94*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "EXTRA-FLAG := dont-encap-dscp\n");
95*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "SELECTOR := [ src ADDR[/PLEN] ] [ dst ADDR[/PLEN] ] [ dev DEV ] [ UPSPEC ]\n");
96*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "UPSPEC := proto { { ");
97*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "%s | ", strxf_proto(IPPROTO_TCP));
98*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "%s | ", strxf_proto(IPPROTO_UDP));
99*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "%s | ", strxf_proto(IPPROTO_SCTP));
100*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "%s", strxf_proto(IPPROTO_DCCP));
101*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " } [ sport PORT ] [ dport PORT ] |\n");
102*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " { ");
103*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "%s | ", strxf_proto(IPPROTO_ICMP));
104*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "%s | ", strxf_proto(IPPROTO_ICMPV6));
105*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "%s", strxf_proto(IPPROTO_MH));
106*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " } [ type NUMBER ] [ code NUMBER ] |\n");
107*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " %s", strxf_proto(IPPROTO_GRE));
108*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " [ key { DOTTED-QUAD | NUMBER } ] | PROTO }\n");
109*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "LIMIT-LIST := [ LIMIT-LIST ] limit LIMIT\n");
110*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "LIMIT := { time-soft | time-hard | time-use-soft | time-use-hard } SECONDS |\n");
111*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " { byte-soft | byte-hard } SIZE | { packet-soft | packet-hard } COUNT\n");
112*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "ENCAP := { espinudp | espinudp-nonike } SPORT DPORT OADDR\n");
113*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "DIR := in | out\n");
114*de1e4e89SAndroid Build Coastguard Worker
115*de1e4e89SAndroid Build Coastguard Worker exit(-1);
116*de1e4e89SAndroid Build Coastguard Worker }
117*de1e4e89SAndroid Build Coastguard Worker
xfrm_algo_parse(struct xfrm_algo * alg,enum xfrm_attr_type_t type,char * name,char * key,char * buf,int max)118*de1e4e89SAndroid Build Coastguard Worker static int xfrm_algo_parse(struct xfrm_algo *alg, enum xfrm_attr_type_t type,
119*de1e4e89SAndroid Build Coastguard Worker char *name, char *key, char *buf, int max)
120*de1e4e89SAndroid Build Coastguard Worker {
121*de1e4e89SAndroid Build Coastguard Worker int len;
122*de1e4e89SAndroid Build Coastguard Worker int slen = strlen(key);
123*de1e4e89SAndroid Build Coastguard Worker
124*de1e4e89SAndroid Build Coastguard Worker #if 0
125*de1e4e89SAndroid Build Coastguard Worker /* XXX: verifying both name and key is required! */
126*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "warning: ALGO-NAME/ALGO-KEYMAT values will be sent to the kernel promiscuously! (verifying them isn't implemented yet)\n");
127*de1e4e89SAndroid Build Coastguard Worker #endif
128*de1e4e89SAndroid Build Coastguard Worker
129*de1e4e89SAndroid Build Coastguard Worker strlcpy(alg->alg_name, name, sizeof(alg->alg_name));
130*de1e4e89SAndroid Build Coastguard Worker
131*de1e4e89SAndroid Build Coastguard Worker if (slen > 2 && strncmp(key, "0x", 2) == 0) {
132*de1e4e89SAndroid Build Coastguard Worker /* split two chars "0x" from the top */
133*de1e4e89SAndroid Build Coastguard Worker char *p = key + 2;
134*de1e4e89SAndroid Build Coastguard Worker int plen = slen - 2;
135*de1e4e89SAndroid Build Coastguard Worker int i;
136*de1e4e89SAndroid Build Coastguard Worker int j;
137*de1e4e89SAndroid Build Coastguard Worker
138*de1e4e89SAndroid Build Coastguard Worker /* Converting hexadecimal numbered string into real key;
139*de1e4e89SAndroid Build Coastguard Worker * Convert each two chars into one char(value). If number
140*de1e4e89SAndroid Build Coastguard Worker * of the length is odd, add zero on the top for rounding.
141*de1e4e89SAndroid Build Coastguard Worker */
142*de1e4e89SAndroid Build Coastguard Worker
143*de1e4e89SAndroid Build Coastguard Worker /* calculate length of the converted values(real key) */
144*de1e4e89SAndroid Build Coastguard Worker len = (plen + 1) / 2;
145*de1e4e89SAndroid Build Coastguard Worker if (len > max)
146*de1e4e89SAndroid Build Coastguard Worker invarg("ALGO-KEYMAT value makes buffer overflow\n", key);
147*de1e4e89SAndroid Build Coastguard Worker
148*de1e4e89SAndroid Build Coastguard Worker for (i = -(plen % 2), j = 0; j < len; i += 2, j++) {
149*de1e4e89SAndroid Build Coastguard Worker char vbuf[3];
150*de1e4e89SAndroid Build Coastguard Worker __u8 val;
151*de1e4e89SAndroid Build Coastguard Worker
152*de1e4e89SAndroid Build Coastguard Worker vbuf[0] = i >= 0 ? p[i] : '0';
153*de1e4e89SAndroid Build Coastguard Worker vbuf[1] = p[i + 1];
154*de1e4e89SAndroid Build Coastguard Worker vbuf[2] = '\0';
155*de1e4e89SAndroid Build Coastguard Worker
156*de1e4e89SAndroid Build Coastguard Worker if (get_u8(&val, vbuf, 16))
157*de1e4e89SAndroid Build Coastguard Worker invarg("ALGO-KEYMAT value is invalid", key);
158*de1e4e89SAndroid Build Coastguard Worker
159*de1e4e89SAndroid Build Coastguard Worker buf[j] = val;
160*de1e4e89SAndroid Build Coastguard Worker }
161*de1e4e89SAndroid Build Coastguard Worker } else {
162*de1e4e89SAndroid Build Coastguard Worker len = slen;
163*de1e4e89SAndroid Build Coastguard Worker if (len > 0) {
164*de1e4e89SAndroid Build Coastguard Worker if (len > max)
165*de1e4e89SAndroid Build Coastguard Worker invarg("ALGO-KEYMAT value makes buffer overflow\n", key);
166*de1e4e89SAndroid Build Coastguard Worker
167*de1e4e89SAndroid Build Coastguard Worker memcpy(buf, key, len);
168*de1e4e89SAndroid Build Coastguard Worker }
169*de1e4e89SAndroid Build Coastguard Worker }
170*de1e4e89SAndroid Build Coastguard Worker
171*de1e4e89SAndroid Build Coastguard Worker alg->alg_key_len = len * 8;
172*de1e4e89SAndroid Build Coastguard Worker
173*de1e4e89SAndroid Build Coastguard Worker return 0;
174*de1e4e89SAndroid Build Coastguard Worker }
175*de1e4e89SAndroid Build Coastguard Worker
xfrm_seq_parse(__u32 * seq,int * argcp,char *** argvp)176*de1e4e89SAndroid Build Coastguard Worker static int xfrm_seq_parse(__u32 *seq, int *argcp, char ***argvp)
177*de1e4e89SAndroid Build Coastguard Worker {
178*de1e4e89SAndroid Build Coastguard Worker int argc = *argcp;
179*de1e4e89SAndroid Build Coastguard Worker char **argv = *argvp;
180*de1e4e89SAndroid Build Coastguard Worker
181*de1e4e89SAndroid Build Coastguard Worker if (get_be32(seq, *argv, 0))
182*de1e4e89SAndroid Build Coastguard Worker invarg("SEQ value is invalid", *argv);
183*de1e4e89SAndroid Build Coastguard Worker
184*de1e4e89SAndroid Build Coastguard Worker *argcp = argc;
185*de1e4e89SAndroid Build Coastguard Worker *argvp = argv;
186*de1e4e89SAndroid Build Coastguard Worker
187*de1e4e89SAndroid Build Coastguard Worker return 0;
188*de1e4e89SAndroid Build Coastguard Worker }
189*de1e4e89SAndroid Build Coastguard Worker
xfrm_state_flag_parse(__u8 * flags,int * argcp,char *** argvp)190*de1e4e89SAndroid Build Coastguard Worker static int xfrm_state_flag_parse(__u8 *flags, int *argcp, char ***argvp)
191*de1e4e89SAndroid Build Coastguard Worker {
192*de1e4e89SAndroid Build Coastguard Worker int argc = *argcp;
193*de1e4e89SAndroid Build Coastguard Worker char **argv = *argvp;
194*de1e4e89SAndroid Build Coastguard Worker int len = strlen(*argv);
195*de1e4e89SAndroid Build Coastguard Worker
196*de1e4e89SAndroid Build Coastguard Worker if (len > 2 && strncmp(*argv, "0x", 2) == 0) {
197*de1e4e89SAndroid Build Coastguard Worker __u8 val = 0;
198*de1e4e89SAndroid Build Coastguard Worker
199*de1e4e89SAndroid Build Coastguard Worker if (get_u8(&val, *argv, 16))
200*de1e4e89SAndroid Build Coastguard Worker invarg("FLAG value is invalid", *argv);
201*de1e4e89SAndroid Build Coastguard Worker *flags = val;
202*de1e4e89SAndroid Build Coastguard Worker } else {
203*de1e4e89SAndroid Build Coastguard Worker while (1) {
204*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "noecn") == 0)
205*de1e4e89SAndroid Build Coastguard Worker *flags |= XFRM_STATE_NOECN;
206*de1e4e89SAndroid Build Coastguard Worker else if (strcmp(*argv, "decap-dscp") == 0)
207*de1e4e89SAndroid Build Coastguard Worker *flags |= XFRM_STATE_DECAP_DSCP;
208*de1e4e89SAndroid Build Coastguard Worker else if (strcmp(*argv, "nopmtudisc") == 0)
209*de1e4e89SAndroid Build Coastguard Worker *flags |= XFRM_STATE_NOPMTUDISC;
210*de1e4e89SAndroid Build Coastguard Worker else if (strcmp(*argv, "wildrecv") == 0)
211*de1e4e89SAndroid Build Coastguard Worker *flags |= XFRM_STATE_WILDRECV;
212*de1e4e89SAndroid Build Coastguard Worker else if (strcmp(*argv, "icmp") == 0)
213*de1e4e89SAndroid Build Coastguard Worker *flags |= XFRM_STATE_ICMP;
214*de1e4e89SAndroid Build Coastguard Worker else if (strcmp(*argv, "af-unspec") == 0)
215*de1e4e89SAndroid Build Coastguard Worker *flags |= XFRM_STATE_AF_UNSPEC;
216*de1e4e89SAndroid Build Coastguard Worker else if (strcmp(*argv, "align4") == 0)
217*de1e4e89SAndroid Build Coastguard Worker *flags |= XFRM_STATE_ALIGN4;
218*de1e4e89SAndroid Build Coastguard Worker else if (strcmp(*argv, "esn") == 0)
219*de1e4e89SAndroid Build Coastguard Worker *flags |= XFRM_STATE_ESN;
220*de1e4e89SAndroid Build Coastguard Worker else {
221*de1e4e89SAndroid Build Coastguard Worker PREV_ARG(); /* back track */
222*de1e4e89SAndroid Build Coastguard Worker break;
223*de1e4e89SAndroid Build Coastguard Worker }
224*de1e4e89SAndroid Build Coastguard Worker
225*de1e4e89SAndroid Build Coastguard Worker if (!NEXT_ARG_OK())
226*de1e4e89SAndroid Build Coastguard Worker break;
227*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
228*de1e4e89SAndroid Build Coastguard Worker }
229*de1e4e89SAndroid Build Coastguard Worker }
230*de1e4e89SAndroid Build Coastguard Worker
231*de1e4e89SAndroid Build Coastguard Worker *argcp = argc;
232*de1e4e89SAndroid Build Coastguard Worker *argvp = argv;
233*de1e4e89SAndroid Build Coastguard Worker
234*de1e4e89SAndroid Build Coastguard Worker return 0;
235*de1e4e89SAndroid Build Coastguard Worker }
236*de1e4e89SAndroid Build Coastguard Worker
xfrm_state_extra_flag_parse(__u32 * extra_flags,int * argcp,char *** argvp)237*de1e4e89SAndroid Build Coastguard Worker static int xfrm_state_extra_flag_parse(__u32 *extra_flags, int *argcp, char ***argvp)
238*de1e4e89SAndroid Build Coastguard Worker {
239*de1e4e89SAndroid Build Coastguard Worker int argc = *argcp;
240*de1e4e89SAndroid Build Coastguard Worker char **argv = *argvp;
241*de1e4e89SAndroid Build Coastguard Worker int len = strlen(*argv);
242*de1e4e89SAndroid Build Coastguard Worker
243*de1e4e89SAndroid Build Coastguard Worker if (len > 2 && strncmp(*argv, "0x", 2) == 0) {
244*de1e4e89SAndroid Build Coastguard Worker __u32 val = 0;
245*de1e4e89SAndroid Build Coastguard Worker
246*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&val, *argv, 16))
247*de1e4e89SAndroid Build Coastguard Worker invarg("\"EXTRA-FLAG\" is invalid", *argv);
248*de1e4e89SAndroid Build Coastguard Worker *extra_flags = val;
249*de1e4e89SAndroid Build Coastguard Worker } else {
250*de1e4e89SAndroid Build Coastguard Worker while (1) {
251*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "dont-encap-dscp") == 0)
252*de1e4e89SAndroid Build Coastguard Worker *extra_flags |= XFRM_SA_XFLAG_DONT_ENCAP_DSCP;
253*de1e4e89SAndroid Build Coastguard Worker else {
254*de1e4e89SAndroid Build Coastguard Worker PREV_ARG(); /* back track */
255*de1e4e89SAndroid Build Coastguard Worker break;
256*de1e4e89SAndroid Build Coastguard Worker }
257*de1e4e89SAndroid Build Coastguard Worker
258*de1e4e89SAndroid Build Coastguard Worker if (!NEXT_ARG_OK())
259*de1e4e89SAndroid Build Coastguard Worker break;
260*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
261*de1e4e89SAndroid Build Coastguard Worker }
262*de1e4e89SAndroid Build Coastguard Worker }
263*de1e4e89SAndroid Build Coastguard Worker
264*de1e4e89SAndroid Build Coastguard Worker *argcp = argc;
265*de1e4e89SAndroid Build Coastguard Worker *argvp = argv;
266*de1e4e89SAndroid Build Coastguard Worker
267*de1e4e89SAndroid Build Coastguard Worker return 0;
268*de1e4e89SAndroid Build Coastguard Worker }
269*de1e4e89SAndroid Build Coastguard Worker
xfrm_offload_dir_parse(__u8 * dir,int * argcp,char *** argvp)270*de1e4e89SAndroid Build Coastguard Worker static int xfrm_offload_dir_parse(__u8 *dir, int *argcp, char ***argvp)
271*de1e4e89SAndroid Build Coastguard Worker {
272*de1e4e89SAndroid Build Coastguard Worker int argc = *argcp;
273*de1e4e89SAndroid Build Coastguard Worker char **argv = *argvp;
274*de1e4e89SAndroid Build Coastguard Worker
275*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "in") == 0)
276*de1e4e89SAndroid Build Coastguard Worker *dir = XFRM_OFFLOAD_INBOUND;
277*de1e4e89SAndroid Build Coastguard Worker else if (strcmp(*argv, "out") == 0)
278*de1e4e89SAndroid Build Coastguard Worker *dir = 0;
279*de1e4e89SAndroid Build Coastguard Worker else
280*de1e4e89SAndroid Build Coastguard Worker invarg("DIR value is invalid", *argv);
281*de1e4e89SAndroid Build Coastguard Worker
282*de1e4e89SAndroid Build Coastguard Worker *argcp = argc;
283*de1e4e89SAndroid Build Coastguard Worker *argvp = argv;
284*de1e4e89SAndroid Build Coastguard Worker
285*de1e4e89SAndroid Build Coastguard Worker return 0;
286*de1e4e89SAndroid Build Coastguard Worker }
287*de1e4e89SAndroid Build Coastguard Worker
xfrm_state_modify(int cmd,unsigned int flags,int argc,char ** argv)288*de1e4e89SAndroid Build Coastguard Worker static int xfrm_state_modify(int cmd, unsigned int flags, int argc, char **argv)
289*de1e4e89SAndroid Build Coastguard Worker {
290*de1e4e89SAndroid Build Coastguard Worker struct rtnl_handle rth;
291*de1e4e89SAndroid Build Coastguard Worker struct {
292*de1e4e89SAndroid Build Coastguard Worker struct nlmsghdr n;
293*de1e4e89SAndroid Build Coastguard Worker struct xfrm_usersa_info xsinfo;
294*de1e4e89SAndroid Build Coastguard Worker char buf[RTA_BUF_SIZE];
295*de1e4e89SAndroid Build Coastguard Worker } req = {
296*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xsinfo)),
297*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_flags = NLM_F_REQUEST | flags,
298*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_type = cmd,
299*de1e4e89SAndroid Build Coastguard Worker .xsinfo.family = preferred_family,
300*de1e4e89SAndroid Build Coastguard Worker .xsinfo.lft.soft_byte_limit = XFRM_INF,
301*de1e4e89SAndroid Build Coastguard Worker .xsinfo.lft.hard_byte_limit = XFRM_INF,
302*de1e4e89SAndroid Build Coastguard Worker .xsinfo.lft.soft_packet_limit = XFRM_INF,
303*de1e4e89SAndroid Build Coastguard Worker .xsinfo.lft.hard_packet_limit = XFRM_INF,
304*de1e4e89SAndroid Build Coastguard Worker };
305*de1e4e89SAndroid Build Coastguard Worker struct xfrm_replay_state replay = {};
306*de1e4e89SAndroid Build Coastguard Worker struct xfrm_replay_state_esn replay_esn = {};
307*de1e4e89SAndroid Build Coastguard Worker struct xfrm_user_offload xuo = {};
308*de1e4e89SAndroid Build Coastguard Worker unsigned int ifindex = 0;
309*de1e4e89SAndroid Build Coastguard Worker __u8 dir = 0;
310*de1e4e89SAndroid Build Coastguard Worker bool is_offload = false;
311*de1e4e89SAndroid Build Coastguard Worker __u32 replay_window = 0;
312*de1e4e89SAndroid Build Coastguard Worker __u32 seq = 0, oseq = 0, seq_hi = 0, oseq_hi = 0;
313*de1e4e89SAndroid Build Coastguard Worker char *idp = NULL;
314*de1e4e89SAndroid Build Coastguard Worker char *aeadop = NULL;
315*de1e4e89SAndroid Build Coastguard Worker char *ealgop = NULL;
316*de1e4e89SAndroid Build Coastguard Worker char *aalgop = NULL;
317*de1e4e89SAndroid Build Coastguard Worker char *calgop = NULL;
318*de1e4e89SAndroid Build Coastguard Worker char *coap = NULL;
319*de1e4e89SAndroid Build Coastguard Worker char *sctxp = NULL;
320*de1e4e89SAndroid Build Coastguard Worker __u32 extra_flags = 0;
321*de1e4e89SAndroid Build Coastguard Worker struct xfrm_mark mark = {0, 0};
322*de1e4e89SAndroid Build Coastguard Worker struct {
323*de1e4e89SAndroid Build Coastguard Worker struct xfrm_user_sec_ctx sctx;
324*de1e4e89SAndroid Build Coastguard Worker char str[CTX_BUF_SIZE];
325*de1e4e89SAndroid Build Coastguard Worker } ctx = {};
326*de1e4e89SAndroid Build Coastguard Worker __u32 output_mark = 0;
327*de1e4e89SAndroid Build Coastguard Worker
328*de1e4e89SAndroid Build Coastguard Worker while (argc > 0) {
329*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "mode") == 0) {
330*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
331*de1e4e89SAndroid Build Coastguard Worker xfrm_mode_parse(&req.xsinfo.mode, &argc, &argv);
332*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "mark") == 0) {
333*de1e4e89SAndroid Build Coastguard Worker xfrm_parse_mark(&mark, &argc, &argv);
334*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "reqid") == 0) {
335*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
336*de1e4e89SAndroid Build Coastguard Worker xfrm_reqid_parse(&req.xsinfo.reqid, &argc, &argv);
337*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "seq") == 0) {
338*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
339*de1e4e89SAndroid Build Coastguard Worker xfrm_seq_parse(&req.xsinfo.seq, &argc, &argv);
340*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "replay-window") == 0) {
341*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
342*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&replay_window, *argv, 0))
343*de1e4e89SAndroid Build Coastguard Worker invarg("value after \"replay-window\" is invalid", *argv);
344*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "replay-seq") == 0) {
345*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
346*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&seq, *argv, 0))
347*de1e4e89SAndroid Build Coastguard Worker invarg("value after \"replay-seq\" is invalid", *argv);
348*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "replay-seq-hi") == 0) {
349*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
350*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&seq_hi, *argv, 0))
351*de1e4e89SAndroid Build Coastguard Worker invarg("value after \"replay-seq-hi\" is invalid", *argv);
352*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "replay-oseq") == 0) {
353*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
354*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&oseq, *argv, 0))
355*de1e4e89SAndroid Build Coastguard Worker invarg("value after \"replay-oseq\" is invalid", *argv);
356*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "replay-oseq-hi") == 0) {
357*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
358*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&oseq_hi, *argv, 0))
359*de1e4e89SAndroid Build Coastguard Worker invarg("value after \"replay-oseq-hi\" is invalid", *argv);
360*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "flag") == 0) {
361*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
362*de1e4e89SAndroid Build Coastguard Worker xfrm_state_flag_parse(&req.xsinfo.flags, &argc, &argv);
363*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "extra-flag") == 0) {
364*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
365*de1e4e89SAndroid Build Coastguard Worker xfrm_state_extra_flag_parse(&extra_flags, &argc, &argv);
366*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "sel") == 0) {
367*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
368*de1e4e89SAndroid Build Coastguard Worker preferred_family = AF_UNSPEC;
369*de1e4e89SAndroid Build Coastguard Worker xfrm_selector_parse(&req.xsinfo.sel, &argc, &argv);
370*de1e4e89SAndroid Build Coastguard Worker preferred_family = req.xsinfo.sel.family;
371*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "limit") == 0) {
372*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
373*de1e4e89SAndroid Build Coastguard Worker xfrm_lifetime_cfg_parse(&req.xsinfo.lft, &argc, &argv);
374*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "encap") == 0) {
375*de1e4e89SAndroid Build Coastguard Worker struct xfrm_encap_tmpl encap;
376*de1e4e89SAndroid Build Coastguard Worker inet_prefix oa;
377*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
378*de1e4e89SAndroid Build Coastguard Worker xfrm_encap_type_parse(&encap.encap_type, &argc, &argv);
379*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
380*de1e4e89SAndroid Build Coastguard Worker if (get_be16(&encap.encap_sport, *argv, 0))
381*de1e4e89SAndroid Build Coastguard Worker invarg("SPORT value after \"encap\" is invalid", *argv);
382*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
383*de1e4e89SAndroid Build Coastguard Worker if (get_be16(&encap.encap_dport, *argv, 0))
384*de1e4e89SAndroid Build Coastguard Worker invarg("DPORT value after \"encap\" is invalid", *argv);
385*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
386*de1e4e89SAndroid Build Coastguard Worker get_addr(&oa, *argv, AF_UNSPEC);
387*de1e4e89SAndroid Build Coastguard Worker memcpy(&encap.encap_oa, &oa.data, sizeof(encap.encap_oa));
388*de1e4e89SAndroid Build Coastguard Worker addattr_l(&req.n, sizeof(req.buf), XFRMA_ENCAP,
389*de1e4e89SAndroid Build Coastguard Worker (void *)&encap, sizeof(encap));
390*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "coa") == 0) {
391*de1e4e89SAndroid Build Coastguard Worker inet_prefix coa;
392*de1e4e89SAndroid Build Coastguard Worker xfrm_address_t xcoa = {};
393*de1e4e89SAndroid Build Coastguard Worker
394*de1e4e89SAndroid Build Coastguard Worker if (coap)
395*de1e4e89SAndroid Build Coastguard Worker duparg("coa", *argv);
396*de1e4e89SAndroid Build Coastguard Worker coap = *argv;
397*de1e4e89SAndroid Build Coastguard Worker
398*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
399*de1e4e89SAndroid Build Coastguard Worker
400*de1e4e89SAndroid Build Coastguard Worker get_prefix(&coa, *argv, preferred_family);
401*de1e4e89SAndroid Build Coastguard Worker if (coa.family == AF_UNSPEC)
402*de1e4e89SAndroid Build Coastguard Worker invarg("value after \"coa\" has an unrecognized address family", *argv);
403*de1e4e89SAndroid Build Coastguard Worker if (coa.bytelen > sizeof(xcoa))
404*de1e4e89SAndroid Build Coastguard Worker invarg("value after \"coa\" is too large", *argv);
405*de1e4e89SAndroid Build Coastguard Worker
406*de1e4e89SAndroid Build Coastguard Worker memcpy(&xcoa, &coa.data, coa.bytelen);
407*de1e4e89SAndroid Build Coastguard Worker
408*de1e4e89SAndroid Build Coastguard Worker addattr_l(&req.n, sizeof(req.buf), XFRMA_COADDR,
409*de1e4e89SAndroid Build Coastguard Worker (void *)&xcoa, sizeof(xcoa));
410*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "ctx") == 0) {
411*de1e4e89SAndroid Build Coastguard Worker char *context;
412*de1e4e89SAndroid Build Coastguard Worker
413*de1e4e89SAndroid Build Coastguard Worker if (sctxp)
414*de1e4e89SAndroid Build Coastguard Worker duparg("ctx", *argv);
415*de1e4e89SAndroid Build Coastguard Worker sctxp = *argv;
416*de1e4e89SAndroid Build Coastguard Worker
417*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
418*de1e4e89SAndroid Build Coastguard Worker context = *argv;
419*de1e4e89SAndroid Build Coastguard Worker
420*de1e4e89SAndroid Build Coastguard Worker xfrm_sctx_parse((char *)&ctx.str, context, &ctx.sctx);
421*de1e4e89SAndroid Build Coastguard Worker addattr_l(&req.n, sizeof(req.buf), XFRMA_SEC_CTX,
422*de1e4e89SAndroid Build Coastguard Worker (void *)&ctx, ctx.sctx.len);
423*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "offload") == 0) {
424*de1e4e89SAndroid Build Coastguard Worker is_offload = true;
425*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
426*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "dev") == 0) {
427*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
428*de1e4e89SAndroid Build Coastguard Worker ifindex = ll_name_to_index(*argv);
429*de1e4e89SAndroid Build Coastguard Worker if (!ifindex) {
430*de1e4e89SAndroid Build Coastguard Worker invarg("value after \"offload dev\" is invalid", *argv);
431*de1e4e89SAndroid Build Coastguard Worker is_offload = false;
432*de1e4e89SAndroid Build Coastguard Worker }
433*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
434*de1e4e89SAndroid Build Coastguard Worker }
435*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "dir") == 0) {
436*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
437*de1e4e89SAndroid Build Coastguard Worker xfrm_offload_dir_parse(&dir, &argc, &argv);
438*de1e4e89SAndroid Build Coastguard Worker } else {
439*de1e4e89SAndroid Build Coastguard Worker invarg("value after \"offload dir\" is invalid", *argv);
440*de1e4e89SAndroid Build Coastguard Worker is_offload = false;
441*de1e4e89SAndroid Build Coastguard Worker }
442*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "output-mark") == 0) {
443*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
444*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&output_mark, *argv, 0))
445*de1e4e89SAndroid Build Coastguard Worker invarg("value after \"output-mark\" is invalid", *argv);
446*de1e4e89SAndroid Build Coastguard Worker } else {
447*de1e4e89SAndroid Build Coastguard Worker /* try to assume ALGO */
448*de1e4e89SAndroid Build Coastguard Worker int type = xfrm_algotype_getbyname(*argv);
449*de1e4e89SAndroid Build Coastguard Worker
450*de1e4e89SAndroid Build Coastguard Worker switch (type) {
451*de1e4e89SAndroid Build Coastguard Worker case XFRMA_ALG_AEAD:
452*de1e4e89SAndroid Build Coastguard Worker case XFRMA_ALG_CRYPT:
453*de1e4e89SAndroid Build Coastguard Worker case XFRMA_ALG_AUTH:
454*de1e4e89SAndroid Build Coastguard Worker case XFRMA_ALG_AUTH_TRUNC:
455*de1e4e89SAndroid Build Coastguard Worker case XFRMA_ALG_COMP:
456*de1e4e89SAndroid Build Coastguard Worker {
457*de1e4e89SAndroid Build Coastguard Worker /* ALGO */
458*de1e4e89SAndroid Build Coastguard Worker struct {
459*de1e4e89SAndroid Build Coastguard Worker union {
460*de1e4e89SAndroid Build Coastguard Worker struct xfrm_algo alg;
461*de1e4e89SAndroid Build Coastguard Worker struct xfrm_algo_aead aead;
462*de1e4e89SAndroid Build Coastguard Worker struct xfrm_algo_auth auth;
463*de1e4e89SAndroid Build Coastguard Worker } u;
464*de1e4e89SAndroid Build Coastguard Worker char buf[XFRM_ALGO_KEY_BUF_SIZE];
465*de1e4e89SAndroid Build Coastguard Worker } alg = {};
466*de1e4e89SAndroid Build Coastguard Worker int len;
467*de1e4e89SAndroid Build Coastguard Worker __u32 icvlen, trunclen;
468*de1e4e89SAndroid Build Coastguard Worker char *name;
469*de1e4e89SAndroid Build Coastguard Worker char *key = "";
470*de1e4e89SAndroid Build Coastguard Worker char *buf;
471*de1e4e89SAndroid Build Coastguard Worker
472*de1e4e89SAndroid Build Coastguard Worker switch (type) {
473*de1e4e89SAndroid Build Coastguard Worker case XFRMA_ALG_AEAD:
474*de1e4e89SAndroid Build Coastguard Worker if (ealgop || aalgop || aeadop)
475*de1e4e89SAndroid Build Coastguard Worker duparg("ALGO-TYPE", *argv);
476*de1e4e89SAndroid Build Coastguard Worker aeadop = *argv;
477*de1e4e89SAndroid Build Coastguard Worker break;
478*de1e4e89SAndroid Build Coastguard Worker case XFRMA_ALG_CRYPT:
479*de1e4e89SAndroid Build Coastguard Worker if (ealgop || aeadop)
480*de1e4e89SAndroid Build Coastguard Worker duparg("ALGO-TYPE", *argv);
481*de1e4e89SAndroid Build Coastguard Worker ealgop = *argv;
482*de1e4e89SAndroid Build Coastguard Worker break;
483*de1e4e89SAndroid Build Coastguard Worker case XFRMA_ALG_AUTH:
484*de1e4e89SAndroid Build Coastguard Worker case XFRMA_ALG_AUTH_TRUNC:
485*de1e4e89SAndroid Build Coastguard Worker if (aalgop || aeadop)
486*de1e4e89SAndroid Build Coastguard Worker duparg("ALGO-TYPE", *argv);
487*de1e4e89SAndroid Build Coastguard Worker aalgop = *argv;
488*de1e4e89SAndroid Build Coastguard Worker break;
489*de1e4e89SAndroid Build Coastguard Worker case XFRMA_ALG_COMP:
490*de1e4e89SAndroid Build Coastguard Worker if (calgop)
491*de1e4e89SAndroid Build Coastguard Worker duparg("ALGO-TYPE", *argv);
492*de1e4e89SAndroid Build Coastguard Worker calgop = *argv;
493*de1e4e89SAndroid Build Coastguard Worker break;
494*de1e4e89SAndroid Build Coastguard Worker default:
495*de1e4e89SAndroid Build Coastguard Worker /* not reached */
496*de1e4e89SAndroid Build Coastguard Worker invarg("ALGO-TYPE value is invalid\n", *argv);
497*de1e4e89SAndroid Build Coastguard Worker }
498*de1e4e89SAndroid Build Coastguard Worker
499*de1e4e89SAndroid Build Coastguard Worker if (!NEXT_ARG_OK())
500*de1e4e89SAndroid Build Coastguard Worker missarg("ALGO-NAME");
501*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
502*de1e4e89SAndroid Build Coastguard Worker name = *argv;
503*de1e4e89SAndroid Build Coastguard Worker
504*de1e4e89SAndroid Build Coastguard Worker switch (type) {
505*de1e4e89SAndroid Build Coastguard Worker case XFRMA_ALG_AEAD:
506*de1e4e89SAndroid Build Coastguard Worker case XFRMA_ALG_CRYPT:
507*de1e4e89SAndroid Build Coastguard Worker case XFRMA_ALG_AUTH:
508*de1e4e89SAndroid Build Coastguard Worker case XFRMA_ALG_AUTH_TRUNC:
509*de1e4e89SAndroid Build Coastguard Worker if (!NEXT_ARG_OK())
510*de1e4e89SAndroid Build Coastguard Worker missarg("ALGO-KEYMAT");
511*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
512*de1e4e89SAndroid Build Coastguard Worker key = *argv;
513*de1e4e89SAndroid Build Coastguard Worker break;
514*de1e4e89SAndroid Build Coastguard Worker }
515*de1e4e89SAndroid Build Coastguard Worker
516*de1e4e89SAndroid Build Coastguard Worker buf = alg.u.alg.alg_key;
517*de1e4e89SAndroid Build Coastguard Worker len = sizeof(alg.u.alg);
518*de1e4e89SAndroid Build Coastguard Worker
519*de1e4e89SAndroid Build Coastguard Worker switch (type) {
520*de1e4e89SAndroid Build Coastguard Worker case XFRMA_ALG_AEAD:
521*de1e4e89SAndroid Build Coastguard Worker if (!NEXT_ARG_OK())
522*de1e4e89SAndroid Build Coastguard Worker missarg("ALGO-ICV-LEN");
523*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
524*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&icvlen, *argv, 0))
525*de1e4e89SAndroid Build Coastguard Worker invarg("ALGO-ICV-LEN value is invalid",
526*de1e4e89SAndroid Build Coastguard Worker *argv);
527*de1e4e89SAndroid Build Coastguard Worker alg.u.aead.alg_icv_len = icvlen;
528*de1e4e89SAndroid Build Coastguard Worker
529*de1e4e89SAndroid Build Coastguard Worker buf = alg.u.aead.alg_key;
530*de1e4e89SAndroid Build Coastguard Worker len = sizeof(alg.u.aead);
531*de1e4e89SAndroid Build Coastguard Worker break;
532*de1e4e89SAndroid Build Coastguard Worker case XFRMA_ALG_AUTH_TRUNC:
533*de1e4e89SAndroid Build Coastguard Worker if (!NEXT_ARG_OK())
534*de1e4e89SAndroid Build Coastguard Worker missarg("ALGO-TRUNC-LEN");
535*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
536*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&trunclen, *argv, 0))
537*de1e4e89SAndroid Build Coastguard Worker invarg("ALGO-TRUNC-LEN value is invalid",
538*de1e4e89SAndroid Build Coastguard Worker *argv);
539*de1e4e89SAndroid Build Coastguard Worker alg.u.auth.alg_trunc_len = trunclen;
540*de1e4e89SAndroid Build Coastguard Worker
541*de1e4e89SAndroid Build Coastguard Worker buf = alg.u.auth.alg_key;
542*de1e4e89SAndroid Build Coastguard Worker len = sizeof(alg.u.auth);
543*de1e4e89SAndroid Build Coastguard Worker break;
544*de1e4e89SAndroid Build Coastguard Worker }
545*de1e4e89SAndroid Build Coastguard Worker
546*de1e4e89SAndroid Build Coastguard Worker xfrm_algo_parse((void *)&alg, type, name, key,
547*de1e4e89SAndroid Build Coastguard Worker buf, sizeof(alg.buf));
548*de1e4e89SAndroid Build Coastguard Worker len += alg.u.alg.alg_key_len / 8;
549*de1e4e89SAndroid Build Coastguard Worker
550*de1e4e89SAndroid Build Coastguard Worker addattr_l(&req.n, sizeof(req.buf), type,
551*de1e4e89SAndroid Build Coastguard Worker (void *)&alg, len);
552*de1e4e89SAndroid Build Coastguard Worker break;
553*de1e4e89SAndroid Build Coastguard Worker }
554*de1e4e89SAndroid Build Coastguard Worker default:
555*de1e4e89SAndroid Build Coastguard Worker /* try to assume ID */
556*de1e4e89SAndroid Build Coastguard Worker if (idp)
557*de1e4e89SAndroid Build Coastguard Worker invarg("unknown", *argv);
558*de1e4e89SAndroid Build Coastguard Worker idp = *argv;
559*de1e4e89SAndroid Build Coastguard Worker
560*de1e4e89SAndroid Build Coastguard Worker /* ID */
561*de1e4e89SAndroid Build Coastguard Worker xfrm_id_parse(&req.xsinfo.saddr, &req.xsinfo.id,
562*de1e4e89SAndroid Build Coastguard Worker &req.xsinfo.family, 0, &argc, &argv);
563*de1e4e89SAndroid Build Coastguard Worker if (preferred_family == AF_UNSPEC)
564*de1e4e89SAndroid Build Coastguard Worker preferred_family = req.xsinfo.family;
565*de1e4e89SAndroid Build Coastguard Worker }
566*de1e4e89SAndroid Build Coastguard Worker }
567*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
568*de1e4e89SAndroid Build Coastguard Worker }
569*de1e4e89SAndroid Build Coastguard Worker
570*de1e4e89SAndroid Build Coastguard Worker if (req.xsinfo.flags & XFRM_STATE_ESN &&
571*de1e4e89SAndroid Build Coastguard Worker replay_window == 0) {
572*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Error: esn flag set without replay-window.\n");
573*de1e4e89SAndroid Build Coastguard Worker exit(-1);
574*de1e4e89SAndroid Build Coastguard Worker }
575*de1e4e89SAndroid Build Coastguard Worker
576*de1e4e89SAndroid Build Coastguard Worker if (replay_window > XFRMA_REPLAY_ESN_MAX) {
577*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr,
578*de1e4e89SAndroid Build Coastguard Worker "Error: replay-window (%u) > XFRMA_REPLAY_ESN_MAX (%u).\n",
579*de1e4e89SAndroid Build Coastguard Worker replay_window, XFRMA_REPLAY_ESN_MAX);
580*de1e4e89SAndroid Build Coastguard Worker exit(-1);
581*de1e4e89SAndroid Build Coastguard Worker }
582*de1e4e89SAndroid Build Coastguard Worker
583*de1e4e89SAndroid Build Coastguard Worker if (is_offload) {
584*de1e4e89SAndroid Build Coastguard Worker xuo.ifindex = ifindex;
585*de1e4e89SAndroid Build Coastguard Worker xuo.flags = dir;
586*de1e4e89SAndroid Build Coastguard Worker addattr_l(&req.n, sizeof(req.buf), XFRMA_OFFLOAD_DEV, &xuo,
587*de1e4e89SAndroid Build Coastguard Worker sizeof(xuo));
588*de1e4e89SAndroid Build Coastguard Worker }
589*de1e4e89SAndroid Build Coastguard Worker if (req.xsinfo.flags & XFRM_STATE_ESN ||
590*de1e4e89SAndroid Build Coastguard Worker replay_window > (sizeof(replay.bitmap) * 8)) {
591*de1e4e89SAndroid Build Coastguard Worker replay_esn.seq = seq;
592*de1e4e89SAndroid Build Coastguard Worker replay_esn.oseq = oseq;
593*de1e4e89SAndroid Build Coastguard Worker replay_esn.seq_hi = seq_hi;
594*de1e4e89SAndroid Build Coastguard Worker replay_esn.oseq_hi = oseq_hi;
595*de1e4e89SAndroid Build Coastguard Worker replay_esn.replay_window = replay_window;
596*de1e4e89SAndroid Build Coastguard Worker replay_esn.bmp_len = (replay_window + sizeof(__u32) * 8 - 1) /
597*de1e4e89SAndroid Build Coastguard Worker (sizeof(__u32) * 8);
598*de1e4e89SAndroid Build Coastguard Worker addattr_l(&req.n, sizeof(req.buf), XFRMA_REPLAY_ESN_VAL,
599*de1e4e89SAndroid Build Coastguard Worker &replay_esn, sizeof(replay_esn));
600*de1e4e89SAndroid Build Coastguard Worker } else {
601*de1e4e89SAndroid Build Coastguard Worker if (seq || oseq) {
602*de1e4e89SAndroid Build Coastguard Worker replay.seq = seq;
603*de1e4e89SAndroid Build Coastguard Worker replay.oseq = oseq;
604*de1e4e89SAndroid Build Coastguard Worker addattr_l(&req.n, sizeof(req.buf), XFRMA_REPLAY_VAL,
605*de1e4e89SAndroid Build Coastguard Worker &replay, sizeof(replay));
606*de1e4e89SAndroid Build Coastguard Worker }
607*de1e4e89SAndroid Build Coastguard Worker req.xsinfo.replay_window = replay_window;
608*de1e4e89SAndroid Build Coastguard Worker }
609*de1e4e89SAndroid Build Coastguard Worker
610*de1e4e89SAndroid Build Coastguard Worker if (extra_flags)
611*de1e4e89SAndroid Build Coastguard Worker addattr32(&req.n, sizeof(req.buf), XFRMA_SA_EXTRA_FLAGS,
612*de1e4e89SAndroid Build Coastguard Worker extra_flags);
613*de1e4e89SAndroid Build Coastguard Worker
614*de1e4e89SAndroid Build Coastguard Worker if (!idp) {
615*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Not enough information: ID is required\n");
616*de1e4e89SAndroid Build Coastguard Worker exit(1);
617*de1e4e89SAndroid Build Coastguard Worker }
618*de1e4e89SAndroid Build Coastguard Worker
619*de1e4e89SAndroid Build Coastguard Worker if (mark.m) {
620*de1e4e89SAndroid Build Coastguard Worker int r = addattr_l(&req.n, sizeof(req.buf), XFRMA_MARK,
621*de1e4e89SAndroid Build Coastguard Worker (void *)&mark, sizeof(mark));
622*de1e4e89SAndroid Build Coastguard Worker if (r < 0) {
623*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "XFRMA_MARK failed\n");
624*de1e4e89SAndroid Build Coastguard Worker exit(1);
625*de1e4e89SAndroid Build Coastguard Worker }
626*de1e4e89SAndroid Build Coastguard Worker }
627*de1e4e89SAndroid Build Coastguard Worker
628*de1e4e89SAndroid Build Coastguard Worker if (xfrm_xfrmproto_is_ipsec(req.xsinfo.id.proto)) {
629*de1e4e89SAndroid Build Coastguard Worker switch (req.xsinfo.mode) {
630*de1e4e89SAndroid Build Coastguard Worker case XFRM_MODE_TRANSPORT:
631*de1e4e89SAndroid Build Coastguard Worker case XFRM_MODE_TUNNEL:
632*de1e4e89SAndroid Build Coastguard Worker break;
633*de1e4e89SAndroid Build Coastguard Worker case XFRM_MODE_BEET:
634*de1e4e89SAndroid Build Coastguard Worker if (req.xsinfo.id.proto == IPPROTO_ESP)
635*de1e4e89SAndroid Build Coastguard Worker break;
636*de1e4e89SAndroid Build Coastguard Worker default:
637*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "MODE value is invalid with XFRM-PROTO value \"%s\"\n",
638*de1e4e89SAndroid Build Coastguard Worker strxf_xfrmproto(req.xsinfo.id.proto));
639*de1e4e89SAndroid Build Coastguard Worker exit(1);
640*de1e4e89SAndroid Build Coastguard Worker }
641*de1e4e89SAndroid Build Coastguard Worker
642*de1e4e89SAndroid Build Coastguard Worker switch (req.xsinfo.id.proto) {
643*de1e4e89SAndroid Build Coastguard Worker case IPPROTO_ESP:
644*de1e4e89SAndroid Build Coastguard Worker if (calgop) {
645*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "ALGO-TYPE value \"%s\" is invalid with XFRM-PROTO value \"%s\"\n",
646*de1e4e89SAndroid Build Coastguard Worker strxf_algotype(XFRMA_ALG_COMP),
647*de1e4e89SAndroid Build Coastguard Worker strxf_xfrmproto(req.xsinfo.id.proto));
648*de1e4e89SAndroid Build Coastguard Worker exit(1);
649*de1e4e89SAndroid Build Coastguard Worker }
650*de1e4e89SAndroid Build Coastguard Worker if (!ealgop && !aeadop) {
651*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "ALGO-TYPE value \"%s\" or \"%s\" is required with XFRM-PROTO value \"%s\"\n",
652*de1e4e89SAndroid Build Coastguard Worker strxf_algotype(XFRMA_ALG_CRYPT),
653*de1e4e89SAndroid Build Coastguard Worker strxf_algotype(XFRMA_ALG_AEAD),
654*de1e4e89SAndroid Build Coastguard Worker strxf_xfrmproto(req.xsinfo.id.proto));
655*de1e4e89SAndroid Build Coastguard Worker exit(1);
656*de1e4e89SAndroid Build Coastguard Worker }
657*de1e4e89SAndroid Build Coastguard Worker break;
658*de1e4e89SAndroid Build Coastguard Worker case IPPROTO_AH:
659*de1e4e89SAndroid Build Coastguard Worker if (ealgop || aeadop || calgop) {
660*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "ALGO-TYPE values \"%s\", \"%s\", and \"%s\" are invalid with XFRM-PROTO value \"%s\"\n",
661*de1e4e89SAndroid Build Coastguard Worker strxf_algotype(XFRMA_ALG_CRYPT),
662*de1e4e89SAndroid Build Coastguard Worker strxf_algotype(XFRMA_ALG_AEAD),
663*de1e4e89SAndroid Build Coastguard Worker strxf_algotype(XFRMA_ALG_COMP),
664*de1e4e89SAndroid Build Coastguard Worker strxf_xfrmproto(req.xsinfo.id.proto));
665*de1e4e89SAndroid Build Coastguard Worker exit(1);
666*de1e4e89SAndroid Build Coastguard Worker }
667*de1e4e89SAndroid Build Coastguard Worker if (!aalgop) {
668*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "ALGO-TYPE value \"%s\" or \"%s\" is required with XFRM-PROTO value \"%s\"\n",
669*de1e4e89SAndroid Build Coastguard Worker strxf_algotype(XFRMA_ALG_AUTH),
670*de1e4e89SAndroid Build Coastguard Worker strxf_algotype(XFRMA_ALG_AUTH_TRUNC),
671*de1e4e89SAndroid Build Coastguard Worker strxf_xfrmproto(req.xsinfo.id.proto));
672*de1e4e89SAndroid Build Coastguard Worker exit(1);
673*de1e4e89SAndroid Build Coastguard Worker }
674*de1e4e89SAndroid Build Coastguard Worker break;
675*de1e4e89SAndroid Build Coastguard Worker case IPPROTO_COMP:
676*de1e4e89SAndroid Build Coastguard Worker if (ealgop || aalgop || aeadop) {
677*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "ALGO-TYPE values \"%s\", \"%s\", \"%s\", and \"%s\" are invalid with XFRM-PROTO value \"%s\"\n",
678*de1e4e89SAndroid Build Coastguard Worker strxf_algotype(XFRMA_ALG_CRYPT),
679*de1e4e89SAndroid Build Coastguard Worker strxf_algotype(XFRMA_ALG_AUTH),
680*de1e4e89SAndroid Build Coastguard Worker strxf_algotype(XFRMA_ALG_AUTH_TRUNC),
681*de1e4e89SAndroid Build Coastguard Worker strxf_algotype(XFRMA_ALG_AEAD),
682*de1e4e89SAndroid Build Coastguard Worker strxf_xfrmproto(req.xsinfo.id.proto));
683*de1e4e89SAndroid Build Coastguard Worker exit(1);
684*de1e4e89SAndroid Build Coastguard Worker }
685*de1e4e89SAndroid Build Coastguard Worker if (!calgop) {
686*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "ALGO-TYPE value \"%s\" is required with XFRM-PROTO value \"%s\"\n",
687*de1e4e89SAndroid Build Coastguard Worker strxf_algotype(XFRMA_ALG_COMP),
688*de1e4e89SAndroid Build Coastguard Worker strxf_xfrmproto(req.xsinfo.id.proto));
689*de1e4e89SAndroid Build Coastguard Worker exit(1);
690*de1e4e89SAndroid Build Coastguard Worker }
691*de1e4e89SAndroid Build Coastguard Worker break;
692*de1e4e89SAndroid Build Coastguard Worker }
693*de1e4e89SAndroid Build Coastguard Worker } else {
694*de1e4e89SAndroid Build Coastguard Worker if (ealgop || aalgop || aeadop || calgop) {
695*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "ALGO is invalid with XFRM-PROTO value \"%s\"\n",
696*de1e4e89SAndroid Build Coastguard Worker strxf_xfrmproto(req.xsinfo.id.proto));
697*de1e4e89SAndroid Build Coastguard Worker exit(1);
698*de1e4e89SAndroid Build Coastguard Worker }
699*de1e4e89SAndroid Build Coastguard Worker }
700*de1e4e89SAndroid Build Coastguard Worker
701*de1e4e89SAndroid Build Coastguard Worker if (xfrm_xfrmproto_is_ro(req.xsinfo.id.proto)) {
702*de1e4e89SAndroid Build Coastguard Worker switch (req.xsinfo.mode) {
703*de1e4e89SAndroid Build Coastguard Worker case XFRM_MODE_ROUTEOPTIMIZATION:
704*de1e4e89SAndroid Build Coastguard Worker case XFRM_MODE_IN_TRIGGER:
705*de1e4e89SAndroid Build Coastguard Worker break;
706*de1e4e89SAndroid Build Coastguard Worker case 0:
707*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "\"mode\" is required with XFRM-PROTO value \"%s\"\n",
708*de1e4e89SAndroid Build Coastguard Worker strxf_xfrmproto(req.xsinfo.id.proto));
709*de1e4e89SAndroid Build Coastguard Worker exit(1);
710*de1e4e89SAndroid Build Coastguard Worker default:
711*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "MODE value is invalid with XFRM-PROTO value \"%s\"\n",
712*de1e4e89SAndroid Build Coastguard Worker strxf_xfrmproto(req.xsinfo.id.proto));
713*de1e4e89SAndroid Build Coastguard Worker exit(1);
714*de1e4e89SAndroid Build Coastguard Worker }
715*de1e4e89SAndroid Build Coastguard Worker
716*de1e4e89SAndroid Build Coastguard Worker if (!coap) {
717*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "\"coa\" is required with XFRM-PROTO value \"%s\"\n",
718*de1e4e89SAndroid Build Coastguard Worker strxf_xfrmproto(req.xsinfo.id.proto));
719*de1e4e89SAndroid Build Coastguard Worker exit(1);
720*de1e4e89SAndroid Build Coastguard Worker }
721*de1e4e89SAndroid Build Coastguard Worker } else {
722*de1e4e89SAndroid Build Coastguard Worker if (coap) {
723*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "\"coa\" is invalid with XFRM-PROTO value \"%s\"\n",
724*de1e4e89SAndroid Build Coastguard Worker strxf_xfrmproto(req.xsinfo.id.proto));
725*de1e4e89SAndroid Build Coastguard Worker exit(1);
726*de1e4e89SAndroid Build Coastguard Worker }
727*de1e4e89SAndroid Build Coastguard Worker }
728*de1e4e89SAndroid Build Coastguard Worker
729*de1e4e89SAndroid Build Coastguard Worker if (output_mark)
730*de1e4e89SAndroid Build Coastguard Worker addattr32(&req.n, sizeof(req.buf), XFRMA_OUTPUT_MARK, output_mark);
731*de1e4e89SAndroid Build Coastguard Worker
732*de1e4e89SAndroid Build Coastguard Worker if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
733*de1e4e89SAndroid Build Coastguard Worker exit(1);
734*de1e4e89SAndroid Build Coastguard Worker
735*de1e4e89SAndroid Build Coastguard Worker if (req.xsinfo.family == AF_UNSPEC)
736*de1e4e89SAndroid Build Coastguard Worker req.xsinfo.family = AF_INET;
737*de1e4e89SAndroid Build Coastguard Worker
738*de1e4e89SAndroid Build Coastguard Worker if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
739*de1e4e89SAndroid Build Coastguard Worker exit(2);
740*de1e4e89SAndroid Build Coastguard Worker
741*de1e4e89SAndroid Build Coastguard Worker rtnl_close(&rth);
742*de1e4e89SAndroid Build Coastguard Worker
743*de1e4e89SAndroid Build Coastguard Worker return 0;
744*de1e4e89SAndroid Build Coastguard Worker }
745*de1e4e89SAndroid Build Coastguard Worker
xfrm_state_allocspi(int argc,char ** argv)746*de1e4e89SAndroid Build Coastguard Worker static int xfrm_state_allocspi(int argc, char **argv)
747*de1e4e89SAndroid Build Coastguard Worker {
748*de1e4e89SAndroid Build Coastguard Worker struct rtnl_handle rth;
749*de1e4e89SAndroid Build Coastguard Worker struct {
750*de1e4e89SAndroid Build Coastguard Worker struct nlmsghdr n;
751*de1e4e89SAndroid Build Coastguard Worker struct xfrm_userspi_info xspi;
752*de1e4e89SAndroid Build Coastguard Worker char buf[RTA_BUF_SIZE];
753*de1e4e89SAndroid Build Coastguard Worker } req = {
754*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xspi)),
755*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_flags = NLM_F_REQUEST,
756*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_type = XFRM_MSG_ALLOCSPI,
757*de1e4e89SAndroid Build Coastguard Worker .xspi.info.family = preferred_family,
758*de1e4e89SAndroid Build Coastguard Worker #if 0
759*de1e4e89SAndroid Build Coastguard Worker .xspi.lft.soft_byte_limit = XFRM_INF,
760*de1e4e89SAndroid Build Coastguard Worker .xspi.lft.hard_byte_limit = XFRM_INF,
761*de1e4e89SAndroid Build Coastguard Worker .xspi.lft.soft_packet_limit = XFRM_INF,
762*de1e4e89SAndroid Build Coastguard Worker .xspi.lft.hard_packet_limit = XFRM_INF,
763*de1e4e89SAndroid Build Coastguard Worker #endif
764*de1e4e89SAndroid Build Coastguard Worker };
765*de1e4e89SAndroid Build Coastguard Worker char *idp = NULL;
766*de1e4e89SAndroid Build Coastguard Worker char *minp = NULL;
767*de1e4e89SAndroid Build Coastguard Worker char *maxp = NULL;
768*de1e4e89SAndroid Build Coastguard Worker struct xfrm_mark mark = {0, 0};
769*de1e4e89SAndroid Build Coastguard Worker char res_buf[NLMSG_BUF_SIZE] = {};
770*de1e4e89SAndroid Build Coastguard Worker struct nlmsghdr *res_n = (struct nlmsghdr *)res_buf;
771*de1e4e89SAndroid Build Coastguard Worker
772*de1e4e89SAndroid Build Coastguard Worker while (argc > 0) {
773*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "mode") == 0) {
774*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
775*de1e4e89SAndroid Build Coastguard Worker xfrm_mode_parse(&req.xspi.info.mode, &argc, &argv);
776*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "mark") == 0) {
777*de1e4e89SAndroid Build Coastguard Worker xfrm_parse_mark(&mark, &argc, &argv);
778*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "reqid") == 0) {
779*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
780*de1e4e89SAndroid Build Coastguard Worker xfrm_reqid_parse(&req.xspi.info.reqid, &argc, &argv);
781*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "seq") == 0) {
782*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
783*de1e4e89SAndroid Build Coastguard Worker xfrm_seq_parse(&req.xspi.info.seq, &argc, &argv);
784*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "min") == 0) {
785*de1e4e89SAndroid Build Coastguard Worker if (minp)
786*de1e4e89SAndroid Build Coastguard Worker duparg("min", *argv);
787*de1e4e89SAndroid Build Coastguard Worker minp = *argv;
788*de1e4e89SAndroid Build Coastguard Worker
789*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
790*de1e4e89SAndroid Build Coastguard Worker
791*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&req.xspi.min, *argv, 0))
792*de1e4e89SAndroid Build Coastguard Worker invarg("value after \"min\" is invalid", *argv);
793*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "max") == 0) {
794*de1e4e89SAndroid Build Coastguard Worker if (maxp)
795*de1e4e89SAndroid Build Coastguard Worker duparg("max", *argv);
796*de1e4e89SAndroid Build Coastguard Worker maxp = *argv;
797*de1e4e89SAndroid Build Coastguard Worker
798*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
799*de1e4e89SAndroid Build Coastguard Worker
800*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&req.xspi.max, *argv, 0))
801*de1e4e89SAndroid Build Coastguard Worker invarg("value after \"max\" is invalid", *argv);
802*de1e4e89SAndroid Build Coastguard Worker } else {
803*de1e4e89SAndroid Build Coastguard Worker /* try to assume ID */
804*de1e4e89SAndroid Build Coastguard Worker if (idp)
805*de1e4e89SAndroid Build Coastguard Worker invarg("unknown", *argv);
806*de1e4e89SAndroid Build Coastguard Worker idp = *argv;
807*de1e4e89SAndroid Build Coastguard Worker
808*de1e4e89SAndroid Build Coastguard Worker /* ID */
809*de1e4e89SAndroid Build Coastguard Worker xfrm_id_parse(&req.xspi.info.saddr, &req.xspi.info.id,
810*de1e4e89SAndroid Build Coastguard Worker &req.xspi.info.family, 0, &argc, &argv);
811*de1e4e89SAndroid Build Coastguard Worker if (req.xspi.info.id.spi) {
812*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "\"spi\" is invalid\n");
813*de1e4e89SAndroid Build Coastguard Worker exit(1);
814*de1e4e89SAndroid Build Coastguard Worker }
815*de1e4e89SAndroid Build Coastguard Worker if (preferred_family == AF_UNSPEC)
816*de1e4e89SAndroid Build Coastguard Worker preferred_family = req.xspi.info.family;
817*de1e4e89SAndroid Build Coastguard Worker }
818*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
819*de1e4e89SAndroid Build Coastguard Worker }
820*de1e4e89SAndroid Build Coastguard Worker
821*de1e4e89SAndroid Build Coastguard Worker if (!idp) {
822*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Not enough information: ID is required\n");
823*de1e4e89SAndroid Build Coastguard Worker exit(1);
824*de1e4e89SAndroid Build Coastguard Worker }
825*de1e4e89SAndroid Build Coastguard Worker
826*de1e4e89SAndroid Build Coastguard Worker if (minp) {
827*de1e4e89SAndroid Build Coastguard Worker if (!maxp) {
828*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "\"max\" is missing\n");
829*de1e4e89SAndroid Build Coastguard Worker exit(1);
830*de1e4e89SAndroid Build Coastguard Worker }
831*de1e4e89SAndroid Build Coastguard Worker if (req.xspi.min > req.xspi.max) {
832*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "value after \"min\" is larger than value after \"max\"\n");
833*de1e4e89SAndroid Build Coastguard Worker exit(1);
834*de1e4e89SAndroid Build Coastguard Worker }
835*de1e4e89SAndroid Build Coastguard Worker } else {
836*de1e4e89SAndroid Build Coastguard Worker if (maxp) {
837*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "\"min\" is missing\n");
838*de1e4e89SAndroid Build Coastguard Worker exit(1);
839*de1e4e89SAndroid Build Coastguard Worker }
840*de1e4e89SAndroid Build Coastguard Worker
841*de1e4e89SAndroid Build Coastguard Worker /* XXX: Default value defined in PF_KEY;
842*de1e4e89SAndroid Build Coastguard Worker * See kernel's net/key/af_key.c(pfkey_getspi).
843*de1e4e89SAndroid Build Coastguard Worker */
844*de1e4e89SAndroid Build Coastguard Worker req.xspi.min = 0x100;
845*de1e4e89SAndroid Build Coastguard Worker req.xspi.max = 0x0fffffff;
846*de1e4e89SAndroid Build Coastguard Worker
847*de1e4e89SAndroid Build Coastguard Worker /* XXX: IPCOMP spi is 16-bits;
848*de1e4e89SAndroid Build Coastguard Worker * See kernel's net/xfrm/xfrm_user(verify_userspi_info).
849*de1e4e89SAndroid Build Coastguard Worker */
850*de1e4e89SAndroid Build Coastguard Worker if (req.xspi.info.id.proto == IPPROTO_COMP)
851*de1e4e89SAndroid Build Coastguard Worker req.xspi.max = 0xffff;
852*de1e4e89SAndroid Build Coastguard Worker }
853*de1e4e89SAndroid Build Coastguard Worker
854*de1e4e89SAndroid Build Coastguard Worker if (mark.m & mark.v) {
855*de1e4e89SAndroid Build Coastguard Worker int r = addattr_l(&req.n, sizeof(req.buf), XFRMA_MARK,
856*de1e4e89SAndroid Build Coastguard Worker (void *)&mark, sizeof(mark));
857*de1e4e89SAndroid Build Coastguard Worker if (r < 0) {
858*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "XFRMA_MARK failed\n");
859*de1e4e89SAndroid Build Coastguard Worker exit(1);
860*de1e4e89SAndroid Build Coastguard Worker }
861*de1e4e89SAndroid Build Coastguard Worker }
862*de1e4e89SAndroid Build Coastguard Worker
863*de1e4e89SAndroid Build Coastguard Worker if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
864*de1e4e89SAndroid Build Coastguard Worker exit(1);
865*de1e4e89SAndroid Build Coastguard Worker
866*de1e4e89SAndroid Build Coastguard Worker if (req.xspi.info.family == AF_UNSPEC)
867*de1e4e89SAndroid Build Coastguard Worker req.xspi.info.family = AF_INET;
868*de1e4e89SAndroid Build Coastguard Worker
869*de1e4e89SAndroid Build Coastguard Worker
870*de1e4e89SAndroid Build Coastguard Worker if (rtnl_talk(&rth, &req.n, res_n, sizeof(res_buf)) < 0)
871*de1e4e89SAndroid Build Coastguard Worker exit(2);
872*de1e4e89SAndroid Build Coastguard Worker
873*de1e4e89SAndroid Build Coastguard Worker if (xfrm_state_print(NULL, res_n, (void *)stdout) < 0) {
874*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "An error :-)\n");
875*de1e4e89SAndroid Build Coastguard Worker exit(1);
876*de1e4e89SAndroid Build Coastguard Worker }
877*de1e4e89SAndroid Build Coastguard Worker
878*de1e4e89SAndroid Build Coastguard Worker rtnl_close(&rth);
879*de1e4e89SAndroid Build Coastguard Worker
880*de1e4e89SAndroid Build Coastguard Worker return 0;
881*de1e4e89SAndroid Build Coastguard Worker }
882*de1e4e89SAndroid Build Coastguard Worker
xfrm_state_filter_match(struct xfrm_usersa_info * xsinfo)883*de1e4e89SAndroid Build Coastguard Worker static int xfrm_state_filter_match(struct xfrm_usersa_info *xsinfo)
884*de1e4e89SAndroid Build Coastguard Worker {
885*de1e4e89SAndroid Build Coastguard Worker if (!filter.use)
886*de1e4e89SAndroid Build Coastguard Worker return 1;
887*de1e4e89SAndroid Build Coastguard Worker
888*de1e4e89SAndroid Build Coastguard Worker if (filter.id_src_mask)
889*de1e4e89SAndroid Build Coastguard Worker if (xfrm_addr_match(&xsinfo->saddr, &filter.xsinfo.saddr,
890*de1e4e89SAndroid Build Coastguard Worker filter.id_src_mask))
891*de1e4e89SAndroid Build Coastguard Worker return 0;
892*de1e4e89SAndroid Build Coastguard Worker if (filter.id_dst_mask)
893*de1e4e89SAndroid Build Coastguard Worker if (xfrm_addr_match(&xsinfo->id.daddr, &filter.xsinfo.id.daddr,
894*de1e4e89SAndroid Build Coastguard Worker filter.id_dst_mask))
895*de1e4e89SAndroid Build Coastguard Worker return 0;
896*de1e4e89SAndroid Build Coastguard Worker if ((xsinfo->id.proto^filter.xsinfo.id.proto)&filter.id_proto_mask)
897*de1e4e89SAndroid Build Coastguard Worker return 0;
898*de1e4e89SAndroid Build Coastguard Worker if ((xsinfo->id.spi^filter.xsinfo.id.spi)&filter.id_spi_mask)
899*de1e4e89SAndroid Build Coastguard Worker return 0;
900*de1e4e89SAndroid Build Coastguard Worker if ((xsinfo->mode^filter.xsinfo.mode)&filter.mode_mask)
901*de1e4e89SAndroid Build Coastguard Worker return 0;
902*de1e4e89SAndroid Build Coastguard Worker if ((xsinfo->reqid^filter.xsinfo.reqid)&filter.reqid_mask)
903*de1e4e89SAndroid Build Coastguard Worker return 0;
904*de1e4e89SAndroid Build Coastguard Worker if (filter.state_flags_mask)
905*de1e4e89SAndroid Build Coastguard Worker if ((xsinfo->flags & filter.xsinfo.flags) == 0)
906*de1e4e89SAndroid Build Coastguard Worker return 0;
907*de1e4e89SAndroid Build Coastguard Worker
908*de1e4e89SAndroid Build Coastguard Worker return 1;
909*de1e4e89SAndroid Build Coastguard Worker }
910*de1e4e89SAndroid Build Coastguard Worker
xfrm_state_print(const struct sockaddr_nl * who,struct nlmsghdr * n,void * arg)911*de1e4e89SAndroid Build Coastguard Worker int xfrm_state_print(const struct sockaddr_nl *who, struct nlmsghdr *n,
912*de1e4e89SAndroid Build Coastguard Worker void *arg)
913*de1e4e89SAndroid Build Coastguard Worker {
914*de1e4e89SAndroid Build Coastguard Worker FILE *fp = (FILE *)arg;
915*de1e4e89SAndroid Build Coastguard Worker struct rtattr *tb[XFRMA_MAX+1];
916*de1e4e89SAndroid Build Coastguard Worker struct rtattr *rta;
917*de1e4e89SAndroid Build Coastguard Worker struct xfrm_usersa_info *xsinfo = NULL;
918*de1e4e89SAndroid Build Coastguard Worker struct xfrm_user_expire *xexp = NULL;
919*de1e4e89SAndroid Build Coastguard Worker struct xfrm_usersa_id *xsid = NULL;
920*de1e4e89SAndroid Build Coastguard Worker int len = n->nlmsg_len;
921*de1e4e89SAndroid Build Coastguard Worker
922*de1e4e89SAndroid Build Coastguard Worker if (n->nlmsg_type != XFRM_MSG_NEWSA &&
923*de1e4e89SAndroid Build Coastguard Worker n->nlmsg_type != XFRM_MSG_DELSA &&
924*de1e4e89SAndroid Build Coastguard Worker n->nlmsg_type != XFRM_MSG_UPDSA &&
925*de1e4e89SAndroid Build Coastguard Worker n->nlmsg_type != XFRM_MSG_EXPIRE) {
926*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Not a state: %08x %08x %08x\n",
927*de1e4e89SAndroid Build Coastguard Worker n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
928*de1e4e89SAndroid Build Coastguard Worker return 0;
929*de1e4e89SAndroid Build Coastguard Worker }
930*de1e4e89SAndroid Build Coastguard Worker
931*de1e4e89SAndroid Build Coastguard Worker if (n->nlmsg_type == XFRM_MSG_DELSA) {
932*de1e4e89SAndroid Build Coastguard Worker /* Dont blame me for this .. Herbert made me do it */
933*de1e4e89SAndroid Build Coastguard Worker xsid = NLMSG_DATA(n);
934*de1e4e89SAndroid Build Coastguard Worker len -= NLMSG_SPACE(sizeof(*xsid));
935*de1e4e89SAndroid Build Coastguard Worker } else if (n->nlmsg_type == XFRM_MSG_EXPIRE) {
936*de1e4e89SAndroid Build Coastguard Worker xexp = NLMSG_DATA(n);
937*de1e4e89SAndroid Build Coastguard Worker xsinfo = &xexp->state;
938*de1e4e89SAndroid Build Coastguard Worker len -= NLMSG_SPACE(sizeof(*xexp));
939*de1e4e89SAndroid Build Coastguard Worker } else {
940*de1e4e89SAndroid Build Coastguard Worker xexp = NULL;
941*de1e4e89SAndroid Build Coastguard Worker xsinfo = NLMSG_DATA(n);
942*de1e4e89SAndroid Build Coastguard Worker len -= NLMSG_SPACE(sizeof(*xsinfo));
943*de1e4e89SAndroid Build Coastguard Worker }
944*de1e4e89SAndroid Build Coastguard Worker
945*de1e4e89SAndroid Build Coastguard Worker if (len < 0) {
946*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
947*de1e4e89SAndroid Build Coastguard Worker return -1;
948*de1e4e89SAndroid Build Coastguard Worker }
949*de1e4e89SAndroid Build Coastguard Worker
950*de1e4e89SAndroid Build Coastguard Worker if (xsinfo && !xfrm_state_filter_match(xsinfo))
951*de1e4e89SAndroid Build Coastguard Worker return 0;
952*de1e4e89SAndroid Build Coastguard Worker
953*de1e4e89SAndroid Build Coastguard Worker if (n->nlmsg_type == XFRM_MSG_DELSA)
954*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "Deleted ");
955*de1e4e89SAndroid Build Coastguard Worker else if (n->nlmsg_type == XFRM_MSG_UPDSA)
956*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "Updated ");
957*de1e4e89SAndroid Build Coastguard Worker else if (n->nlmsg_type == XFRM_MSG_EXPIRE)
958*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "Expired ");
959*de1e4e89SAndroid Build Coastguard Worker
960*de1e4e89SAndroid Build Coastguard Worker if (n->nlmsg_type == XFRM_MSG_DELSA)
961*de1e4e89SAndroid Build Coastguard Worker rta = XFRMSID_RTA(xsid);
962*de1e4e89SAndroid Build Coastguard Worker else if (n->nlmsg_type == XFRM_MSG_EXPIRE)
963*de1e4e89SAndroid Build Coastguard Worker rta = XFRMEXP_RTA(xexp);
964*de1e4e89SAndroid Build Coastguard Worker else
965*de1e4e89SAndroid Build Coastguard Worker rta = XFRMS_RTA(xsinfo);
966*de1e4e89SAndroid Build Coastguard Worker
967*de1e4e89SAndroid Build Coastguard Worker parse_rtattr(tb, XFRMA_MAX, rta, len);
968*de1e4e89SAndroid Build Coastguard Worker
969*de1e4e89SAndroid Build Coastguard Worker if (n->nlmsg_type == XFRM_MSG_DELSA) {
970*de1e4e89SAndroid Build Coastguard Worker /* xfrm_policy_id_print(); */
971*de1e4e89SAndroid Build Coastguard Worker
972*de1e4e89SAndroid Build Coastguard Worker if (!tb[XFRMA_SA]) {
973*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Buggy XFRM_MSG_DELSA: no XFRMA_SA\n");
974*de1e4e89SAndroid Build Coastguard Worker return -1;
975*de1e4e89SAndroid Build Coastguard Worker }
976*de1e4e89SAndroid Build Coastguard Worker if (RTA_PAYLOAD(tb[XFRMA_SA]) < sizeof(*xsinfo)) {
977*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Buggy XFRM_MSG_DELPOLICY: too short XFRMA_POLICY len\n");
978*de1e4e89SAndroid Build Coastguard Worker return -1;
979*de1e4e89SAndroid Build Coastguard Worker }
980*de1e4e89SAndroid Build Coastguard Worker xsinfo = RTA_DATA(tb[XFRMA_SA]);
981*de1e4e89SAndroid Build Coastguard Worker }
982*de1e4e89SAndroid Build Coastguard Worker
983*de1e4e89SAndroid Build Coastguard Worker xfrm_state_info_print(xsinfo, tb, fp, NULL, NULL);
984*de1e4e89SAndroid Build Coastguard Worker
985*de1e4e89SAndroid Build Coastguard Worker if (n->nlmsg_type == XFRM_MSG_EXPIRE) {
986*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "\t");
987*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "hard %u", xexp->hard);
988*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "%s", _SL_);
989*de1e4e89SAndroid Build Coastguard Worker }
990*de1e4e89SAndroid Build Coastguard Worker
991*de1e4e89SAndroid Build Coastguard Worker if (oneline)
992*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "\n");
993*de1e4e89SAndroid Build Coastguard Worker fflush(fp);
994*de1e4e89SAndroid Build Coastguard Worker
995*de1e4e89SAndroid Build Coastguard Worker return 0;
996*de1e4e89SAndroid Build Coastguard Worker }
997*de1e4e89SAndroid Build Coastguard Worker
xfrm_state_get_or_delete(int argc,char ** argv,int delete)998*de1e4e89SAndroid Build Coastguard Worker static int xfrm_state_get_or_delete(int argc, char **argv, int delete)
999*de1e4e89SAndroid Build Coastguard Worker {
1000*de1e4e89SAndroid Build Coastguard Worker struct rtnl_handle rth;
1001*de1e4e89SAndroid Build Coastguard Worker struct {
1002*de1e4e89SAndroid Build Coastguard Worker struct nlmsghdr n;
1003*de1e4e89SAndroid Build Coastguard Worker struct xfrm_usersa_id xsid;
1004*de1e4e89SAndroid Build Coastguard Worker char buf[RTA_BUF_SIZE];
1005*de1e4e89SAndroid Build Coastguard Worker } req = {
1006*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xsid)),
1007*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_flags = NLM_F_REQUEST,
1008*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_type = delete ? XFRM_MSG_DELSA : XFRM_MSG_GETSA,
1009*de1e4e89SAndroid Build Coastguard Worker .xsid.family = preferred_family,
1010*de1e4e89SAndroid Build Coastguard Worker };
1011*de1e4e89SAndroid Build Coastguard Worker struct xfrm_id id;
1012*de1e4e89SAndroid Build Coastguard Worker char *idp = NULL;
1013*de1e4e89SAndroid Build Coastguard Worker struct xfrm_mark mark = {0, 0};
1014*de1e4e89SAndroid Build Coastguard Worker
1015*de1e4e89SAndroid Build Coastguard Worker while (argc > 0) {
1016*de1e4e89SAndroid Build Coastguard Worker xfrm_address_t saddr;
1017*de1e4e89SAndroid Build Coastguard Worker
1018*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "mark") == 0) {
1019*de1e4e89SAndroid Build Coastguard Worker xfrm_parse_mark(&mark, &argc, &argv);
1020*de1e4e89SAndroid Build Coastguard Worker } else {
1021*de1e4e89SAndroid Build Coastguard Worker if (idp)
1022*de1e4e89SAndroid Build Coastguard Worker invarg("unknown", *argv);
1023*de1e4e89SAndroid Build Coastguard Worker idp = *argv;
1024*de1e4e89SAndroid Build Coastguard Worker
1025*de1e4e89SAndroid Build Coastguard Worker /* ID */
1026*de1e4e89SAndroid Build Coastguard Worker memset(&id, 0, sizeof(id));
1027*de1e4e89SAndroid Build Coastguard Worker memset(&saddr, 0, sizeof(saddr));
1028*de1e4e89SAndroid Build Coastguard Worker xfrm_id_parse(&saddr, &id, &req.xsid.family, 0,
1029*de1e4e89SAndroid Build Coastguard Worker &argc, &argv);
1030*de1e4e89SAndroid Build Coastguard Worker
1031*de1e4e89SAndroid Build Coastguard Worker memcpy(&req.xsid.daddr, &id.daddr, sizeof(req.xsid.daddr));
1032*de1e4e89SAndroid Build Coastguard Worker req.xsid.spi = id.spi;
1033*de1e4e89SAndroid Build Coastguard Worker req.xsid.proto = id.proto;
1034*de1e4e89SAndroid Build Coastguard Worker
1035*de1e4e89SAndroid Build Coastguard Worker addattr_l(&req.n, sizeof(req.buf), XFRMA_SRCADDR,
1036*de1e4e89SAndroid Build Coastguard Worker (void *)&saddr, sizeof(saddr));
1037*de1e4e89SAndroid Build Coastguard Worker }
1038*de1e4e89SAndroid Build Coastguard Worker
1039*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
1040*de1e4e89SAndroid Build Coastguard Worker }
1041*de1e4e89SAndroid Build Coastguard Worker
1042*de1e4e89SAndroid Build Coastguard Worker if (mark.m & mark.v) {
1043*de1e4e89SAndroid Build Coastguard Worker int r = addattr_l(&req.n, sizeof(req.buf), XFRMA_MARK,
1044*de1e4e89SAndroid Build Coastguard Worker (void *)&mark, sizeof(mark));
1045*de1e4e89SAndroid Build Coastguard Worker if (r < 0) {
1046*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "XFRMA_MARK failed\n");
1047*de1e4e89SAndroid Build Coastguard Worker exit(1);
1048*de1e4e89SAndroid Build Coastguard Worker }
1049*de1e4e89SAndroid Build Coastguard Worker }
1050*de1e4e89SAndroid Build Coastguard Worker
1051*de1e4e89SAndroid Build Coastguard Worker if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
1052*de1e4e89SAndroid Build Coastguard Worker exit(1);
1053*de1e4e89SAndroid Build Coastguard Worker
1054*de1e4e89SAndroid Build Coastguard Worker if (req.xsid.family == AF_UNSPEC)
1055*de1e4e89SAndroid Build Coastguard Worker req.xsid.family = AF_INET;
1056*de1e4e89SAndroid Build Coastguard Worker
1057*de1e4e89SAndroid Build Coastguard Worker if (delete) {
1058*de1e4e89SAndroid Build Coastguard Worker if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
1059*de1e4e89SAndroid Build Coastguard Worker exit(2);
1060*de1e4e89SAndroid Build Coastguard Worker } else {
1061*de1e4e89SAndroid Build Coastguard Worker char buf[NLMSG_BUF_SIZE] = {};
1062*de1e4e89SAndroid Build Coastguard Worker struct nlmsghdr *res_n = (struct nlmsghdr *)buf;
1063*de1e4e89SAndroid Build Coastguard Worker
1064*de1e4e89SAndroid Build Coastguard Worker if (rtnl_talk(&rth, &req.n, res_n, sizeof(req)) < 0)
1065*de1e4e89SAndroid Build Coastguard Worker exit(2);
1066*de1e4e89SAndroid Build Coastguard Worker
1067*de1e4e89SAndroid Build Coastguard Worker if (xfrm_state_print(NULL, res_n, (void *)stdout) < 0) {
1068*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "An error :-)\n");
1069*de1e4e89SAndroid Build Coastguard Worker exit(1);
1070*de1e4e89SAndroid Build Coastguard Worker }
1071*de1e4e89SAndroid Build Coastguard Worker }
1072*de1e4e89SAndroid Build Coastguard Worker
1073*de1e4e89SAndroid Build Coastguard Worker rtnl_close(&rth);
1074*de1e4e89SAndroid Build Coastguard Worker
1075*de1e4e89SAndroid Build Coastguard Worker return 0;
1076*de1e4e89SAndroid Build Coastguard Worker }
1077*de1e4e89SAndroid Build Coastguard Worker
1078*de1e4e89SAndroid Build Coastguard Worker /*
1079*de1e4e89SAndroid Build Coastguard Worker * With an existing state of nlmsg, make new nlmsg for deleting the state
1080*de1e4e89SAndroid Build Coastguard Worker * and store it to buffer.
1081*de1e4e89SAndroid Build Coastguard Worker */
xfrm_state_keep(const struct sockaddr_nl * who,struct nlmsghdr * n,void * arg)1082*de1e4e89SAndroid Build Coastguard Worker static int xfrm_state_keep(const struct sockaddr_nl *who,
1083*de1e4e89SAndroid Build Coastguard Worker struct nlmsghdr *n,
1084*de1e4e89SAndroid Build Coastguard Worker void *arg)
1085*de1e4e89SAndroid Build Coastguard Worker {
1086*de1e4e89SAndroid Build Coastguard Worker struct xfrm_buffer *xb = (struct xfrm_buffer *)arg;
1087*de1e4e89SAndroid Build Coastguard Worker struct rtnl_handle *rth = xb->rth;
1088*de1e4e89SAndroid Build Coastguard Worker struct xfrm_usersa_info *xsinfo = NLMSG_DATA(n);
1089*de1e4e89SAndroid Build Coastguard Worker int len = n->nlmsg_len;
1090*de1e4e89SAndroid Build Coastguard Worker struct nlmsghdr *new_n;
1091*de1e4e89SAndroid Build Coastguard Worker struct xfrm_usersa_id *xsid;
1092*de1e4e89SAndroid Build Coastguard Worker struct rtattr *tb[XFRMA_MAX+1];
1093*de1e4e89SAndroid Build Coastguard Worker
1094*de1e4e89SAndroid Build Coastguard Worker if (n->nlmsg_type != XFRM_MSG_NEWSA) {
1095*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Not a state: %08x %08x %08x\n",
1096*de1e4e89SAndroid Build Coastguard Worker n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
1097*de1e4e89SAndroid Build Coastguard Worker return 0;
1098*de1e4e89SAndroid Build Coastguard Worker }
1099*de1e4e89SAndroid Build Coastguard Worker
1100*de1e4e89SAndroid Build Coastguard Worker len -= NLMSG_LENGTH(sizeof(*xsinfo));
1101*de1e4e89SAndroid Build Coastguard Worker if (len < 0) {
1102*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
1103*de1e4e89SAndroid Build Coastguard Worker return -1;
1104*de1e4e89SAndroid Build Coastguard Worker }
1105*de1e4e89SAndroid Build Coastguard Worker
1106*de1e4e89SAndroid Build Coastguard Worker if (!xfrm_state_filter_match(xsinfo))
1107*de1e4e89SAndroid Build Coastguard Worker return 0;
1108*de1e4e89SAndroid Build Coastguard Worker
1109*de1e4e89SAndroid Build Coastguard Worker if (xb->offset > xb->size) {
1110*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "State buffer overflow\n");
1111*de1e4e89SAndroid Build Coastguard Worker return -1;
1112*de1e4e89SAndroid Build Coastguard Worker }
1113*de1e4e89SAndroid Build Coastguard Worker
1114*de1e4e89SAndroid Build Coastguard Worker new_n = (struct nlmsghdr *)(xb->buf + xb->offset);
1115*de1e4e89SAndroid Build Coastguard Worker new_n->nlmsg_len = NLMSG_LENGTH(sizeof(*xsid));
1116*de1e4e89SAndroid Build Coastguard Worker new_n->nlmsg_flags = NLM_F_REQUEST;
1117*de1e4e89SAndroid Build Coastguard Worker new_n->nlmsg_type = XFRM_MSG_DELSA;
1118*de1e4e89SAndroid Build Coastguard Worker new_n->nlmsg_seq = ++rth->seq;
1119*de1e4e89SAndroid Build Coastguard Worker
1120*de1e4e89SAndroid Build Coastguard Worker xsid = NLMSG_DATA(new_n);
1121*de1e4e89SAndroid Build Coastguard Worker xsid->family = xsinfo->family;
1122*de1e4e89SAndroid Build Coastguard Worker memcpy(&xsid->daddr, &xsinfo->id.daddr, sizeof(xsid->daddr));
1123*de1e4e89SAndroid Build Coastguard Worker xsid->spi = xsinfo->id.spi;
1124*de1e4e89SAndroid Build Coastguard Worker xsid->proto = xsinfo->id.proto;
1125*de1e4e89SAndroid Build Coastguard Worker
1126*de1e4e89SAndroid Build Coastguard Worker addattr_l(new_n, xb->size, XFRMA_SRCADDR, &xsinfo->saddr,
1127*de1e4e89SAndroid Build Coastguard Worker sizeof(xsid->daddr));
1128*de1e4e89SAndroid Build Coastguard Worker
1129*de1e4e89SAndroid Build Coastguard Worker parse_rtattr(tb, XFRMA_MAX, XFRMS_RTA(xsinfo), len);
1130*de1e4e89SAndroid Build Coastguard Worker
1131*de1e4e89SAndroid Build Coastguard Worker if (tb[XFRMA_MARK]) {
1132*de1e4e89SAndroid Build Coastguard Worker int r = addattr_l(new_n, xb->size, XFRMA_MARK,
1133*de1e4e89SAndroid Build Coastguard Worker (void *)RTA_DATA(tb[XFRMA_MARK]), tb[XFRMA_MARK]->rta_len);
1134*de1e4e89SAndroid Build Coastguard Worker if (r < 0) {
1135*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "%s: XFRMA_MARK failed\n", __func__);
1136*de1e4e89SAndroid Build Coastguard Worker exit(1);
1137*de1e4e89SAndroid Build Coastguard Worker }
1138*de1e4e89SAndroid Build Coastguard Worker }
1139*de1e4e89SAndroid Build Coastguard Worker
1140*de1e4e89SAndroid Build Coastguard Worker xb->offset += new_n->nlmsg_len;
1141*de1e4e89SAndroid Build Coastguard Worker xb->nlmsg_count++;
1142*de1e4e89SAndroid Build Coastguard Worker
1143*de1e4e89SAndroid Build Coastguard Worker return 0;
1144*de1e4e89SAndroid Build Coastguard Worker }
1145*de1e4e89SAndroid Build Coastguard Worker
xfrm_state_list_or_deleteall(int argc,char ** argv,int deleteall)1146*de1e4e89SAndroid Build Coastguard Worker static int xfrm_state_list_or_deleteall(int argc, char **argv, int deleteall)
1147*de1e4e89SAndroid Build Coastguard Worker {
1148*de1e4e89SAndroid Build Coastguard Worker char *idp = NULL;
1149*de1e4e89SAndroid Build Coastguard Worker struct rtnl_handle rth;
1150*de1e4e89SAndroid Build Coastguard Worker
1151*de1e4e89SAndroid Build Coastguard Worker if (argc > 0)
1152*de1e4e89SAndroid Build Coastguard Worker filter.use = 1;
1153*de1e4e89SAndroid Build Coastguard Worker filter.xsinfo.family = preferred_family;
1154*de1e4e89SAndroid Build Coastguard Worker
1155*de1e4e89SAndroid Build Coastguard Worker while (argc > 0) {
1156*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "mode") == 0) {
1157*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1158*de1e4e89SAndroid Build Coastguard Worker xfrm_mode_parse(&filter.xsinfo.mode, &argc, &argv);
1159*de1e4e89SAndroid Build Coastguard Worker
1160*de1e4e89SAndroid Build Coastguard Worker filter.mode_mask = XFRM_FILTER_MASK_FULL;
1161*de1e4e89SAndroid Build Coastguard Worker
1162*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "reqid") == 0) {
1163*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1164*de1e4e89SAndroid Build Coastguard Worker xfrm_reqid_parse(&filter.xsinfo.reqid, &argc, &argv);
1165*de1e4e89SAndroid Build Coastguard Worker
1166*de1e4e89SAndroid Build Coastguard Worker filter.reqid_mask = XFRM_FILTER_MASK_FULL;
1167*de1e4e89SAndroid Build Coastguard Worker
1168*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "flag") == 0) {
1169*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1170*de1e4e89SAndroid Build Coastguard Worker xfrm_state_flag_parse(&filter.xsinfo.flags, &argc, &argv);
1171*de1e4e89SAndroid Build Coastguard Worker
1172*de1e4e89SAndroid Build Coastguard Worker filter.state_flags_mask = XFRM_FILTER_MASK_FULL;
1173*de1e4e89SAndroid Build Coastguard Worker
1174*de1e4e89SAndroid Build Coastguard Worker } else {
1175*de1e4e89SAndroid Build Coastguard Worker if (idp)
1176*de1e4e89SAndroid Build Coastguard Worker invarg("unknown", *argv);
1177*de1e4e89SAndroid Build Coastguard Worker idp = *argv;
1178*de1e4e89SAndroid Build Coastguard Worker
1179*de1e4e89SAndroid Build Coastguard Worker /* ID */
1180*de1e4e89SAndroid Build Coastguard Worker xfrm_id_parse(&filter.xsinfo.saddr, &filter.xsinfo.id,
1181*de1e4e89SAndroid Build Coastguard Worker &filter.xsinfo.family, 1, &argc, &argv);
1182*de1e4e89SAndroid Build Coastguard Worker if (preferred_family == AF_UNSPEC)
1183*de1e4e89SAndroid Build Coastguard Worker preferred_family = filter.xsinfo.family;
1184*de1e4e89SAndroid Build Coastguard Worker }
1185*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
1186*de1e4e89SAndroid Build Coastguard Worker }
1187*de1e4e89SAndroid Build Coastguard Worker
1188*de1e4e89SAndroid Build Coastguard Worker if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
1189*de1e4e89SAndroid Build Coastguard Worker exit(1);
1190*de1e4e89SAndroid Build Coastguard Worker
1191*de1e4e89SAndroid Build Coastguard Worker if (deleteall) {
1192*de1e4e89SAndroid Build Coastguard Worker struct xfrm_buffer xb;
1193*de1e4e89SAndroid Build Coastguard Worker char buf[NLMSG_DELETEALL_BUF_SIZE];
1194*de1e4e89SAndroid Build Coastguard Worker int i;
1195*de1e4e89SAndroid Build Coastguard Worker
1196*de1e4e89SAndroid Build Coastguard Worker xb.buf = buf;
1197*de1e4e89SAndroid Build Coastguard Worker xb.size = sizeof(buf);
1198*de1e4e89SAndroid Build Coastguard Worker xb.rth = &rth;
1199*de1e4e89SAndroid Build Coastguard Worker
1200*de1e4e89SAndroid Build Coastguard Worker for (i = 0; ; i++) {
1201*de1e4e89SAndroid Build Coastguard Worker struct {
1202*de1e4e89SAndroid Build Coastguard Worker struct nlmsghdr n;
1203*de1e4e89SAndroid Build Coastguard Worker char buf[NLMSG_BUF_SIZE];
1204*de1e4e89SAndroid Build Coastguard Worker } req = {
1205*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_len = NLMSG_HDRLEN,
1206*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
1207*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_type = XFRM_MSG_GETSA,
1208*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_seq = rth.dump = ++rth.seq,
1209*de1e4e89SAndroid Build Coastguard Worker };
1210*de1e4e89SAndroid Build Coastguard Worker
1211*de1e4e89SAndroid Build Coastguard Worker xb.offset = 0;
1212*de1e4e89SAndroid Build Coastguard Worker xb.nlmsg_count = 0;
1213*de1e4e89SAndroid Build Coastguard Worker
1214*de1e4e89SAndroid Build Coastguard Worker if (show_stats > 1)
1215*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Delete-all round = %d\n", i);
1216*de1e4e89SAndroid Build Coastguard Worker
1217*de1e4e89SAndroid Build Coastguard Worker if (rtnl_send(&rth, (void *)&req, req.n.nlmsg_len) < 0) {
1218*de1e4e89SAndroid Build Coastguard Worker perror("Cannot send dump request");
1219*de1e4e89SAndroid Build Coastguard Worker exit(1);
1220*de1e4e89SAndroid Build Coastguard Worker }
1221*de1e4e89SAndroid Build Coastguard Worker
1222*de1e4e89SAndroid Build Coastguard Worker if (rtnl_dump_filter(&rth, xfrm_state_keep, &xb) < 0) {
1223*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Delete-all terminated\n");
1224*de1e4e89SAndroid Build Coastguard Worker exit(1);
1225*de1e4e89SAndroid Build Coastguard Worker }
1226*de1e4e89SAndroid Build Coastguard Worker if (xb.nlmsg_count == 0) {
1227*de1e4e89SAndroid Build Coastguard Worker if (show_stats > 1)
1228*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Delete-all completed\n");
1229*de1e4e89SAndroid Build Coastguard Worker break;
1230*de1e4e89SAndroid Build Coastguard Worker }
1231*de1e4e89SAndroid Build Coastguard Worker
1232*de1e4e89SAndroid Build Coastguard Worker if (rtnl_send_check(&rth, xb.buf, xb.offset) < 0) {
1233*de1e4e89SAndroid Build Coastguard Worker perror("Failed to send delete-all request\n");
1234*de1e4e89SAndroid Build Coastguard Worker exit(1);
1235*de1e4e89SAndroid Build Coastguard Worker }
1236*de1e4e89SAndroid Build Coastguard Worker if (show_stats > 1)
1237*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Delete-all nlmsg count = %d\n", xb.nlmsg_count);
1238*de1e4e89SAndroid Build Coastguard Worker
1239*de1e4e89SAndroid Build Coastguard Worker xb.offset = 0;
1240*de1e4e89SAndroid Build Coastguard Worker xb.nlmsg_count = 0;
1241*de1e4e89SAndroid Build Coastguard Worker }
1242*de1e4e89SAndroid Build Coastguard Worker
1243*de1e4e89SAndroid Build Coastguard Worker } else {
1244*de1e4e89SAndroid Build Coastguard Worker struct xfrm_address_filter addrfilter = {
1245*de1e4e89SAndroid Build Coastguard Worker .saddr = filter.xsinfo.saddr,
1246*de1e4e89SAndroid Build Coastguard Worker .daddr = filter.xsinfo.id.daddr,
1247*de1e4e89SAndroid Build Coastguard Worker .family = filter.xsinfo.family,
1248*de1e4e89SAndroid Build Coastguard Worker .splen = filter.id_src_mask,
1249*de1e4e89SAndroid Build Coastguard Worker .dplen = filter.id_dst_mask,
1250*de1e4e89SAndroid Build Coastguard Worker };
1251*de1e4e89SAndroid Build Coastguard Worker struct {
1252*de1e4e89SAndroid Build Coastguard Worker struct nlmsghdr n;
1253*de1e4e89SAndroid Build Coastguard Worker char buf[NLMSG_BUF_SIZE];
1254*de1e4e89SAndroid Build Coastguard Worker } req = {
1255*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_len = NLMSG_HDRLEN,
1256*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
1257*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_type = XFRM_MSG_GETSA,
1258*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_seq = rth.dump = ++rth.seq,
1259*de1e4e89SAndroid Build Coastguard Worker };
1260*de1e4e89SAndroid Build Coastguard Worker
1261*de1e4e89SAndroid Build Coastguard Worker if (filter.xsinfo.id.proto)
1262*de1e4e89SAndroid Build Coastguard Worker addattr8(&req.n, sizeof(req), XFRMA_PROTO,
1263*de1e4e89SAndroid Build Coastguard Worker filter.xsinfo.id.proto);
1264*de1e4e89SAndroid Build Coastguard Worker addattr_l(&req.n, sizeof(req), XFRMA_ADDRESS_FILTER,
1265*de1e4e89SAndroid Build Coastguard Worker &addrfilter, sizeof(addrfilter));
1266*de1e4e89SAndroid Build Coastguard Worker
1267*de1e4e89SAndroid Build Coastguard Worker if (rtnl_send(&rth, (void *)&req, req.n.nlmsg_len) < 0) {
1268*de1e4e89SAndroid Build Coastguard Worker perror("Cannot send dump request");
1269*de1e4e89SAndroid Build Coastguard Worker exit(1);
1270*de1e4e89SAndroid Build Coastguard Worker }
1271*de1e4e89SAndroid Build Coastguard Worker
1272*de1e4e89SAndroid Build Coastguard Worker if (rtnl_dump_filter(&rth, xfrm_state_print, stdout) < 0) {
1273*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Dump terminated\n");
1274*de1e4e89SAndroid Build Coastguard Worker exit(1);
1275*de1e4e89SAndroid Build Coastguard Worker }
1276*de1e4e89SAndroid Build Coastguard Worker }
1277*de1e4e89SAndroid Build Coastguard Worker
1278*de1e4e89SAndroid Build Coastguard Worker rtnl_close(&rth);
1279*de1e4e89SAndroid Build Coastguard Worker
1280*de1e4e89SAndroid Build Coastguard Worker exit(0);
1281*de1e4e89SAndroid Build Coastguard Worker }
1282*de1e4e89SAndroid Build Coastguard Worker
print_sadinfo(struct nlmsghdr * n,void * arg)1283*de1e4e89SAndroid Build Coastguard Worker static int print_sadinfo(struct nlmsghdr *n, void *arg)
1284*de1e4e89SAndroid Build Coastguard Worker {
1285*de1e4e89SAndroid Build Coastguard Worker FILE *fp = (FILE *)arg;
1286*de1e4e89SAndroid Build Coastguard Worker __u32 *f = NLMSG_DATA(n);
1287*de1e4e89SAndroid Build Coastguard Worker struct rtattr *tb[XFRMA_SAD_MAX+1];
1288*de1e4e89SAndroid Build Coastguard Worker struct rtattr *rta;
1289*de1e4e89SAndroid Build Coastguard Worker int len = n->nlmsg_len;
1290*de1e4e89SAndroid Build Coastguard Worker
1291*de1e4e89SAndroid Build Coastguard Worker len -= NLMSG_LENGTH(sizeof(__u32));
1292*de1e4e89SAndroid Build Coastguard Worker if (len < 0) {
1293*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "SADinfo: Wrong len %d\n", len);
1294*de1e4e89SAndroid Build Coastguard Worker return -1;
1295*de1e4e89SAndroid Build Coastguard Worker }
1296*de1e4e89SAndroid Build Coastguard Worker
1297*de1e4e89SAndroid Build Coastguard Worker rta = XFRMSAPD_RTA(f);
1298*de1e4e89SAndroid Build Coastguard Worker parse_rtattr(tb, XFRMA_SAD_MAX, rta, len);
1299*de1e4e89SAndroid Build Coastguard Worker
1300*de1e4e89SAndroid Build Coastguard Worker if (tb[XFRMA_SAD_CNT]) {
1301*de1e4e89SAndroid Build Coastguard Worker __u32 cnt;
1302*de1e4e89SAndroid Build Coastguard Worker
1303*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "\t SAD");
1304*de1e4e89SAndroid Build Coastguard Worker cnt = rta_getattr_u32(tb[XFRMA_SAD_CNT]);
1305*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, " count %u", cnt);
1306*de1e4e89SAndroid Build Coastguard Worker } else {
1307*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "BAD SAD info returned\n");
1308*de1e4e89SAndroid Build Coastguard Worker return -1;
1309*de1e4e89SAndroid Build Coastguard Worker }
1310*de1e4e89SAndroid Build Coastguard Worker
1311*de1e4e89SAndroid Build Coastguard Worker if (show_stats) {
1312*de1e4e89SAndroid Build Coastguard Worker if (tb[XFRMA_SAD_HINFO]) {
1313*de1e4e89SAndroid Build Coastguard Worker struct xfrmu_sadhinfo *si;
1314*de1e4e89SAndroid Build Coastguard Worker
1315*de1e4e89SAndroid Build Coastguard Worker if (RTA_PAYLOAD(tb[XFRMA_SAD_HINFO]) < sizeof(*si)) {
1316*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "BAD SAD length returned\n");
1317*de1e4e89SAndroid Build Coastguard Worker return -1;
1318*de1e4e89SAndroid Build Coastguard Worker }
1319*de1e4e89SAndroid Build Coastguard Worker
1320*de1e4e89SAndroid Build Coastguard Worker si = RTA_DATA(tb[XFRMA_SAD_HINFO]);
1321*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, " (buckets ");
1322*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "count %d", si->sadhcnt);
1323*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, " Max %d", si->sadhmcnt);
1324*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, ")");
1325*de1e4e89SAndroid Build Coastguard Worker }
1326*de1e4e89SAndroid Build Coastguard Worker }
1327*de1e4e89SAndroid Build Coastguard Worker fprintf(fp, "\n");
1328*de1e4e89SAndroid Build Coastguard Worker
1329*de1e4e89SAndroid Build Coastguard Worker return 0;
1330*de1e4e89SAndroid Build Coastguard Worker }
1331*de1e4e89SAndroid Build Coastguard Worker
xfrm_sad_getinfo(int argc,char ** argv)1332*de1e4e89SAndroid Build Coastguard Worker static int xfrm_sad_getinfo(int argc, char **argv)
1333*de1e4e89SAndroid Build Coastguard Worker {
1334*de1e4e89SAndroid Build Coastguard Worker struct rtnl_handle rth;
1335*de1e4e89SAndroid Build Coastguard Worker struct {
1336*de1e4e89SAndroid Build Coastguard Worker struct nlmsghdr n;
1337*de1e4e89SAndroid Build Coastguard Worker __u32 flags;
1338*de1e4e89SAndroid Build Coastguard Worker char ans[64];
1339*de1e4e89SAndroid Build Coastguard Worker } req = {
1340*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_len = NLMSG_LENGTH(sizeof(req.flags)),
1341*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_flags = NLM_F_REQUEST,
1342*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_type = XFRM_MSG_GETSADINFO,
1343*de1e4e89SAndroid Build Coastguard Worker .flags = 0XFFFFFFFF,
1344*de1e4e89SAndroid Build Coastguard Worker };
1345*de1e4e89SAndroid Build Coastguard Worker
1346*de1e4e89SAndroid Build Coastguard Worker if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
1347*de1e4e89SAndroid Build Coastguard Worker exit(1);
1348*de1e4e89SAndroid Build Coastguard Worker
1349*de1e4e89SAndroid Build Coastguard Worker if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0)
1350*de1e4e89SAndroid Build Coastguard Worker exit(2);
1351*de1e4e89SAndroid Build Coastguard Worker
1352*de1e4e89SAndroid Build Coastguard Worker print_sadinfo(&req.n, (void *)stdout);
1353*de1e4e89SAndroid Build Coastguard Worker
1354*de1e4e89SAndroid Build Coastguard Worker rtnl_close(&rth);
1355*de1e4e89SAndroid Build Coastguard Worker
1356*de1e4e89SAndroid Build Coastguard Worker return 0;
1357*de1e4e89SAndroid Build Coastguard Worker }
1358*de1e4e89SAndroid Build Coastguard Worker
xfrm_state_flush(int argc,char ** argv)1359*de1e4e89SAndroid Build Coastguard Worker static int xfrm_state_flush(int argc, char **argv)
1360*de1e4e89SAndroid Build Coastguard Worker {
1361*de1e4e89SAndroid Build Coastguard Worker struct rtnl_handle rth;
1362*de1e4e89SAndroid Build Coastguard Worker struct {
1363*de1e4e89SAndroid Build Coastguard Worker struct nlmsghdr n;
1364*de1e4e89SAndroid Build Coastguard Worker struct xfrm_usersa_flush xsf;
1365*de1e4e89SAndroid Build Coastguard Worker } req = {
1366*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xsf)),
1367*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_flags = NLM_F_REQUEST,
1368*de1e4e89SAndroid Build Coastguard Worker .n.nlmsg_type = XFRM_MSG_FLUSHSA,
1369*de1e4e89SAndroid Build Coastguard Worker };
1370*de1e4e89SAndroid Build Coastguard Worker char *protop = NULL;
1371*de1e4e89SAndroid Build Coastguard Worker
1372*de1e4e89SAndroid Build Coastguard Worker while (argc > 0) {
1373*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "proto") == 0) {
1374*de1e4e89SAndroid Build Coastguard Worker int ret;
1375*de1e4e89SAndroid Build Coastguard Worker
1376*de1e4e89SAndroid Build Coastguard Worker if (protop)
1377*de1e4e89SAndroid Build Coastguard Worker duparg("proto", *argv);
1378*de1e4e89SAndroid Build Coastguard Worker protop = *argv;
1379*de1e4e89SAndroid Build Coastguard Worker
1380*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1381*de1e4e89SAndroid Build Coastguard Worker
1382*de1e4e89SAndroid Build Coastguard Worker ret = xfrm_xfrmproto_getbyname(*argv);
1383*de1e4e89SAndroid Build Coastguard Worker if (ret < 0)
1384*de1e4e89SAndroid Build Coastguard Worker invarg("XFRM-PROTO value is invalid", *argv);
1385*de1e4e89SAndroid Build Coastguard Worker
1386*de1e4e89SAndroid Build Coastguard Worker req.xsf.proto = (__u8)ret;
1387*de1e4e89SAndroid Build Coastguard Worker } else
1388*de1e4e89SAndroid Build Coastguard Worker invarg("unknown", *argv);
1389*de1e4e89SAndroid Build Coastguard Worker
1390*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
1391*de1e4e89SAndroid Build Coastguard Worker }
1392*de1e4e89SAndroid Build Coastguard Worker
1393*de1e4e89SAndroid Build Coastguard Worker if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
1394*de1e4e89SAndroid Build Coastguard Worker exit(1);
1395*de1e4e89SAndroid Build Coastguard Worker
1396*de1e4e89SAndroid Build Coastguard Worker if (show_stats > 1)
1397*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Flush state with XFRM-PROTO value \"%s\"\n",
1398*de1e4e89SAndroid Build Coastguard Worker strxf_xfrmproto(req.xsf.proto));
1399*de1e4e89SAndroid Build Coastguard Worker
1400*de1e4e89SAndroid Build Coastguard Worker if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
1401*de1e4e89SAndroid Build Coastguard Worker exit(2);
1402*de1e4e89SAndroid Build Coastguard Worker
1403*de1e4e89SAndroid Build Coastguard Worker rtnl_close(&rth);
1404*de1e4e89SAndroid Build Coastguard Worker
1405*de1e4e89SAndroid Build Coastguard Worker return 0;
1406*de1e4e89SAndroid Build Coastguard Worker }
1407*de1e4e89SAndroid Build Coastguard Worker
do_xfrm_state(int argc,char ** argv)1408*de1e4e89SAndroid Build Coastguard Worker int do_xfrm_state(int argc, char **argv)
1409*de1e4e89SAndroid Build Coastguard Worker {
1410*de1e4e89SAndroid Build Coastguard Worker if (argc < 1)
1411*de1e4e89SAndroid Build Coastguard Worker return xfrm_state_list_or_deleteall(0, NULL, 0);
1412*de1e4e89SAndroid Build Coastguard Worker
1413*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "add") == 0)
1414*de1e4e89SAndroid Build Coastguard Worker return xfrm_state_modify(XFRM_MSG_NEWSA, 0,
1415*de1e4e89SAndroid Build Coastguard Worker argc-1, argv+1);
1416*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "update") == 0)
1417*de1e4e89SAndroid Build Coastguard Worker return xfrm_state_modify(XFRM_MSG_UPDSA, 0,
1418*de1e4e89SAndroid Build Coastguard Worker argc-1, argv+1);
1419*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "allocspi") == 0)
1420*de1e4e89SAndroid Build Coastguard Worker return xfrm_state_allocspi(argc-1, argv+1);
1421*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "delete") == 0)
1422*de1e4e89SAndroid Build Coastguard Worker return xfrm_state_get_or_delete(argc-1, argv+1, 1);
1423*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "deleteall") == 0 || matches(*argv, "delall") == 0)
1424*de1e4e89SAndroid Build Coastguard Worker return xfrm_state_list_or_deleteall(argc-1, argv+1, 1);
1425*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0
1426*de1e4e89SAndroid Build Coastguard Worker || matches(*argv, "lst") == 0)
1427*de1e4e89SAndroid Build Coastguard Worker return xfrm_state_list_or_deleteall(argc-1, argv+1, 0);
1428*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "get") == 0)
1429*de1e4e89SAndroid Build Coastguard Worker return xfrm_state_get_or_delete(argc-1, argv+1, 0);
1430*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "flush") == 0)
1431*de1e4e89SAndroid Build Coastguard Worker return xfrm_state_flush(argc-1, argv+1);
1432*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "count") == 0) {
1433*de1e4e89SAndroid Build Coastguard Worker return xfrm_sad_getinfo(argc, argv);
1434*de1e4e89SAndroid Build Coastguard Worker }
1435*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "help") == 0)
1436*de1e4e89SAndroid Build Coastguard Worker usage();
1437*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Command \"%s\" is unknown, try \"ip xfrm state help\".\n", *argv);
1438*de1e4e89SAndroid Build Coastguard Worker exit(-1);
1439*de1e4e89SAndroid Build Coastguard Worker }
1440