1*053f45beSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0
2*053f45beSAndroid Build Coastguard Worker /*
3*053f45beSAndroid Build Coastguard Worker * ipsec.c - Check xfrm on veth inside a net-ns.
4*053f45beSAndroid Build Coastguard Worker * Copyright (c) 2018 Dmitry Safonov
5*053f45beSAndroid Build Coastguard Worker */
6*053f45beSAndroid Build Coastguard Worker
7*053f45beSAndroid Build Coastguard Worker #define _GNU_SOURCE
8*053f45beSAndroid Build Coastguard Worker
9*053f45beSAndroid Build Coastguard Worker #include <arpa/inet.h>
10*053f45beSAndroid Build Coastguard Worker #include <asm/types.h>
11*053f45beSAndroid Build Coastguard Worker #include <errno.h>
12*053f45beSAndroid Build Coastguard Worker #include <fcntl.h>
13*053f45beSAndroid Build Coastguard Worker #include <limits.h>
14*053f45beSAndroid Build Coastguard Worker #include <linux/limits.h>
15*053f45beSAndroid Build Coastguard Worker #include <linux/netlink.h>
16*053f45beSAndroid Build Coastguard Worker #include <linux/random.h>
17*053f45beSAndroid Build Coastguard Worker #include <linux/rtnetlink.h>
18*053f45beSAndroid Build Coastguard Worker #include <linux/veth.h>
19*053f45beSAndroid Build Coastguard Worker #include <linux/xfrm.h>
20*053f45beSAndroid Build Coastguard Worker #include <netinet/in.h>
21*053f45beSAndroid Build Coastguard Worker #include <net/if.h>
22*053f45beSAndroid Build Coastguard Worker #include <sched.h>
23*053f45beSAndroid Build Coastguard Worker #include <stdbool.h>
24*053f45beSAndroid Build Coastguard Worker #include <stdint.h>
25*053f45beSAndroid Build Coastguard Worker #include <stdio.h>
26*053f45beSAndroid Build Coastguard Worker #include <stdlib.h>
27*053f45beSAndroid Build Coastguard Worker #include <string.h>
28*053f45beSAndroid Build Coastguard Worker #include <sys/mman.h>
29*053f45beSAndroid Build Coastguard Worker #include <sys/socket.h>
30*053f45beSAndroid Build Coastguard Worker #include <sys/stat.h>
31*053f45beSAndroid Build Coastguard Worker #include <sys/syscall.h>
32*053f45beSAndroid Build Coastguard Worker #include <sys/types.h>
33*053f45beSAndroid Build Coastguard Worker #include <sys/wait.h>
34*053f45beSAndroid Build Coastguard Worker #include <time.h>
35*053f45beSAndroid Build Coastguard Worker #include <unistd.h>
36*053f45beSAndroid Build Coastguard Worker
37*053f45beSAndroid Build Coastguard Worker #include "../kselftest.h"
38*053f45beSAndroid Build Coastguard Worker
39*053f45beSAndroid Build Coastguard Worker #define printk(fmt, ...) \
40*053f45beSAndroid Build Coastguard Worker ksft_print_msg("%d[%u] " fmt "\n", getpid(), __LINE__, ##__VA_ARGS__)
41*053f45beSAndroid Build Coastguard Worker
42*053f45beSAndroid Build Coastguard Worker #define pr_err(fmt, ...) printk(fmt ": %m", ##__VA_ARGS__)
43*053f45beSAndroid Build Coastguard Worker
44*053f45beSAndroid Build Coastguard Worker #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
45*053f45beSAndroid Build Coastguard Worker
46*053f45beSAndroid Build Coastguard Worker #define IPV4_STR_SZ 16 /* xxx.xxx.xxx.xxx is longest + \0 */
47*053f45beSAndroid Build Coastguard Worker #define MAX_PAYLOAD 2048
48*053f45beSAndroid Build Coastguard Worker #define XFRM_ALGO_KEY_BUF_SIZE 512
49*053f45beSAndroid Build Coastguard Worker #define MAX_PROCESSES (1 << 14) /* /16 mask divided by /30 subnets */
50*053f45beSAndroid Build Coastguard Worker #define INADDR_A ((in_addr_t) 0x0a000000) /* 10.0.0.0 */
51*053f45beSAndroid Build Coastguard Worker #define INADDR_B ((in_addr_t) 0xc0a80000) /* 192.168.0.0 */
52*053f45beSAndroid Build Coastguard Worker
53*053f45beSAndroid Build Coastguard Worker /* /30 mask for one veth connection */
54*053f45beSAndroid Build Coastguard Worker #define PREFIX_LEN 30
55*053f45beSAndroid Build Coastguard Worker #define child_ip(nr) (4*nr + 1)
56*053f45beSAndroid Build Coastguard Worker #define grchild_ip(nr) (4*nr + 2)
57*053f45beSAndroid Build Coastguard Worker
58*053f45beSAndroid Build Coastguard Worker #define VETH_FMT "ktst-%d"
59*053f45beSAndroid Build Coastguard Worker #define VETH_LEN 12
60*053f45beSAndroid Build Coastguard Worker
61*053f45beSAndroid Build Coastguard Worker #define XFRM_ALGO_NR_KEYS 29
62*053f45beSAndroid Build Coastguard Worker
63*053f45beSAndroid Build Coastguard Worker static int nsfd_parent = -1;
64*053f45beSAndroid Build Coastguard Worker static int nsfd_childa = -1;
65*053f45beSAndroid Build Coastguard Worker static int nsfd_childb = -1;
66*053f45beSAndroid Build Coastguard Worker static long page_size;
67*053f45beSAndroid Build Coastguard Worker
68*053f45beSAndroid Build Coastguard Worker /*
69*053f45beSAndroid Build Coastguard Worker * ksft_cnt is static in kselftest, so isn't shared with children.
70*053f45beSAndroid Build Coastguard Worker * We have to send a test result back to parent and count there.
71*053f45beSAndroid Build Coastguard Worker * results_fd is a pipe with test feedback from children.
72*053f45beSAndroid Build Coastguard Worker */
73*053f45beSAndroid Build Coastguard Worker static int results_fd[2];
74*053f45beSAndroid Build Coastguard Worker
75*053f45beSAndroid Build Coastguard Worker const unsigned int ping_delay_nsec = 50 * 1000 * 1000;
76*053f45beSAndroid Build Coastguard Worker const unsigned int ping_timeout = 300;
77*053f45beSAndroid Build Coastguard Worker const unsigned int ping_count = 100;
78*053f45beSAndroid Build Coastguard Worker const unsigned int ping_success = 80;
79*053f45beSAndroid Build Coastguard Worker
80*053f45beSAndroid Build Coastguard Worker struct xfrm_key_entry {
81*053f45beSAndroid Build Coastguard Worker char algo_name[35];
82*053f45beSAndroid Build Coastguard Worker int key_len;
83*053f45beSAndroid Build Coastguard Worker };
84*053f45beSAndroid Build Coastguard Worker
85*053f45beSAndroid Build Coastguard Worker struct xfrm_key_entry xfrm_key_entries[] = {
86*053f45beSAndroid Build Coastguard Worker {"digest_null", 0},
87*053f45beSAndroid Build Coastguard Worker {"ecb(cipher_null)", 0},
88*053f45beSAndroid Build Coastguard Worker {"cbc(des)", 64},
89*053f45beSAndroid Build Coastguard Worker {"hmac(md5)", 128},
90*053f45beSAndroid Build Coastguard Worker {"cmac(aes)", 128},
91*053f45beSAndroid Build Coastguard Worker {"xcbc(aes)", 128},
92*053f45beSAndroid Build Coastguard Worker {"cbc(cast5)", 128},
93*053f45beSAndroid Build Coastguard Worker {"cbc(serpent)", 128},
94*053f45beSAndroid Build Coastguard Worker {"hmac(sha1)", 160},
95*053f45beSAndroid Build Coastguard Worker {"hmac(rmd160)", 160},
96*053f45beSAndroid Build Coastguard Worker {"cbc(des3_ede)", 192},
97*053f45beSAndroid Build Coastguard Worker {"hmac(sha256)", 256},
98*053f45beSAndroid Build Coastguard Worker {"cbc(aes)", 256},
99*053f45beSAndroid Build Coastguard Worker {"cbc(camellia)", 256},
100*053f45beSAndroid Build Coastguard Worker {"cbc(twofish)", 256},
101*053f45beSAndroid Build Coastguard Worker {"rfc3686(ctr(aes))", 288},
102*053f45beSAndroid Build Coastguard Worker {"hmac(sha384)", 384},
103*053f45beSAndroid Build Coastguard Worker {"cbc(blowfish)", 448},
104*053f45beSAndroid Build Coastguard Worker {"hmac(sha512)", 512},
105*053f45beSAndroid Build Coastguard Worker {"rfc4106(gcm(aes))-128", 160},
106*053f45beSAndroid Build Coastguard Worker {"rfc4543(gcm(aes))-128", 160},
107*053f45beSAndroid Build Coastguard Worker {"rfc4309(ccm(aes))-128", 152},
108*053f45beSAndroid Build Coastguard Worker {"rfc4106(gcm(aes))-192", 224},
109*053f45beSAndroid Build Coastguard Worker {"rfc4543(gcm(aes))-192", 224},
110*053f45beSAndroid Build Coastguard Worker {"rfc4309(ccm(aes))-192", 216},
111*053f45beSAndroid Build Coastguard Worker {"rfc4106(gcm(aes))-256", 288},
112*053f45beSAndroid Build Coastguard Worker {"rfc4543(gcm(aes))-256", 288},
113*053f45beSAndroid Build Coastguard Worker {"rfc4309(ccm(aes))-256", 280},
114*053f45beSAndroid Build Coastguard Worker {"rfc7539(chacha20,poly1305)-128", 0}
115*053f45beSAndroid Build Coastguard Worker };
116*053f45beSAndroid Build Coastguard Worker
randomize_buffer(void * buf,size_t buflen)117*053f45beSAndroid Build Coastguard Worker static void randomize_buffer(void *buf, size_t buflen)
118*053f45beSAndroid Build Coastguard Worker {
119*053f45beSAndroid Build Coastguard Worker int *p = (int *)buf;
120*053f45beSAndroid Build Coastguard Worker size_t words = buflen / sizeof(int);
121*053f45beSAndroid Build Coastguard Worker size_t leftover = buflen % sizeof(int);
122*053f45beSAndroid Build Coastguard Worker
123*053f45beSAndroid Build Coastguard Worker if (!buflen)
124*053f45beSAndroid Build Coastguard Worker return;
125*053f45beSAndroid Build Coastguard Worker
126*053f45beSAndroid Build Coastguard Worker while (words--)
127*053f45beSAndroid Build Coastguard Worker *p++ = rand();
128*053f45beSAndroid Build Coastguard Worker
129*053f45beSAndroid Build Coastguard Worker if (leftover) {
130*053f45beSAndroid Build Coastguard Worker int tmp = rand();
131*053f45beSAndroid Build Coastguard Worker
132*053f45beSAndroid Build Coastguard Worker memcpy(buf + buflen - leftover, &tmp, leftover);
133*053f45beSAndroid Build Coastguard Worker }
134*053f45beSAndroid Build Coastguard Worker
135*053f45beSAndroid Build Coastguard Worker return;
136*053f45beSAndroid Build Coastguard Worker }
137*053f45beSAndroid Build Coastguard Worker
unshare_open(void)138*053f45beSAndroid Build Coastguard Worker static int unshare_open(void)
139*053f45beSAndroid Build Coastguard Worker {
140*053f45beSAndroid Build Coastguard Worker const char *netns_path = "/proc/self/ns/net";
141*053f45beSAndroid Build Coastguard Worker int fd;
142*053f45beSAndroid Build Coastguard Worker
143*053f45beSAndroid Build Coastguard Worker if (unshare(CLONE_NEWNET) != 0) {
144*053f45beSAndroid Build Coastguard Worker pr_err("unshare()");
145*053f45beSAndroid Build Coastguard Worker return -1;
146*053f45beSAndroid Build Coastguard Worker }
147*053f45beSAndroid Build Coastguard Worker
148*053f45beSAndroid Build Coastguard Worker fd = open(netns_path, O_RDONLY);
149*053f45beSAndroid Build Coastguard Worker if (fd <= 0) {
150*053f45beSAndroid Build Coastguard Worker pr_err("open(%s)", netns_path);
151*053f45beSAndroid Build Coastguard Worker return -1;
152*053f45beSAndroid Build Coastguard Worker }
153*053f45beSAndroid Build Coastguard Worker
154*053f45beSAndroid Build Coastguard Worker return fd;
155*053f45beSAndroid Build Coastguard Worker }
156*053f45beSAndroid Build Coastguard Worker
switch_ns(int fd)157*053f45beSAndroid Build Coastguard Worker static int switch_ns(int fd)
158*053f45beSAndroid Build Coastguard Worker {
159*053f45beSAndroid Build Coastguard Worker if (setns(fd, CLONE_NEWNET)) {
160*053f45beSAndroid Build Coastguard Worker pr_err("setns()");
161*053f45beSAndroid Build Coastguard Worker return -1;
162*053f45beSAndroid Build Coastguard Worker }
163*053f45beSAndroid Build Coastguard Worker return 0;
164*053f45beSAndroid Build Coastguard Worker }
165*053f45beSAndroid Build Coastguard Worker
166*053f45beSAndroid Build Coastguard Worker /*
167*053f45beSAndroid Build Coastguard Worker * Running the test inside a new parent net namespace to bother less
168*053f45beSAndroid Build Coastguard Worker * about cleanup on error-path.
169*053f45beSAndroid Build Coastguard Worker */
init_namespaces(void)170*053f45beSAndroid Build Coastguard Worker static int init_namespaces(void)
171*053f45beSAndroid Build Coastguard Worker {
172*053f45beSAndroid Build Coastguard Worker nsfd_parent = unshare_open();
173*053f45beSAndroid Build Coastguard Worker if (nsfd_parent <= 0)
174*053f45beSAndroid Build Coastguard Worker return -1;
175*053f45beSAndroid Build Coastguard Worker
176*053f45beSAndroid Build Coastguard Worker nsfd_childa = unshare_open();
177*053f45beSAndroid Build Coastguard Worker if (nsfd_childa <= 0)
178*053f45beSAndroid Build Coastguard Worker return -1;
179*053f45beSAndroid Build Coastguard Worker
180*053f45beSAndroid Build Coastguard Worker if (switch_ns(nsfd_parent))
181*053f45beSAndroid Build Coastguard Worker return -1;
182*053f45beSAndroid Build Coastguard Worker
183*053f45beSAndroid Build Coastguard Worker nsfd_childb = unshare_open();
184*053f45beSAndroid Build Coastguard Worker if (nsfd_childb <= 0)
185*053f45beSAndroid Build Coastguard Worker return -1;
186*053f45beSAndroid Build Coastguard Worker
187*053f45beSAndroid Build Coastguard Worker if (switch_ns(nsfd_parent))
188*053f45beSAndroid Build Coastguard Worker return -1;
189*053f45beSAndroid Build Coastguard Worker return 0;
190*053f45beSAndroid Build Coastguard Worker }
191*053f45beSAndroid Build Coastguard Worker
netlink_sock(int * sock,uint32_t * seq_nr,int proto)192*053f45beSAndroid Build Coastguard Worker static int netlink_sock(int *sock, uint32_t *seq_nr, int proto)
193*053f45beSAndroid Build Coastguard Worker {
194*053f45beSAndroid Build Coastguard Worker if (*sock > 0) {
195*053f45beSAndroid Build Coastguard Worker seq_nr++;
196*053f45beSAndroid Build Coastguard Worker return 0;
197*053f45beSAndroid Build Coastguard Worker }
198*053f45beSAndroid Build Coastguard Worker
199*053f45beSAndroid Build Coastguard Worker *sock = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, proto);
200*053f45beSAndroid Build Coastguard Worker if (*sock <= 0) {
201*053f45beSAndroid Build Coastguard Worker pr_err("socket(AF_NETLINK)");
202*053f45beSAndroid Build Coastguard Worker return -1;
203*053f45beSAndroid Build Coastguard Worker }
204*053f45beSAndroid Build Coastguard Worker
205*053f45beSAndroid Build Coastguard Worker randomize_buffer(seq_nr, sizeof(*seq_nr));
206*053f45beSAndroid Build Coastguard Worker
207*053f45beSAndroid Build Coastguard Worker return 0;
208*053f45beSAndroid Build Coastguard Worker }
209*053f45beSAndroid Build Coastguard Worker
rtattr_hdr(struct nlmsghdr * nh)210*053f45beSAndroid Build Coastguard Worker static inline struct rtattr *rtattr_hdr(struct nlmsghdr *nh)
211*053f45beSAndroid Build Coastguard Worker {
212*053f45beSAndroid Build Coastguard Worker return (struct rtattr *)((char *)(nh) + RTA_ALIGN((nh)->nlmsg_len));
213*053f45beSAndroid Build Coastguard Worker }
214*053f45beSAndroid Build Coastguard Worker
rtattr_pack(struct nlmsghdr * nh,size_t req_sz,unsigned short rta_type,const void * payload,size_t size)215*053f45beSAndroid Build Coastguard Worker static int rtattr_pack(struct nlmsghdr *nh, size_t req_sz,
216*053f45beSAndroid Build Coastguard Worker unsigned short rta_type, const void *payload, size_t size)
217*053f45beSAndroid Build Coastguard Worker {
218*053f45beSAndroid Build Coastguard Worker /* NLMSG_ALIGNTO == RTA_ALIGNTO, nlmsg_len already aligned */
219*053f45beSAndroid Build Coastguard Worker struct rtattr *attr = rtattr_hdr(nh);
220*053f45beSAndroid Build Coastguard Worker size_t nl_size = RTA_ALIGN(nh->nlmsg_len) + RTA_LENGTH(size);
221*053f45beSAndroid Build Coastguard Worker
222*053f45beSAndroid Build Coastguard Worker if (req_sz < nl_size) {
223*053f45beSAndroid Build Coastguard Worker printk("req buf is too small: %zu < %zu", req_sz, nl_size);
224*053f45beSAndroid Build Coastguard Worker return -1;
225*053f45beSAndroid Build Coastguard Worker }
226*053f45beSAndroid Build Coastguard Worker nh->nlmsg_len = nl_size;
227*053f45beSAndroid Build Coastguard Worker
228*053f45beSAndroid Build Coastguard Worker attr->rta_len = RTA_LENGTH(size);
229*053f45beSAndroid Build Coastguard Worker attr->rta_type = rta_type;
230*053f45beSAndroid Build Coastguard Worker memcpy(RTA_DATA(attr), payload, size);
231*053f45beSAndroid Build Coastguard Worker
232*053f45beSAndroid Build Coastguard Worker return 0;
233*053f45beSAndroid Build Coastguard Worker }
234*053f45beSAndroid Build Coastguard Worker
_rtattr_begin(struct nlmsghdr * nh,size_t req_sz,unsigned short rta_type,const void * payload,size_t size)235*053f45beSAndroid Build Coastguard Worker static struct rtattr *_rtattr_begin(struct nlmsghdr *nh, size_t req_sz,
236*053f45beSAndroid Build Coastguard Worker unsigned short rta_type, const void *payload, size_t size)
237*053f45beSAndroid Build Coastguard Worker {
238*053f45beSAndroid Build Coastguard Worker struct rtattr *ret = rtattr_hdr(nh);
239*053f45beSAndroid Build Coastguard Worker
240*053f45beSAndroid Build Coastguard Worker if (rtattr_pack(nh, req_sz, rta_type, payload, size))
241*053f45beSAndroid Build Coastguard Worker return 0;
242*053f45beSAndroid Build Coastguard Worker
243*053f45beSAndroid Build Coastguard Worker return ret;
244*053f45beSAndroid Build Coastguard Worker }
245*053f45beSAndroid Build Coastguard Worker
rtattr_begin(struct nlmsghdr * nh,size_t req_sz,unsigned short rta_type)246*053f45beSAndroid Build Coastguard Worker static inline struct rtattr *rtattr_begin(struct nlmsghdr *nh, size_t req_sz,
247*053f45beSAndroid Build Coastguard Worker unsigned short rta_type)
248*053f45beSAndroid Build Coastguard Worker {
249*053f45beSAndroid Build Coastguard Worker return _rtattr_begin(nh, req_sz, rta_type, 0, 0);
250*053f45beSAndroid Build Coastguard Worker }
251*053f45beSAndroid Build Coastguard Worker
rtattr_end(struct nlmsghdr * nh,struct rtattr * attr)252*053f45beSAndroid Build Coastguard Worker static inline void rtattr_end(struct nlmsghdr *nh, struct rtattr *attr)
253*053f45beSAndroid Build Coastguard Worker {
254*053f45beSAndroid Build Coastguard Worker char *nlmsg_end = (char *)nh + nh->nlmsg_len;
255*053f45beSAndroid Build Coastguard Worker
256*053f45beSAndroid Build Coastguard Worker attr->rta_len = nlmsg_end - (char *)attr;
257*053f45beSAndroid Build Coastguard Worker }
258*053f45beSAndroid Build Coastguard Worker
veth_pack_peerb(struct nlmsghdr * nh,size_t req_sz,const char * peer,int ns)259*053f45beSAndroid Build Coastguard Worker static int veth_pack_peerb(struct nlmsghdr *nh, size_t req_sz,
260*053f45beSAndroid Build Coastguard Worker const char *peer, int ns)
261*053f45beSAndroid Build Coastguard Worker {
262*053f45beSAndroid Build Coastguard Worker struct ifinfomsg pi;
263*053f45beSAndroid Build Coastguard Worker struct rtattr *peer_attr;
264*053f45beSAndroid Build Coastguard Worker
265*053f45beSAndroid Build Coastguard Worker memset(&pi, 0, sizeof(pi));
266*053f45beSAndroid Build Coastguard Worker pi.ifi_family = AF_UNSPEC;
267*053f45beSAndroid Build Coastguard Worker pi.ifi_change = 0xFFFFFFFF;
268*053f45beSAndroid Build Coastguard Worker
269*053f45beSAndroid Build Coastguard Worker peer_attr = _rtattr_begin(nh, req_sz, VETH_INFO_PEER, &pi, sizeof(pi));
270*053f45beSAndroid Build Coastguard Worker if (!peer_attr)
271*053f45beSAndroid Build Coastguard Worker return -1;
272*053f45beSAndroid Build Coastguard Worker
273*053f45beSAndroid Build Coastguard Worker if (rtattr_pack(nh, req_sz, IFLA_IFNAME, peer, strlen(peer)))
274*053f45beSAndroid Build Coastguard Worker return -1;
275*053f45beSAndroid Build Coastguard Worker
276*053f45beSAndroid Build Coastguard Worker if (rtattr_pack(nh, req_sz, IFLA_NET_NS_FD, &ns, sizeof(ns)))
277*053f45beSAndroid Build Coastguard Worker return -1;
278*053f45beSAndroid Build Coastguard Worker
279*053f45beSAndroid Build Coastguard Worker rtattr_end(nh, peer_attr);
280*053f45beSAndroid Build Coastguard Worker
281*053f45beSAndroid Build Coastguard Worker return 0;
282*053f45beSAndroid Build Coastguard Worker }
283*053f45beSAndroid Build Coastguard Worker
netlink_check_answer(int sock)284*053f45beSAndroid Build Coastguard Worker static int netlink_check_answer(int sock)
285*053f45beSAndroid Build Coastguard Worker {
286*053f45beSAndroid Build Coastguard Worker struct nlmsgerror {
287*053f45beSAndroid Build Coastguard Worker struct nlmsghdr hdr;
288*053f45beSAndroid Build Coastguard Worker int error;
289*053f45beSAndroid Build Coastguard Worker struct nlmsghdr orig_msg;
290*053f45beSAndroid Build Coastguard Worker } answer;
291*053f45beSAndroid Build Coastguard Worker
292*053f45beSAndroid Build Coastguard Worker if (recv(sock, &answer, sizeof(answer), 0) < 0) {
293*053f45beSAndroid Build Coastguard Worker pr_err("recv()");
294*053f45beSAndroid Build Coastguard Worker return -1;
295*053f45beSAndroid Build Coastguard Worker } else if (answer.hdr.nlmsg_type != NLMSG_ERROR) {
296*053f45beSAndroid Build Coastguard Worker printk("expected NLMSG_ERROR, got %d", (int)answer.hdr.nlmsg_type);
297*053f45beSAndroid Build Coastguard Worker return -1;
298*053f45beSAndroid Build Coastguard Worker } else if (answer.error) {
299*053f45beSAndroid Build Coastguard Worker printk("NLMSG_ERROR: %d: %s",
300*053f45beSAndroid Build Coastguard Worker answer.error, strerror(-answer.error));
301*053f45beSAndroid Build Coastguard Worker return answer.error;
302*053f45beSAndroid Build Coastguard Worker }
303*053f45beSAndroid Build Coastguard Worker
304*053f45beSAndroid Build Coastguard Worker return 0;
305*053f45beSAndroid Build Coastguard Worker }
306*053f45beSAndroid Build Coastguard Worker
veth_add(int sock,uint32_t seq,const char * peera,int ns_a,const char * peerb,int ns_b)307*053f45beSAndroid Build Coastguard Worker static int veth_add(int sock, uint32_t seq, const char *peera, int ns_a,
308*053f45beSAndroid Build Coastguard Worker const char *peerb, int ns_b)
309*053f45beSAndroid Build Coastguard Worker {
310*053f45beSAndroid Build Coastguard Worker uint16_t flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE;
311*053f45beSAndroid Build Coastguard Worker struct {
312*053f45beSAndroid Build Coastguard Worker struct nlmsghdr nh;
313*053f45beSAndroid Build Coastguard Worker struct ifinfomsg info;
314*053f45beSAndroid Build Coastguard Worker char attrbuf[MAX_PAYLOAD];
315*053f45beSAndroid Build Coastguard Worker } req;
316*053f45beSAndroid Build Coastguard Worker const char veth_type[] = "veth";
317*053f45beSAndroid Build Coastguard Worker struct rtattr *link_info, *info_data;
318*053f45beSAndroid Build Coastguard Worker
319*053f45beSAndroid Build Coastguard Worker memset(&req, 0, sizeof(req));
320*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.info));
321*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_type = RTM_NEWLINK;
322*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_flags = flags;
323*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_seq = seq;
324*053f45beSAndroid Build Coastguard Worker req.info.ifi_family = AF_UNSPEC;
325*053f45beSAndroid Build Coastguard Worker req.info.ifi_change = 0xFFFFFFFF;
326*053f45beSAndroid Build Coastguard Worker
327*053f45beSAndroid Build Coastguard Worker if (rtattr_pack(&req.nh, sizeof(req), IFLA_IFNAME, peera, strlen(peera)))
328*053f45beSAndroid Build Coastguard Worker return -1;
329*053f45beSAndroid Build Coastguard Worker
330*053f45beSAndroid Build Coastguard Worker if (rtattr_pack(&req.nh, sizeof(req), IFLA_NET_NS_FD, &ns_a, sizeof(ns_a)))
331*053f45beSAndroid Build Coastguard Worker return -1;
332*053f45beSAndroid Build Coastguard Worker
333*053f45beSAndroid Build Coastguard Worker link_info = rtattr_begin(&req.nh, sizeof(req), IFLA_LINKINFO);
334*053f45beSAndroid Build Coastguard Worker if (!link_info)
335*053f45beSAndroid Build Coastguard Worker return -1;
336*053f45beSAndroid Build Coastguard Worker
337*053f45beSAndroid Build Coastguard Worker if (rtattr_pack(&req.nh, sizeof(req), IFLA_INFO_KIND, veth_type, sizeof(veth_type)))
338*053f45beSAndroid Build Coastguard Worker return -1;
339*053f45beSAndroid Build Coastguard Worker
340*053f45beSAndroid Build Coastguard Worker info_data = rtattr_begin(&req.nh, sizeof(req), IFLA_INFO_DATA);
341*053f45beSAndroid Build Coastguard Worker if (!info_data)
342*053f45beSAndroid Build Coastguard Worker return -1;
343*053f45beSAndroid Build Coastguard Worker
344*053f45beSAndroid Build Coastguard Worker if (veth_pack_peerb(&req.nh, sizeof(req), peerb, ns_b))
345*053f45beSAndroid Build Coastguard Worker return -1;
346*053f45beSAndroid Build Coastguard Worker
347*053f45beSAndroid Build Coastguard Worker rtattr_end(&req.nh, info_data);
348*053f45beSAndroid Build Coastguard Worker rtattr_end(&req.nh, link_info);
349*053f45beSAndroid Build Coastguard Worker
350*053f45beSAndroid Build Coastguard Worker if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) {
351*053f45beSAndroid Build Coastguard Worker pr_err("send()");
352*053f45beSAndroid Build Coastguard Worker return -1;
353*053f45beSAndroid Build Coastguard Worker }
354*053f45beSAndroid Build Coastguard Worker return netlink_check_answer(sock);
355*053f45beSAndroid Build Coastguard Worker }
356*053f45beSAndroid Build Coastguard Worker
ip4_addr_set(int sock,uint32_t seq,const char * intf,struct in_addr addr,uint8_t prefix)357*053f45beSAndroid Build Coastguard Worker static int ip4_addr_set(int sock, uint32_t seq, const char *intf,
358*053f45beSAndroid Build Coastguard Worker struct in_addr addr, uint8_t prefix)
359*053f45beSAndroid Build Coastguard Worker {
360*053f45beSAndroid Build Coastguard Worker uint16_t flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE;
361*053f45beSAndroid Build Coastguard Worker struct {
362*053f45beSAndroid Build Coastguard Worker struct nlmsghdr nh;
363*053f45beSAndroid Build Coastguard Worker struct ifaddrmsg info;
364*053f45beSAndroid Build Coastguard Worker char attrbuf[MAX_PAYLOAD];
365*053f45beSAndroid Build Coastguard Worker } req;
366*053f45beSAndroid Build Coastguard Worker
367*053f45beSAndroid Build Coastguard Worker memset(&req, 0, sizeof(req));
368*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.info));
369*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_type = RTM_NEWADDR;
370*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_flags = flags;
371*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_seq = seq;
372*053f45beSAndroid Build Coastguard Worker req.info.ifa_family = AF_INET;
373*053f45beSAndroid Build Coastguard Worker req.info.ifa_prefixlen = prefix;
374*053f45beSAndroid Build Coastguard Worker req.info.ifa_index = if_nametoindex(intf);
375*053f45beSAndroid Build Coastguard Worker
376*053f45beSAndroid Build Coastguard Worker #ifdef DEBUG
377*053f45beSAndroid Build Coastguard Worker {
378*053f45beSAndroid Build Coastguard Worker char addr_str[IPV4_STR_SZ] = {};
379*053f45beSAndroid Build Coastguard Worker
380*053f45beSAndroid Build Coastguard Worker strncpy(addr_str, inet_ntoa(addr), IPV4_STR_SZ - 1);
381*053f45beSAndroid Build Coastguard Worker
382*053f45beSAndroid Build Coastguard Worker printk("ip addr set %s", addr_str);
383*053f45beSAndroid Build Coastguard Worker }
384*053f45beSAndroid Build Coastguard Worker #endif
385*053f45beSAndroid Build Coastguard Worker
386*053f45beSAndroid Build Coastguard Worker if (rtattr_pack(&req.nh, sizeof(req), IFA_LOCAL, &addr, sizeof(addr)))
387*053f45beSAndroid Build Coastguard Worker return -1;
388*053f45beSAndroid Build Coastguard Worker
389*053f45beSAndroid Build Coastguard Worker if (rtattr_pack(&req.nh, sizeof(req), IFA_ADDRESS, &addr, sizeof(addr)))
390*053f45beSAndroid Build Coastguard Worker return -1;
391*053f45beSAndroid Build Coastguard Worker
392*053f45beSAndroid Build Coastguard Worker if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) {
393*053f45beSAndroid Build Coastguard Worker pr_err("send()");
394*053f45beSAndroid Build Coastguard Worker return -1;
395*053f45beSAndroid Build Coastguard Worker }
396*053f45beSAndroid Build Coastguard Worker return netlink_check_answer(sock);
397*053f45beSAndroid Build Coastguard Worker }
398*053f45beSAndroid Build Coastguard Worker
link_set_up(int sock,uint32_t seq,const char * intf)399*053f45beSAndroid Build Coastguard Worker static int link_set_up(int sock, uint32_t seq, const char *intf)
400*053f45beSAndroid Build Coastguard Worker {
401*053f45beSAndroid Build Coastguard Worker struct {
402*053f45beSAndroid Build Coastguard Worker struct nlmsghdr nh;
403*053f45beSAndroid Build Coastguard Worker struct ifinfomsg info;
404*053f45beSAndroid Build Coastguard Worker char attrbuf[MAX_PAYLOAD];
405*053f45beSAndroid Build Coastguard Worker } req;
406*053f45beSAndroid Build Coastguard Worker
407*053f45beSAndroid Build Coastguard Worker memset(&req, 0, sizeof(req));
408*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.info));
409*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_type = RTM_NEWLINK;
410*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
411*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_seq = seq;
412*053f45beSAndroid Build Coastguard Worker req.info.ifi_family = AF_UNSPEC;
413*053f45beSAndroid Build Coastguard Worker req.info.ifi_change = 0xFFFFFFFF;
414*053f45beSAndroid Build Coastguard Worker req.info.ifi_index = if_nametoindex(intf);
415*053f45beSAndroid Build Coastguard Worker req.info.ifi_flags = IFF_UP;
416*053f45beSAndroid Build Coastguard Worker req.info.ifi_change = IFF_UP;
417*053f45beSAndroid Build Coastguard Worker
418*053f45beSAndroid Build Coastguard Worker if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) {
419*053f45beSAndroid Build Coastguard Worker pr_err("send()");
420*053f45beSAndroid Build Coastguard Worker return -1;
421*053f45beSAndroid Build Coastguard Worker }
422*053f45beSAndroid Build Coastguard Worker return netlink_check_answer(sock);
423*053f45beSAndroid Build Coastguard Worker }
424*053f45beSAndroid Build Coastguard Worker
ip4_route_set(int sock,uint32_t seq,const char * intf,struct in_addr src,struct in_addr dst)425*053f45beSAndroid Build Coastguard Worker static int ip4_route_set(int sock, uint32_t seq, const char *intf,
426*053f45beSAndroid Build Coastguard Worker struct in_addr src, struct in_addr dst)
427*053f45beSAndroid Build Coastguard Worker {
428*053f45beSAndroid Build Coastguard Worker struct {
429*053f45beSAndroid Build Coastguard Worker struct nlmsghdr nh;
430*053f45beSAndroid Build Coastguard Worker struct rtmsg rt;
431*053f45beSAndroid Build Coastguard Worker char attrbuf[MAX_PAYLOAD];
432*053f45beSAndroid Build Coastguard Worker } req;
433*053f45beSAndroid Build Coastguard Worker unsigned int index = if_nametoindex(intf);
434*053f45beSAndroid Build Coastguard Worker
435*053f45beSAndroid Build Coastguard Worker memset(&req, 0, sizeof(req));
436*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.rt));
437*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_type = RTM_NEWROUTE;
438*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE;
439*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_seq = seq;
440*053f45beSAndroid Build Coastguard Worker req.rt.rtm_family = AF_INET;
441*053f45beSAndroid Build Coastguard Worker req.rt.rtm_dst_len = 32;
442*053f45beSAndroid Build Coastguard Worker req.rt.rtm_table = RT_TABLE_MAIN;
443*053f45beSAndroid Build Coastguard Worker req.rt.rtm_protocol = RTPROT_BOOT;
444*053f45beSAndroid Build Coastguard Worker req.rt.rtm_scope = RT_SCOPE_LINK;
445*053f45beSAndroid Build Coastguard Worker req.rt.rtm_type = RTN_UNICAST;
446*053f45beSAndroid Build Coastguard Worker
447*053f45beSAndroid Build Coastguard Worker if (rtattr_pack(&req.nh, sizeof(req), RTA_DST, &dst, sizeof(dst)))
448*053f45beSAndroid Build Coastguard Worker return -1;
449*053f45beSAndroid Build Coastguard Worker
450*053f45beSAndroid Build Coastguard Worker if (rtattr_pack(&req.nh, sizeof(req), RTA_PREFSRC, &src, sizeof(src)))
451*053f45beSAndroid Build Coastguard Worker return -1;
452*053f45beSAndroid Build Coastguard Worker
453*053f45beSAndroid Build Coastguard Worker if (rtattr_pack(&req.nh, sizeof(req), RTA_OIF, &index, sizeof(index)))
454*053f45beSAndroid Build Coastguard Worker return -1;
455*053f45beSAndroid Build Coastguard Worker
456*053f45beSAndroid Build Coastguard Worker if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) {
457*053f45beSAndroid Build Coastguard Worker pr_err("send()");
458*053f45beSAndroid Build Coastguard Worker return -1;
459*053f45beSAndroid Build Coastguard Worker }
460*053f45beSAndroid Build Coastguard Worker
461*053f45beSAndroid Build Coastguard Worker return netlink_check_answer(sock);
462*053f45beSAndroid Build Coastguard Worker }
463*053f45beSAndroid Build Coastguard Worker
tunnel_set_route(int route_sock,uint32_t * route_seq,char * veth,struct in_addr tunsrc,struct in_addr tundst)464*053f45beSAndroid Build Coastguard Worker static int tunnel_set_route(int route_sock, uint32_t *route_seq, char *veth,
465*053f45beSAndroid Build Coastguard Worker struct in_addr tunsrc, struct in_addr tundst)
466*053f45beSAndroid Build Coastguard Worker {
467*053f45beSAndroid Build Coastguard Worker if (ip4_addr_set(route_sock, (*route_seq)++, "lo",
468*053f45beSAndroid Build Coastguard Worker tunsrc, PREFIX_LEN)) {
469*053f45beSAndroid Build Coastguard Worker printk("Failed to set ipv4 addr");
470*053f45beSAndroid Build Coastguard Worker return -1;
471*053f45beSAndroid Build Coastguard Worker }
472*053f45beSAndroid Build Coastguard Worker
473*053f45beSAndroid Build Coastguard Worker if (ip4_route_set(route_sock, (*route_seq)++, veth, tunsrc, tundst)) {
474*053f45beSAndroid Build Coastguard Worker printk("Failed to set ipv4 route");
475*053f45beSAndroid Build Coastguard Worker return -1;
476*053f45beSAndroid Build Coastguard Worker }
477*053f45beSAndroid Build Coastguard Worker
478*053f45beSAndroid Build Coastguard Worker return 0;
479*053f45beSAndroid Build Coastguard Worker }
480*053f45beSAndroid Build Coastguard Worker
init_child(int nsfd,char * veth,unsigned int src,unsigned int dst)481*053f45beSAndroid Build Coastguard Worker static int init_child(int nsfd, char *veth, unsigned int src, unsigned int dst)
482*053f45beSAndroid Build Coastguard Worker {
483*053f45beSAndroid Build Coastguard Worker struct in_addr intsrc = inet_makeaddr(INADDR_B, src);
484*053f45beSAndroid Build Coastguard Worker struct in_addr tunsrc = inet_makeaddr(INADDR_A, src);
485*053f45beSAndroid Build Coastguard Worker struct in_addr tundst = inet_makeaddr(INADDR_A, dst);
486*053f45beSAndroid Build Coastguard Worker int route_sock = -1, ret = -1;
487*053f45beSAndroid Build Coastguard Worker uint32_t route_seq;
488*053f45beSAndroid Build Coastguard Worker
489*053f45beSAndroid Build Coastguard Worker if (switch_ns(nsfd))
490*053f45beSAndroid Build Coastguard Worker return -1;
491*053f45beSAndroid Build Coastguard Worker
492*053f45beSAndroid Build Coastguard Worker if (netlink_sock(&route_sock, &route_seq, NETLINK_ROUTE)) {
493*053f45beSAndroid Build Coastguard Worker printk("Failed to open netlink route socket in child");
494*053f45beSAndroid Build Coastguard Worker return -1;
495*053f45beSAndroid Build Coastguard Worker }
496*053f45beSAndroid Build Coastguard Worker
497*053f45beSAndroid Build Coastguard Worker if (ip4_addr_set(route_sock, route_seq++, veth, intsrc, PREFIX_LEN)) {
498*053f45beSAndroid Build Coastguard Worker printk("Failed to set ipv4 addr");
499*053f45beSAndroid Build Coastguard Worker goto err;
500*053f45beSAndroid Build Coastguard Worker }
501*053f45beSAndroid Build Coastguard Worker
502*053f45beSAndroid Build Coastguard Worker if (link_set_up(route_sock, route_seq++, veth)) {
503*053f45beSAndroid Build Coastguard Worker printk("Failed to bring up %s", veth);
504*053f45beSAndroid Build Coastguard Worker goto err;
505*053f45beSAndroid Build Coastguard Worker }
506*053f45beSAndroid Build Coastguard Worker
507*053f45beSAndroid Build Coastguard Worker if (tunnel_set_route(route_sock, &route_seq, veth, tunsrc, tundst)) {
508*053f45beSAndroid Build Coastguard Worker printk("Failed to add tunnel route on %s", veth);
509*053f45beSAndroid Build Coastguard Worker goto err;
510*053f45beSAndroid Build Coastguard Worker }
511*053f45beSAndroid Build Coastguard Worker ret = 0;
512*053f45beSAndroid Build Coastguard Worker
513*053f45beSAndroid Build Coastguard Worker err:
514*053f45beSAndroid Build Coastguard Worker close(route_sock);
515*053f45beSAndroid Build Coastguard Worker return ret;
516*053f45beSAndroid Build Coastguard Worker }
517*053f45beSAndroid Build Coastguard Worker
518*053f45beSAndroid Build Coastguard Worker #define ALGO_LEN 64
519*053f45beSAndroid Build Coastguard Worker enum desc_type {
520*053f45beSAndroid Build Coastguard Worker CREATE_TUNNEL = 0,
521*053f45beSAndroid Build Coastguard Worker ALLOCATE_SPI,
522*053f45beSAndroid Build Coastguard Worker MONITOR_ACQUIRE,
523*053f45beSAndroid Build Coastguard Worker EXPIRE_STATE,
524*053f45beSAndroid Build Coastguard Worker EXPIRE_POLICY,
525*053f45beSAndroid Build Coastguard Worker SPDINFO_ATTRS,
526*053f45beSAndroid Build Coastguard Worker };
527*053f45beSAndroid Build Coastguard Worker const char *desc_name[] = {
528*053f45beSAndroid Build Coastguard Worker "create tunnel",
529*053f45beSAndroid Build Coastguard Worker "alloc spi",
530*053f45beSAndroid Build Coastguard Worker "monitor acquire",
531*053f45beSAndroid Build Coastguard Worker "expire state",
532*053f45beSAndroid Build Coastguard Worker "expire policy",
533*053f45beSAndroid Build Coastguard Worker "spdinfo attributes",
534*053f45beSAndroid Build Coastguard Worker ""
535*053f45beSAndroid Build Coastguard Worker };
536*053f45beSAndroid Build Coastguard Worker struct xfrm_desc {
537*053f45beSAndroid Build Coastguard Worker enum desc_type type;
538*053f45beSAndroid Build Coastguard Worker uint8_t proto;
539*053f45beSAndroid Build Coastguard Worker char a_algo[ALGO_LEN];
540*053f45beSAndroid Build Coastguard Worker char e_algo[ALGO_LEN];
541*053f45beSAndroid Build Coastguard Worker char c_algo[ALGO_LEN];
542*053f45beSAndroid Build Coastguard Worker char ae_algo[ALGO_LEN];
543*053f45beSAndroid Build Coastguard Worker unsigned int icv_len;
544*053f45beSAndroid Build Coastguard Worker /* unsigned key_len; */
545*053f45beSAndroid Build Coastguard Worker };
546*053f45beSAndroid Build Coastguard Worker
547*053f45beSAndroid Build Coastguard Worker enum msg_type {
548*053f45beSAndroid Build Coastguard Worker MSG_ACK = 0,
549*053f45beSAndroid Build Coastguard Worker MSG_EXIT,
550*053f45beSAndroid Build Coastguard Worker MSG_PING,
551*053f45beSAndroid Build Coastguard Worker MSG_XFRM_PREPARE,
552*053f45beSAndroid Build Coastguard Worker MSG_XFRM_ADD,
553*053f45beSAndroid Build Coastguard Worker MSG_XFRM_DEL,
554*053f45beSAndroid Build Coastguard Worker MSG_XFRM_CLEANUP,
555*053f45beSAndroid Build Coastguard Worker };
556*053f45beSAndroid Build Coastguard Worker
557*053f45beSAndroid Build Coastguard Worker struct test_desc {
558*053f45beSAndroid Build Coastguard Worker enum msg_type type;
559*053f45beSAndroid Build Coastguard Worker union {
560*053f45beSAndroid Build Coastguard Worker struct {
561*053f45beSAndroid Build Coastguard Worker in_addr_t reply_ip;
562*053f45beSAndroid Build Coastguard Worker unsigned int port;
563*053f45beSAndroid Build Coastguard Worker } ping;
564*053f45beSAndroid Build Coastguard Worker struct xfrm_desc xfrm_desc;
565*053f45beSAndroid Build Coastguard Worker } body;
566*053f45beSAndroid Build Coastguard Worker };
567*053f45beSAndroid Build Coastguard Worker
568*053f45beSAndroid Build Coastguard Worker struct test_result {
569*053f45beSAndroid Build Coastguard Worker struct xfrm_desc desc;
570*053f45beSAndroid Build Coastguard Worker unsigned int res;
571*053f45beSAndroid Build Coastguard Worker };
572*053f45beSAndroid Build Coastguard Worker
write_test_result(unsigned int res,struct xfrm_desc * d)573*053f45beSAndroid Build Coastguard Worker static void write_test_result(unsigned int res, struct xfrm_desc *d)
574*053f45beSAndroid Build Coastguard Worker {
575*053f45beSAndroid Build Coastguard Worker struct test_result tr = {};
576*053f45beSAndroid Build Coastguard Worker ssize_t ret;
577*053f45beSAndroid Build Coastguard Worker
578*053f45beSAndroid Build Coastguard Worker tr.desc = *d;
579*053f45beSAndroid Build Coastguard Worker tr.res = res;
580*053f45beSAndroid Build Coastguard Worker
581*053f45beSAndroid Build Coastguard Worker ret = write(results_fd[1], &tr, sizeof(tr));
582*053f45beSAndroid Build Coastguard Worker if (ret != sizeof(tr))
583*053f45beSAndroid Build Coastguard Worker pr_err("Failed to write the result in pipe %zd", ret);
584*053f45beSAndroid Build Coastguard Worker }
585*053f45beSAndroid Build Coastguard Worker
write_msg(int fd,struct test_desc * msg,bool exit_of_fail)586*053f45beSAndroid Build Coastguard Worker static void write_msg(int fd, struct test_desc *msg, bool exit_of_fail)
587*053f45beSAndroid Build Coastguard Worker {
588*053f45beSAndroid Build Coastguard Worker ssize_t bytes = write(fd, msg, sizeof(*msg));
589*053f45beSAndroid Build Coastguard Worker
590*053f45beSAndroid Build Coastguard Worker /* Make sure that write/read is atomic to a pipe */
591*053f45beSAndroid Build Coastguard Worker BUILD_BUG_ON(sizeof(struct test_desc) > PIPE_BUF);
592*053f45beSAndroid Build Coastguard Worker
593*053f45beSAndroid Build Coastguard Worker if (bytes < 0) {
594*053f45beSAndroid Build Coastguard Worker pr_err("write()");
595*053f45beSAndroid Build Coastguard Worker if (exit_of_fail)
596*053f45beSAndroid Build Coastguard Worker exit(KSFT_FAIL);
597*053f45beSAndroid Build Coastguard Worker }
598*053f45beSAndroid Build Coastguard Worker if (bytes != sizeof(*msg)) {
599*053f45beSAndroid Build Coastguard Worker pr_err("sent part of the message %zd/%zu", bytes, sizeof(*msg));
600*053f45beSAndroid Build Coastguard Worker if (exit_of_fail)
601*053f45beSAndroid Build Coastguard Worker exit(KSFT_FAIL);
602*053f45beSAndroid Build Coastguard Worker }
603*053f45beSAndroid Build Coastguard Worker }
604*053f45beSAndroid Build Coastguard Worker
read_msg(int fd,struct test_desc * msg,bool exit_of_fail)605*053f45beSAndroid Build Coastguard Worker static void read_msg(int fd, struct test_desc *msg, bool exit_of_fail)
606*053f45beSAndroid Build Coastguard Worker {
607*053f45beSAndroid Build Coastguard Worker ssize_t bytes = read(fd, msg, sizeof(*msg));
608*053f45beSAndroid Build Coastguard Worker
609*053f45beSAndroid Build Coastguard Worker if (bytes < 0) {
610*053f45beSAndroid Build Coastguard Worker pr_err("read()");
611*053f45beSAndroid Build Coastguard Worker if (exit_of_fail)
612*053f45beSAndroid Build Coastguard Worker exit(KSFT_FAIL);
613*053f45beSAndroid Build Coastguard Worker }
614*053f45beSAndroid Build Coastguard Worker if (bytes != sizeof(*msg)) {
615*053f45beSAndroid Build Coastguard Worker pr_err("got incomplete message %zd/%zu", bytes, sizeof(*msg));
616*053f45beSAndroid Build Coastguard Worker if (exit_of_fail)
617*053f45beSAndroid Build Coastguard Worker exit(KSFT_FAIL);
618*053f45beSAndroid Build Coastguard Worker }
619*053f45beSAndroid Build Coastguard Worker }
620*053f45beSAndroid Build Coastguard Worker
udp_ping_init(struct in_addr listen_ip,unsigned int u_timeout,unsigned int * server_port,int sock[2])621*053f45beSAndroid Build Coastguard Worker static int udp_ping_init(struct in_addr listen_ip, unsigned int u_timeout,
622*053f45beSAndroid Build Coastguard Worker unsigned int *server_port, int sock[2])
623*053f45beSAndroid Build Coastguard Worker {
624*053f45beSAndroid Build Coastguard Worker struct sockaddr_in server;
625*053f45beSAndroid Build Coastguard Worker struct timeval t = { .tv_sec = 0, .tv_usec = u_timeout };
626*053f45beSAndroid Build Coastguard Worker socklen_t s_len = sizeof(server);
627*053f45beSAndroid Build Coastguard Worker
628*053f45beSAndroid Build Coastguard Worker sock[0] = socket(AF_INET, SOCK_DGRAM, 0);
629*053f45beSAndroid Build Coastguard Worker if (sock[0] < 0) {
630*053f45beSAndroid Build Coastguard Worker pr_err("socket()");
631*053f45beSAndroid Build Coastguard Worker return -1;
632*053f45beSAndroid Build Coastguard Worker }
633*053f45beSAndroid Build Coastguard Worker
634*053f45beSAndroid Build Coastguard Worker server.sin_family = AF_INET;
635*053f45beSAndroid Build Coastguard Worker server.sin_port = 0;
636*053f45beSAndroid Build Coastguard Worker memcpy(&server.sin_addr.s_addr, &listen_ip, sizeof(struct in_addr));
637*053f45beSAndroid Build Coastguard Worker
638*053f45beSAndroid Build Coastguard Worker if (bind(sock[0], (struct sockaddr *)&server, s_len)) {
639*053f45beSAndroid Build Coastguard Worker pr_err("bind()");
640*053f45beSAndroid Build Coastguard Worker goto err_close_server;
641*053f45beSAndroid Build Coastguard Worker }
642*053f45beSAndroid Build Coastguard Worker
643*053f45beSAndroid Build Coastguard Worker if (getsockname(sock[0], (struct sockaddr *)&server, &s_len)) {
644*053f45beSAndroid Build Coastguard Worker pr_err("getsockname()");
645*053f45beSAndroid Build Coastguard Worker goto err_close_server;
646*053f45beSAndroid Build Coastguard Worker }
647*053f45beSAndroid Build Coastguard Worker
648*053f45beSAndroid Build Coastguard Worker *server_port = ntohs(server.sin_port);
649*053f45beSAndroid Build Coastguard Worker
650*053f45beSAndroid Build Coastguard Worker if (setsockopt(sock[0], SOL_SOCKET, SO_RCVTIMEO, (const char *)&t, sizeof t)) {
651*053f45beSAndroid Build Coastguard Worker pr_err("setsockopt()");
652*053f45beSAndroid Build Coastguard Worker goto err_close_server;
653*053f45beSAndroid Build Coastguard Worker }
654*053f45beSAndroid Build Coastguard Worker
655*053f45beSAndroid Build Coastguard Worker sock[1] = socket(AF_INET, SOCK_DGRAM, 0);
656*053f45beSAndroid Build Coastguard Worker if (sock[1] < 0) {
657*053f45beSAndroid Build Coastguard Worker pr_err("socket()");
658*053f45beSAndroid Build Coastguard Worker goto err_close_server;
659*053f45beSAndroid Build Coastguard Worker }
660*053f45beSAndroid Build Coastguard Worker
661*053f45beSAndroid Build Coastguard Worker return 0;
662*053f45beSAndroid Build Coastguard Worker
663*053f45beSAndroid Build Coastguard Worker err_close_server:
664*053f45beSAndroid Build Coastguard Worker close(sock[0]);
665*053f45beSAndroid Build Coastguard Worker return -1;
666*053f45beSAndroid Build Coastguard Worker }
667*053f45beSAndroid Build Coastguard Worker
udp_ping_send(int sock[2],in_addr_t dest_ip,unsigned int port,char * buf,size_t buf_len)668*053f45beSAndroid Build Coastguard Worker static int udp_ping_send(int sock[2], in_addr_t dest_ip, unsigned int port,
669*053f45beSAndroid Build Coastguard Worker char *buf, size_t buf_len)
670*053f45beSAndroid Build Coastguard Worker {
671*053f45beSAndroid Build Coastguard Worker struct sockaddr_in server;
672*053f45beSAndroid Build Coastguard Worker const struct sockaddr *dest_addr = (struct sockaddr *)&server;
673*053f45beSAndroid Build Coastguard Worker char *sock_buf[buf_len];
674*053f45beSAndroid Build Coastguard Worker ssize_t r_bytes, s_bytes;
675*053f45beSAndroid Build Coastguard Worker
676*053f45beSAndroid Build Coastguard Worker server.sin_family = AF_INET;
677*053f45beSAndroid Build Coastguard Worker server.sin_port = htons(port);
678*053f45beSAndroid Build Coastguard Worker server.sin_addr.s_addr = dest_ip;
679*053f45beSAndroid Build Coastguard Worker
680*053f45beSAndroid Build Coastguard Worker s_bytes = sendto(sock[1], buf, buf_len, 0, dest_addr, sizeof(server));
681*053f45beSAndroid Build Coastguard Worker if (s_bytes < 0) {
682*053f45beSAndroid Build Coastguard Worker pr_err("sendto()");
683*053f45beSAndroid Build Coastguard Worker return -1;
684*053f45beSAndroid Build Coastguard Worker } else if (s_bytes != buf_len) {
685*053f45beSAndroid Build Coastguard Worker printk("send part of the message: %zd/%zu", s_bytes, sizeof(server));
686*053f45beSAndroid Build Coastguard Worker return -1;
687*053f45beSAndroid Build Coastguard Worker }
688*053f45beSAndroid Build Coastguard Worker
689*053f45beSAndroid Build Coastguard Worker r_bytes = recv(sock[0], sock_buf, buf_len, 0);
690*053f45beSAndroid Build Coastguard Worker if (r_bytes < 0) {
691*053f45beSAndroid Build Coastguard Worker if (errno != EAGAIN)
692*053f45beSAndroid Build Coastguard Worker pr_err("recv()");
693*053f45beSAndroid Build Coastguard Worker return -1;
694*053f45beSAndroid Build Coastguard Worker } else if (r_bytes == 0) { /* EOF */
695*053f45beSAndroid Build Coastguard Worker printk("EOF on reply to ping");
696*053f45beSAndroid Build Coastguard Worker return -1;
697*053f45beSAndroid Build Coastguard Worker } else if (r_bytes != buf_len || memcmp(buf, sock_buf, buf_len)) {
698*053f45beSAndroid Build Coastguard Worker printk("ping reply packet is corrupted %zd/%zu", r_bytes, buf_len);
699*053f45beSAndroid Build Coastguard Worker return -1;
700*053f45beSAndroid Build Coastguard Worker }
701*053f45beSAndroid Build Coastguard Worker
702*053f45beSAndroid Build Coastguard Worker return 0;
703*053f45beSAndroid Build Coastguard Worker }
704*053f45beSAndroid Build Coastguard Worker
udp_ping_reply(int sock[2],in_addr_t dest_ip,unsigned int port,char * buf,size_t buf_len)705*053f45beSAndroid Build Coastguard Worker static int udp_ping_reply(int sock[2], in_addr_t dest_ip, unsigned int port,
706*053f45beSAndroid Build Coastguard Worker char *buf, size_t buf_len)
707*053f45beSAndroid Build Coastguard Worker {
708*053f45beSAndroid Build Coastguard Worker struct sockaddr_in server;
709*053f45beSAndroid Build Coastguard Worker const struct sockaddr *dest_addr = (struct sockaddr *)&server;
710*053f45beSAndroid Build Coastguard Worker char *sock_buf[buf_len];
711*053f45beSAndroid Build Coastguard Worker ssize_t r_bytes, s_bytes;
712*053f45beSAndroid Build Coastguard Worker
713*053f45beSAndroid Build Coastguard Worker server.sin_family = AF_INET;
714*053f45beSAndroid Build Coastguard Worker server.sin_port = htons(port);
715*053f45beSAndroid Build Coastguard Worker server.sin_addr.s_addr = dest_ip;
716*053f45beSAndroid Build Coastguard Worker
717*053f45beSAndroid Build Coastguard Worker r_bytes = recv(sock[0], sock_buf, buf_len, 0);
718*053f45beSAndroid Build Coastguard Worker if (r_bytes < 0) {
719*053f45beSAndroid Build Coastguard Worker if (errno != EAGAIN)
720*053f45beSAndroid Build Coastguard Worker pr_err("recv()");
721*053f45beSAndroid Build Coastguard Worker return -1;
722*053f45beSAndroid Build Coastguard Worker }
723*053f45beSAndroid Build Coastguard Worker if (r_bytes == 0) { /* EOF */
724*053f45beSAndroid Build Coastguard Worker printk("EOF on reply to ping");
725*053f45beSAndroid Build Coastguard Worker return -1;
726*053f45beSAndroid Build Coastguard Worker }
727*053f45beSAndroid Build Coastguard Worker if (r_bytes != buf_len || memcmp(buf, sock_buf, buf_len)) {
728*053f45beSAndroid Build Coastguard Worker printk("ping reply packet is corrupted %zd/%zu", r_bytes, buf_len);
729*053f45beSAndroid Build Coastguard Worker return -1;
730*053f45beSAndroid Build Coastguard Worker }
731*053f45beSAndroid Build Coastguard Worker
732*053f45beSAndroid Build Coastguard Worker s_bytes = sendto(sock[1], buf, buf_len, 0, dest_addr, sizeof(server));
733*053f45beSAndroid Build Coastguard Worker if (s_bytes < 0) {
734*053f45beSAndroid Build Coastguard Worker pr_err("sendto()");
735*053f45beSAndroid Build Coastguard Worker return -1;
736*053f45beSAndroid Build Coastguard Worker } else if (s_bytes != buf_len) {
737*053f45beSAndroid Build Coastguard Worker printk("send part of the message: %zd/%zu", s_bytes, sizeof(server));
738*053f45beSAndroid Build Coastguard Worker return -1;
739*053f45beSAndroid Build Coastguard Worker }
740*053f45beSAndroid Build Coastguard Worker
741*053f45beSAndroid Build Coastguard Worker return 0;
742*053f45beSAndroid Build Coastguard Worker }
743*053f45beSAndroid Build Coastguard Worker
744*053f45beSAndroid Build Coastguard Worker typedef int (*ping_f)(int sock[2], in_addr_t dest_ip, unsigned int port,
745*053f45beSAndroid Build Coastguard Worker char *buf, size_t buf_len);
do_ping(int cmd_fd,char * buf,size_t buf_len,struct in_addr from,bool init_side,int d_port,in_addr_t to,ping_f func)746*053f45beSAndroid Build Coastguard Worker static int do_ping(int cmd_fd, char *buf, size_t buf_len, struct in_addr from,
747*053f45beSAndroid Build Coastguard Worker bool init_side, int d_port, in_addr_t to, ping_f func)
748*053f45beSAndroid Build Coastguard Worker {
749*053f45beSAndroid Build Coastguard Worker struct test_desc msg;
750*053f45beSAndroid Build Coastguard Worker unsigned int s_port, i, ping_succeeded = 0;
751*053f45beSAndroid Build Coastguard Worker int ping_sock[2];
752*053f45beSAndroid Build Coastguard Worker char to_str[IPV4_STR_SZ] = {}, from_str[IPV4_STR_SZ] = {};
753*053f45beSAndroid Build Coastguard Worker
754*053f45beSAndroid Build Coastguard Worker if (udp_ping_init(from, ping_timeout, &s_port, ping_sock)) {
755*053f45beSAndroid Build Coastguard Worker printk("Failed to init ping");
756*053f45beSAndroid Build Coastguard Worker return -1;
757*053f45beSAndroid Build Coastguard Worker }
758*053f45beSAndroid Build Coastguard Worker
759*053f45beSAndroid Build Coastguard Worker memset(&msg, 0, sizeof(msg));
760*053f45beSAndroid Build Coastguard Worker msg.type = MSG_PING;
761*053f45beSAndroid Build Coastguard Worker msg.body.ping.port = s_port;
762*053f45beSAndroid Build Coastguard Worker memcpy(&msg.body.ping.reply_ip, &from, sizeof(from));
763*053f45beSAndroid Build Coastguard Worker
764*053f45beSAndroid Build Coastguard Worker write_msg(cmd_fd, &msg, 0);
765*053f45beSAndroid Build Coastguard Worker if (init_side) {
766*053f45beSAndroid Build Coastguard Worker /* The other end sends ip to ping */
767*053f45beSAndroid Build Coastguard Worker read_msg(cmd_fd, &msg, 0);
768*053f45beSAndroid Build Coastguard Worker if (msg.type != MSG_PING)
769*053f45beSAndroid Build Coastguard Worker return -1;
770*053f45beSAndroid Build Coastguard Worker to = msg.body.ping.reply_ip;
771*053f45beSAndroid Build Coastguard Worker d_port = msg.body.ping.port;
772*053f45beSAndroid Build Coastguard Worker }
773*053f45beSAndroid Build Coastguard Worker
774*053f45beSAndroid Build Coastguard Worker for (i = 0; i < ping_count ; i++) {
775*053f45beSAndroid Build Coastguard Worker struct timespec sleep_time = {
776*053f45beSAndroid Build Coastguard Worker .tv_sec = 0,
777*053f45beSAndroid Build Coastguard Worker .tv_nsec = ping_delay_nsec,
778*053f45beSAndroid Build Coastguard Worker };
779*053f45beSAndroid Build Coastguard Worker
780*053f45beSAndroid Build Coastguard Worker ping_succeeded += !func(ping_sock, to, d_port, buf, page_size);
781*053f45beSAndroid Build Coastguard Worker nanosleep(&sleep_time, 0);
782*053f45beSAndroid Build Coastguard Worker }
783*053f45beSAndroid Build Coastguard Worker
784*053f45beSAndroid Build Coastguard Worker close(ping_sock[0]);
785*053f45beSAndroid Build Coastguard Worker close(ping_sock[1]);
786*053f45beSAndroid Build Coastguard Worker
787*053f45beSAndroid Build Coastguard Worker strncpy(to_str, inet_ntoa(*(struct in_addr *)&to), IPV4_STR_SZ - 1);
788*053f45beSAndroid Build Coastguard Worker strncpy(from_str, inet_ntoa(from), IPV4_STR_SZ - 1);
789*053f45beSAndroid Build Coastguard Worker
790*053f45beSAndroid Build Coastguard Worker if (ping_succeeded < ping_success) {
791*053f45beSAndroid Build Coastguard Worker printk("ping (%s) %s->%s failed %u/%u times",
792*053f45beSAndroid Build Coastguard Worker init_side ? "send" : "reply", from_str, to_str,
793*053f45beSAndroid Build Coastguard Worker ping_count - ping_succeeded, ping_count);
794*053f45beSAndroid Build Coastguard Worker return -1;
795*053f45beSAndroid Build Coastguard Worker }
796*053f45beSAndroid Build Coastguard Worker
797*053f45beSAndroid Build Coastguard Worker #ifdef DEBUG
798*053f45beSAndroid Build Coastguard Worker printk("ping (%s) %s->%s succeeded %u/%u times",
799*053f45beSAndroid Build Coastguard Worker init_side ? "send" : "reply", from_str, to_str,
800*053f45beSAndroid Build Coastguard Worker ping_succeeded, ping_count);
801*053f45beSAndroid Build Coastguard Worker #endif
802*053f45beSAndroid Build Coastguard Worker
803*053f45beSAndroid Build Coastguard Worker return 0;
804*053f45beSAndroid Build Coastguard Worker }
805*053f45beSAndroid Build Coastguard Worker
xfrm_fill_key(char * name,char * buf,size_t buf_len,unsigned int * key_len)806*053f45beSAndroid Build Coastguard Worker static int xfrm_fill_key(char *name, char *buf,
807*053f45beSAndroid Build Coastguard Worker size_t buf_len, unsigned int *key_len)
808*053f45beSAndroid Build Coastguard Worker {
809*053f45beSAndroid Build Coastguard Worker int i;
810*053f45beSAndroid Build Coastguard Worker
811*053f45beSAndroid Build Coastguard Worker for (i = 0; i < XFRM_ALGO_NR_KEYS; i++) {
812*053f45beSAndroid Build Coastguard Worker if (strncmp(name, xfrm_key_entries[i].algo_name, ALGO_LEN) == 0)
813*053f45beSAndroid Build Coastguard Worker *key_len = xfrm_key_entries[i].key_len;
814*053f45beSAndroid Build Coastguard Worker }
815*053f45beSAndroid Build Coastguard Worker
816*053f45beSAndroid Build Coastguard Worker if (*key_len > buf_len) {
817*053f45beSAndroid Build Coastguard Worker printk("Can't pack a key - too big for buffer");
818*053f45beSAndroid Build Coastguard Worker return -1;
819*053f45beSAndroid Build Coastguard Worker }
820*053f45beSAndroid Build Coastguard Worker
821*053f45beSAndroid Build Coastguard Worker randomize_buffer(buf, *key_len);
822*053f45beSAndroid Build Coastguard Worker
823*053f45beSAndroid Build Coastguard Worker return 0;
824*053f45beSAndroid Build Coastguard Worker }
825*053f45beSAndroid Build Coastguard Worker
xfrm_state_pack_algo(struct nlmsghdr * nh,size_t req_sz,struct xfrm_desc * desc)826*053f45beSAndroid Build Coastguard Worker static int xfrm_state_pack_algo(struct nlmsghdr *nh, size_t req_sz,
827*053f45beSAndroid Build Coastguard Worker struct xfrm_desc *desc)
828*053f45beSAndroid Build Coastguard Worker {
829*053f45beSAndroid Build Coastguard Worker struct {
830*053f45beSAndroid Build Coastguard Worker union {
831*053f45beSAndroid Build Coastguard Worker struct xfrm_algo alg;
832*053f45beSAndroid Build Coastguard Worker struct xfrm_algo_aead aead;
833*053f45beSAndroid Build Coastguard Worker struct xfrm_algo_auth auth;
834*053f45beSAndroid Build Coastguard Worker } u;
835*053f45beSAndroid Build Coastguard Worker char buf[XFRM_ALGO_KEY_BUF_SIZE];
836*053f45beSAndroid Build Coastguard Worker } alg = {};
837*053f45beSAndroid Build Coastguard Worker size_t alen, elen, clen, aelen;
838*053f45beSAndroid Build Coastguard Worker unsigned short type;
839*053f45beSAndroid Build Coastguard Worker
840*053f45beSAndroid Build Coastguard Worker alen = strlen(desc->a_algo);
841*053f45beSAndroid Build Coastguard Worker elen = strlen(desc->e_algo);
842*053f45beSAndroid Build Coastguard Worker clen = strlen(desc->c_algo);
843*053f45beSAndroid Build Coastguard Worker aelen = strlen(desc->ae_algo);
844*053f45beSAndroid Build Coastguard Worker
845*053f45beSAndroid Build Coastguard Worker /* Verify desc */
846*053f45beSAndroid Build Coastguard Worker switch (desc->proto) {
847*053f45beSAndroid Build Coastguard Worker case IPPROTO_AH:
848*053f45beSAndroid Build Coastguard Worker if (!alen || elen || clen || aelen) {
849*053f45beSAndroid Build Coastguard Worker printk("BUG: buggy ah desc");
850*053f45beSAndroid Build Coastguard Worker return -1;
851*053f45beSAndroid Build Coastguard Worker }
852*053f45beSAndroid Build Coastguard Worker strncpy(alg.u.alg.alg_name, desc->a_algo, ALGO_LEN - 1);
853*053f45beSAndroid Build Coastguard Worker if (xfrm_fill_key(desc->a_algo, alg.u.alg.alg_key,
854*053f45beSAndroid Build Coastguard Worker sizeof(alg.buf), &alg.u.alg.alg_key_len))
855*053f45beSAndroid Build Coastguard Worker return -1;
856*053f45beSAndroid Build Coastguard Worker type = XFRMA_ALG_AUTH;
857*053f45beSAndroid Build Coastguard Worker break;
858*053f45beSAndroid Build Coastguard Worker case IPPROTO_COMP:
859*053f45beSAndroid Build Coastguard Worker if (!clen || elen || alen || aelen) {
860*053f45beSAndroid Build Coastguard Worker printk("BUG: buggy comp desc");
861*053f45beSAndroid Build Coastguard Worker return -1;
862*053f45beSAndroid Build Coastguard Worker }
863*053f45beSAndroid Build Coastguard Worker strncpy(alg.u.alg.alg_name, desc->c_algo, ALGO_LEN - 1);
864*053f45beSAndroid Build Coastguard Worker if (xfrm_fill_key(desc->c_algo, alg.u.alg.alg_key,
865*053f45beSAndroid Build Coastguard Worker sizeof(alg.buf), &alg.u.alg.alg_key_len))
866*053f45beSAndroid Build Coastguard Worker return -1;
867*053f45beSAndroid Build Coastguard Worker type = XFRMA_ALG_COMP;
868*053f45beSAndroid Build Coastguard Worker break;
869*053f45beSAndroid Build Coastguard Worker case IPPROTO_ESP:
870*053f45beSAndroid Build Coastguard Worker if (!((alen && elen) ^ aelen) || clen) {
871*053f45beSAndroid Build Coastguard Worker printk("BUG: buggy esp desc");
872*053f45beSAndroid Build Coastguard Worker return -1;
873*053f45beSAndroid Build Coastguard Worker }
874*053f45beSAndroid Build Coastguard Worker if (aelen) {
875*053f45beSAndroid Build Coastguard Worker alg.u.aead.alg_icv_len = desc->icv_len;
876*053f45beSAndroid Build Coastguard Worker strncpy(alg.u.aead.alg_name, desc->ae_algo, ALGO_LEN - 1);
877*053f45beSAndroid Build Coastguard Worker if (xfrm_fill_key(desc->ae_algo, alg.u.aead.alg_key,
878*053f45beSAndroid Build Coastguard Worker sizeof(alg.buf), &alg.u.aead.alg_key_len))
879*053f45beSAndroid Build Coastguard Worker return -1;
880*053f45beSAndroid Build Coastguard Worker type = XFRMA_ALG_AEAD;
881*053f45beSAndroid Build Coastguard Worker } else {
882*053f45beSAndroid Build Coastguard Worker
883*053f45beSAndroid Build Coastguard Worker strncpy(alg.u.alg.alg_name, desc->e_algo, ALGO_LEN - 1);
884*053f45beSAndroid Build Coastguard Worker type = XFRMA_ALG_CRYPT;
885*053f45beSAndroid Build Coastguard Worker if (xfrm_fill_key(desc->e_algo, alg.u.alg.alg_key,
886*053f45beSAndroid Build Coastguard Worker sizeof(alg.buf), &alg.u.alg.alg_key_len))
887*053f45beSAndroid Build Coastguard Worker return -1;
888*053f45beSAndroid Build Coastguard Worker if (rtattr_pack(nh, req_sz, type, &alg, sizeof(alg)))
889*053f45beSAndroid Build Coastguard Worker return -1;
890*053f45beSAndroid Build Coastguard Worker
891*053f45beSAndroid Build Coastguard Worker strncpy(alg.u.alg.alg_name, desc->a_algo, ALGO_LEN);
892*053f45beSAndroid Build Coastguard Worker type = XFRMA_ALG_AUTH;
893*053f45beSAndroid Build Coastguard Worker if (xfrm_fill_key(desc->a_algo, alg.u.alg.alg_key,
894*053f45beSAndroid Build Coastguard Worker sizeof(alg.buf), &alg.u.alg.alg_key_len))
895*053f45beSAndroid Build Coastguard Worker return -1;
896*053f45beSAndroid Build Coastguard Worker }
897*053f45beSAndroid Build Coastguard Worker break;
898*053f45beSAndroid Build Coastguard Worker default:
899*053f45beSAndroid Build Coastguard Worker printk("BUG: unknown proto in desc");
900*053f45beSAndroid Build Coastguard Worker return -1;
901*053f45beSAndroid Build Coastguard Worker }
902*053f45beSAndroid Build Coastguard Worker
903*053f45beSAndroid Build Coastguard Worker if (rtattr_pack(nh, req_sz, type, &alg, sizeof(alg)))
904*053f45beSAndroid Build Coastguard Worker return -1;
905*053f45beSAndroid Build Coastguard Worker
906*053f45beSAndroid Build Coastguard Worker return 0;
907*053f45beSAndroid Build Coastguard Worker }
908*053f45beSAndroid Build Coastguard Worker
gen_spi(struct in_addr src)909*053f45beSAndroid Build Coastguard Worker static inline uint32_t gen_spi(struct in_addr src)
910*053f45beSAndroid Build Coastguard Worker {
911*053f45beSAndroid Build Coastguard Worker return htonl(inet_lnaof(src));
912*053f45beSAndroid Build Coastguard Worker }
913*053f45beSAndroid Build Coastguard Worker
xfrm_state_add(int xfrm_sock,uint32_t seq,uint32_t spi,struct in_addr src,struct in_addr dst,struct xfrm_desc * desc)914*053f45beSAndroid Build Coastguard Worker static int xfrm_state_add(int xfrm_sock, uint32_t seq, uint32_t spi,
915*053f45beSAndroid Build Coastguard Worker struct in_addr src, struct in_addr dst,
916*053f45beSAndroid Build Coastguard Worker struct xfrm_desc *desc)
917*053f45beSAndroid Build Coastguard Worker {
918*053f45beSAndroid Build Coastguard Worker struct {
919*053f45beSAndroid Build Coastguard Worker struct nlmsghdr nh;
920*053f45beSAndroid Build Coastguard Worker struct xfrm_usersa_info info;
921*053f45beSAndroid Build Coastguard Worker char attrbuf[MAX_PAYLOAD];
922*053f45beSAndroid Build Coastguard Worker } req;
923*053f45beSAndroid Build Coastguard Worker
924*053f45beSAndroid Build Coastguard Worker memset(&req, 0, sizeof(req));
925*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.info));
926*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_type = XFRM_MSG_NEWSA;
927*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
928*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_seq = seq;
929*053f45beSAndroid Build Coastguard Worker
930*053f45beSAndroid Build Coastguard Worker /* Fill selector. */
931*053f45beSAndroid Build Coastguard Worker memcpy(&req.info.sel.daddr, &dst, sizeof(dst));
932*053f45beSAndroid Build Coastguard Worker memcpy(&req.info.sel.saddr, &src, sizeof(src));
933*053f45beSAndroid Build Coastguard Worker req.info.sel.family = AF_INET;
934*053f45beSAndroid Build Coastguard Worker req.info.sel.prefixlen_d = PREFIX_LEN;
935*053f45beSAndroid Build Coastguard Worker req.info.sel.prefixlen_s = PREFIX_LEN;
936*053f45beSAndroid Build Coastguard Worker
937*053f45beSAndroid Build Coastguard Worker /* Fill id */
938*053f45beSAndroid Build Coastguard Worker memcpy(&req.info.id.daddr, &dst, sizeof(dst));
939*053f45beSAndroid Build Coastguard Worker /* Note: zero-spi cannot be deleted */
940*053f45beSAndroid Build Coastguard Worker req.info.id.spi = spi;
941*053f45beSAndroid Build Coastguard Worker req.info.id.proto = desc->proto;
942*053f45beSAndroid Build Coastguard Worker
943*053f45beSAndroid Build Coastguard Worker memcpy(&req.info.saddr, &src, sizeof(src));
944*053f45beSAndroid Build Coastguard Worker
945*053f45beSAndroid Build Coastguard Worker /* Fill lifteme_cfg */
946*053f45beSAndroid Build Coastguard Worker req.info.lft.soft_byte_limit = XFRM_INF;
947*053f45beSAndroid Build Coastguard Worker req.info.lft.hard_byte_limit = XFRM_INF;
948*053f45beSAndroid Build Coastguard Worker req.info.lft.soft_packet_limit = XFRM_INF;
949*053f45beSAndroid Build Coastguard Worker req.info.lft.hard_packet_limit = XFRM_INF;
950*053f45beSAndroid Build Coastguard Worker
951*053f45beSAndroid Build Coastguard Worker req.info.family = AF_INET;
952*053f45beSAndroid Build Coastguard Worker req.info.mode = XFRM_MODE_TUNNEL;
953*053f45beSAndroid Build Coastguard Worker
954*053f45beSAndroid Build Coastguard Worker if (xfrm_state_pack_algo(&req.nh, sizeof(req), desc))
955*053f45beSAndroid Build Coastguard Worker return -1;
956*053f45beSAndroid Build Coastguard Worker
957*053f45beSAndroid Build Coastguard Worker if (send(xfrm_sock, &req, req.nh.nlmsg_len, 0) < 0) {
958*053f45beSAndroid Build Coastguard Worker pr_err("send()");
959*053f45beSAndroid Build Coastguard Worker return -1;
960*053f45beSAndroid Build Coastguard Worker }
961*053f45beSAndroid Build Coastguard Worker
962*053f45beSAndroid Build Coastguard Worker return netlink_check_answer(xfrm_sock);
963*053f45beSAndroid Build Coastguard Worker }
964*053f45beSAndroid Build Coastguard Worker
xfrm_usersa_found(struct xfrm_usersa_info * info,uint32_t spi,struct in_addr src,struct in_addr dst,struct xfrm_desc * desc)965*053f45beSAndroid Build Coastguard Worker static bool xfrm_usersa_found(struct xfrm_usersa_info *info, uint32_t spi,
966*053f45beSAndroid Build Coastguard Worker struct in_addr src, struct in_addr dst,
967*053f45beSAndroid Build Coastguard Worker struct xfrm_desc *desc)
968*053f45beSAndroid Build Coastguard Worker {
969*053f45beSAndroid Build Coastguard Worker if (memcmp(&info->sel.daddr, &dst, sizeof(dst)))
970*053f45beSAndroid Build Coastguard Worker return false;
971*053f45beSAndroid Build Coastguard Worker
972*053f45beSAndroid Build Coastguard Worker if (memcmp(&info->sel.saddr, &src, sizeof(src)))
973*053f45beSAndroid Build Coastguard Worker return false;
974*053f45beSAndroid Build Coastguard Worker
975*053f45beSAndroid Build Coastguard Worker if (info->sel.family != AF_INET ||
976*053f45beSAndroid Build Coastguard Worker info->sel.prefixlen_d != PREFIX_LEN ||
977*053f45beSAndroid Build Coastguard Worker info->sel.prefixlen_s != PREFIX_LEN)
978*053f45beSAndroid Build Coastguard Worker return false;
979*053f45beSAndroid Build Coastguard Worker
980*053f45beSAndroid Build Coastguard Worker if (info->id.spi != spi || info->id.proto != desc->proto)
981*053f45beSAndroid Build Coastguard Worker return false;
982*053f45beSAndroid Build Coastguard Worker
983*053f45beSAndroid Build Coastguard Worker if (memcmp(&info->id.daddr, &dst, sizeof(dst)))
984*053f45beSAndroid Build Coastguard Worker return false;
985*053f45beSAndroid Build Coastguard Worker
986*053f45beSAndroid Build Coastguard Worker if (memcmp(&info->saddr, &src, sizeof(src)))
987*053f45beSAndroid Build Coastguard Worker return false;
988*053f45beSAndroid Build Coastguard Worker
989*053f45beSAndroid Build Coastguard Worker if (info->lft.soft_byte_limit != XFRM_INF ||
990*053f45beSAndroid Build Coastguard Worker info->lft.hard_byte_limit != XFRM_INF ||
991*053f45beSAndroid Build Coastguard Worker info->lft.soft_packet_limit != XFRM_INF ||
992*053f45beSAndroid Build Coastguard Worker info->lft.hard_packet_limit != XFRM_INF)
993*053f45beSAndroid Build Coastguard Worker return false;
994*053f45beSAndroid Build Coastguard Worker
995*053f45beSAndroid Build Coastguard Worker if (info->family != AF_INET || info->mode != XFRM_MODE_TUNNEL)
996*053f45beSAndroid Build Coastguard Worker return false;
997*053f45beSAndroid Build Coastguard Worker
998*053f45beSAndroid Build Coastguard Worker /* XXX: check xfrm algo, see xfrm_state_pack_algo(). */
999*053f45beSAndroid Build Coastguard Worker
1000*053f45beSAndroid Build Coastguard Worker return true;
1001*053f45beSAndroid Build Coastguard Worker }
1002*053f45beSAndroid Build Coastguard Worker
xfrm_state_check(int xfrm_sock,uint32_t seq,uint32_t spi,struct in_addr src,struct in_addr dst,struct xfrm_desc * desc)1003*053f45beSAndroid Build Coastguard Worker static int xfrm_state_check(int xfrm_sock, uint32_t seq, uint32_t spi,
1004*053f45beSAndroid Build Coastguard Worker struct in_addr src, struct in_addr dst,
1005*053f45beSAndroid Build Coastguard Worker struct xfrm_desc *desc)
1006*053f45beSAndroid Build Coastguard Worker {
1007*053f45beSAndroid Build Coastguard Worker struct {
1008*053f45beSAndroid Build Coastguard Worker struct nlmsghdr nh;
1009*053f45beSAndroid Build Coastguard Worker char attrbuf[MAX_PAYLOAD];
1010*053f45beSAndroid Build Coastguard Worker } req;
1011*053f45beSAndroid Build Coastguard Worker struct {
1012*053f45beSAndroid Build Coastguard Worker struct nlmsghdr nh;
1013*053f45beSAndroid Build Coastguard Worker union {
1014*053f45beSAndroid Build Coastguard Worker struct xfrm_usersa_info info;
1015*053f45beSAndroid Build Coastguard Worker int error;
1016*053f45beSAndroid Build Coastguard Worker };
1017*053f45beSAndroid Build Coastguard Worker char attrbuf[MAX_PAYLOAD];
1018*053f45beSAndroid Build Coastguard Worker } answer;
1019*053f45beSAndroid Build Coastguard Worker struct xfrm_address_filter filter = {};
1020*053f45beSAndroid Build Coastguard Worker bool found = false;
1021*053f45beSAndroid Build Coastguard Worker
1022*053f45beSAndroid Build Coastguard Worker
1023*053f45beSAndroid Build Coastguard Worker memset(&req, 0, sizeof(req));
1024*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_len = NLMSG_LENGTH(0);
1025*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_type = XFRM_MSG_GETSA;
1026*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
1027*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_seq = seq;
1028*053f45beSAndroid Build Coastguard Worker
1029*053f45beSAndroid Build Coastguard Worker /*
1030*053f45beSAndroid Build Coastguard Worker * Add dump filter by source address as there may be other tunnels
1031*053f45beSAndroid Build Coastguard Worker * in this netns (if tests run in parallel).
1032*053f45beSAndroid Build Coastguard Worker */
1033*053f45beSAndroid Build Coastguard Worker filter.family = AF_INET;
1034*053f45beSAndroid Build Coastguard Worker filter.splen = 0x1f; /* 0xffffffff mask see addr_match() */
1035*053f45beSAndroid Build Coastguard Worker memcpy(&filter.saddr, &src, sizeof(src));
1036*053f45beSAndroid Build Coastguard Worker if (rtattr_pack(&req.nh, sizeof(req), XFRMA_ADDRESS_FILTER,
1037*053f45beSAndroid Build Coastguard Worker &filter, sizeof(filter)))
1038*053f45beSAndroid Build Coastguard Worker return -1;
1039*053f45beSAndroid Build Coastguard Worker
1040*053f45beSAndroid Build Coastguard Worker if (send(xfrm_sock, &req, req.nh.nlmsg_len, 0) < 0) {
1041*053f45beSAndroid Build Coastguard Worker pr_err("send()");
1042*053f45beSAndroid Build Coastguard Worker return -1;
1043*053f45beSAndroid Build Coastguard Worker }
1044*053f45beSAndroid Build Coastguard Worker
1045*053f45beSAndroid Build Coastguard Worker while (1) {
1046*053f45beSAndroid Build Coastguard Worker if (recv(xfrm_sock, &answer, sizeof(answer), 0) < 0) {
1047*053f45beSAndroid Build Coastguard Worker pr_err("recv()");
1048*053f45beSAndroid Build Coastguard Worker return -1;
1049*053f45beSAndroid Build Coastguard Worker }
1050*053f45beSAndroid Build Coastguard Worker if (answer.nh.nlmsg_type == NLMSG_ERROR) {
1051*053f45beSAndroid Build Coastguard Worker printk("NLMSG_ERROR: %d: %s",
1052*053f45beSAndroid Build Coastguard Worker answer.error, strerror(-answer.error));
1053*053f45beSAndroid Build Coastguard Worker return -1;
1054*053f45beSAndroid Build Coastguard Worker } else if (answer.nh.nlmsg_type == NLMSG_DONE) {
1055*053f45beSAndroid Build Coastguard Worker if (found)
1056*053f45beSAndroid Build Coastguard Worker return 0;
1057*053f45beSAndroid Build Coastguard Worker printk("didn't find allocated xfrm state in dump");
1058*053f45beSAndroid Build Coastguard Worker return -1;
1059*053f45beSAndroid Build Coastguard Worker } else if (answer.nh.nlmsg_type == XFRM_MSG_NEWSA) {
1060*053f45beSAndroid Build Coastguard Worker if (xfrm_usersa_found(&answer.info, spi, src, dst, desc))
1061*053f45beSAndroid Build Coastguard Worker found = true;
1062*053f45beSAndroid Build Coastguard Worker }
1063*053f45beSAndroid Build Coastguard Worker }
1064*053f45beSAndroid Build Coastguard Worker }
1065*053f45beSAndroid Build Coastguard Worker
xfrm_set(int xfrm_sock,uint32_t * seq,struct in_addr src,struct in_addr dst,struct in_addr tunsrc,struct in_addr tundst,struct xfrm_desc * desc)1066*053f45beSAndroid Build Coastguard Worker static int xfrm_set(int xfrm_sock, uint32_t *seq,
1067*053f45beSAndroid Build Coastguard Worker struct in_addr src, struct in_addr dst,
1068*053f45beSAndroid Build Coastguard Worker struct in_addr tunsrc, struct in_addr tundst,
1069*053f45beSAndroid Build Coastguard Worker struct xfrm_desc *desc)
1070*053f45beSAndroid Build Coastguard Worker {
1071*053f45beSAndroid Build Coastguard Worker int err;
1072*053f45beSAndroid Build Coastguard Worker
1073*053f45beSAndroid Build Coastguard Worker err = xfrm_state_add(xfrm_sock, (*seq)++, gen_spi(src), src, dst, desc);
1074*053f45beSAndroid Build Coastguard Worker if (err) {
1075*053f45beSAndroid Build Coastguard Worker printk("Failed to add xfrm state");
1076*053f45beSAndroid Build Coastguard Worker return -1;
1077*053f45beSAndroid Build Coastguard Worker }
1078*053f45beSAndroid Build Coastguard Worker
1079*053f45beSAndroid Build Coastguard Worker err = xfrm_state_add(xfrm_sock, (*seq)++, gen_spi(src), dst, src, desc);
1080*053f45beSAndroid Build Coastguard Worker if (err) {
1081*053f45beSAndroid Build Coastguard Worker printk("Failed to add xfrm state");
1082*053f45beSAndroid Build Coastguard Worker return -1;
1083*053f45beSAndroid Build Coastguard Worker }
1084*053f45beSAndroid Build Coastguard Worker
1085*053f45beSAndroid Build Coastguard Worker /* Check dumps for XFRM_MSG_GETSA */
1086*053f45beSAndroid Build Coastguard Worker err = xfrm_state_check(xfrm_sock, (*seq)++, gen_spi(src), src, dst, desc);
1087*053f45beSAndroid Build Coastguard Worker err |= xfrm_state_check(xfrm_sock, (*seq)++, gen_spi(src), dst, src, desc);
1088*053f45beSAndroid Build Coastguard Worker if (err) {
1089*053f45beSAndroid Build Coastguard Worker printk("Failed to check xfrm state");
1090*053f45beSAndroid Build Coastguard Worker return -1;
1091*053f45beSAndroid Build Coastguard Worker }
1092*053f45beSAndroid Build Coastguard Worker
1093*053f45beSAndroid Build Coastguard Worker return 0;
1094*053f45beSAndroid Build Coastguard Worker }
1095*053f45beSAndroid Build Coastguard Worker
xfrm_policy_add(int xfrm_sock,uint32_t seq,uint32_t spi,struct in_addr src,struct in_addr dst,uint8_t dir,struct in_addr tunsrc,struct in_addr tundst,uint8_t proto)1096*053f45beSAndroid Build Coastguard Worker static int xfrm_policy_add(int xfrm_sock, uint32_t seq, uint32_t spi,
1097*053f45beSAndroid Build Coastguard Worker struct in_addr src, struct in_addr dst, uint8_t dir,
1098*053f45beSAndroid Build Coastguard Worker struct in_addr tunsrc, struct in_addr tundst, uint8_t proto)
1099*053f45beSAndroid Build Coastguard Worker {
1100*053f45beSAndroid Build Coastguard Worker struct {
1101*053f45beSAndroid Build Coastguard Worker struct nlmsghdr nh;
1102*053f45beSAndroid Build Coastguard Worker struct xfrm_userpolicy_info info;
1103*053f45beSAndroid Build Coastguard Worker char attrbuf[MAX_PAYLOAD];
1104*053f45beSAndroid Build Coastguard Worker } req;
1105*053f45beSAndroid Build Coastguard Worker struct xfrm_user_tmpl tmpl;
1106*053f45beSAndroid Build Coastguard Worker
1107*053f45beSAndroid Build Coastguard Worker memset(&req, 0, sizeof(req));
1108*053f45beSAndroid Build Coastguard Worker memset(&tmpl, 0, sizeof(tmpl));
1109*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.info));
1110*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_type = XFRM_MSG_NEWPOLICY;
1111*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1112*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_seq = seq;
1113*053f45beSAndroid Build Coastguard Worker
1114*053f45beSAndroid Build Coastguard Worker /* Fill selector. */
1115*053f45beSAndroid Build Coastguard Worker memcpy(&req.info.sel.daddr, &dst, sizeof(tundst));
1116*053f45beSAndroid Build Coastguard Worker memcpy(&req.info.sel.saddr, &src, sizeof(tunsrc));
1117*053f45beSAndroid Build Coastguard Worker req.info.sel.family = AF_INET;
1118*053f45beSAndroid Build Coastguard Worker req.info.sel.prefixlen_d = PREFIX_LEN;
1119*053f45beSAndroid Build Coastguard Worker req.info.sel.prefixlen_s = PREFIX_LEN;
1120*053f45beSAndroid Build Coastguard Worker
1121*053f45beSAndroid Build Coastguard Worker /* Fill lifteme_cfg */
1122*053f45beSAndroid Build Coastguard Worker req.info.lft.soft_byte_limit = XFRM_INF;
1123*053f45beSAndroid Build Coastguard Worker req.info.lft.hard_byte_limit = XFRM_INF;
1124*053f45beSAndroid Build Coastguard Worker req.info.lft.soft_packet_limit = XFRM_INF;
1125*053f45beSAndroid Build Coastguard Worker req.info.lft.hard_packet_limit = XFRM_INF;
1126*053f45beSAndroid Build Coastguard Worker
1127*053f45beSAndroid Build Coastguard Worker req.info.dir = dir;
1128*053f45beSAndroid Build Coastguard Worker
1129*053f45beSAndroid Build Coastguard Worker /* Fill tmpl */
1130*053f45beSAndroid Build Coastguard Worker memcpy(&tmpl.id.daddr, &dst, sizeof(dst));
1131*053f45beSAndroid Build Coastguard Worker /* Note: zero-spi cannot be deleted */
1132*053f45beSAndroid Build Coastguard Worker tmpl.id.spi = spi;
1133*053f45beSAndroid Build Coastguard Worker tmpl.id.proto = proto;
1134*053f45beSAndroid Build Coastguard Worker tmpl.family = AF_INET;
1135*053f45beSAndroid Build Coastguard Worker memcpy(&tmpl.saddr, &src, sizeof(src));
1136*053f45beSAndroid Build Coastguard Worker tmpl.mode = XFRM_MODE_TUNNEL;
1137*053f45beSAndroid Build Coastguard Worker tmpl.aalgos = (~(uint32_t)0);
1138*053f45beSAndroid Build Coastguard Worker tmpl.ealgos = (~(uint32_t)0);
1139*053f45beSAndroid Build Coastguard Worker tmpl.calgos = (~(uint32_t)0);
1140*053f45beSAndroid Build Coastguard Worker
1141*053f45beSAndroid Build Coastguard Worker if (rtattr_pack(&req.nh, sizeof(req), XFRMA_TMPL, &tmpl, sizeof(tmpl)))
1142*053f45beSAndroid Build Coastguard Worker return -1;
1143*053f45beSAndroid Build Coastguard Worker
1144*053f45beSAndroid Build Coastguard Worker if (send(xfrm_sock, &req, req.nh.nlmsg_len, 0) < 0) {
1145*053f45beSAndroid Build Coastguard Worker pr_err("send()");
1146*053f45beSAndroid Build Coastguard Worker return -1;
1147*053f45beSAndroid Build Coastguard Worker }
1148*053f45beSAndroid Build Coastguard Worker
1149*053f45beSAndroid Build Coastguard Worker return netlink_check_answer(xfrm_sock);
1150*053f45beSAndroid Build Coastguard Worker }
1151*053f45beSAndroid Build Coastguard Worker
xfrm_prepare(int xfrm_sock,uint32_t * seq,struct in_addr src,struct in_addr dst,struct in_addr tunsrc,struct in_addr tundst,uint8_t proto)1152*053f45beSAndroid Build Coastguard Worker static int xfrm_prepare(int xfrm_sock, uint32_t *seq,
1153*053f45beSAndroid Build Coastguard Worker struct in_addr src, struct in_addr dst,
1154*053f45beSAndroid Build Coastguard Worker struct in_addr tunsrc, struct in_addr tundst, uint8_t proto)
1155*053f45beSAndroid Build Coastguard Worker {
1156*053f45beSAndroid Build Coastguard Worker if (xfrm_policy_add(xfrm_sock, (*seq)++, gen_spi(src), src, dst,
1157*053f45beSAndroid Build Coastguard Worker XFRM_POLICY_OUT, tunsrc, tundst, proto)) {
1158*053f45beSAndroid Build Coastguard Worker printk("Failed to add xfrm policy");
1159*053f45beSAndroid Build Coastguard Worker return -1;
1160*053f45beSAndroid Build Coastguard Worker }
1161*053f45beSAndroid Build Coastguard Worker
1162*053f45beSAndroid Build Coastguard Worker if (xfrm_policy_add(xfrm_sock, (*seq)++, gen_spi(src), dst, src,
1163*053f45beSAndroid Build Coastguard Worker XFRM_POLICY_IN, tunsrc, tundst, proto)) {
1164*053f45beSAndroid Build Coastguard Worker printk("Failed to add xfrm policy");
1165*053f45beSAndroid Build Coastguard Worker return -1;
1166*053f45beSAndroid Build Coastguard Worker }
1167*053f45beSAndroid Build Coastguard Worker
1168*053f45beSAndroid Build Coastguard Worker return 0;
1169*053f45beSAndroid Build Coastguard Worker }
1170*053f45beSAndroid Build Coastguard Worker
xfrm_policy_del(int xfrm_sock,uint32_t seq,struct in_addr src,struct in_addr dst,uint8_t dir,struct in_addr tunsrc,struct in_addr tundst)1171*053f45beSAndroid Build Coastguard Worker static int xfrm_policy_del(int xfrm_sock, uint32_t seq,
1172*053f45beSAndroid Build Coastguard Worker struct in_addr src, struct in_addr dst, uint8_t dir,
1173*053f45beSAndroid Build Coastguard Worker struct in_addr tunsrc, struct in_addr tundst)
1174*053f45beSAndroid Build Coastguard Worker {
1175*053f45beSAndroid Build Coastguard Worker struct {
1176*053f45beSAndroid Build Coastguard Worker struct nlmsghdr nh;
1177*053f45beSAndroid Build Coastguard Worker struct xfrm_userpolicy_id id;
1178*053f45beSAndroid Build Coastguard Worker char attrbuf[MAX_PAYLOAD];
1179*053f45beSAndroid Build Coastguard Worker } req;
1180*053f45beSAndroid Build Coastguard Worker
1181*053f45beSAndroid Build Coastguard Worker memset(&req, 0, sizeof(req));
1182*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.id));
1183*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_type = XFRM_MSG_DELPOLICY;
1184*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1185*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_seq = seq;
1186*053f45beSAndroid Build Coastguard Worker
1187*053f45beSAndroid Build Coastguard Worker /* Fill id */
1188*053f45beSAndroid Build Coastguard Worker memcpy(&req.id.sel.daddr, &dst, sizeof(tundst));
1189*053f45beSAndroid Build Coastguard Worker memcpy(&req.id.sel.saddr, &src, sizeof(tunsrc));
1190*053f45beSAndroid Build Coastguard Worker req.id.sel.family = AF_INET;
1191*053f45beSAndroid Build Coastguard Worker req.id.sel.prefixlen_d = PREFIX_LEN;
1192*053f45beSAndroid Build Coastguard Worker req.id.sel.prefixlen_s = PREFIX_LEN;
1193*053f45beSAndroid Build Coastguard Worker req.id.dir = dir;
1194*053f45beSAndroid Build Coastguard Worker
1195*053f45beSAndroid Build Coastguard Worker if (send(xfrm_sock, &req, req.nh.nlmsg_len, 0) < 0) {
1196*053f45beSAndroid Build Coastguard Worker pr_err("send()");
1197*053f45beSAndroid Build Coastguard Worker return -1;
1198*053f45beSAndroid Build Coastguard Worker }
1199*053f45beSAndroid Build Coastguard Worker
1200*053f45beSAndroid Build Coastguard Worker return netlink_check_answer(xfrm_sock);
1201*053f45beSAndroid Build Coastguard Worker }
1202*053f45beSAndroid Build Coastguard Worker
xfrm_cleanup(int xfrm_sock,uint32_t * seq,struct in_addr src,struct in_addr dst,struct in_addr tunsrc,struct in_addr tundst)1203*053f45beSAndroid Build Coastguard Worker static int xfrm_cleanup(int xfrm_sock, uint32_t *seq,
1204*053f45beSAndroid Build Coastguard Worker struct in_addr src, struct in_addr dst,
1205*053f45beSAndroid Build Coastguard Worker struct in_addr tunsrc, struct in_addr tundst)
1206*053f45beSAndroid Build Coastguard Worker {
1207*053f45beSAndroid Build Coastguard Worker if (xfrm_policy_del(xfrm_sock, (*seq)++, src, dst,
1208*053f45beSAndroid Build Coastguard Worker XFRM_POLICY_OUT, tunsrc, tundst)) {
1209*053f45beSAndroid Build Coastguard Worker printk("Failed to add xfrm policy");
1210*053f45beSAndroid Build Coastguard Worker return -1;
1211*053f45beSAndroid Build Coastguard Worker }
1212*053f45beSAndroid Build Coastguard Worker
1213*053f45beSAndroid Build Coastguard Worker if (xfrm_policy_del(xfrm_sock, (*seq)++, dst, src,
1214*053f45beSAndroid Build Coastguard Worker XFRM_POLICY_IN, tunsrc, tundst)) {
1215*053f45beSAndroid Build Coastguard Worker printk("Failed to add xfrm policy");
1216*053f45beSAndroid Build Coastguard Worker return -1;
1217*053f45beSAndroid Build Coastguard Worker }
1218*053f45beSAndroid Build Coastguard Worker
1219*053f45beSAndroid Build Coastguard Worker return 0;
1220*053f45beSAndroid Build Coastguard Worker }
1221*053f45beSAndroid Build Coastguard Worker
xfrm_state_del(int xfrm_sock,uint32_t seq,uint32_t spi,struct in_addr src,struct in_addr dst,uint8_t proto)1222*053f45beSAndroid Build Coastguard Worker static int xfrm_state_del(int xfrm_sock, uint32_t seq, uint32_t spi,
1223*053f45beSAndroid Build Coastguard Worker struct in_addr src, struct in_addr dst, uint8_t proto)
1224*053f45beSAndroid Build Coastguard Worker {
1225*053f45beSAndroid Build Coastguard Worker struct {
1226*053f45beSAndroid Build Coastguard Worker struct nlmsghdr nh;
1227*053f45beSAndroid Build Coastguard Worker struct xfrm_usersa_id id;
1228*053f45beSAndroid Build Coastguard Worker char attrbuf[MAX_PAYLOAD];
1229*053f45beSAndroid Build Coastguard Worker } req;
1230*053f45beSAndroid Build Coastguard Worker xfrm_address_t saddr = {};
1231*053f45beSAndroid Build Coastguard Worker
1232*053f45beSAndroid Build Coastguard Worker memset(&req, 0, sizeof(req));
1233*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.id));
1234*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_type = XFRM_MSG_DELSA;
1235*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1236*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_seq = seq;
1237*053f45beSAndroid Build Coastguard Worker
1238*053f45beSAndroid Build Coastguard Worker memcpy(&req.id.daddr, &dst, sizeof(dst));
1239*053f45beSAndroid Build Coastguard Worker req.id.family = AF_INET;
1240*053f45beSAndroid Build Coastguard Worker req.id.proto = proto;
1241*053f45beSAndroid Build Coastguard Worker /* Note: zero-spi cannot be deleted */
1242*053f45beSAndroid Build Coastguard Worker req.id.spi = spi;
1243*053f45beSAndroid Build Coastguard Worker
1244*053f45beSAndroid Build Coastguard Worker memcpy(&saddr, &src, sizeof(src));
1245*053f45beSAndroid Build Coastguard Worker if (rtattr_pack(&req.nh, sizeof(req), XFRMA_SRCADDR, &saddr, sizeof(saddr)))
1246*053f45beSAndroid Build Coastguard Worker return -1;
1247*053f45beSAndroid Build Coastguard Worker
1248*053f45beSAndroid Build Coastguard Worker if (send(xfrm_sock, &req, req.nh.nlmsg_len, 0) < 0) {
1249*053f45beSAndroid Build Coastguard Worker pr_err("send()");
1250*053f45beSAndroid Build Coastguard Worker return -1;
1251*053f45beSAndroid Build Coastguard Worker }
1252*053f45beSAndroid Build Coastguard Worker
1253*053f45beSAndroid Build Coastguard Worker return netlink_check_answer(xfrm_sock);
1254*053f45beSAndroid Build Coastguard Worker }
1255*053f45beSAndroid Build Coastguard Worker
xfrm_delete(int xfrm_sock,uint32_t * seq,struct in_addr src,struct in_addr dst,struct in_addr tunsrc,struct in_addr tundst,uint8_t proto)1256*053f45beSAndroid Build Coastguard Worker static int xfrm_delete(int xfrm_sock, uint32_t *seq,
1257*053f45beSAndroid Build Coastguard Worker struct in_addr src, struct in_addr dst,
1258*053f45beSAndroid Build Coastguard Worker struct in_addr tunsrc, struct in_addr tundst, uint8_t proto)
1259*053f45beSAndroid Build Coastguard Worker {
1260*053f45beSAndroid Build Coastguard Worker if (xfrm_state_del(xfrm_sock, (*seq)++, gen_spi(src), src, dst, proto)) {
1261*053f45beSAndroid Build Coastguard Worker printk("Failed to remove xfrm state");
1262*053f45beSAndroid Build Coastguard Worker return -1;
1263*053f45beSAndroid Build Coastguard Worker }
1264*053f45beSAndroid Build Coastguard Worker
1265*053f45beSAndroid Build Coastguard Worker if (xfrm_state_del(xfrm_sock, (*seq)++, gen_spi(src), dst, src, proto)) {
1266*053f45beSAndroid Build Coastguard Worker printk("Failed to remove xfrm state");
1267*053f45beSAndroid Build Coastguard Worker return -1;
1268*053f45beSAndroid Build Coastguard Worker }
1269*053f45beSAndroid Build Coastguard Worker
1270*053f45beSAndroid Build Coastguard Worker return 0;
1271*053f45beSAndroid Build Coastguard Worker }
1272*053f45beSAndroid Build Coastguard Worker
xfrm_state_allocspi(int xfrm_sock,uint32_t * seq,uint32_t spi,uint8_t proto)1273*053f45beSAndroid Build Coastguard Worker static int xfrm_state_allocspi(int xfrm_sock, uint32_t *seq,
1274*053f45beSAndroid Build Coastguard Worker uint32_t spi, uint8_t proto)
1275*053f45beSAndroid Build Coastguard Worker {
1276*053f45beSAndroid Build Coastguard Worker struct {
1277*053f45beSAndroid Build Coastguard Worker struct nlmsghdr nh;
1278*053f45beSAndroid Build Coastguard Worker struct xfrm_userspi_info spi;
1279*053f45beSAndroid Build Coastguard Worker } req;
1280*053f45beSAndroid Build Coastguard Worker struct {
1281*053f45beSAndroid Build Coastguard Worker struct nlmsghdr nh;
1282*053f45beSAndroid Build Coastguard Worker union {
1283*053f45beSAndroid Build Coastguard Worker struct xfrm_usersa_info info;
1284*053f45beSAndroid Build Coastguard Worker int error;
1285*053f45beSAndroid Build Coastguard Worker };
1286*053f45beSAndroid Build Coastguard Worker } answer;
1287*053f45beSAndroid Build Coastguard Worker
1288*053f45beSAndroid Build Coastguard Worker memset(&req, 0, sizeof(req));
1289*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.spi));
1290*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_type = XFRM_MSG_ALLOCSPI;
1291*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_flags = NLM_F_REQUEST;
1292*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_seq = (*seq)++;
1293*053f45beSAndroid Build Coastguard Worker
1294*053f45beSAndroid Build Coastguard Worker req.spi.info.family = AF_INET;
1295*053f45beSAndroid Build Coastguard Worker req.spi.min = spi;
1296*053f45beSAndroid Build Coastguard Worker req.spi.max = spi;
1297*053f45beSAndroid Build Coastguard Worker req.spi.info.id.proto = proto;
1298*053f45beSAndroid Build Coastguard Worker
1299*053f45beSAndroid Build Coastguard Worker if (send(xfrm_sock, &req, req.nh.nlmsg_len, 0) < 0) {
1300*053f45beSAndroid Build Coastguard Worker pr_err("send()");
1301*053f45beSAndroid Build Coastguard Worker return KSFT_FAIL;
1302*053f45beSAndroid Build Coastguard Worker }
1303*053f45beSAndroid Build Coastguard Worker
1304*053f45beSAndroid Build Coastguard Worker if (recv(xfrm_sock, &answer, sizeof(answer), 0) < 0) {
1305*053f45beSAndroid Build Coastguard Worker pr_err("recv()");
1306*053f45beSAndroid Build Coastguard Worker return KSFT_FAIL;
1307*053f45beSAndroid Build Coastguard Worker } else if (answer.nh.nlmsg_type == XFRM_MSG_NEWSA) {
1308*053f45beSAndroid Build Coastguard Worker uint32_t new_spi = htonl(answer.info.id.spi);
1309*053f45beSAndroid Build Coastguard Worker
1310*053f45beSAndroid Build Coastguard Worker if (new_spi != spi) {
1311*053f45beSAndroid Build Coastguard Worker printk("allocated spi is different from requested: %#x != %#x",
1312*053f45beSAndroid Build Coastguard Worker new_spi, spi);
1313*053f45beSAndroid Build Coastguard Worker return KSFT_FAIL;
1314*053f45beSAndroid Build Coastguard Worker }
1315*053f45beSAndroid Build Coastguard Worker return KSFT_PASS;
1316*053f45beSAndroid Build Coastguard Worker } else if (answer.nh.nlmsg_type != NLMSG_ERROR) {
1317*053f45beSAndroid Build Coastguard Worker printk("expected NLMSG_ERROR, got %d", (int)answer.nh.nlmsg_type);
1318*053f45beSAndroid Build Coastguard Worker return KSFT_FAIL;
1319*053f45beSAndroid Build Coastguard Worker }
1320*053f45beSAndroid Build Coastguard Worker
1321*053f45beSAndroid Build Coastguard Worker printk("NLMSG_ERROR: %d: %s", answer.error, strerror(-answer.error));
1322*053f45beSAndroid Build Coastguard Worker return (answer.error) ? KSFT_FAIL : KSFT_PASS;
1323*053f45beSAndroid Build Coastguard Worker }
1324*053f45beSAndroid Build Coastguard Worker
netlink_sock_bind(int * sock,uint32_t * seq,int proto,uint32_t groups)1325*053f45beSAndroid Build Coastguard Worker static int netlink_sock_bind(int *sock, uint32_t *seq, int proto, uint32_t groups)
1326*053f45beSAndroid Build Coastguard Worker {
1327*053f45beSAndroid Build Coastguard Worker struct sockaddr_nl snl = {};
1328*053f45beSAndroid Build Coastguard Worker socklen_t addr_len;
1329*053f45beSAndroid Build Coastguard Worker int ret = -1;
1330*053f45beSAndroid Build Coastguard Worker
1331*053f45beSAndroid Build Coastguard Worker snl.nl_family = AF_NETLINK;
1332*053f45beSAndroid Build Coastguard Worker snl.nl_groups = groups;
1333*053f45beSAndroid Build Coastguard Worker
1334*053f45beSAndroid Build Coastguard Worker if (netlink_sock(sock, seq, proto)) {
1335*053f45beSAndroid Build Coastguard Worker printk("Failed to open xfrm netlink socket");
1336*053f45beSAndroid Build Coastguard Worker return -1;
1337*053f45beSAndroid Build Coastguard Worker }
1338*053f45beSAndroid Build Coastguard Worker
1339*053f45beSAndroid Build Coastguard Worker if (bind(*sock, (struct sockaddr *)&snl, sizeof(snl)) < 0) {
1340*053f45beSAndroid Build Coastguard Worker pr_err("bind()");
1341*053f45beSAndroid Build Coastguard Worker goto out_close;
1342*053f45beSAndroid Build Coastguard Worker }
1343*053f45beSAndroid Build Coastguard Worker
1344*053f45beSAndroid Build Coastguard Worker addr_len = sizeof(snl);
1345*053f45beSAndroid Build Coastguard Worker if (getsockname(*sock, (struct sockaddr *)&snl, &addr_len) < 0) {
1346*053f45beSAndroid Build Coastguard Worker pr_err("getsockname()");
1347*053f45beSAndroid Build Coastguard Worker goto out_close;
1348*053f45beSAndroid Build Coastguard Worker }
1349*053f45beSAndroid Build Coastguard Worker if (addr_len != sizeof(snl)) {
1350*053f45beSAndroid Build Coastguard Worker printk("Wrong address length %d", addr_len);
1351*053f45beSAndroid Build Coastguard Worker goto out_close;
1352*053f45beSAndroid Build Coastguard Worker }
1353*053f45beSAndroid Build Coastguard Worker if (snl.nl_family != AF_NETLINK) {
1354*053f45beSAndroid Build Coastguard Worker printk("Wrong address family %d", snl.nl_family);
1355*053f45beSAndroid Build Coastguard Worker goto out_close;
1356*053f45beSAndroid Build Coastguard Worker }
1357*053f45beSAndroid Build Coastguard Worker return 0;
1358*053f45beSAndroid Build Coastguard Worker
1359*053f45beSAndroid Build Coastguard Worker out_close:
1360*053f45beSAndroid Build Coastguard Worker close(*sock);
1361*053f45beSAndroid Build Coastguard Worker return ret;
1362*053f45beSAndroid Build Coastguard Worker }
1363*053f45beSAndroid Build Coastguard Worker
xfrm_monitor_acquire(int xfrm_sock,uint32_t * seq,unsigned int nr)1364*053f45beSAndroid Build Coastguard Worker static int xfrm_monitor_acquire(int xfrm_sock, uint32_t *seq, unsigned int nr)
1365*053f45beSAndroid Build Coastguard Worker {
1366*053f45beSAndroid Build Coastguard Worker struct {
1367*053f45beSAndroid Build Coastguard Worker struct nlmsghdr nh;
1368*053f45beSAndroid Build Coastguard Worker union {
1369*053f45beSAndroid Build Coastguard Worker struct xfrm_user_acquire acq;
1370*053f45beSAndroid Build Coastguard Worker int error;
1371*053f45beSAndroid Build Coastguard Worker };
1372*053f45beSAndroid Build Coastguard Worker char attrbuf[MAX_PAYLOAD];
1373*053f45beSAndroid Build Coastguard Worker } req;
1374*053f45beSAndroid Build Coastguard Worker struct xfrm_user_tmpl xfrm_tmpl = {};
1375*053f45beSAndroid Build Coastguard Worker int xfrm_listen = -1, ret = KSFT_FAIL;
1376*053f45beSAndroid Build Coastguard Worker uint32_t seq_listen;
1377*053f45beSAndroid Build Coastguard Worker
1378*053f45beSAndroid Build Coastguard Worker if (netlink_sock_bind(&xfrm_listen, &seq_listen, NETLINK_XFRM, XFRMNLGRP_ACQUIRE))
1379*053f45beSAndroid Build Coastguard Worker return KSFT_FAIL;
1380*053f45beSAndroid Build Coastguard Worker
1381*053f45beSAndroid Build Coastguard Worker memset(&req, 0, sizeof(req));
1382*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.acq));
1383*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_type = XFRM_MSG_ACQUIRE;
1384*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1385*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_seq = (*seq)++;
1386*053f45beSAndroid Build Coastguard Worker
1387*053f45beSAndroid Build Coastguard Worker req.acq.policy.sel.family = AF_INET;
1388*053f45beSAndroid Build Coastguard Worker req.acq.aalgos = 0xfeed;
1389*053f45beSAndroid Build Coastguard Worker req.acq.ealgos = 0xbaad;
1390*053f45beSAndroid Build Coastguard Worker req.acq.calgos = 0xbabe;
1391*053f45beSAndroid Build Coastguard Worker
1392*053f45beSAndroid Build Coastguard Worker xfrm_tmpl.family = AF_INET;
1393*053f45beSAndroid Build Coastguard Worker xfrm_tmpl.id.proto = IPPROTO_ESP;
1394*053f45beSAndroid Build Coastguard Worker if (rtattr_pack(&req.nh, sizeof(req), XFRMA_TMPL, &xfrm_tmpl, sizeof(xfrm_tmpl)))
1395*053f45beSAndroid Build Coastguard Worker goto out_close;
1396*053f45beSAndroid Build Coastguard Worker
1397*053f45beSAndroid Build Coastguard Worker if (send(xfrm_sock, &req, req.nh.nlmsg_len, 0) < 0) {
1398*053f45beSAndroid Build Coastguard Worker pr_err("send()");
1399*053f45beSAndroid Build Coastguard Worker goto out_close;
1400*053f45beSAndroid Build Coastguard Worker }
1401*053f45beSAndroid Build Coastguard Worker
1402*053f45beSAndroid Build Coastguard Worker if (recv(xfrm_sock, &req, sizeof(req), 0) < 0) {
1403*053f45beSAndroid Build Coastguard Worker pr_err("recv()");
1404*053f45beSAndroid Build Coastguard Worker goto out_close;
1405*053f45beSAndroid Build Coastguard Worker } else if (req.nh.nlmsg_type != NLMSG_ERROR) {
1406*053f45beSAndroid Build Coastguard Worker printk("expected NLMSG_ERROR, got %d", (int)req.nh.nlmsg_type);
1407*053f45beSAndroid Build Coastguard Worker goto out_close;
1408*053f45beSAndroid Build Coastguard Worker }
1409*053f45beSAndroid Build Coastguard Worker
1410*053f45beSAndroid Build Coastguard Worker if (req.error) {
1411*053f45beSAndroid Build Coastguard Worker printk("NLMSG_ERROR: %d: %s", req.error, strerror(-req.error));
1412*053f45beSAndroid Build Coastguard Worker ret = req.error;
1413*053f45beSAndroid Build Coastguard Worker goto out_close;
1414*053f45beSAndroid Build Coastguard Worker }
1415*053f45beSAndroid Build Coastguard Worker
1416*053f45beSAndroid Build Coastguard Worker if (recv(xfrm_listen, &req, sizeof(req), 0) < 0) {
1417*053f45beSAndroid Build Coastguard Worker pr_err("recv()");
1418*053f45beSAndroid Build Coastguard Worker goto out_close;
1419*053f45beSAndroid Build Coastguard Worker }
1420*053f45beSAndroid Build Coastguard Worker
1421*053f45beSAndroid Build Coastguard Worker if (req.acq.aalgos != 0xfeed || req.acq.ealgos != 0xbaad
1422*053f45beSAndroid Build Coastguard Worker || req.acq.calgos != 0xbabe) {
1423*053f45beSAndroid Build Coastguard Worker printk("xfrm_user_acquire has changed %x %x %x",
1424*053f45beSAndroid Build Coastguard Worker req.acq.aalgos, req.acq.ealgos, req.acq.calgos);
1425*053f45beSAndroid Build Coastguard Worker goto out_close;
1426*053f45beSAndroid Build Coastguard Worker }
1427*053f45beSAndroid Build Coastguard Worker
1428*053f45beSAndroid Build Coastguard Worker ret = KSFT_PASS;
1429*053f45beSAndroid Build Coastguard Worker out_close:
1430*053f45beSAndroid Build Coastguard Worker close(xfrm_listen);
1431*053f45beSAndroid Build Coastguard Worker return ret;
1432*053f45beSAndroid Build Coastguard Worker }
1433*053f45beSAndroid Build Coastguard Worker
xfrm_expire_state(int xfrm_sock,uint32_t * seq,unsigned int nr,struct xfrm_desc * desc)1434*053f45beSAndroid Build Coastguard Worker static int xfrm_expire_state(int xfrm_sock, uint32_t *seq,
1435*053f45beSAndroid Build Coastguard Worker unsigned int nr, struct xfrm_desc *desc)
1436*053f45beSAndroid Build Coastguard Worker {
1437*053f45beSAndroid Build Coastguard Worker struct {
1438*053f45beSAndroid Build Coastguard Worker struct nlmsghdr nh;
1439*053f45beSAndroid Build Coastguard Worker union {
1440*053f45beSAndroid Build Coastguard Worker struct xfrm_user_expire expire;
1441*053f45beSAndroid Build Coastguard Worker int error;
1442*053f45beSAndroid Build Coastguard Worker };
1443*053f45beSAndroid Build Coastguard Worker } req;
1444*053f45beSAndroid Build Coastguard Worker struct in_addr src, dst;
1445*053f45beSAndroid Build Coastguard Worker int xfrm_listen = -1, ret = KSFT_FAIL;
1446*053f45beSAndroid Build Coastguard Worker uint32_t seq_listen;
1447*053f45beSAndroid Build Coastguard Worker
1448*053f45beSAndroid Build Coastguard Worker src = inet_makeaddr(INADDR_B, child_ip(nr));
1449*053f45beSAndroid Build Coastguard Worker dst = inet_makeaddr(INADDR_B, grchild_ip(nr));
1450*053f45beSAndroid Build Coastguard Worker
1451*053f45beSAndroid Build Coastguard Worker if (xfrm_state_add(xfrm_sock, (*seq)++, gen_spi(src), src, dst, desc)) {
1452*053f45beSAndroid Build Coastguard Worker printk("Failed to add xfrm state");
1453*053f45beSAndroid Build Coastguard Worker return KSFT_FAIL;
1454*053f45beSAndroid Build Coastguard Worker }
1455*053f45beSAndroid Build Coastguard Worker
1456*053f45beSAndroid Build Coastguard Worker if (netlink_sock_bind(&xfrm_listen, &seq_listen, NETLINK_XFRM, XFRMNLGRP_EXPIRE))
1457*053f45beSAndroid Build Coastguard Worker return KSFT_FAIL;
1458*053f45beSAndroid Build Coastguard Worker
1459*053f45beSAndroid Build Coastguard Worker memset(&req, 0, sizeof(req));
1460*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.expire));
1461*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_type = XFRM_MSG_EXPIRE;
1462*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1463*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_seq = (*seq)++;
1464*053f45beSAndroid Build Coastguard Worker
1465*053f45beSAndroid Build Coastguard Worker memcpy(&req.expire.state.id.daddr, &dst, sizeof(dst));
1466*053f45beSAndroid Build Coastguard Worker req.expire.state.id.spi = gen_spi(src);
1467*053f45beSAndroid Build Coastguard Worker req.expire.state.id.proto = desc->proto;
1468*053f45beSAndroid Build Coastguard Worker req.expire.state.family = AF_INET;
1469*053f45beSAndroid Build Coastguard Worker req.expire.hard = 0xff;
1470*053f45beSAndroid Build Coastguard Worker
1471*053f45beSAndroid Build Coastguard Worker if (send(xfrm_sock, &req, req.nh.nlmsg_len, 0) < 0) {
1472*053f45beSAndroid Build Coastguard Worker pr_err("send()");
1473*053f45beSAndroid Build Coastguard Worker goto out_close;
1474*053f45beSAndroid Build Coastguard Worker }
1475*053f45beSAndroid Build Coastguard Worker
1476*053f45beSAndroid Build Coastguard Worker if (recv(xfrm_sock, &req, sizeof(req), 0) < 0) {
1477*053f45beSAndroid Build Coastguard Worker pr_err("recv()");
1478*053f45beSAndroid Build Coastguard Worker goto out_close;
1479*053f45beSAndroid Build Coastguard Worker } else if (req.nh.nlmsg_type != NLMSG_ERROR) {
1480*053f45beSAndroid Build Coastguard Worker printk("expected NLMSG_ERROR, got %d", (int)req.nh.nlmsg_type);
1481*053f45beSAndroid Build Coastguard Worker goto out_close;
1482*053f45beSAndroid Build Coastguard Worker }
1483*053f45beSAndroid Build Coastguard Worker
1484*053f45beSAndroid Build Coastguard Worker if (req.error) {
1485*053f45beSAndroid Build Coastguard Worker printk("NLMSG_ERROR: %d: %s", req.error, strerror(-req.error));
1486*053f45beSAndroid Build Coastguard Worker ret = req.error;
1487*053f45beSAndroid Build Coastguard Worker goto out_close;
1488*053f45beSAndroid Build Coastguard Worker }
1489*053f45beSAndroid Build Coastguard Worker
1490*053f45beSAndroid Build Coastguard Worker if (recv(xfrm_listen, &req, sizeof(req), 0) < 0) {
1491*053f45beSAndroid Build Coastguard Worker pr_err("recv()");
1492*053f45beSAndroid Build Coastguard Worker goto out_close;
1493*053f45beSAndroid Build Coastguard Worker }
1494*053f45beSAndroid Build Coastguard Worker
1495*053f45beSAndroid Build Coastguard Worker if (req.expire.hard != 0x1) {
1496*053f45beSAndroid Build Coastguard Worker printk("expire.hard is not set: %x", req.expire.hard);
1497*053f45beSAndroid Build Coastguard Worker goto out_close;
1498*053f45beSAndroid Build Coastguard Worker }
1499*053f45beSAndroid Build Coastguard Worker
1500*053f45beSAndroid Build Coastguard Worker ret = KSFT_PASS;
1501*053f45beSAndroid Build Coastguard Worker out_close:
1502*053f45beSAndroid Build Coastguard Worker close(xfrm_listen);
1503*053f45beSAndroid Build Coastguard Worker return ret;
1504*053f45beSAndroid Build Coastguard Worker }
1505*053f45beSAndroid Build Coastguard Worker
xfrm_expire_policy(int xfrm_sock,uint32_t * seq,unsigned int nr,struct xfrm_desc * desc)1506*053f45beSAndroid Build Coastguard Worker static int xfrm_expire_policy(int xfrm_sock, uint32_t *seq,
1507*053f45beSAndroid Build Coastguard Worker unsigned int nr, struct xfrm_desc *desc)
1508*053f45beSAndroid Build Coastguard Worker {
1509*053f45beSAndroid Build Coastguard Worker struct {
1510*053f45beSAndroid Build Coastguard Worker struct nlmsghdr nh;
1511*053f45beSAndroid Build Coastguard Worker union {
1512*053f45beSAndroid Build Coastguard Worker struct xfrm_user_polexpire expire;
1513*053f45beSAndroid Build Coastguard Worker int error;
1514*053f45beSAndroid Build Coastguard Worker };
1515*053f45beSAndroid Build Coastguard Worker } req;
1516*053f45beSAndroid Build Coastguard Worker struct in_addr src, dst, tunsrc, tundst;
1517*053f45beSAndroid Build Coastguard Worker int xfrm_listen = -1, ret = KSFT_FAIL;
1518*053f45beSAndroid Build Coastguard Worker uint32_t seq_listen;
1519*053f45beSAndroid Build Coastguard Worker
1520*053f45beSAndroid Build Coastguard Worker src = inet_makeaddr(INADDR_B, child_ip(nr));
1521*053f45beSAndroid Build Coastguard Worker dst = inet_makeaddr(INADDR_B, grchild_ip(nr));
1522*053f45beSAndroid Build Coastguard Worker tunsrc = inet_makeaddr(INADDR_A, child_ip(nr));
1523*053f45beSAndroid Build Coastguard Worker tundst = inet_makeaddr(INADDR_A, grchild_ip(nr));
1524*053f45beSAndroid Build Coastguard Worker
1525*053f45beSAndroid Build Coastguard Worker if (xfrm_policy_add(xfrm_sock, (*seq)++, gen_spi(src), src, dst,
1526*053f45beSAndroid Build Coastguard Worker XFRM_POLICY_OUT, tunsrc, tundst, desc->proto)) {
1527*053f45beSAndroid Build Coastguard Worker printk("Failed to add xfrm policy");
1528*053f45beSAndroid Build Coastguard Worker return KSFT_FAIL;
1529*053f45beSAndroid Build Coastguard Worker }
1530*053f45beSAndroid Build Coastguard Worker
1531*053f45beSAndroid Build Coastguard Worker if (netlink_sock_bind(&xfrm_listen, &seq_listen, NETLINK_XFRM, XFRMNLGRP_EXPIRE))
1532*053f45beSAndroid Build Coastguard Worker return KSFT_FAIL;
1533*053f45beSAndroid Build Coastguard Worker
1534*053f45beSAndroid Build Coastguard Worker memset(&req, 0, sizeof(req));
1535*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.expire));
1536*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_type = XFRM_MSG_POLEXPIRE;
1537*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1538*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_seq = (*seq)++;
1539*053f45beSAndroid Build Coastguard Worker
1540*053f45beSAndroid Build Coastguard Worker /* Fill selector. */
1541*053f45beSAndroid Build Coastguard Worker memcpy(&req.expire.pol.sel.daddr, &dst, sizeof(tundst));
1542*053f45beSAndroid Build Coastguard Worker memcpy(&req.expire.pol.sel.saddr, &src, sizeof(tunsrc));
1543*053f45beSAndroid Build Coastguard Worker req.expire.pol.sel.family = AF_INET;
1544*053f45beSAndroid Build Coastguard Worker req.expire.pol.sel.prefixlen_d = PREFIX_LEN;
1545*053f45beSAndroid Build Coastguard Worker req.expire.pol.sel.prefixlen_s = PREFIX_LEN;
1546*053f45beSAndroid Build Coastguard Worker req.expire.pol.dir = XFRM_POLICY_OUT;
1547*053f45beSAndroid Build Coastguard Worker req.expire.hard = 0xff;
1548*053f45beSAndroid Build Coastguard Worker
1549*053f45beSAndroid Build Coastguard Worker if (send(xfrm_sock, &req, req.nh.nlmsg_len, 0) < 0) {
1550*053f45beSAndroid Build Coastguard Worker pr_err("send()");
1551*053f45beSAndroid Build Coastguard Worker goto out_close;
1552*053f45beSAndroid Build Coastguard Worker }
1553*053f45beSAndroid Build Coastguard Worker
1554*053f45beSAndroid Build Coastguard Worker if (recv(xfrm_sock, &req, sizeof(req), 0) < 0) {
1555*053f45beSAndroid Build Coastguard Worker pr_err("recv()");
1556*053f45beSAndroid Build Coastguard Worker goto out_close;
1557*053f45beSAndroid Build Coastguard Worker } else if (req.nh.nlmsg_type != NLMSG_ERROR) {
1558*053f45beSAndroid Build Coastguard Worker printk("expected NLMSG_ERROR, got %d", (int)req.nh.nlmsg_type);
1559*053f45beSAndroid Build Coastguard Worker goto out_close;
1560*053f45beSAndroid Build Coastguard Worker }
1561*053f45beSAndroid Build Coastguard Worker
1562*053f45beSAndroid Build Coastguard Worker if (req.error) {
1563*053f45beSAndroid Build Coastguard Worker printk("NLMSG_ERROR: %d: %s", req.error, strerror(-req.error));
1564*053f45beSAndroid Build Coastguard Worker ret = req.error;
1565*053f45beSAndroid Build Coastguard Worker goto out_close;
1566*053f45beSAndroid Build Coastguard Worker }
1567*053f45beSAndroid Build Coastguard Worker
1568*053f45beSAndroid Build Coastguard Worker if (recv(xfrm_listen, &req, sizeof(req), 0) < 0) {
1569*053f45beSAndroid Build Coastguard Worker pr_err("recv()");
1570*053f45beSAndroid Build Coastguard Worker goto out_close;
1571*053f45beSAndroid Build Coastguard Worker }
1572*053f45beSAndroid Build Coastguard Worker
1573*053f45beSAndroid Build Coastguard Worker if (req.expire.hard != 0x1) {
1574*053f45beSAndroid Build Coastguard Worker printk("expire.hard is not set: %x", req.expire.hard);
1575*053f45beSAndroid Build Coastguard Worker goto out_close;
1576*053f45beSAndroid Build Coastguard Worker }
1577*053f45beSAndroid Build Coastguard Worker
1578*053f45beSAndroid Build Coastguard Worker ret = KSFT_PASS;
1579*053f45beSAndroid Build Coastguard Worker out_close:
1580*053f45beSAndroid Build Coastguard Worker close(xfrm_listen);
1581*053f45beSAndroid Build Coastguard Worker return ret;
1582*053f45beSAndroid Build Coastguard Worker }
1583*053f45beSAndroid Build Coastguard Worker
xfrm_spdinfo_set_thresh(int xfrm_sock,uint32_t * seq,unsigned thresh4_l,unsigned thresh4_r,unsigned thresh6_l,unsigned thresh6_r,bool add_bad_attr)1584*053f45beSAndroid Build Coastguard Worker static int xfrm_spdinfo_set_thresh(int xfrm_sock, uint32_t *seq,
1585*053f45beSAndroid Build Coastguard Worker unsigned thresh4_l, unsigned thresh4_r,
1586*053f45beSAndroid Build Coastguard Worker unsigned thresh6_l, unsigned thresh6_r,
1587*053f45beSAndroid Build Coastguard Worker bool add_bad_attr)
1588*053f45beSAndroid Build Coastguard Worker
1589*053f45beSAndroid Build Coastguard Worker {
1590*053f45beSAndroid Build Coastguard Worker struct {
1591*053f45beSAndroid Build Coastguard Worker struct nlmsghdr nh;
1592*053f45beSAndroid Build Coastguard Worker union {
1593*053f45beSAndroid Build Coastguard Worker uint32_t unused;
1594*053f45beSAndroid Build Coastguard Worker int error;
1595*053f45beSAndroid Build Coastguard Worker };
1596*053f45beSAndroid Build Coastguard Worker char attrbuf[MAX_PAYLOAD];
1597*053f45beSAndroid Build Coastguard Worker } req;
1598*053f45beSAndroid Build Coastguard Worker struct xfrmu_spdhthresh thresh;
1599*053f45beSAndroid Build Coastguard Worker
1600*053f45beSAndroid Build Coastguard Worker memset(&req, 0, sizeof(req));
1601*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.unused));
1602*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_type = XFRM_MSG_NEWSPDINFO;
1603*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1604*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_seq = (*seq)++;
1605*053f45beSAndroid Build Coastguard Worker
1606*053f45beSAndroid Build Coastguard Worker thresh.lbits = thresh4_l;
1607*053f45beSAndroid Build Coastguard Worker thresh.rbits = thresh4_r;
1608*053f45beSAndroid Build Coastguard Worker if (rtattr_pack(&req.nh, sizeof(req), XFRMA_SPD_IPV4_HTHRESH, &thresh, sizeof(thresh)))
1609*053f45beSAndroid Build Coastguard Worker return -1;
1610*053f45beSAndroid Build Coastguard Worker
1611*053f45beSAndroid Build Coastguard Worker thresh.lbits = thresh6_l;
1612*053f45beSAndroid Build Coastguard Worker thresh.rbits = thresh6_r;
1613*053f45beSAndroid Build Coastguard Worker if (rtattr_pack(&req.nh, sizeof(req), XFRMA_SPD_IPV6_HTHRESH, &thresh, sizeof(thresh)))
1614*053f45beSAndroid Build Coastguard Worker return -1;
1615*053f45beSAndroid Build Coastguard Worker
1616*053f45beSAndroid Build Coastguard Worker if (add_bad_attr) {
1617*053f45beSAndroid Build Coastguard Worker BUILD_BUG_ON(XFRMA_IF_ID <= XFRMA_SPD_MAX + 1);
1618*053f45beSAndroid Build Coastguard Worker if (rtattr_pack(&req.nh, sizeof(req), XFRMA_IF_ID, NULL, 0)) {
1619*053f45beSAndroid Build Coastguard Worker pr_err("adding attribute failed: no space");
1620*053f45beSAndroid Build Coastguard Worker return -1;
1621*053f45beSAndroid Build Coastguard Worker }
1622*053f45beSAndroid Build Coastguard Worker }
1623*053f45beSAndroid Build Coastguard Worker
1624*053f45beSAndroid Build Coastguard Worker if (send(xfrm_sock, &req, req.nh.nlmsg_len, 0) < 0) {
1625*053f45beSAndroid Build Coastguard Worker pr_err("send()");
1626*053f45beSAndroid Build Coastguard Worker return -1;
1627*053f45beSAndroid Build Coastguard Worker }
1628*053f45beSAndroid Build Coastguard Worker
1629*053f45beSAndroid Build Coastguard Worker if (recv(xfrm_sock, &req, sizeof(req), 0) < 0) {
1630*053f45beSAndroid Build Coastguard Worker pr_err("recv()");
1631*053f45beSAndroid Build Coastguard Worker return -1;
1632*053f45beSAndroid Build Coastguard Worker } else if (req.nh.nlmsg_type != NLMSG_ERROR) {
1633*053f45beSAndroid Build Coastguard Worker printk("expected NLMSG_ERROR, got %d", (int)req.nh.nlmsg_type);
1634*053f45beSAndroid Build Coastguard Worker return -1;
1635*053f45beSAndroid Build Coastguard Worker }
1636*053f45beSAndroid Build Coastguard Worker
1637*053f45beSAndroid Build Coastguard Worker if (req.error) {
1638*053f45beSAndroid Build Coastguard Worker printk("NLMSG_ERROR: %d: %s", req.error, strerror(-req.error));
1639*053f45beSAndroid Build Coastguard Worker return -1;
1640*053f45beSAndroid Build Coastguard Worker }
1641*053f45beSAndroid Build Coastguard Worker
1642*053f45beSAndroid Build Coastguard Worker return 0;
1643*053f45beSAndroid Build Coastguard Worker }
1644*053f45beSAndroid Build Coastguard Worker
xfrm_spdinfo_attrs(int xfrm_sock,uint32_t * seq)1645*053f45beSAndroid Build Coastguard Worker static int xfrm_spdinfo_attrs(int xfrm_sock, uint32_t *seq)
1646*053f45beSAndroid Build Coastguard Worker {
1647*053f45beSAndroid Build Coastguard Worker struct {
1648*053f45beSAndroid Build Coastguard Worker struct nlmsghdr nh;
1649*053f45beSAndroid Build Coastguard Worker union {
1650*053f45beSAndroid Build Coastguard Worker uint32_t unused;
1651*053f45beSAndroid Build Coastguard Worker int error;
1652*053f45beSAndroid Build Coastguard Worker };
1653*053f45beSAndroid Build Coastguard Worker char attrbuf[MAX_PAYLOAD];
1654*053f45beSAndroid Build Coastguard Worker } req;
1655*053f45beSAndroid Build Coastguard Worker
1656*053f45beSAndroid Build Coastguard Worker if (xfrm_spdinfo_set_thresh(xfrm_sock, seq, 32, 31, 120, 16, false)) {
1657*053f45beSAndroid Build Coastguard Worker pr_err("Can't set SPD HTHRESH");
1658*053f45beSAndroid Build Coastguard Worker return KSFT_FAIL;
1659*053f45beSAndroid Build Coastguard Worker }
1660*053f45beSAndroid Build Coastguard Worker
1661*053f45beSAndroid Build Coastguard Worker memset(&req, 0, sizeof(req));
1662*053f45beSAndroid Build Coastguard Worker
1663*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.unused));
1664*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_type = XFRM_MSG_GETSPDINFO;
1665*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_flags = NLM_F_REQUEST;
1666*053f45beSAndroid Build Coastguard Worker req.nh.nlmsg_seq = (*seq)++;
1667*053f45beSAndroid Build Coastguard Worker if (send(xfrm_sock, &req, req.nh.nlmsg_len, 0) < 0) {
1668*053f45beSAndroid Build Coastguard Worker pr_err("send()");
1669*053f45beSAndroid Build Coastguard Worker return KSFT_FAIL;
1670*053f45beSAndroid Build Coastguard Worker }
1671*053f45beSAndroid Build Coastguard Worker
1672*053f45beSAndroid Build Coastguard Worker if (recv(xfrm_sock, &req, sizeof(req), 0) < 0) {
1673*053f45beSAndroid Build Coastguard Worker pr_err("recv()");
1674*053f45beSAndroid Build Coastguard Worker return KSFT_FAIL;
1675*053f45beSAndroid Build Coastguard Worker } else if (req.nh.nlmsg_type == XFRM_MSG_NEWSPDINFO) {
1676*053f45beSAndroid Build Coastguard Worker size_t len = NLMSG_PAYLOAD(&req.nh, sizeof(req.unused));
1677*053f45beSAndroid Build Coastguard Worker struct rtattr *attr = (void *)req.attrbuf;
1678*053f45beSAndroid Build Coastguard Worker int got_thresh = 0;
1679*053f45beSAndroid Build Coastguard Worker
1680*053f45beSAndroid Build Coastguard Worker for (; RTA_OK(attr, len); attr = RTA_NEXT(attr, len)) {
1681*053f45beSAndroid Build Coastguard Worker if (attr->rta_type == XFRMA_SPD_IPV4_HTHRESH) {
1682*053f45beSAndroid Build Coastguard Worker struct xfrmu_spdhthresh *t = RTA_DATA(attr);
1683*053f45beSAndroid Build Coastguard Worker
1684*053f45beSAndroid Build Coastguard Worker got_thresh++;
1685*053f45beSAndroid Build Coastguard Worker if (t->lbits != 32 || t->rbits != 31) {
1686*053f45beSAndroid Build Coastguard Worker pr_err("thresh differ: %u, %u",
1687*053f45beSAndroid Build Coastguard Worker t->lbits, t->rbits);
1688*053f45beSAndroid Build Coastguard Worker return KSFT_FAIL;
1689*053f45beSAndroid Build Coastguard Worker }
1690*053f45beSAndroid Build Coastguard Worker }
1691*053f45beSAndroid Build Coastguard Worker if (attr->rta_type == XFRMA_SPD_IPV6_HTHRESH) {
1692*053f45beSAndroid Build Coastguard Worker struct xfrmu_spdhthresh *t = RTA_DATA(attr);
1693*053f45beSAndroid Build Coastguard Worker
1694*053f45beSAndroid Build Coastguard Worker got_thresh++;
1695*053f45beSAndroid Build Coastguard Worker if (t->lbits != 120 || t->rbits != 16) {
1696*053f45beSAndroid Build Coastguard Worker pr_err("thresh differ: %u, %u",
1697*053f45beSAndroid Build Coastguard Worker t->lbits, t->rbits);
1698*053f45beSAndroid Build Coastguard Worker return KSFT_FAIL;
1699*053f45beSAndroid Build Coastguard Worker }
1700*053f45beSAndroid Build Coastguard Worker }
1701*053f45beSAndroid Build Coastguard Worker }
1702*053f45beSAndroid Build Coastguard Worker if (got_thresh != 2) {
1703*053f45beSAndroid Build Coastguard Worker pr_err("only %d thresh returned by XFRM_MSG_GETSPDINFO", got_thresh);
1704*053f45beSAndroid Build Coastguard Worker return KSFT_FAIL;
1705*053f45beSAndroid Build Coastguard Worker }
1706*053f45beSAndroid Build Coastguard Worker } else if (req.nh.nlmsg_type != NLMSG_ERROR) {
1707*053f45beSAndroid Build Coastguard Worker printk("expected NLMSG_ERROR, got %d", (int)req.nh.nlmsg_type);
1708*053f45beSAndroid Build Coastguard Worker return KSFT_FAIL;
1709*053f45beSAndroid Build Coastguard Worker } else {
1710*053f45beSAndroid Build Coastguard Worker printk("NLMSG_ERROR: %d: %s", req.error, strerror(-req.error));
1711*053f45beSAndroid Build Coastguard Worker return -1;
1712*053f45beSAndroid Build Coastguard Worker }
1713*053f45beSAndroid Build Coastguard Worker
1714*053f45beSAndroid Build Coastguard Worker /* Restore the default */
1715*053f45beSAndroid Build Coastguard Worker if (xfrm_spdinfo_set_thresh(xfrm_sock, seq, 32, 32, 128, 128, false)) {
1716*053f45beSAndroid Build Coastguard Worker pr_err("Can't restore SPD HTHRESH");
1717*053f45beSAndroid Build Coastguard Worker return KSFT_FAIL;
1718*053f45beSAndroid Build Coastguard Worker }
1719*053f45beSAndroid Build Coastguard Worker
1720*053f45beSAndroid Build Coastguard Worker /*
1721*053f45beSAndroid Build Coastguard Worker * At this moment xfrm uses nlmsg_parse_deprecated(), which
1722*053f45beSAndroid Build Coastguard Worker * implies NL_VALIDATE_LIBERAL - ignoring attributes with
1723*053f45beSAndroid Build Coastguard Worker * (type > maxtype). nla_parse_depricated_strict() would enforce
1724*053f45beSAndroid Build Coastguard Worker * it. Or even stricter nla_parse().
1725*053f45beSAndroid Build Coastguard Worker * Right now it's not expected to fail, but to be ignored.
1726*053f45beSAndroid Build Coastguard Worker */
1727*053f45beSAndroid Build Coastguard Worker if (xfrm_spdinfo_set_thresh(xfrm_sock, seq, 32, 32, 128, 128, true))
1728*053f45beSAndroid Build Coastguard Worker return KSFT_PASS;
1729*053f45beSAndroid Build Coastguard Worker
1730*053f45beSAndroid Build Coastguard Worker return KSFT_PASS;
1731*053f45beSAndroid Build Coastguard Worker }
1732*053f45beSAndroid Build Coastguard Worker
child_serv(int xfrm_sock,uint32_t * seq,unsigned int nr,int cmd_fd,void * buf,struct xfrm_desc * desc)1733*053f45beSAndroid Build Coastguard Worker static int child_serv(int xfrm_sock, uint32_t *seq,
1734*053f45beSAndroid Build Coastguard Worker unsigned int nr, int cmd_fd, void *buf, struct xfrm_desc *desc)
1735*053f45beSAndroid Build Coastguard Worker {
1736*053f45beSAndroid Build Coastguard Worker struct in_addr src, dst, tunsrc, tundst;
1737*053f45beSAndroid Build Coastguard Worker struct test_desc msg;
1738*053f45beSAndroid Build Coastguard Worker int ret = KSFT_FAIL;
1739*053f45beSAndroid Build Coastguard Worker
1740*053f45beSAndroid Build Coastguard Worker src = inet_makeaddr(INADDR_B, child_ip(nr));
1741*053f45beSAndroid Build Coastguard Worker dst = inet_makeaddr(INADDR_B, grchild_ip(nr));
1742*053f45beSAndroid Build Coastguard Worker tunsrc = inet_makeaddr(INADDR_A, child_ip(nr));
1743*053f45beSAndroid Build Coastguard Worker tundst = inet_makeaddr(INADDR_A, grchild_ip(nr));
1744*053f45beSAndroid Build Coastguard Worker
1745*053f45beSAndroid Build Coastguard Worker /* UDP pinging without xfrm */
1746*053f45beSAndroid Build Coastguard Worker if (do_ping(cmd_fd, buf, page_size, src, true, 0, 0, udp_ping_send)) {
1747*053f45beSAndroid Build Coastguard Worker printk("ping failed before setting xfrm");
1748*053f45beSAndroid Build Coastguard Worker return KSFT_FAIL;
1749*053f45beSAndroid Build Coastguard Worker }
1750*053f45beSAndroid Build Coastguard Worker
1751*053f45beSAndroid Build Coastguard Worker memset(&msg, 0, sizeof(msg));
1752*053f45beSAndroid Build Coastguard Worker msg.type = MSG_XFRM_PREPARE;
1753*053f45beSAndroid Build Coastguard Worker memcpy(&msg.body.xfrm_desc, desc, sizeof(*desc));
1754*053f45beSAndroid Build Coastguard Worker write_msg(cmd_fd, &msg, 1);
1755*053f45beSAndroid Build Coastguard Worker
1756*053f45beSAndroid Build Coastguard Worker if (xfrm_prepare(xfrm_sock, seq, src, dst, tunsrc, tundst, desc->proto)) {
1757*053f45beSAndroid Build Coastguard Worker printk("failed to prepare xfrm");
1758*053f45beSAndroid Build Coastguard Worker goto cleanup;
1759*053f45beSAndroid Build Coastguard Worker }
1760*053f45beSAndroid Build Coastguard Worker
1761*053f45beSAndroid Build Coastguard Worker memset(&msg, 0, sizeof(msg));
1762*053f45beSAndroid Build Coastguard Worker msg.type = MSG_XFRM_ADD;
1763*053f45beSAndroid Build Coastguard Worker memcpy(&msg.body.xfrm_desc, desc, sizeof(*desc));
1764*053f45beSAndroid Build Coastguard Worker write_msg(cmd_fd, &msg, 1);
1765*053f45beSAndroid Build Coastguard Worker if (xfrm_set(xfrm_sock, seq, src, dst, tunsrc, tundst, desc)) {
1766*053f45beSAndroid Build Coastguard Worker printk("failed to set xfrm");
1767*053f45beSAndroid Build Coastguard Worker goto delete;
1768*053f45beSAndroid Build Coastguard Worker }
1769*053f45beSAndroid Build Coastguard Worker
1770*053f45beSAndroid Build Coastguard Worker /* UDP pinging with xfrm tunnel */
1771*053f45beSAndroid Build Coastguard Worker if (do_ping(cmd_fd, buf, page_size, tunsrc,
1772*053f45beSAndroid Build Coastguard Worker true, 0, 0, udp_ping_send)) {
1773*053f45beSAndroid Build Coastguard Worker printk("ping failed for xfrm");
1774*053f45beSAndroid Build Coastguard Worker goto delete;
1775*053f45beSAndroid Build Coastguard Worker }
1776*053f45beSAndroid Build Coastguard Worker
1777*053f45beSAndroid Build Coastguard Worker ret = KSFT_PASS;
1778*053f45beSAndroid Build Coastguard Worker delete:
1779*053f45beSAndroid Build Coastguard Worker /* xfrm delete */
1780*053f45beSAndroid Build Coastguard Worker memset(&msg, 0, sizeof(msg));
1781*053f45beSAndroid Build Coastguard Worker msg.type = MSG_XFRM_DEL;
1782*053f45beSAndroid Build Coastguard Worker memcpy(&msg.body.xfrm_desc, desc, sizeof(*desc));
1783*053f45beSAndroid Build Coastguard Worker write_msg(cmd_fd, &msg, 1);
1784*053f45beSAndroid Build Coastguard Worker
1785*053f45beSAndroid Build Coastguard Worker if (xfrm_delete(xfrm_sock, seq, src, dst, tunsrc, tundst, desc->proto)) {
1786*053f45beSAndroid Build Coastguard Worker printk("failed ping to remove xfrm");
1787*053f45beSAndroid Build Coastguard Worker ret = KSFT_FAIL;
1788*053f45beSAndroid Build Coastguard Worker }
1789*053f45beSAndroid Build Coastguard Worker
1790*053f45beSAndroid Build Coastguard Worker cleanup:
1791*053f45beSAndroid Build Coastguard Worker memset(&msg, 0, sizeof(msg));
1792*053f45beSAndroid Build Coastguard Worker msg.type = MSG_XFRM_CLEANUP;
1793*053f45beSAndroid Build Coastguard Worker memcpy(&msg.body.xfrm_desc, desc, sizeof(*desc));
1794*053f45beSAndroid Build Coastguard Worker write_msg(cmd_fd, &msg, 1);
1795*053f45beSAndroid Build Coastguard Worker if (xfrm_cleanup(xfrm_sock, seq, src, dst, tunsrc, tundst)) {
1796*053f45beSAndroid Build Coastguard Worker printk("failed ping to cleanup xfrm");
1797*053f45beSAndroid Build Coastguard Worker ret = KSFT_FAIL;
1798*053f45beSAndroid Build Coastguard Worker }
1799*053f45beSAndroid Build Coastguard Worker return ret;
1800*053f45beSAndroid Build Coastguard Worker }
1801*053f45beSAndroid Build Coastguard Worker
child_f(unsigned int nr,int test_desc_fd,int cmd_fd,void * buf)1802*053f45beSAndroid Build Coastguard Worker static int child_f(unsigned int nr, int test_desc_fd, int cmd_fd, void *buf)
1803*053f45beSAndroid Build Coastguard Worker {
1804*053f45beSAndroid Build Coastguard Worker struct xfrm_desc desc;
1805*053f45beSAndroid Build Coastguard Worker struct test_desc msg;
1806*053f45beSAndroid Build Coastguard Worker int xfrm_sock = -1;
1807*053f45beSAndroid Build Coastguard Worker uint32_t seq;
1808*053f45beSAndroid Build Coastguard Worker
1809*053f45beSAndroid Build Coastguard Worker if (switch_ns(nsfd_childa))
1810*053f45beSAndroid Build Coastguard Worker exit(KSFT_FAIL);
1811*053f45beSAndroid Build Coastguard Worker
1812*053f45beSAndroid Build Coastguard Worker if (netlink_sock(&xfrm_sock, &seq, NETLINK_XFRM)) {
1813*053f45beSAndroid Build Coastguard Worker printk("Failed to open xfrm netlink socket");
1814*053f45beSAndroid Build Coastguard Worker exit(KSFT_FAIL);
1815*053f45beSAndroid Build Coastguard Worker }
1816*053f45beSAndroid Build Coastguard Worker
1817*053f45beSAndroid Build Coastguard Worker /* Check that seq sock is ready, just for sure. */
1818*053f45beSAndroid Build Coastguard Worker memset(&msg, 0, sizeof(msg));
1819*053f45beSAndroid Build Coastguard Worker msg.type = MSG_ACK;
1820*053f45beSAndroid Build Coastguard Worker write_msg(cmd_fd, &msg, 1);
1821*053f45beSAndroid Build Coastguard Worker read_msg(cmd_fd, &msg, 1);
1822*053f45beSAndroid Build Coastguard Worker if (msg.type != MSG_ACK) {
1823*053f45beSAndroid Build Coastguard Worker printk("Ack failed");
1824*053f45beSAndroid Build Coastguard Worker exit(KSFT_FAIL);
1825*053f45beSAndroid Build Coastguard Worker }
1826*053f45beSAndroid Build Coastguard Worker
1827*053f45beSAndroid Build Coastguard Worker for (;;) {
1828*053f45beSAndroid Build Coastguard Worker ssize_t received = read(test_desc_fd, &desc, sizeof(desc));
1829*053f45beSAndroid Build Coastguard Worker int ret;
1830*053f45beSAndroid Build Coastguard Worker
1831*053f45beSAndroid Build Coastguard Worker if (received == 0) /* EOF */
1832*053f45beSAndroid Build Coastguard Worker break;
1833*053f45beSAndroid Build Coastguard Worker
1834*053f45beSAndroid Build Coastguard Worker if (received != sizeof(desc)) {
1835*053f45beSAndroid Build Coastguard Worker pr_err("read() returned %zd", received);
1836*053f45beSAndroid Build Coastguard Worker exit(KSFT_FAIL);
1837*053f45beSAndroid Build Coastguard Worker }
1838*053f45beSAndroid Build Coastguard Worker
1839*053f45beSAndroid Build Coastguard Worker switch (desc.type) {
1840*053f45beSAndroid Build Coastguard Worker case CREATE_TUNNEL:
1841*053f45beSAndroid Build Coastguard Worker ret = child_serv(xfrm_sock, &seq, nr,
1842*053f45beSAndroid Build Coastguard Worker cmd_fd, buf, &desc);
1843*053f45beSAndroid Build Coastguard Worker break;
1844*053f45beSAndroid Build Coastguard Worker case ALLOCATE_SPI:
1845*053f45beSAndroid Build Coastguard Worker ret = xfrm_state_allocspi(xfrm_sock, &seq,
1846*053f45beSAndroid Build Coastguard Worker -1, desc.proto);
1847*053f45beSAndroid Build Coastguard Worker break;
1848*053f45beSAndroid Build Coastguard Worker case MONITOR_ACQUIRE:
1849*053f45beSAndroid Build Coastguard Worker ret = xfrm_monitor_acquire(xfrm_sock, &seq, nr);
1850*053f45beSAndroid Build Coastguard Worker break;
1851*053f45beSAndroid Build Coastguard Worker case EXPIRE_STATE:
1852*053f45beSAndroid Build Coastguard Worker ret = xfrm_expire_state(xfrm_sock, &seq, nr, &desc);
1853*053f45beSAndroid Build Coastguard Worker break;
1854*053f45beSAndroid Build Coastguard Worker case EXPIRE_POLICY:
1855*053f45beSAndroid Build Coastguard Worker ret = xfrm_expire_policy(xfrm_sock, &seq, nr, &desc);
1856*053f45beSAndroid Build Coastguard Worker break;
1857*053f45beSAndroid Build Coastguard Worker case SPDINFO_ATTRS:
1858*053f45beSAndroid Build Coastguard Worker ret = xfrm_spdinfo_attrs(xfrm_sock, &seq);
1859*053f45beSAndroid Build Coastguard Worker break;
1860*053f45beSAndroid Build Coastguard Worker default:
1861*053f45beSAndroid Build Coastguard Worker printk("Unknown desc type %d", desc.type);
1862*053f45beSAndroid Build Coastguard Worker exit(KSFT_FAIL);
1863*053f45beSAndroid Build Coastguard Worker }
1864*053f45beSAndroid Build Coastguard Worker write_test_result(ret, &desc);
1865*053f45beSAndroid Build Coastguard Worker }
1866*053f45beSAndroid Build Coastguard Worker
1867*053f45beSAndroid Build Coastguard Worker close(xfrm_sock);
1868*053f45beSAndroid Build Coastguard Worker
1869*053f45beSAndroid Build Coastguard Worker msg.type = MSG_EXIT;
1870*053f45beSAndroid Build Coastguard Worker write_msg(cmd_fd, &msg, 1);
1871*053f45beSAndroid Build Coastguard Worker exit(KSFT_PASS);
1872*053f45beSAndroid Build Coastguard Worker }
1873*053f45beSAndroid Build Coastguard Worker
grand_child_serv(unsigned int nr,int cmd_fd,void * buf,struct test_desc * msg,int xfrm_sock,uint32_t * seq)1874*053f45beSAndroid Build Coastguard Worker static void grand_child_serv(unsigned int nr, int cmd_fd, void *buf,
1875*053f45beSAndroid Build Coastguard Worker struct test_desc *msg, int xfrm_sock, uint32_t *seq)
1876*053f45beSAndroid Build Coastguard Worker {
1877*053f45beSAndroid Build Coastguard Worker struct in_addr src, dst, tunsrc, tundst;
1878*053f45beSAndroid Build Coastguard Worker bool tun_reply;
1879*053f45beSAndroid Build Coastguard Worker struct xfrm_desc *desc = &msg->body.xfrm_desc;
1880*053f45beSAndroid Build Coastguard Worker
1881*053f45beSAndroid Build Coastguard Worker src = inet_makeaddr(INADDR_B, grchild_ip(nr));
1882*053f45beSAndroid Build Coastguard Worker dst = inet_makeaddr(INADDR_B, child_ip(nr));
1883*053f45beSAndroid Build Coastguard Worker tunsrc = inet_makeaddr(INADDR_A, grchild_ip(nr));
1884*053f45beSAndroid Build Coastguard Worker tundst = inet_makeaddr(INADDR_A, child_ip(nr));
1885*053f45beSAndroid Build Coastguard Worker
1886*053f45beSAndroid Build Coastguard Worker switch (msg->type) {
1887*053f45beSAndroid Build Coastguard Worker case MSG_EXIT:
1888*053f45beSAndroid Build Coastguard Worker exit(KSFT_PASS);
1889*053f45beSAndroid Build Coastguard Worker case MSG_ACK:
1890*053f45beSAndroid Build Coastguard Worker write_msg(cmd_fd, msg, 1);
1891*053f45beSAndroid Build Coastguard Worker break;
1892*053f45beSAndroid Build Coastguard Worker case MSG_PING:
1893*053f45beSAndroid Build Coastguard Worker tun_reply = memcmp(&dst, &msg->body.ping.reply_ip, sizeof(in_addr_t));
1894*053f45beSAndroid Build Coastguard Worker /* UDP pinging without xfrm */
1895*053f45beSAndroid Build Coastguard Worker if (do_ping(cmd_fd, buf, page_size, tun_reply ? tunsrc : src,
1896*053f45beSAndroid Build Coastguard Worker false, msg->body.ping.port,
1897*053f45beSAndroid Build Coastguard Worker msg->body.ping.reply_ip, udp_ping_reply)) {
1898*053f45beSAndroid Build Coastguard Worker printk("ping failed before setting xfrm");
1899*053f45beSAndroid Build Coastguard Worker }
1900*053f45beSAndroid Build Coastguard Worker break;
1901*053f45beSAndroid Build Coastguard Worker case MSG_XFRM_PREPARE:
1902*053f45beSAndroid Build Coastguard Worker if (xfrm_prepare(xfrm_sock, seq, src, dst, tunsrc, tundst,
1903*053f45beSAndroid Build Coastguard Worker desc->proto)) {
1904*053f45beSAndroid Build Coastguard Worker xfrm_cleanup(xfrm_sock, seq, src, dst, tunsrc, tundst);
1905*053f45beSAndroid Build Coastguard Worker printk("failed to prepare xfrm");
1906*053f45beSAndroid Build Coastguard Worker }
1907*053f45beSAndroid Build Coastguard Worker break;
1908*053f45beSAndroid Build Coastguard Worker case MSG_XFRM_ADD:
1909*053f45beSAndroid Build Coastguard Worker if (xfrm_set(xfrm_sock, seq, src, dst, tunsrc, tundst, desc)) {
1910*053f45beSAndroid Build Coastguard Worker xfrm_cleanup(xfrm_sock, seq, src, dst, tunsrc, tundst);
1911*053f45beSAndroid Build Coastguard Worker printk("failed to set xfrm");
1912*053f45beSAndroid Build Coastguard Worker }
1913*053f45beSAndroid Build Coastguard Worker break;
1914*053f45beSAndroid Build Coastguard Worker case MSG_XFRM_DEL:
1915*053f45beSAndroid Build Coastguard Worker if (xfrm_delete(xfrm_sock, seq, src, dst, tunsrc, tundst,
1916*053f45beSAndroid Build Coastguard Worker desc->proto)) {
1917*053f45beSAndroid Build Coastguard Worker xfrm_cleanup(xfrm_sock, seq, src, dst, tunsrc, tundst);
1918*053f45beSAndroid Build Coastguard Worker printk("failed to remove xfrm");
1919*053f45beSAndroid Build Coastguard Worker }
1920*053f45beSAndroid Build Coastguard Worker break;
1921*053f45beSAndroid Build Coastguard Worker case MSG_XFRM_CLEANUP:
1922*053f45beSAndroid Build Coastguard Worker if (xfrm_cleanup(xfrm_sock, seq, src, dst, tunsrc, tundst)) {
1923*053f45beSAndroid Build Coastguard Worker printk("failed to cleanup xfrm");
1924*053f45beSAndroid Build Coastguard Worker }
1925*053f45beSAndroid Build Coastguard Worker break;
1926*053f45beSAndroid Build Coastguard Worker default:
1927*053f45beSAndroid Build Coastguard Worker printk("got unknown msg type %d", msg->type);
1928*053f45beSAndroid Build Coastguard Worker }
1929*053f45beSAndroid Build Coastguard Worker }
1930*053f45beSAndroid Build Coastguard Worker
grand_child_f(unsigned int nr,int cmd_fd,void * buf)1931*053f45beSAndroid Build Coastguard Worker static int grand_child_f(unsigned int nr, int cmd_fd, void *buf)
1932*053f45beSAndroid Build Coastguard Worker {
1933*053f45beSAndroid Build Coastguard Worker struct test_desc msg;
1934*053f45beSAndroid Build Coastguard Worker int xfrm_sock = -1;
1935*053f45beSAndroid Build Coastguard Worker uint32_t seq;
1936*053f45beSAndroid Build Coastguard Worker
1937*053f45beSAndroid Build Coastguard Worker if (switch_ns(nsfd_childb))
1938*053f45beSAndroid Build Coastguard Worker exit(KSFT_FAIL);
1939*053f45beSAndroid Build Coastguard Worker
1940*053f45beSAndroid Build Coastguard Worker if (netlink_sock(&xfrm_sock, &seq, NETLINK_XFRM)) {
1941*053f45beSAndroid Build Coastguard Worker printk("Failed to open xfrm netlink socket");
1942*053f45beSAndroid Build Coastguard Worker exit(KSFT_FAIL);
1943*053f45beSAndroid Build Coastguard Worker }
1944*053f45beSAndroid Build Coastguard Worker
1945*053f45beSAndroid Build Coastguard Worker do {
1946*053f45beSAndroid Build Coastguard Worker read_msg(cmd_fd, &msg, 1);
1947*053f45beSAndroid Build Coastguard Worker grand_child_serv(nr, cmd_fd, buf, &msg, xfrm_sock, &seq);
1948*053f45beSAndroid Build Coastguard Worker } while (1);
1949*053f45beSAndroid Build Coastguard Worker
1950*053f45beSAndroid Build Coastguard Worker close(xfrm_sock);
1951*053f45beSAndroid Build Coastguard Worker exit(KSFT_FAIL);
1952*053f45beSAndroid Build Coastguard Worker }
1953*053f45beSAndroid Build Coastguard Worker
start_child(unsigned int nr,char * veth,int test_desc_fd[2])1954*053f45beSAndroid Build Coastguard Worker static int start_child(unsigned int nr, char *veth, int test_desc_fd[2])
1955*053f45beSAndroid Build Coastguard Worker {
1956*053f45beSAndroid Build Coastguard Worker int cmd_sock[2];
1957*053f45beSAndroid Build Coastguard Worker void *data_map;
1958*053f45beSAndroid Build Coastguard Worker pid_t child;
1959*053f45beSAndroid Build Coastguard Worker
1960*053f45beSAndroid Build Coastguard Worker if (init_child(nsfd_childa, veth, child_ip(nr), grchild_ip(nr)))
1961*053f45beSAndroid Build Coastguard Worker return -1;
1962*053f45beSAndroid Build Coastguard Worker
1963*053f45beSAndroid Build Coastguard Worker if (init_child(nsfd_childb, veth, grchild_ip(nr), child_ip(nr)))
1964*053f45beSAndroid Build Coastguard Worker return -1;
1965*053f45beSAndroid Build Coastguard Worker
1966*053f45beSAndroid Build Coastguard Worker child = fork();
1967*053f45beSAndroid Build Coastguard Worker if (child < 0) {
1968*053f45beSAndroid Build Coastguard Worker pr_err("fork()");
1969*053f45beSAndroid Build Coastguard Worker return -1;
1970*053f45beSAndroid Build Coastguard Worker } else if (child) {
1971*053f45beSAndroid Build Coastguard Worker /* in parent - selftest */
1972*053f45beSAndroid Build Coastguard Worker return switch_ns(nsfd_parent);
1973*053f45beSAndroid Build Coastguard Worker }
1974*053f45beSAndroid Build Coastguard Worker
1975*053f45beSAndroid Build Coastguard Worker if (close(test_desc_fd[1])) {
1976*053f45beSAndroid Build Coastguard Worker pr_err("close()");
1977*053f45beSAndroid Build Coastguard Worker return -1;
1978*053f45beSAndroid Build Coastguard Worker }
1979*053f45beSAndroid Build Coastguard Worker
1980*053f45beSAndroid Build Coastguard Worker /* child */
1981*053f45beSAndroid Build Coastguard Worker data_map = mmap(0, page_size, PROT_READ | PROT_WRITE,
1982*053f45beSAndroid Build Coastguard Worker MAP_SHARED | MAP_ANONYMOUS, -1, 0);
1983*053f45beSAndroid Build Coastguard Worker if (data_map == MAP_FAILED) {
1984*053f45beSAndroid Build Coastguard Worker pr_err("mmap()");
1985*053f45beSAndroid Build Coastguard Worker return -1;
1986*053f45beSAndroid Build Coastguard Worker }
1987*053f45beSAndroid Build Coastguard Worker
1988*053f45beSAndroid Build Coastguard Worker randomize_buffer(data_map, page_size);
1989*053f45beSAndroid Build Coastguard Worker
1990*053f45beSAndroid Build Coastguard Worker if (socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, cmd_sock)) {
1991*053f45beSAndroid Build Coastguard Worker pr_err("socketpair()");
1992*053f45beSAndroid Build Coastguard Worker return -1;
1993*053f45beSAndroid Build Coastguard Worker }
1994*053f45beSAndroid Build Coastguard Worker
1995*053f45beSAndroid Build Coastguard Worker child = fork();
1996*053f45beSAndroid Build Coastguard Worker if (child < 0) {
1997*053f45beSAndroid Build Coastguard Worker pr_err("fork()");
1998*053f45beSAndroid Build Coastguard Worker return -1;
1999*053f45beSAndroid Build Coastguard Worker } else if (child) {
2000*053f45beSAndroid Build Coastguard Worker if (close(cmd_sock[0])) {
2001*053f45beSAndroid Build Coastguard Worker pr_err("close()");
2002*053f45beSAndroid Build Coastguard Worker return -1;
2003*053f45beSAndroid Build Coastguard Worker }
2004*053f45beSAndroid Build Coastguard Worker return child_f(nr, test_desc_fd[0], cmd_sock[1], data_map);
2005*053f45beSAndroid Build Coastguard Worker }
2006*053f45beSAndroid Build Coastguard Worker if (close(cmd_sock[1])) {
2007*053f45beSAndroid Build Coastguard Worker pr_err("close()");
2008*053f45beSAndroid Build Coastguard Worker return -1;
2009*053f45beSAndroid Build Coastguard Worker }
2010*053f45beSAndroid Build Coastguard Worker return grand_child_f(nr, cmd_sock[0], data_map);
2011*053f45beSAndroid Build Coastguard Worker }
2012*053f45beSAndroid Build Coastguard Worker
exit_usage(char ** argv)2013*053f45beSAndroid Build Coastguard Worker static void exit_usage(char **argv)
2014*053f45beSAndroid Build Coastguard Worker {
2015*053f45beSAndroid Build Coastguard Worker printk("Usage: %s [nr_process]", argv[0]);
2016*053f45beSAndroid Build Coastguard Worker exit(KSFT_FAIL);
2017*053f45beSAndroid Build Coastguard Worker }
2018*053f45beSAndroid Build Coastguard Worker
__write_desc(int test_desc_fd,struct xfrm_desc * desc)2019*053f45beSAndroid Build Coastguard Worker static int __write_desc(int test_desc_fd, struct xfrm_desc *desc)
2020*053f45beSAndroid Build Coastguard Worker {
2021*053f45beSAndroid Build Coastguard Worker ssize_t ret;
2022*053f45beSAndroid Build Coastguard Worker
2023*053f45beSAndroid Build Coastguard Worker ret = write(test_desc_fd, desc, sizeof(*desc));
2024*053f45beSAndroid Build Coastguard Worker
2025*053f45beSAndroid Build Coastguard Worker if (ret == sizeof(*desc))
2026*053f45beSAndroid Build Coastguard Worker return 0;
2027*053f45beSAndroid Build Coastguard Worker
2028*053f45beSAndroid Build Coastguard Worker pr_err("Writing test's desc failed %ld", ret);
2029*053f45beSAndroid Build Coastguard Worker
2030*053f45beSAndroid Build Coastguard Worker return -1;
2031*053f45beSAndroid Build Coastguard Worker }
2032*053f45beSAndroid Build Coastguard Worker
write_desc(int proto,int test_desc_fd,char * a,char * e,char * c,char * ae)2033*053f45beSAndroid Build Coastguard Worker static int write_desc(int proto, int test_desc_fd,
2034*053f45beSAndroid Build Coastguard Worker char *a, char *e, char *c, char *ae)
2035*053f45beSAndroid Build Coastguard Worker {
2036*053f45beSAndroid Build Coastguard Worker struct xfrm_desc desc = {};
2037*053f45beSAndroid Build Coastguard Worker
2038*053f45beSAndroid Build Coastguard Worker desc.type = CREATE_TUNNEL;
2039*053f45beSAndroid Build Coastguard Worker desc.proto = proto;
2040*053f45beSAndroid Build Coastguard Worker
2041*053f45beSAndroid Build Coastguard Worker if (a)
2042*053f45beSAndroid Build Coastguard Worker strncpy(desc.a_algo, a, ALGO_LEN - 1);
2043*053f45beSAndroid Build Coastguard Worker if (e)
2044*053f45beSAndroid Build Coastguard Worker strncpy(desc.e_algo, e, ALGO_LEN - 1);
2045*053f45beSAndroid Build Coastguard Worker if (c)
2046*053f45beSAndroid Build Coastguard Worker strncpy(desc.c_algo, c, ALGO_LEN - 1);
2047*053f45beSAndroid Build Coastguard Worker if (ae)
2048*053f45beSAndroid Build Coastguard Worker strncpy(desc.ae_algo, ae, ALGO_LEN - 1);
2049*053f45beSAndroid Build Coastguard Worker
2050*053f45beSAndroid Build Coastguard Worker return __write_desc(test_desc_fd, &desc);
2051*053f45beSAndroid Build Coastguard Worker }
2052*053f45beSAndroid Build Coastguard Worker
2053*053f45beSAndroid Build Coastguard Worker int proto_list[] = { IPPROTO_AH, IPPROTO_COMP, IPPROTO_ESP };
2054*053f45beSAndroid Build Coastguard Worker char *ah_list[] = {
2055*053f45beSAndroid Build Coastguard Worker "digest_null", "hmac(md5)", "hmac(sha1)", "hmac(sha256)",
2056*053f45beSAndroid Build Coastguard Worker "hmac(sha384)", "hmac(sha512)", "hmac(rmd160)",
2057*053f45beSAndroid Build Coastguard Worker "xcbc(aes)", "cmac(aes)"
2058*053f45beSAndroid Build Coastguard Worker };
2059*053f45beSAndroid Build Coastguard Worker char *comp_list[] = {
2060*053f45beSAndroid Build Coastguard Worker "deflate",
2061*053f45beSAndroid Build Coastguard Worker #if 0
2062*053f45beSAndroid Build Coastguard Worker /* No compression backend realization */
2063*053f45beSAndroid Build Coastguard Worker "lzs", "lzjh"
2064*053f45beSAndroid Build Coastguard Worker #endif
2065*053f45beSAndroid Build Coastguard Worker };
2066*053f45beSAndroid Build Coastguard Worker char *e_list[] = {
2067*053f45beSAndroid Build Coastguard Worker "ecb(cipher_null)", "cbc(des)", "cbc(des3_ede)", "cbc(cast5)",
2068*053f45beSAndroid Build Coastguard Worker "cbc(blowfish)", "cbc(aes)", "cbc(serpent)", "cbc(camellia)",
2069*053f45beSAndroid Build Coastguard Worker "cbc(twofish)", "rfc3686(ctr(aes))"
2070*053f45beSAndroid Build Coastguard Worker };
2071*053f45beSAndroid Build Coastguard Worker char *ae_list[] = {
2072*053f45beSAndroid Build Coastguard Worker #if 0
2073*053f45beSAndroid Build Coastguard Worker /* not implemented */
2074*053f45beSAndroid Build Coastguard Worker "rfc4106(gcm(aes))", "rfc4309(ccm(aes))", "rfc4543(gcm(aes))",
2075*053f45beSAndroid Build Coastguard Worker "rfc7539esp(chacha20,poly1305)"
2076*053f45beSAndroid Build Coastguard Worker #endif
2077*053f45beSAndroid Build Coastguard Worker };
2078*053f45beSAndroid Build Coastguard Worker
2079*053f45beSAndroid Build Coastguard Worker const unsigned int proto_plan = ARRAY_SIZE(ah_list) + ARRAY_SIZE(comp_list) \
2080*053f45beSAndroid Build Coastguard Worker + (ARRAY_SIZE(ah_list) * ARRAY_SIZE(e_list)) \
2081*053f45beSAndroid Build Coastguard Worker + ARRAY_SIZE(ae_list);
2082*053f45beSAndroid Build Coastguard Worker
write_proto_plan(int fd,int proto)2083*053f45beSAndroid Build Coastguard Worker static int write_proto_plan(int fd, int proto)
2084*053f45beSAndroid Build Coastguard Worker {
2085*053f45beSAndroid Build Coastguard Worker unsigned int i;
2086*053f45beSAndroid Build Coastguard Worker
2087*053f45beSAndroid Build Coastguard Worker switch (proto) {
2088*053f45beSAndroid Build Coastguard Worker case IPPROTO_AH:
2089*053f45beSAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(ah_list); i++) {
2090*053f45beSAndroid Build Coastguard Worker if (write_desc(proto, fd, ah_list[i], 0, 0, 0))
2091*053f45beSAndroid Build Coastguard Worker return -1;
2092*053f45beSAndroid Build Coastguard Worker }
2093*053f45beSAndroid Build Coastguard Worker break;
2094*053f45beSAndroid Build Coastguard Worker case IPPROTO_COMP:
2095*053f45beSAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(comp_list); i++) {
2096*053f45beSAndroid Build Coastguard Worker if (write_desc(proto, fd, 0, 0, comp_list[i], 0))
2097*053f45beSAndroid Build Coastguard Worker return -1;
2098*053f45beSAndroid Build Coastguard Worker }
2099*053f45beSAndroid Build Coastguard Worker break;
2100*053f45beSAndroid Build Coastguard Worker case IPPROTO_ESP:
2101*053f45beSAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(ah_list); i++) {
2102*053f45beSAndroid Build Coastguard Worker int j;
2103*053f45beSAndroid Build Coastguard Worker
2104*053f45beSAndroid Build Coastguard Worker for (j = 0; j < ARRAY_SIZE(e_list); j++) {
2105*053f45beSAndroid Build Coastguard Worker if (write_desc(proto, fd, ah_list[i],
2106*053f45beSAndroid Build Coastguard Worker e_list[j], 0, 0))
2107*053f45beSAndroid Build Coastguard Worker return -1;
2108*053f45beSAndroid Build Coastguard Worker }
2109*053f45beSAndroid Build Coastguard Worker }
2110*053f45beSAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(ae_list); i++) {
2111*053f45beSAndroid Build Coastguard Worker if (write_desc(proto, fd, 0, 0, 0, ae_list[i]))
2112*053f45beSAndroid Build Coastguard Worker return -1;
2113*053f45beSAndroid Build Coastguard Worker }
2114*053f45beSAndroid Build Coastguard Worker break;
2115*053f45beSAndroid Build Coastguard Worker default:
2116*053f45beSAndroid Build Coastguard Worker printk("BUG: Specified unknown proto %d", proto);
2117*053f45beSAndroid Build Coastguard Worker return -1;
2118*053f45beSAndroid Build Coastguard Worker }
2119*053f45beSAndroid Build Coastguard Worker
2120*053f45beSAndroid Build Coastguard Worker return 0;
2121*053f45beSAndroid Build Coastguard Worker }
2122*053f45beSAndroid Build Coastguard Worker
2123*053f45beSAndroid Build Coastguard Worker /*
2124*053f45beSAndroid Build Coastguard Worker * Some structures in xfrm uapi header differ in size between
2125*053f45beSAndroid Build Coastguard Worker * 64-bit and 32-bit ABI:
2126*053f45beSAndroid Build Coastguard Worker *
2127*053f45beSAndroid Build Coastguard Worker * 32-bit UABI | 64-bit UABI
2128*053f45beSAndroid Build Coastguard Worker * -------------------------------------|-------------------------------------
2129*053f45beSAndroid Build Coastguard Worker * sizeof(xfrm_usersa_info) = 220 | sizeof(xfrm_usersa_info) = 224
2130*053f45beSAndroid Build Coastguard Worker * sizeof(xfrm_userpolicy_info) = 164 | sizeof(xfrm_userpolicy_info) = 168
2131*053f45beSAndroid Build Coastguard Worker * sizeof(xfrm_userspi_info) = 228 | sizeof(xfrm_userspi_info) = 232
2132*053f45beSAndroid Build Coastguard Worker * sizeof(xfrm_user_acquire) = 276 | sizeof(xfrm_user_acquire) = 280
2133*053f45beSAndroid Build Coastguard Worker * sizeof(xfrm_user_expire) = 224 | sizeof(xfrm_user_expire) = 232
2134*053f45beSAndroid Build Coastguard Worker * sizeof(xfrm_user_polexpire) = 168 | sizeof(xfrm_user_polexpire) = 176
2135*053f45beSAndroid Build Coastguard Worker *
2136*053f45beSAndroid Build Coastguard Worker * Check the affected by the UABI difference structures.
2137*053f45beSAndroid Build Coastguard Worker * Also, check translation for xfrm_set_spdinfo: it has it's own attributes
2138*053f45beSAndroid Build Coastguard Worker * which needs to be correctly copied, but not translated.
2139*053f45beSAndroid Build Coastguard Worker */
2140*053f45beSAndroid Build Coastguard Worker const unsigned int compat_plan = 5;
write_compat_struct_tests(int test_desc_fd)2141*053f45beSAndroid Build Coastguard Worker static int write_compat_struct_tests(int test_desc_fd)
2142*053f45beSAndroid Build Coastguard Worker {
2143*053f45beSAndroid Build Coastguard Worker struct xfrm_desc desc = {};
2144*053f45beSAndroid Build Coastguard Worker
2145*053f45beSAndroid Build Coastguard Worker desc.type = ALLOCATE_SPI;
2146*053f45beSAndroid Build Coastguard Worker desc.proto = IPPROTO_AH;
2147*053f45beSAndroid Build Coastguard Worker strncpy(desc.a_algo, ah_list[0], ALGO_LEN - 1);
2148*053f45beSAndroid Build Coastguard Worker
2149*053f45beSAndroid Build Coastguard Worker if (__write_desc(test_desc_fd, &desc))
2150*053f45beSAndroid Build Coastguard Worker return -1;
2151*053f45beSAndroid Build Coastguard Worker
2152*053f45beSAndroid Build Coastguard Worker desc.type = MONITOR_ACQUIRE;
2153*053f45beSAndroid Build Coastguard Worker if (__write_desc(test_desc_fd, &desc))
2154*053f45beSAndroid Build Coastguard Worker return -1;
2155*053f45beSAndroid Build Coastguard Worker
2156*053f45beSAndroid Build Coastguard Worker desc.type = EXPIRE_STATE;
2157*053f45beSAndroid Build Coastguard Worker if (__write_desc(test_desc_fd, &desc))
2158*053f45beSAndroid Build Coastguard Worker return -1;
2159*053f45beSAndroid Build Coastguard Worker
2160*053f45beSAndroid Build Coastguard Worker desc.type = EXPIRE_POLICY;
2161*053f45beSAndroid Build Coastguard Worker if (__write_desc(test_desc_fd, &desc))
2162*053f45beSAndroid Build Coastguard Worker return -1;
2163*053f45beSAndroid Build Coastguard Worker
2164*053f45beSAndroid Build Coastguard Worker desc.type = SPDINFO_ATTRS;
2165*053f45beSAndroid Build Coastguard Worker if (__write_desc(test_desc_fd, &desc))
2166*053f45beSAndroid Build Coastguard Worker return -1;
2167*053f45beSAndroid Build Coastguard Worker
2168*053f45beSAndroid Build Coastguard Worker return 0;
2169*053f45beSAndroid Build Coastguard Worker }
2170*053f45beSAndroid Build Coastguard Worker
write_test_plan(int test_desc_fd)2171*053f45beSAndroid Build Coastguard Worker static int write_test_plan(int test_desc_fd)
2172*053f45beSAndroid Build Coastguard Worker {
2173*053f45beSAndroid Build Coastguard Worker unsigned int i;
2174*053f45beSAndroid Build Coastguard Worker pid_t child;
2175*053f45beSAndroid Build Coastguard Worker
2176*053f45beSAndroid Build Coastguard Worker child = fork();
2177*053f45beSAndroid Build Coastguard Worker if (child < 0) {
2178*053f45beSAndroid Build Coastguard Worker pr_err("fork()");
2179*053f45beSAndroid Build Coastguard Worker return -1;
2180*053f45beSAndroid Build Coastguard Worker }
2181*053f45beSAndroid Build Coastguard Worker if (child) {
2182*053f45beSAndroid Build Coastguard Worker if (close(test_desc_fd))
2183*053f45beSAndroid Build Coastguard Worker printk("close(): %m");
2184*053f45beSAndroid Build Coastguard Worker return 0;
2185*053f45beSAndroid Build Coastguard Worker }
2186*053f45beSAndroid Build Coastguard Worker
2187*053f45beSAndroid Build Coastguard Worker if (write_compat_struct_tests(test_desc_fd))
2188*053f45beSAndroid Build Coastguard Worker exit(KSFT_FAIL);
2189*053f45beSAndroid Build Coastguard Worker
2190*053f45beSAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(proto_list); i++) {
2191*053f45beSAndroid Build Coastguard Worker if (write_proto_plan(test_desc_fd, proto_list[i]))
2192*053f45beSAndroid Build Coastguard Worker exit(KSFT_FAIL);
2193*053f45beSAndroid Build Coastguard Worker }
2194*053f45beSAndroid Build Coastguard Worker
2195*053f45beSAndroid Build Coastguard Worker exit(KSFT_PASS);
2196*053f45beSAndroid Build Coastguard Worker }
2197*053f45beSAndroid Build Coastguard Worker
children_cleanup(void)2198*053f45beSAndroid Build Coastguard Worker static int children_cleanup(void)
2199*053f45beSAndroid Build Coastguard Worker {
2200*053f45beSAndroid Build Coastguard Worker unsigned ret = KSFT_PASS;
2201*053f45beSAndroid Build Coastguard Worker
2202*053f45beSAndroid Build Coastguard Worker while (1) {
2203*053f45beSAndroid Build Coastguard Worker int status;
2204*053f45beSAndroid Build Coastguard Worker pid_t p = wait(&status);
2205*053f45beSAndroid Build Coastguard Worker
2206*053f45beSAndroid Build Coastguard Worker if ((p < 0) && errno == ECHILD)
2207*053f45beSAndroid Build Coastguard Worker break;
2208*053f45beSAndroid Build Coastguard Worker
2209*053f45beSAndroid Build Coastguard Worker if (p < 0) {
2210*053f45beSAndroid Build Coastguard Worker pr_err("wait()");
2211*053f45beSAndroid Build Coastguard Worker return KSFT_FAIL;
2212*053f45beSAndroid Build Coastguard Worker }
2213*053f45beSAndroid Build Coastguard Worker
2214*053f45beSAndroid Build Coastguard Worker if (!WIFEXITED(status)) {
2215*053f45beSAndroid Build Coastguard Worker ret = KSFT_FAIL;
2216*053f45beSAndroid Build Coastguard Worker continue;
2217*053f45beSAndroid Build Coastguard Worker }
2218*053f45beSAndroid Build Coastguard Worker
2219*053f45beSAndroid Build Coastguard Worker if (WEXITSTATUS(status) == KSFT_FAIL)
2220*053f45beSAndroid Build Coastguard Worker ret = KSFT_FAIL;
2221*053f45beSAndroid Build Coastguard Worker }
2222*053f45beSAndroid Build Coastguard Worker
2223*053f45beSAndroid Build Coastguard Worker return ret;
2224*053f45beSAndroid Build Coastguard Worker }
2225*053f45beSAndroid Build Coastguard Worker
2226*053f45beSAndroid Build Coastguard Worker typedef void (*print_res)(const char *, ...);
2227*053f45beSAndroid Build Coastguard Worker
check_results(void)2228*053f45beSAndroid Build Coastguard Worker static int check_results(void)
2229*053f45beSAndroid Build Coastguard Worker {
2230*053f45beSAndroid Build Coastguard Worker struct test_result tr = {};
2231*053f45beSAndroid Build Coastguard Worker struct xfrm_desc *d = &tr.desc;
2232*053f45beSAndroid Build Coastguard Worker int ret = KSFT_PASS;
2233*053f45beSAndroid Build Coastguard Worker
2234*053f45beSAndroid Build Coastguard Worker while (1) {
2235*053f45beSAndroid Build Coastguard Worker ssize_t received = read(results_fd[0], &tr, sizeof(tr));
2236*053f45beSAndroid Build Coastguard Worker print_res result;
2237*053f45beSAndroid Build Coastguard Worker
2238*053f45beSAndroid Build Coastguard Worker if (received == 0) /* EOF */
2239*053f45beSAndroid Build Coastguard Worker break;
2240*053f45beSAndroid Build Coastguard Worker
2241*053f45beSAndroid Build Coastguard Worker if (received != sizeof(tr)) {
2242*053f45beSAndroid Build Coastguard Worker pr_err("read() returned %zd", received);
2243*053f45beSAndroid Build Coastguard Worker return KSFT_FAIL;
2244*053f45beSAndroid Build Coastguard Worker }
2245*053f45beSAndroid Build Coastguard Worker
2246*053f45beSAndroid Build Coastguard Worker switch (tr.res) {
2247*053f45beSAndroid Build Coastguard Worker case KSFT_PASS:
2248*053f45beSAndroid Build Coastguard Worker result = ksft_test_result_pass;
2249*053f45beSAndroid Build Coastguard Worker break;
2250*053f45beSAndroid Build Coastguard Worker case KSFT_FAIL:
2251*053f45beSAndroid Build Coastguard Worker default:
2252*053f45beSAndroid Build Coastguard Worker result = ksft_test_result_fail;
2253*053f45beSAndroid Build Coastguard Worker ret = KSFT_FAIL;
2254*053f45beSAndroid Build Coastguard Worker }
2255*053f45beSAndroid Build Coastguard Worker
2256*053f45beSAndroid Build Coastguard Worker result(" %s: [%u, '%s', '%s', '%s', '%s', %u]\n",
2257*053f45beSAndroid Build Coastguard Worker desc_name[d->type], (unsigned int)d->proto, d->a_algo,
2258*053f45beSAndroid Build Coastguard Worker d->e_algo, d->c_algo, d->ae_algo, d->icv_len);
2259*053f45beSAndroid Build Coastguard Worker }
2260*053f45beSAndroid Build Coastguard Worker
2261*053f45beSAndroid Build Coastguard Worker return ret;
2262*053f45beSAndroid Build Coastguard Worker }
2263*053f45beSAndroid Build Coastguard Worker
main(int argc,char ** argv)2264*053f45beSAndroid Build Coastguard Worker int main(int argc, char **argv)
2265*053f45beSAndroid Build Coastguard Worker {
2266*053f45beSAndroid Build Coastguard Worker unsigned int nr_process = 1;
2267*053f45beSAndroid Build Coastguard Worker int route_sock = -1, ret = KSFT_SKIP;
2268*053f45beSAndroid Build Coastguard Worker int test_desc_fd[2];
2269*053f45beSAndroid Build Coastguard Worker uint32_t route_seq;
2270*053f45beSAndroid Build Coastguard Worker unsigned int i;
2271*053f45beSAndroid Build Coastguard Worker
2272*053f45beSAndroid Build Coastguard Worker if (argc > 2)
2273*053f45beSAndroid Build Coastguard Worker exit_usage(argv);
2274*053f45beSAndroid Build Coastguard Worker
2275*053f45beSAndroid Build Coastguard Worker if (argc > 1) {
2276*053f45beSAndroid Build Coastguard Worker char *endptr;
2277*053f45beSAndroid Build Coastguard Worker
2278*053f45beSAndroid Build Coastguard Worker errno = 0;
2279*053f45beSAndroid Build Coastguard Worker nr_process = strtol(argv[1], &endptr, 10);
2280*053f45beSAndroid Build Coastguard Worker if ((errno == ERANGE && (nr_process == LONG_MAX || nr_process == LONG_MIN))
2281*053f45beSAndroid Build Coastguard Worker || (errno != 0 && nr_process == 0)
2282*053f45beSAndroid Build Coastguard Worker || (endptr == argv[1]) || (*endptr != '\0')) {
2283*053f45beSAndroid Build Coastguard Worker printk("Failed to parse [nr_process]");
2284*053f45beSAndroid Build Coastguard Worker exit_usage(argv);
2285*053f45beSAndroid Build Coastguard Worker }
2286*053f45beSAndroid Build Coastguard Worker
2287*053f45beSAndroid Build Coastguard Worker if (nr_process > MAX_PROCESSES || !nr_process) {
2288*053f45beSAndroid Build Coastguard Worker printk("nr_process should be between [1; %u]",
2289*053f45beSAndroid Build Coastguard Worker MAX_PROCESSES);
2290*053f45beSAndroid Build Coastguard Worker exit_usage(argv);
2291*053f45beSAndroid Build Coastguard Worker }
2292*053f45beSAndroid Build Coastguard Worker }
2293*053f45beSAndroid Build Coastguard Worker
2294*053f45beSAndroid Build Coastguard Worker srand(time(NULL));
2295*053f45beSAndroid Build Coastguard Worker page_size = sysconf(_SC_PAGESIZE);
2296*053f45beSAndroid Build Coastguard Worker if (page_size < 1)
2297*053f45beSAndroid Build Coastguard Worker ksft_exit_skip("sysconf(): %m\n");
2298*053f45beSAndroid Build Coastguard Worker
2299*053f45beSAndroid Build Coastguard Worker if (pipe2(test_desc_fd, O_DIRECT) < 0)
2300*053f45beSAndroid Build Coastguard Worker ksft_exit_skip("pipe(): %m\n");
2301*053f45beSAndroid Build Coastguard Worker
2302*053f45beSAndroid Build Coastguard Worker if (pipe2(results_fd, O_DIRECT) < 0)
2303*053f45beSAndroid Build Coastguard Worker ksft_exit_skip("pipe(): %m\n");
2304*053f45beSAndroid Build Coastguard Worker
2305*053f45beSAndroid Build Coastguard Worker if (init_namespaces())
2306*053f45beSAndroid Build Coastguard Worker ksft_exit_skip("Failed to create namespaces\n");
2307*053f45beSAndroid Build Coastguard Worker
2308*053f45beSAndroid Build Coastguard Worker if (netlink_sock(&route_sock, &route_seq, NETLINK_ROUTE))
2309*053f45beSAndroid Build Coastguard Worker ksft_exit_skip("Failed to open netlink route socket\n");
2310*053f45beSAndroid Build Coastguard Worker
2311*053f45beSAndroid Build Coastguard Worker for (i = 0; i < nr_process; i++) {
2312*053f45beSAndroid Build Coastguard Worker char veth[VETH_LEN];
2313*053f45beSAndroid Build Coastguard Worker
2314*053f45beSAndroid Build Coastguard Worker snprintf(veth, VETH_LEN, VETH_FMT, i);
2315*053f45beSAndroid Build Coastguard Worker
2316*053f45beSAndroid Build Coastguard Worker if (veth_add(route_sock, route_seq++, veth, nsfd_childa, veth, nsfd_childb)) {
2317*053f45beSAndroid Build Coastguard Worker close(route_sock);
2318*053f45beSAndroid Build Coastguard Worker ksft_exit_fail_msg("Failed to create veth device");
2319*053f45beSAndroid Build Coastguard Worker }
2320*053f45beSAndroid Build Coastguard Worker
2321*053f45beSAndroid Build Coastguard Worker if (start_child(i, veth, test_desc_fd)) {
2322*053f45beSAndroid Build Coastguard Worker close(route_sock);
2323*053f45beSAndroid Build Coastguard Worker ksft_exit_fail_msg("Child %u failed to start", i);
2324*053f45beSAndroid Build Coastguard Worker }
2325*053f45beSAndroid Build Coastguard Worker }
2326*053f45beSAndroid Build Coastguard Worker
2327*053f45beSAndroid Build Coastguard Worker if (close(route_sock) || close(test_desc_fd[0]) || close(results_fd[1]))
2328*053f45beSAndroid Build Coastguard Worker ksft_exit_fail_msg("close(): %m");
2329*053f45beSAndroid Build Coastguard Worker
2330*053f45beSAndroid Build Coastguard Worker ksft_set_plan(proto_plan + compat_plan);
2331*053f45beSAndroid Build Coastguard Worker
2332*053f45beSAndroid Build Coastguard Worker if (write_test_plan(test_desc_fd[1]))
2333*053f45beSAndroid Build Coastguard Worker ksft_exit_fail_msg("Failed to write test plan to pipe");
2334*053f45beSAndroid Build Coastguard Worker
2335*053f45beSAndroid Build Coastguard Worker ret = check_results();
2336*053f45beSAndroid Build Coastguard Worker
2337*053f45beSAndroid Build Coastguard Worker if (children_cleanup() == KSFT_FAIL)
2338*053f45beSAndroid Build Coastguard Worker exit(KSFT_FAIL);
2339*053f45beSAndroid Build Coastguard Worker
2340*053f45beSAndroid Build Coastguard Worker exit(ret);
2341*053f45beSAndroid Build Coastguard Worker }
2342