xref: /aosp_15_r20/external/linux-kselftest/tools/testing/selftests/net/ipsec.c (revision 053f45be4e351dfd5e965df293cd45b779f579ee)
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