xref: /aosp_15_r20/external/libnl/tests/nl-test-util.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
1*4dc78e53SAndroid Build Coastguard Worker /* SPDX-License-Identifier: LGPL-2.1-only */
2*4dc78e53SAndroid Build Coastguard Worker 
3*4dc78e53SAndroid Build Coastguard Worker #include "nl-default.h"
4*4dc78e53SAndroid Build Coastguard Worker 
5*4dc78e53SAndroid Build Coastguard Worker #include "nl-test-util.h"
6*4dc78e53SAndroid Build Coastguard Worker 
7*4dc78e53SAndroid Build Coastguard Worker #include <fcntl.h>
8*4dc78e53SAndroid Build Coastguard Worker #include <fnmatch.h>
9*4dc78e53SAndroid Build Coastguard Worker #include <sched.h>
10*4dc78e53SAndroid Build Coastguard Worker #include <stdio.h>
11*4dc78e53SAndroid Build Coastguard Worker #include <sys/mount.h>
12*4dc78e53SAndroid Build Coastguard Worker 
13*4dc78e53SAndroid Build Coastguard Worker #include <netlink/netlink.h>
14*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/link.h>
15*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/route.h>
16*4dc78e53SAndroid Build Coastguard Worker #include <netlink/socket.h>
17*4dc78e53SAndroid Build Coastguard Worker 
18*4dc78e53SAndroid Build Coastguard Worker #include "lib/route/nl-route.h"
19*4dc78e53SAndroid Build Coastguard Worker 
20*4dc78e53SAndroid Build Coastguard Worker #include "nl-aux-route/nl-route.h"
21*4dc78e53SAndroid Build Coastguard Worker 
22*4dc78e53SAndroid Build Coastguard Worker /*****************************************************************************/
23*4dc78e53SAndroid Build Coastguard Worker 
_nltst_get_urandom(void * ptr,size_t len)24*4dc78e53SAndroid Build Coastguard Worker void _nltst_get_urandom(void *ptr, size_t len)
25*4dc78e53SAndroid Build Coastguard Worker {
26*4dc78e53SAndroid Build Coastguard Worker 	int fd;
27*4dc78e53SAndroid Build Coastguard Worker 	ssize_t nread;
28*4dc78e53SAndroid Build Coastguard Worker 
29*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_int_gt(len, 0);
30*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_ptr_nonnull(ptr);
31*4dc78e53SAndroid Build Coastguard Worker 
32*4dc78e53SAndroid Build Coastguard Worker 	fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC | O_NOCTTY);
33*4dc78e53SAndroid Build Coastguard Worker 	_nltst_assert_errno(fd >= 0);
34*4dc78e53SAndroid Build Coastguard Worker 
35*4dc78e53SAndroid Build Coastguard Worker 	nread = read(fd, ptr, len);
36*4dc78e53SAndroid Build Coastguard Worker 	_nltst_assert_errno(nread >= 0 && ((size_t)nread) == len);
37*4dc78e53SAndroid Build Coastguard Worker 
38*4dc78e53SAndroid Build Coastguard Worker 	_nltst_close(fd);
39*4dc78e53SAndroid Build Coastguard Worker }
40*4dc78e53SAndroid Build Coastguard Worker 
_nltst_rand_u32(void)41*4dc78e53SAndroid Build Coastguard Worker uint32_t _nltst_rand_u32(void)
42*4dc78e53SAndroid Build Coastguard Worker {
43*4dc78e53SAndroid Build Coastguard Worker 	_nl_thread_local static unsigned short entropy[3];
44*4dc78e53SAndroid Build Coastguard Worker 	_nl_thread_local static bool has_entropy = false;
45*4dc78e53SAndroid Build Coastguard Worker 
46*4dc78e53SAndroid Build Coastguard Worker 	if (!has_entropy) {
47*4dc78e53SAndroid Build Coastguard Worker 		unsigned long long seed;
48*4dc78e53SAndroid Build Coastguard Worker 		uint64_t seed64;
49*4dc78e53SAndroid Build Coastguard Worker 		const char *s;
50*4dc78e53SAndroid Build Coastguard Worker 		char *s_end;
51*4dc78e53SAndroid Build Coastguard Worker 
52*4dc78e53SAndroid Build Coastguard Worker 		memset(entropy, 0, sizeof(entropy));
53*4dc78e53SAndroid Build Coastguard Worker 		s = getenv("NLTST_SEED_RAND");
54*4dc78e53SAndroid Build Coastguard Worker 		if (!s)
55*4dc78e53SAndroid Build Coastguard Worker 			seed = 0;
56*4dc78e53SAndroid Build Coastguard Worker 		else if (s[0] != '\0') {
57*4dc78e53SAndroid Build Coastguard Worker 			errno = 0;
58*4dc78e53SAndroid Build Coastguard Worker 			seed = strtoull(s, &s_end, 10);
59*4dc78e53SAndroid Build Coastguard Worker 			if (errno != 0 || s_end[0] != '\0') {
60*4dc78e53SAndroid Build Coastguard Worker 				ck_assert_msg(
61*4dc78e53SAndroid Build Coastguard Worker 					0,
62*4dc78e53SAndroid Build Coastguard Worker 					"invalid NLTST_SEED_RAND=\"%s\". Must be an integer to seed the random numbers",
63*4dc78e53SAndroid Build Coastguard Worker 					s);
64*4dc78e53SAndroid Build Coastguard Worker 			}
65*4dc78e53SAndroid Build Coastguard Worker 		} else
66*4dc78e53SAndroid Build Coastguard Worker 			_nltst_get_urandom(&seed, sizeof(seed));
67*4dc78e53SAndroid Build Coastguard Worker 
68*4dc78e53SAndroid Build Coastguard Worker 		seed64 = seed;
69*4dc78e53SAndroid Build Coastguard Worker 		printf("runs with NLTST_SEED_RAND=%" PRIu64 "\n", seed64);
70*4dc78e53SAndroid Build Coastguard Worker 
71*4dc78e53SAndroid Build Coastguard Worker 		entropy[0] = (seed64 >> 0) ^ (seed64 >> 48);
72*4dc78e53SAndroid Build Coastguard Worker 		entropy[1] = (seed64 >> 16) ^ (seed64 >> 0);
73*4dc78e53SAndroid Build Coastguard Worker 		entropy[2] = (seed64 >> 32) ^ (seed64 >> 16);
74*4dc78e53SAndroid Build Coastguard Worker 		has_entropy = true;
75*4dc78e53SAndroid Build Coastguard Worker 	}
76*4dc78e53SAndroid Build Coastguard Worker 
77*4dc78e53SAndroid Build Coastguard Worker 	_NL_STATIC_ASSERT(sizeof(long) >= sizeof(uint32_t));
78*4dc78e53SAndroid Build Coastguard Worker 	return jrand48(entropy);
79*4dc78e53SAndroid Build Coastguard Worker }
80*4dc78e53SAndroid Build Coastguard Worker 
81*4dc78e53SAndroid Build Coastguard Worker /*****************************************************************************/
82*4dc78e53SAndroid Build Coastguard Worker 
83*4dc78e53SAndroid Build Coastguard Worker #define _CANARY 539339
84*4dc78e53SAndroid Build Coastguard Worker 
85*4dc78e53SAndroid Build Coastguard Worker struct nltst_netns {
86*4dc78e53SAndroid Build Coastguard Worker 	int canary;
87*4dc78e53SAndroid Build Coastguard Worker };
88*4dc78e53SAndroid Build Coastguard Worker 
89*4dc78e53SAndroid Build Coastguard Worker /*****************************************************************************/
90*4dc78e53SAndroid Build Coastguard Worker 
91*4dc78e53SAndroid Build Coastguard Worker #define _assert_nltst_netns(nsdata)                           \
92*4dc78e53SAndroid Build Coastguard Worker 	do {                                                  \
93*4dc78e53SAndroid Build Coastguard Worker 		const struct nltst_netns *_nsdata = (nsdata); \
94*4dc78e53SAndroid Build Coastguard Worker                                                               \
95*4dc78e53SAndroid Build Coastguard Worker 		ck_assert_ptr_nonnull(_nsdata);               \
96*4dc78e53SAndroid Build Coastguard Worker 		ck_assert_int_eq(_nsdata->canary, _CANARY);   \
97*4dc78e53SAndroid Build Coastguard Worker 	} while (0)
98*4dc78e53SAndroid Build Coastguard Worker 
99*4dc78e53SAndroid Build Coastguard Worker static struct {
100*4dc78e53SAndroid Build Coastguard Worker 	struct nltst_netns *nsdata;
101*4dc78e53SAndroid Build Coastguard Worker } _netns_fixture_global;
102*4dc78e53SAndroid Build Coastguard Worker 
nltst_netns_fixture_setup(void)103*4dc78e53SAndroid Build Coastguard Worker void nltst_netns_fixture_setup(void)
104*4dc78e53SAndroid Build Coastguard Worker {
105*4dc78e53SAndroid Build Coastguard Worker 	ck_assert(!_netns_fixture_global.nsdata);
106*4dc78e53SAndroid Build Coastguard Worker 
107*4dc78e53SAndroid Build Coastguard Worker 	_netns_fixture_global.nsdata = nltst_netns_enter();
108*4dc78e53SAndroid Build Coastguard Worker 	_assert_nltst_netns(_netns_fixture_global.nsdata);
109*4dc78e53SAndroid Build Coastguard Worker }
110*4dc78e53SAndroid Build Coastguard Worker 
nltst_netns_fixture_teardown(void)111*4dc78e53SAndroid Build Coastguard Worker void nltst_netns_fixture_teardown(void)
112*4dc78e53SAndroid Build Coastguard Worker {
113*4dc78e53SAndroid Build Coastguard Worker 	_assert_nltst_netns(_netns_fixture_global.nsdata);
114*4dc78e53SAndroid Build Coastguard Worker 	_nl_clear_pointer(&_netns_fixture_global.nsdata, nltst_netns_leave);
115*4dc78e53SAndroid Build Coastguard Worker }
116*4dc78e53SAndroid Build Coastguard Worker 
117*4dc78e53SAndroid Build Coastguard Worker /*****************************************************************************/
118*4dc78e53SAndroid Build Coastguard Worker 
unshare_user(void)119*4dc78e53SAndroid Build Coastguard Worker static void unshare_user(void)
120*4dc78e53SAndroid Build Coastguard Worker {
121*4dc78e53SAndroid Build Coastguard Worker 	const uid_t uid = geteuid();
122*4dc78e53SAndroid Build Coastguard Worker 	const gid_t gid = getegid();
123*4dc78e53SAndroid Build Coastguard Worker 	FILE *f;
124*4dc78e53SAndroid Build Coastguard Worker 	int r;
125*4dc78e53SAndroid Build Coastguard Worker 
126*4dc78e53SAndroid Build Coastguard Worker 	/* Become a root in new user NS. */
127*4dc78e53SAndroid Build Coastguard Worker 	r = unshare(CLONE_NEWUSER);
128*4dc78e53SAndroid Build Coastguard Worker 	_nltst_assert_errno(r == 0);
129*4dc78e53SAndroid Build Coastguard Worker 
130*4dc78e53SAndroid Build Coastguard Worker 	/* Since Linux 3.19 we have to disable setgroups() in order to map users.
131*4dc78e53SAndroid Build Coastguard Worker 	 * Just proceed if the file is not there. */
132*4dc78e53SAndroid Build Coastguard Worker 	f = fopen("/proc/self/setgroups", "we");
133*4dc78e53SAndroid Build Coastguard Worker 	if (f) {
134*4dc78e53SAndroid Build Coastguard Worker 		r = fprintf(f, "deny");
135*4dc78e53SAndroid Build Coastguard Worker 		_nltst_assert_errno(r > 0);
136*4dc78e53SAndroid Build Coastguard Worker 		_nltst_fclose(f);
137*4dc78e53SAndroid Build Coastguard Worker 	}
138*4dc78e53SAndroid Build Coastguard Worker 
139*4dc78e53SAndroid Build Coastguard Worker 	/* Map current UID to root in NS to be created. */
140*4dc78e53SAndroid Build Coastguard Worker 	f = fopen("/proc/self/uid_map", "we");
141*4dc78e53SAndroid Build Coastguard Worker 	if (!f) {
142*4dc78e53SAndroid Build Coastguard Worker 		if (errno == EACCES) {
143*4dc78e53SAndroid Build Coastguard Worker 			/* Accessing uid_map might fail due to sandboxing.
144*4dc78e53SAndroid Build Coastguard Worker 			 * We ignore that error and proceed with the test. It will probably
145*4dc78e53SAndroid Build Coastguard Worker 			 * still work. */
146*4dc78e53SAndroid Build Coastguard Worker 			return;
147*4dc78e53SAndroid Build Coastguard Worker 		}
148*4dc78e53SAndroid Build Coastguard Worker 		_nltst_assert_errno(f);
149*4dc78e53SAndroid Build Coastguard Worker 	}
150*4dc78e53SAndroid Build Coastguard Worker 	r = fprintf(f, "0 %d 1", uid);
151*4dc78e53SAndroid Build Coastguard Worker 	_nltst_assert_errno(r > 0);
152*4dc78e53SAndroid Build Coastguard Worker 	_nltst_fclose(f);
153*4dc78e53SAndroid Build Coastguard Worker 
154*4dc78e53SAndroid Build Coastguard Worker 	/* Map current GID to root in NS to be created. */
155*4dc78e53SAndroid Build Coastguard Worker 	f = fopen("/proc/self/gid_map", "we");
156*4dc78e53SAndroid Build Coastguard Worker 	_nltst_assert_errno(f);
157*4dc78e53SAndroid Build Coastguard Worker 	r = fprintf(f, "0 %d 1", gid);
158*4dc78e53SAndroid Build Coastguard Worker 	_nltst_assert_errno(r > 0);
159*4dc78e53SAndroid Build Coastguard Worker 	_nltst_fclose(f);
160*4dc78e53SAndroid Build Coastguard Worker }
161*4dc78e53SAndroid Build Coastguard Worker 
nltst_netns_enter(void)162*4dc78e53SAndroid Build Coastguard Worker struct nltst_netns *nltst_netns_enter(void)
163*4dc78e53SAndroid Build Coastguard Worker {
164*4dc78e53SAndroid Build Coastguard Worker 	struct nltst_netns *nsdata;
165*4dc78e53SAndroid Build Coastguard Worker 	int r;
166*4dc78e53SAndroid Build Coastguard Worker 
167*4dc78e53SAndroid Build Coastguard Worker 	nsdata = calloc(1, sizeof(struct nltst_netns));
168*4dc78e53SAndroid Build Coastguard Worker 	ck_assert(nsdata);
169*4dc78e53SAndroid Build Coastguard Worker 
170*4dc78e53SAndroid Build Coastguard Worker 	nsdata->canary = _CANARY;
171*4dc78e53SAndroid Build Coastguard Worker 
172*4dc78e53SAndroid Build Coastguard Worker 	unshare_user();
173*4dc78e53SAndroid Build Coastguard Worker 
174*4dc78e53SAndroid Build Coastguard Worker 	r = unshare(CLONE_NEWNET | CLONE_NEWNS);
175*4dc78e53SAndroid Build Coastguard Worker 	_nltst_assert_errno(r == 0);
176*4dc78e53SAndroid Build Coastguard Worker 
177*4dc78e53SAndroid Build Coastguard Worker 	/* We need a read-only /sys so that the platform knows there's no udev. */
178*4dc78e53SAndroid Build Coastguard Worker 	mount(NULL, "/sys", "sysfs", MS_SLAVE, NULL);
179*4dc78e53SAndroid Build Coastguard Worker 	r = mount("sys", "/sys", "sysfs", MS_RDONLY, NULL);
180*4dc78e53SAndroid Build Coastguard Worker 	_nltst_assert_errno(r == 0);
181*4dc78e53SAndroid Build Coastguard Worker 
182*4dc78e53SAndroid Build Coastguard Worker 	return nsdata;
183*4dc78e53SAndroid Build Coastguard Worker }
184*4dc78e53SAndroid Build Coastguard Worker 
nltst_netns_leave(struct nltst_netns * nsdata)185*4dc78e53SAndroid Build Coastguard Worker void nltst_netns_leave(struct nltst_netns *nsdata)
186*4dc78e53SAndroid Build Coastguard Worker {
187*4dc78e53SAndroid Build Coastguard Worker 	ck_assert(nsdata);
188*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_int_eq(nsdata->canary, _CANARY);
189*4dc78e53SAndroid Build Coastguard Worker 
190*4dc78e53SAndroid Build Coastguard Worker 	/* nltst_netns_leave() was supposed to enter the original namespaces again
191*4dc78e53SAndroid Build Coastguard Worker 	 * and undo enter.
192*4dc78e53SAndroid Build Coastguard Worker 	 *
193*4dc78e53SAndroid Build Coastguard Worker 	 * However, I could get it to work (setns() always fails with EPERM)
194*4dc78e53SAndroid Build Coastguard Worker 	 * and valgrind on current Ubuntu seems not to support setns() call.
195*4dc78e53SAndroid Build Coastguard Worker 	 *
196*4dc78e53SAndroid Build Coastguard Worker 	 * So, do nothing. It's not really a problem, because the next test
197*4dc78e53SAndroid Build Coastguard Worker 	 * either should unshare yet another namespace, or not care about
198*4dc78e53SAndroid Build Coastguard Worker 	 * such things. */
199*4dc78e53SAndroid Build Coastguard Worker 
200*4dc78e53SAndroid Build Coastguard Worker 	free(nsdata);
201*4dc78e53SAndroid Build Coastguard Worker }
202*4dc78e53SAndroid Build Coastguard Worker 
203*4dc78e53SAndroid Build Coastguard Worker /*****************************************************************************/
204*4dc78e53SAndroid Build Coastguard Worker 
_nltst_object_identical(const void * a,const void * b)205*4dc78e53SAndroid Build Coastguard Worker void _nltst_object_identical(const void *a, const void *b)
206*4dc78e53SAndroid Build Coastguard Worker {
207*4dc78e53SAndroid Build Coastguard Worker 	struct nl_object *o_a = (void *)a;
208*4dc78e53SAndroid Build Coastguard Worker 	struct nl_object *o_b = (void *)b;
209*4dc78e53SAndroid Build Coastguard Worker 
210*4dc78e53SAndroid Build Coastguard Worker 	ck_assert(a);
211*4dc78e53SAndroid Build Coastguard Worker 	ck_assert(b);
212*4dc78e53SAndroid Build Coastguard Worker 
213*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_int_eq(nl_object_identical(o_a, o_b), 1);
214*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_int_eq(nl_object_identical(o_b, o_a), 1);
215*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_int_eq(nl_object_diff64(o_b, o_a), 0);
216*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_int_eq(nl_object_diff64(o_a, o_b), 0);
217*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_int_eq(nl_object_diff(o_a, o_b), 0);
218*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_int_eq(nl_object_diff(o_b, o_a), 0);
219*4dc78e53SAndroid Build Coastguard Worker }
220*4dc78e53SAndroid Build Coastguard Worker 
221*4dc78e53SAndroid Build Coastguard Worker /*****************************************************************************/
222*4dc78e53SAndroid Build Coastguard Worker 
_nltst_object_to_string(const struct nl_object * obj)223*4dc78e53SAndroid Build Coastguard Worker char *_nltst_object_to_string(const struct nl_object *obj)
224*4dc78e53SAndroid Build Coastguard Worker {
225*4dc78e53SAndroid Build Coastguard Worker 	size_t L = 1024;
226*4dc78e53SAndroid Build Coastguard Worker 	size_t l;
227*4dc78e53SAndroid Build Coastguard Worker 	char *s;
228*4dc78e53SAndroid Build Coastguard Worker 	struct nl_dump_params dp;
229*4dc78e53SAndroid Build Coastguard Worker 	char canary;
230*4dc78e53SAndroid Build Coastguard Worker 
231*4dc78e53SAndroid Build Coastguard Worker 	if (!obj)
232*4dc78e53SAndroid Build Coastguard Worker 		return strdup("(null)");
233*4dc78e53SAndroid Build Coastguard Worker 
234*4dc78e53SAndroid Build Coastguard Worker 	s = malloc(L);
235*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_ptr_nonnull(s);
236*4dc78e53SAndroid Build Coastguard Worker 
237*4dc78e53SAndroid Build Coastguard Worker 	canary = _nltst_rand_u32();
238*4dc78e53SAndroid Build Coastguard Worker 	s[L - 1u] = canary;
239*4dc78e53SAndroid Build Coastguard Worker 
240*4dc78e53SAndroid Build Coastguard Worker 	dp = (struct nl_dump_params){
241*4dc78e53SAndroid Build Coastguard Worker 		.dp_type = NL_DUMP_LINE,
242*4dc78e53SAndroid Build Coastguard Worker 		.dp_buf = s,
243*4dc78e53SAndroid Build Coastguard Worker 		.dp_buflen = L - 1u,
244*4dc78e53SAndroid Build Coastguard Worker 	};
245*4dc78e53SAndroid Build Coastguard Worker 
246*4dc78e53SAndroid Build Coastguard Worker 	nl_object_dump((struct nl_object *)obj, &dp);
247*4dc78e53SAndroid Build Coastguard Worker 
248*4dc78e53SAndroid Build Coastguard Worker 	l = strlen(s);
249*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_int_ge(l, 2);
250*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_int_lt(l, L);
251*4dc78e53SAndroid Build Coastguard Worker 	ck_assert(canary == s[L - 1u]);
252*4dc78e53SAndroid Build Coastguard Worker 	s = realloc(s, l + 1);
253*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_ptr_nonnull(s);
254*4dc78e53SAndroid Build Coastguard Worker 
255*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_msg(s[l - 1u] == '\n',
256*4dc78e53SAndroid Build Coastguard Worker 		      "expects newline after dump. Got \"%s\"", s);
257*4dc78e53SAndroid Build Coastguard Worker 	s[l - 1u] = '\0';
258*4dc78e53SAndroid Build Coastguard Worker 
259*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_msg(!strchr(s, '\n'),
260*4dc78e53SAndroid Build Coastguard Worker 		      "no further newline expected. Got \"%s\"", s);
261*4dc78e53SAndroid Build Coastguard Worker 
262*4dc78e53SAndroid Build Coastguard Worker 	return s;
263*4dc78e53SAndroid Build Coastguard Worker }
264*4dc78e53SAndroid Build Coastguard Worker 
265*4dc78e53SAndroid Build Coastguard Worker struct cache_get_all_data {
266*4dc78e53SAndroid Build Coastguard Worker 	struct nl_object **arr;
267*4dc78e53SAndroid Build Coastguard Worker 	size_t len;
268*4dc78e53SAndroid Build Coastguard Worker 	size_t idx;
269*4dc78e53SAndroid Build Coastguard Worker };
270*4dc78e53SAndroid Build Coastguard Worker 
_cache_get_all_fcn(struct nl_object * obj,void * user_data)271*4dc78e53SAndroid Build Coastguard Worker static void _cache_get_all_fcn(struct nl_object *obj, void *user_data)
272*4dc78e53SAndroid Build Coastguard Worker {
273*4dc78e53SAndroid Build Coastguard Worker 	struct cache_get_all_data *data = user_data;
274*4dc78e53SAndroid Build Coastguard Worker 	size_t i;
275*4dc78e53SAndroid Build Coastguard Worker 
276*4dc78e53SAndroid Build Coastguard Worker 	ck_assert(obj);
277*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_int_lt(data->idx, data->len);
278*4dc78e53SAndroid Build Coastguard Worker 
279*4dc78e53SAndroid Build Coastguard Worker 	for (i = 0; i < data->idx; i++)
280*4dc78e53SAndroid Build Coastguard Worker 		ck_assert_ptr_ne(data->arr[i], obj);
281*4dc78e53SAndroid Build Coastguard Worker 
282*4dc78e53SAndroid Build Coastguard Worker 	data->arr[data->idx++] = obj;
283*4dc78e53SAndroid Build Coastguard Worker }
284*4dc78e53SAndroid Build Coastguard Worker 
_nltst_cache_get_all(struct nl_cache * cache,size_t * out_len)285*4dc78e53SAndroid Build Coastguard Worker struct nl_object **_nltst_cache_get_all(struct nl_cache *cache, size_t *out_len)
286*4dc78e53SAndroid Build Coastguard Worker {
287*4dc78e53SAndroid Build Coastguard Worker 	int nitems;
288*4dc78e53SAndroid Build Coastguard Worker 	struct cache_get_all_data data = {
289*4dc78e53SAndroid Build Coastguard Worker 		.idx = 0,
290*4dc78e53SAndroid Build Coastguard Worker 		.len = 0,
291*4dc78e53SAndroid Build Coastguard Worker 	};
292*4dc78e53SAndroid Build Coastguard Worker 	size_t len2 = 0;
293*4dc78e53SAndroid Build Coastguard Worker 	size_t i;
294*4dc78e53SAndroid Build Coastguard Worker 	size_t j;
295*4dc78e53SAndroid Build Coastguard Worker 
296*4dc78e53SAndroid Build Coastguard Worker 	ck_assert(cache);
297*4dc78e53SAndroid Build Coastguard Worker 
298*4dc78e53SAndroid Build Coastguard Worker 	nitems = nl_cache_nitems(cache);
299*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_int_ge(nitems, 0);
300*4dc78e53SAndroid Build Coastguard Worker 
301*4dc78e53SAndroid Build Coastguard Worker 	data.len = nitems;
302*4dc78e53SAndroid Build Coastguard Worker 	data.arr = malloc(sizeof(struct nl_object *) * (data.len + 1));
303*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_ptr_nonnull(data.arr);
304*4dc78e53SAndroid Build Coastguard Worker 
305*4dc78e53SAndroid Build Coastguard Worker 	nl_cache_foreach(cache, _cache_get_all_fcn, &data);
306*4dc78e53SAndroid Build Coastguard Worker 
307*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_int_eq(data.idx, data.len);
308*4dc78e53SAndroid Build Coastguard Worker 
309*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_int_le(data.len, SSIZE_MAX);
310*4dc78e53SAndroid Build Coastguard Worker 
311*4dc78e53SAndroid Build Coastguard Worker 	data.arr[data.len] = NULL;
312*4dc78e53SAndroid Build Coastguard Worker 	if (out_len)
313*4dc78e53SAndroid Build Coastguard Worker 		*out_len = data.len;
314*4dc78e53SAndroid Build Coastguard Worker 
315*4dc78e53SAndroid Build Coastguard Worker 	/* double check the result. */
316*4dc78e53SAndroid Build Coastguard Worker 	for (struct nl_object *obj = nl_cache_get_first(cache); obj;
317*4dc78e53SAndroid Build Coastguard Worker 	     obj = nl_cache_get_next(obj)) {
318*4dc78e53SAndroid Build Coastguard Worker 		ck_assert_ptr_eq(data.arr[len2], obj);
319*4dc78e53SAndroid Build Coastguard Worker 		len2++;
320*4dc78e53SAndroid Build Coastguard Worker 	}
321*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_ptr_null(data.arr[len2]);
322*4dc78e53SAndroid Build Coastguard Worker 
323*4dc78e53SAndroid Build Coastguard Worker 	for (i = 0; i < data.len; i++) {
324*4dc78e53SAndroid Build Coastguard Worker 		ck_assert_ptr_nonnull(data.arr[i]);
325*4dc78e53SAndroid Build Coastguard Worker 		for (j = i + 1; j < data.len; j++)
326*4dc78e53SAndroid Build Coastguard Worker 			ck_assert_ptr_ne(data.arr[i], data.arr[j]);
327*4dc78e53SAndroid Build Coastguard Worker 	}
328*4dc78e53SAndroid Build Coastguard Worker 
329*4dc78e53SAndroid Build Coastguard Worker 	return data.arr;
330*4dc78e53SAndroid Build Coastguard Worker }
331*4dc78e53SAndroid Build Coastguard Worker 
_nltst_cache_get_link(struct nl_cache * cache,const char * ifname)332*4dc78e53SAndroid Build Coastguard Worker struct rtnl_link *_nltst_cache_get_link(struct nl_cache *cache,
333*4dc78e53SAndroid Build Coastguard Worker 					const char *ifname)
334*4dc78e53SAndroid Build Coastguard Worker {
335*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_free struct nl_object **objs = NULL;
336*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_link *link = NULL;
337*4dc78e53SAndroid Build Coastguard Worker 	size_t i;
338*4dc78e53SAndroid Build Coastguard Worker 
339*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_ptr_nonnull(cache);
340*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_ptr_nonnull(ifname);
341*4dc78e53SAndroid Build Coastguard Worker 
342*4dc78e53SAndroid Build Coastguard Worker 	objs = _nltst_cache_get_all(cache, NULL);
343*4dc78e53SAndroid Build Coastguard Worker 	for (i = 0; objs[i]; i++) {
344*4dc78e53SAndroid Build Coastguard Worker 		if (_nl_streq(rtnl_link_get_name((struct rtnl_link *)objs[i]),
345*4dc78e53SAndroid Build Coastguard Worker 			      ifname)) {
346*4dc78e53SAndroid Build Coastguard Worker 			ck_assert_ptr_null(link);
347*4dc78e53SAndroid Build Coastguard Worker 			link = (struct rtnl_link *)objs[i];
348*4dc78e53SAndroid Build Coastguard Worker 		}
349*4dc78e53SAndroid Build Coastguard Worker 	}
350*4dc78e53SAndroid Build Coastguard Worker 
351*4dc78e53SAndroid Build Coastguard Worker 	if (_nltst_rand_u32_range(5) == 0) {
352*4dc78e53SAndroid Build Coastguard Worker 		_nl_auto_rtnl_link struct rtnl_link *link2 = NULL;
353*4dc78e53SAndroid Build Coastguard Worker 
354*4dc78e53SAndroid Build Coastguard Worker 		link2 = rtnl_link_get_by_name(cache, ifname);
355*4dc78e53SAndroid Build Coastguard Worker 		ck_assert_ptr_eq(link2, link);
356*4dc78e53SAndroid Build Coastguard Worker 	}
357*4dc78e53SAndroid Build Coastguard Worker 
358*4dc78e53SAndroid Build Coastguard Worker 	return link;
359*4dc78e53SAndroid Build Coastguard Worker }
360*4dc78e53SAndroid Build Coastguard Worker 
361*4dc78e53SAndroid Build Coastguard Worker /*****************************************************************************/
362*4dc78e53SAndroid Build Coastguard Worker 
_nltst_socket(int protocol)363*4dc78e53SAndroid Build Coastguard Worker struct nl_sock *_nltst_socket(int protocol)
364*4dc78e53SAndroid Build Coastguard Worker {
365*4dc78e53SAndroid Build Coastguard Worker 	struct nl_sock *sk;
366*4dc78e53SAndroid Build Coastguard Worker 	int r;
367*4dc78e53SAndroid Build Coastguard Worker 
368*4dc78e53SAndroid Build Coastguard Worker 	sk = nl_socket_alloc();
369*4dc78e53SAndroid Build Coastguard Worker 	ck_assert(sk);
370*4dc78e53SAndroid Build Coastguard Worker 
371*4dc78e53SAndroid Build Coastguard Worker 	r = nl_connect(sk, protocol);
372*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_int_eq(r, 0);
373*4dc78e53SAndroid Build Coastguard Worker 
374*4dc78e53SAndroid Build Coastguard Worker 	if (_nltst_rand_u32_range(5) == 0)
375*4dc78e53SAndroid Build Coastguard Worker 		nl_cache_free(_nltst_rtnl_link_alloc_cache(sk, AF_UNSPEC, 0));
376*4dc78e53SAndroid Build Coastguard Worker 
377*4dc78e53SAndroid Build Coastguard Worker 	if (_nltst_rand_u32_range(5) == 0)
378*4dc78e53SAndroid Build Coastguard Worker 		nl_cache_free(_nltst_rtnl_route_alloc_cache(
379*4dc78e53SAndroid Build Coastguard Worker 			sk, _nltst_rand_select(AF_UNSPEC, AF_INET, AF_INET6)));
380*4dc78e53SAndroid Build Coastguard Worker 
381*4dc78e53SAndroid Build Coastguard Worker 	return sk;
382*4dc78e53SAndroid Build Coastguard Worker }
383*4dc78e53SAndroid Build Coastguard Worker 
_nltst_add_link(struct nl_sock * sk,const char * ifname,const char * kind,int * out_ifindex)384*4dc78e53SAndroid Build Coastguard Worker void _nltst_add_link(struct nl_sock *sk, const char *ifname, const char *kind,
385*4dc78e53SAndroid Build Coastguard Worker 		     int *out_ifindex)
386*4dc78e53SAndroid Build Coastguard Worker {
387*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_nl_socket struct nl_sock *sk_free = NULL;
388*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_rtnl_link struct rtnl_link *link = NULL;
389*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_nl_cache struct nl_cache *cache = NULL;
390*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_link *link2;
391*4dc78e53SAndroid Build Coastguard Worker 	int ifindex;
392*4dc78e53SAndroid Build Coastguard Worker 	int r;
393*4dc78e53SAndroid Build Coastguard Worker 
394*4dc78e53SAndroid Build Coastguard Worker 	ck_assert(ifname);
395*4dc78e53SAndroid Build Coastguard Worker 	ck_assert(kind);
396*4dc78e53SAndroid Build Coastguard Worker 
397*4dc78e53SAndroid Build Coastguard Worker 	if (_nltst_rand_u32_range(5) == 0)
398*4dc78e53SAndroid Build Coastguard Worker 		_nltst_assert_link_not_exists(ifname);
399*4dc78e53SAndroid Build Coastguard Worker 
400*4dc78e53SAndroid Build Coastguard Worker 	if (!sk) {
401*4dc78e53SAndroid Build Coastguard Worker 		sk = _nltst_socket(NETLINK_ROUTE);
402*4dc78e53SAndroid Build Coastguard Worker 		sk_free = sk;
403*4dc78e53SAndroid Build Coastguard Worker 	}
404*4dc78e53SAndroid Build Coastguard Worker 
405*4dc78e53SAndroid Build Coastguard Worker 	link = rtnl_link_alloc();
406*4dc78e53SAndroid Build Coastguard Worker 	ck_assert(link);
407*4dc78e53SAndroid Build Coastguard Worker 
408*4dc78e53SAndroid Build Coastguard Worker 	r = rtnl_link_set_type(link, kind);
409*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_int_eq(r, 0);
410*4dc78e53SAndroid Build Coastguard Worker 
411*4dc78e53SAndroid Build Coastguard Worker 	rtnl_link_set_name(link, ifname);
412*4dc78e53SAndroid Build Coastguard Worker 
413*4dc78e53SAndroid Build Coastguard Worker 	r = rtnl_link_add(sk, link, NLM_F_CREATE);
414*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_int_eq(r, 0);
415*4dc78e53SAndroid Build Coastguard Worker 
416*4dc78e53SAndroid Build Coastguard Worker 	if (!out_ifindex && _nltst_rand_u32_range(5) != 0)
417*4dc78e53SAndroid Build Coastguard Worker 		return;
418*4dc78e53SAndroid Build Coastguard Worker 
419*4dc78e53SAndroid Build Coastguard Worker 	cache = _nltst_rtnl_link_alloc_cache(sk, AF_UNSPEC, 0);
420*4dc78e53SAndroid Build Coastguard Worker 
421*4dc78e53SAndroid Build Coastguard Worker 	link2 = _nltst_cache_get_link(cache, ifname);
422*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_ptr_nonnull(link2);
423*4dc78e53SAndroid Build Coastguard Worker 
424*4dc78e53SAndroid Build Coastguard Worker 	ifindex = rtnl_link_get_ifindex(link2);
425*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_int_gt(ifindex, 0);
426*4dc78e53SAndroid Build Coastguard Worker 
427*4dc78e53SAndroid Build Coastguard Worker 	if (out_ifindex)
428*4dc78e53SAndroid Build Coastguard Worker 		*out_ifindex = ifindex;
429*4dc78e53SAndroid Build Coastguard Worker }
430*4dc78e53SAndroid Build Coastguard Worker 
_nltst_delete_link(struct nl_sock * sk,const char * ifname)431*4dc78e53SAndroid Build Coastguard Worker void _nltst_delete_link(struct nl_sock *sk, const char *ifname)
432*4dc78e53SAndroid Build Coastguard Worker {
433*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_nl_socket struct nl_sock *sk_free = NULL;
434*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_rtnl_link struct rtnl_link *link = NULL;
435*4dc78e53SAndroid Build Coastguard Worker 
436*4dc78e53SAndroid Build Coastguard Worker 	_nltst_assert_link_exists(ifname);
437*4dc78e53SAndroid Build Coastguard Worker 
438*4dc78e53SAndroid Build Coastguard Worker 	if (!sk) {
439*4dc78e53SAndroid Build Coastguard Worker 		sk = _nltst_socket(NETLINK_ROUTE);
440*4dc78e53SAndroid Build Coastguard Worker 		sk_free = sk;
441*4dc78e53SAndroid Build Coastguard Worker 	}
442*4dc78e53SAndroid Build Coastguard Worker 
443*4dc78e53SAndroid Build Coastguard Worker 	if (_nltst_rand_u32_range(5) == 0) {
444*4dc78e53SAndroid Build Coastguard Worker 		_nl_auto_nl_cache struct nl_cache *cache = NULL;
445*4dc78e53SAndroid Build Coastguard Worker 
446*4dc78e53SAndroid Build Coastguard Worker 		cache = _nltst_rtnl_link_alloc_cache(sk, AF_UNSPEC, 0);
447*4dc78e53SAndroid Build Coastguard Worker 		ck_assert_ptr_nonnull(_nltst_cache_get_link(cache, ifname));
448*4dc78e53SAndroid Build Coastguard Worker 	}
449*4dc78e53SAndroid Build Coastguard Worker 
450*4dc78e53SAndroid Build Coastguard Worker 	link = rtnl_link_alloc();
451*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_ptr_nonnull(link);
452*4dc78e53SAndroid Build Coastguard Worker 
453*4dc78e53SAndroid Build Coastguard Worker 	rtnl_link_set_name(link, ifname);
454*4dc78e53SAndroid Build Coastguard Worker 
455*4dc78e53SAndroid Build Coastguard Worker 	_nltst_assert_retcode(rtnl_link_delete(sk, link));
456*4dc78e53SAndroid Build Coastguard Worker 
457*4dc78e53SAndroid Build Coastguard Worker 	_nltst_assert_link_not_exists(ifname);
458*4dc78e53SAndroid Build Coastguard Worker }
459*4dc78e53SAndroid Build Coastguard Worker 
_nltst_get_link(struct nl_sock * sk,const char * ifname,int * out_ifindex,struct rtnl_link ** out_link)460*4dc78e53SAndroid Build Coastguard Worker void _nltst_get_link(struct nl_sock *sk, const char *ifname, int *out_ifindex,
461*4dc78e53SAndroid Build Coastguard Worker 		     struct rtnl_link **out_link)
462*4dc78e53SAndroid Build Coastguard Worker {
463*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_nl_cache struct nl_cache *cache = NULL;
464*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_link *link;
465*4dc78e53SAndroid Build Coastguard Worker 
466*4dc78e53SAndroid Build Coastguard Worker 	if (_nltst_rand_u32_range(5) == 0)
467*4dc78e53SAndroid Build Coastguard Worker 		_nltst_assert_link_exists(ifname);
468*4dc78e53SAndroid Build Coastguard Worker 
469*4dc78e53SAndroid Build Coastguard Worker 	cache = _nltst_rtnl_link_alloc_cache(sk, AF_UNSPEC, 0);
470*4dc78e53SAndroid Build Coastguard Worker 
471*4dc78e53SAndroid Build Coastguard Worker 	link = _nltst_cache_get_link(cache, ifname);
472*4dc78e53SAndroid Build Coastguard Worker 	ck_assert(link);
473*4dc78e53SAndroid Build Coastguard Worker 
474*4dc78e53SAndroid Build Coastguard Worker 	if (out_ifindex)
475*4dc78e53SAndroid Build Coastguard Worker 		*out_ifindex = rtnl_link_get_ifindex(link);
476*4dc78e53SAndroid Build Coastguard Worker 
477*4dc78e53SAndroid Build Coastguard Worker 	if (out_link) {
478*4dc78e53SAndroid Build Coastguard Worker 		nl_object_get((struct nl_object *)link);
479*4dc78e53SAndroid Build Coastguard Worker 		*out_link = link;
480*4dc78e53SAndroid Build Coastguard Worker 	}
481*4dc78e53SAndroid Build Coastguard Worker }
482*4dc78e53SAndroid Build Coastguard Worker 
_nltst_rtnl_link_alloc_cache(struct nl_sock * sk,int addr_family,unsigned flags)483*4dc78e53SAndroid Build Coastguard Worker struct nl_cache *_nltst_rtnl_link_alloc_cache(struct nl_sock *sk,
484*4dc78e53SAndroid Build Coastguard Worker 					      int addr_family, unsigned flags)
485*4dc78e53SAndroid Build Coastguard Worker {
486*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_nl_socket struct nl_sock *sk_free = NULL;
487*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache *cache;
488*4dc78e53SAndroid Build Coastguard Worker 	int r;
489*4dc78e53SAndroid Build Coastguard Worker 
490*4dc78e53SAndroid Build Coastguard Worker 	if (!sk) {
491*4dc78e53SAndroid Build Coastguard Worker 		sk = _nltst_socket(NETLINK_ROUTE);
492*4dc78e53SAndroid Build Coastguard Worker 		sk_free = sk;
493*4dc78e53SAndroid Build Coastguard Worker 	}
494*4dc78e53SAndroid Build Coastguard Worker 
495*4dc78e53SAndroid Build Coastguard Worker 	if (flags == 0 && _nltst_rand_bool())
496*4dc78e53SAndroid Build Coastguard Worker 		r = rtnl_link_alloc_cache(sk, addr_family, &cache);
497*4dc78e53SAndroid Build Coastguard Worker 	else
498*4dc78e53SAndroid Build Coastguard Worker 		r = rtnl_link_alloc_cache_flags(sk, addr_family, &cache, flags);
499*4dc78e53SAndroid Build Coastguard Worker 
500*4dc78e53SAndroid Build Coastguard Worker 	_nltst_assert_retcode(r);
501*4dc78e53SAndroid Build Coastguard Worker 
502*4dc78e53SAndroid Build Coastguard Worker 	if (_nltst_rand_u32_range(5) == 0)
503*4dc78e53SAndroid Build Coastguard Worker 		free(_nltst_cache_get_all(cache, NULL));
504*4dc78e53SAndroid Build Coastguard Worker 
505*4dc78e53SAndroid Build Coastguard Worker 	return _nltst_assert(cache);
506*4dc78e53SAndroid Build Coastguard Worker }
507*4dc78e53SAndroid Build Coastguard Worker 
_nltst_rtnl_route_alloc_cache(struct nl_sock * sk,int addr_family)508*4dc78e53SAndroid Build Coastguard Worker struct nl_cache *_nltst_rtnl_route_alloc_cache(struct nl_sock *sk,
509*4dc78e53SAndroid Build Coastguard Worker 					       int addr_family)
510*4dc78e53SAndroid Build Coastguard Worker {
511*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache *cache;
512*4dc78e53SAndroid Build Coastguard Worker 
513*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_ptr_nonnull(sk);
514*4dc78e53SAndroid Build Coastguard Worker 	ck_assert(addr_family == AF_UNSPEC || addr_family == AF_INET ||
515*4dc78e53SAndroid Build Coastguard Worker 		  addr_family == AF_INET6);
516*4dc78e53SAndroid Build Coastguard Worker 
517*4dc78e53SAndroid Build Coastguard Worker 	_nltst_assert_retcode(
518*4dc78e53SAndroid Build Coastguard Worker 		rtnl_route_alloc_cache(sk, addr_family, 0, &cache));
519*4dc78e53SAndroid Build Coastguard Worker 
520*4dc78e53SAndroid Build Coastguard Worker 	if (_nltst_rand_u32_range(5) == 0)
521*4dc78e53SAndroid Build Coastguard Worker 		free(_nltst_cache_get_all(cache, NULL));
522*4dc78e53SAndroid Build Coastguard Worker 
523*4dc78e53SAndroid Build Coastguard Worker 	return _nltst_assert(cache);
524*4dc78e53SAndroid Build Coastguard Worker }
525*4dc78e53SAndroid Build Coastguard Worker 
526*4dc78e53SAndroid Build Coastguard Worker /*****************************************************************************/
527*4dc78e53SAndroid Build Coastguard Worker 
_nltst_strtok(const char ** p_str)528*4dc78e53SAndroid Build Coastguard Worker char *_nltst_strtok(const char **p_str)
529*4dc78e53SAndroid Build Coastguard Worker {
530*4dc78e53SAndroid Build Coastguard Worker 	const char *str;
531*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_free char *dst = NULL;
532*4dc78e53SAndroid Build Coastguard Worker 	size_t dst_len = 0;
533*4dc78e53SAndroid Build Coastguard Worker 	size_t dst_alloc = 0;
534*4dc78e53SAndroid Build Coastguard Worker 	size_t i;
535*4dc78e53SAndroid Build Coastguard Worker 
536*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_ptr_nonnull(p_str);
537*4dc78e53SAndroid Build Coastguard Worker 
538*4dc78e53SAndroid Build Coastguard Worker 	str = _nltst_str_skip_space(*p_str);
539*4dc78e53SAndroid Build Coastguard Worker 
540*4dc78e53SAndroid Build Coastguard Worker 	if (str[0] == '\0') {
541*4dc78e53SAndroid Build Coastguard Worker 		*p_str = str;
542*4dc78e53SAndroid Build Coastguard Worker 		return NULL;
543*4dc78e53SAndroid Build Coastguard Worker 	}
544*4dc78e53SAndroid Build Coastguard Worker 
545*4dc78e53SAndroid Build Coastguard Worker 	dst_len = 0;
546*4dc78e53SAndroid Build Coastguard Worker 	dst_alloc = 10;
547*4dc78e53SAndroid Build Coastguard Worker 	dst = malloc(dst_alloc);
548*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_ptr_nonnull(dst);
549*4dc78e53SAndroid Build Coastguard Worker 
550*4dc78e53SAndroid Build Coastguard Worker 	i = 0;
551*4dc78e53SAndroid Build Coastguard Worker 	while (true) {
552*4dc78e53SAndroid Build Coastguard Worker 		char ch1 = '\0';
553*4dc78e53SAndroid Build Coastguard Worker 		char ch2 = '\0';
554*4dc78e53SAndroid Build Coastguard Worker 
555*4dc78e53SAndroid Build Coastguard Worker 		/* We take the first word, up until whitespace. Note that backslash
556*4dc78e53SAndroid Build Coastguard Worker 		 * escape is honored, so you can backslash escape spaces. The returned
557*4dc78e53SAndroid Build Coastguard Worker 		 * string will NOT have backslashes removed. */
558*4dc78e53SAndroid Build Coastguard Worker 
559*4dc78e53SAndroid Build Coastguard Worker 		if (str[i] == '\0') {
560*4dc78e53SAndroid Build Coastguard Worker 			*p_str = &str[i];
561*4dc78e53SAndroid Build Coastguard Worker 			break;
562*4dc78e53SAndroid Build Coastguard Worker 		}
563*4dc78e53SAndroid Build Coastguard Worker 		if (_nltst_char_is_space(str[i])) {
564*4dc78e53SAndroid Build Coastguard Worker 			*p_str = _nltst_str_skip_space(&str[i + 1]);
565*4dc78e53SAndroid Build Coastguard Worker 			break;
566*4dc78e53SAndroid Build Coastguard Worker 		}
567*4dc78e53SAndroid Build Coastguard Worker 		ch1 = str[i];
568*4dc78e53SAndroid Build Coastguard Worker 		if (str[i] == '\\') {
569*4dc78e53SAndroid Build Coastguard Worker 			if (str[i + 1] != '\0') {
570*4dc78e53SAndroid Build Coastguard Worker 				ch2 = str[i + 1];
571*4dc78e53SAndroid Build Coastguard Worker 				i += 2;
572*4dc78e53SAndroid Build Coastguard Worker 			} else
573*4dc78e53SAndroid Build Coastguard Worker 				i += 1;
574*4dc78e53SAndroid Build Coastguard Worker 		} else
575*4dc78e53SAndroid Build Coastguard Worker 			i += 1;
576*4dc78e53SAndroid Build Coastguard Worker 
577*4dc78e53SAndroid Build Coastguard Worker 		if (dst_len + 3 >= dst_alloc) {
578*4dc78e53SAndroid Build Coastguard Worker 			dst_alloc *= 2;
579*4dc78e53SAndroid Build Coastguard Worker 			dst = realloc(dst, dst_alloc);
580*4dc78e53SAndroid Build Coastguard Worker 			ck_assert_ptr_nonnull(dst);
581*4dc78e53SAndroid Build Coastguard Worker 		}
582*4dc78e53SAndroid Build Coastguard Worker 		dst[dst_len++] = ch1;
583*4dc78e53SAndroid Build Coastguard Worker 		if (ch2 != '\0')
584*4dc78e53SAndroid Build Coastguard Worker 			dst[dst_len++] = ch2;
585*4dc78e53SAndroid Build Coastguard Worker 	}
586*4dc78e53SAndroid Build Coastguard Worker 
587*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_int_gt(dst_len, 0);
588*4dc78e53SAndroid Build Coastguard Worker 	return strndup(dst, dst_len);
589*4dc78e53SAndroid Build Coastguard Worker }
590*4dc78e53SAndroid Build Coastguard Worker 
_nltst_strtokv(const char * str)591*4dc78e53SAndroid Build Coastguard Worker char **_nltst_strtokv(const char *str)
592*4dc78e53SAndroid Build Coastguard Worker {
593*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_free char *s = NULL;
594*4dc78e53SAndroid Build Coastguard Worker 	_nltst_auto_strfreev char **result = NULL;
595*4dc78e53SAndroid Build Coastguard Worker 	size_t r_len = 0;
596*4dc78e53SAndroid Build Coastguard Worker 	size_t r_alloc = 0;
597*4dc78e53SAndroid Build Coastguard Worker 
598*4dc78e53SAndroid Build Coastguard Worker 	if (!str)
599*4dc78e53SAndroid Build Coastguard Worker 		return NULL;
600*4dc78e53SAndroid Build Coastguard Worker 
601*4dc78e53SAndroid Build Coastguard Worker 	r_alloc = 4;
602*4dc78e53SAndroid Build Coastguard Worker 	result = malloc(sizeof(char *) * r_alloc);
603*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_ptr_nonnull(result);
604*4dc78e53SAndroid Build Coastguard Worker 
605*4dc78e53SAndroid Build Coastguard Worker 	while ((s = _nltst_strtok(&str))) {
606*4dc78e53SAndroid Build Coastguard Worker 		if (r_len + 2 >= r_alloc) {
607*4dc78e53SAndroid Build Coastguard Worker 			r_alloc *= 2;
608*4dc78e53SAndroid Build Coastguard Worker 			result = realloc(result, sizeof(char *) * r_alloc);
609*4dc78e53SAndroid Build Coastguard Worker 			ck_assert_ptr_nonnull(result);
610*4dc78e53SAndroid Build Coastguard Worker 		}
611*4dc78e53SAndroid Build Coastguard Worker 		result[r_len++] = _nl_steal_pointer(&s);
612*4dc78e53SAndroid Build Coastguard Worker 	}
613*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_int_lt(r_len, r_alloc);
614*4dc78e53SAndroid Build Coastguard Worker 	result[r_len] = NULL;
615*4dc78e53SAndroid Build Coastguard Worker 	return _nl_steal_pointer(&result);
616*4dc78e53SAndroid Build Coastguard Worker }
617*4dc78e53SAndroid Build Coastguard Worker 
618*4dc78e53SAndroid Build Coastguard Worker /*****************************************************************************/
619*4dc78e53SAndroid Build Coastguard Worker 
_nltst_assert_link_exists_full(const char * ifname,bool exists)620*4dc78e53SAndroid Build Coastguard Worker void _nltst_assert_link_exists_full(const char *ifname, bool exists)
621*4dc78e53SAndroid Build Coastguard Worker {
622*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_nl_cache struct nl_cache *cache = NULL;
623*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_rtnl_link struct rtnl_link *link_clone = NULL;
624*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_link *link;
625*4dc78e53SAndroid Build Coastguard Worker 	char path[100];
626*4dc78e53SAndroid Build Coastguard Worker 	struct stat st;
627*4dc78e53SAndroid Build Coastguard Worker 	int rnd;
628*4dc78e53SAndroid Build Coastguard Worker 	int r;
629*4dc78e53SAndroid Build Coastguard Worker 
630*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_pstr_ne(ifname, NULL);
631*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_int_lt(strlen(ifname), IFNAMSIZ);
632*4dc78e53SAndroid Build Coastguard Worker 
633*4dc78e53SAndroid Build Coastguard Worker 	strcpy(path, "/sys/class/net/");
634*4dc78e53SAndroid Build Coastguard Worker 	strcat(path, ifname);
635*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_int_lt(strlen(path), sizeof(path));
636*4dc78e53SAndroid Build Coastguard Worker 
637*4dc78e53SAndroid Build Coastguard Worker 	r = stat(path, &st);
638*4dc78e53SAndroid Build Coastguard Worker 	if (exists) {
639*4dc78e53SAndroid Build Coastguard Worker 		if (r != 0) {
640*4dc78e53SAndroid Build Coastguard Worker 			const int errsv = (errno);
641*4dc78e53SAndroid Build Coastguard Worker 
642*4dc78e53SAndroid Build Coastguard Worker 			ck_assert_msg(
643*4dc78e53SAndroid Build Coastguard Worker 				0,
644*4dc78e53SAndroid Build Coastguard Worker 				"link(%s) does not exist (stat(%s) failed with r=%d, errno=%d (%s)",
645*4dc78e53SAndroid Build Coastguard Worker 				ifname, path, r, errsv, strerror(errsv));
646*4dc78e53SAndroid Build Coastguard Worker 		}
647*4dc78e53SAndroid Build Coastguard Worker 	} else {
648*4dc78e53SAndroid Build Coastguard Worker 		if (r != -1 && errno != ENOENT) {
649*4dc78e53SAndroid Build Coastguard Worker 			const int errsv = (errno);
650*4dc78e53SAndroid Build Coastguard Worker 
651*4dc78e53SAndroid Build Coastguard Worker 			ck_assert_msg(
652*4dc78e53SAndroid Build Coastguard Worker 				0,
653*4dc78e53SAndroid Build Coastguard Worker 				"link(%s) should not exist but stat(%s) gave r=%d, errno=%d (%s)",
654*4dc78e53SAndroid Build Coastguard Worker 				ifname, path, r, errsv, strerror(errsv));
655*4dc78e53SAndroid Build Coastguard Worker 		}
656*4dc78e53SAndroid Build Coastguard Worker 	}
657*4dc78e53SAndroid Build Coastguard Worker 
658*4dc78e53SAndroid Build Coastguard Worker 	rnd = _nltst_rand_u32_range(3);
659*4dc78e53SAndroid Build Coastguard Worker 
660*4dc78e53SAndroid Build Coastguard Worker 	if (rnd == 0)
661*4dc78e53SAndroid Build Coastguard Worker 		return;
662*4dc78e53SAndroid Build Coastguard Worker 
663*4dc78e53SAndroid Build Coastguard Worker 	cache = _nltst_rtnl_link_alloc_cache(NULL, AF_UNSPEC, 0);
664*4dc78e53SAndroid Build Coastguard Worker 
665*4dc78e53SAndroid Build Coastguard Worker 	link = _nltst_cache_get_link(cache, ifname);
666*4dc78e53SAndroid Build Coastguard Worker 	if (exists)
667*4dc78e53SAndroid Build Coastguard Worker 		ck_assert_ptr_nonnull(link);
668*4dc78e53SAndroid Build Coastguard Worker 	else
669*4dc78e53SAndroid Build Coastguard Worker 		ck_assert_ptr_null(link);
670*4dc78e53SAndroid Build Coastguard Worker 
671*4dc78e53SAndroid Build Coastguard Worker 	if (!link || rnd == 1)
672*4dc78e53SAndroid Build Coastguard Worker 		return;
673*4dc78e53SAndroid Build Coastguard Worker 
674*4dc78e53SAndroid Build Coastguard Worker 	link_clone =
675*4dc78e53SAndroid Build Coastguard Worker 		(struct rtnl_link *)nl_object_clone((struct nl_object *)link);
676*4dc78e53SAndroid Build Coastguard Worker 	ck_assert(link_clone);
677*4dc78e53SAndroid Build Coastguard Worker 
678*4dc78e53SAndroid Build Coastguard Worker 	/* FIXME: we would expect that the cloned object is identical. It is not. */
679*4dc78e53SAndroid Build Coastguard Worker 	/* _nltst_object_identical(link, link_clone); */
680*4dc78e53SAndroid Build Coastguard Worker }
681*4dc78e53SAndroid Build Coastguard Worker 
682*4dc78e53SAndroid Build Coastguard Worker /*****************************************************************************/
683*4dc78e53SAndroid Build Coastguard Worker 
_nltst_in_ci(void)684*4dc78e53SAndroid Build Coastguard Worker bool _nltst_in_ci(void)
685*4dc78e53SAndroid Build Coastguard Worker {
686*4dc78e53SAndroid Build Coastguard Worker 	return _nl_streq0(getenv("NLTST_IN_CI"), "1");
687*4dc78e53SAndroid Build Coastguard Worker }
688*4dc78e53SAndroid Build Coastguard Worker 
689*4dc78e53SAndroid Build Coastguard Worker /*****************************************************************************/
690*4dc78e53SAndroid Build Coastguard Worker 
_nltst_has_iproute2(void)691*4dc78e53SAndroid Build Coastguard Worker bool _nltst_has_iproute2(void)
692*4dc78e53SAndroid Build Coastguard Worker {
693*4dc78e53SAndroid Build Coastguard Worker 	static int has = -1;
694*4dc78e53SAndroid Build Coastguard Worker 
695*4dc78e53SAndroid Build Coastguard Worker 	if (has == -1)
696*4dc78e53SAndroid Build Coastguard Worker 		has = (system("ip link &>/dev/null") == 0);
697*4dc78e53SAndroid Build Coastguard Worker 
698*4dc78e53SAndroid Build Coastguard Worker 	return has;
699*4dc78e53SAndroid Build Coastguard Worker }
700*4dc78e53SAndroid Build Coastguard Worker 
_nltst_skip_no_iproute2(const char * msg)701*4dc78e53SAndroid Build Coastguard Worker bool _nltst_skip_no_iproute2(const char *msg)
702*4dc78e53SAndroid Build Coastguard Worker {
703*4dc78e53SAndroid Build Coastguard Worker 	if (_nltst_has_iproute2())
704*4dc78e53SAndroid Build Coastguard Worker 		return false;
705*4dc78e53SAndroid Build Coastguard Worker 
706*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_msg(
707*4dc78e53SAndroid Build Coastguard Worker 		!_nltst_in_ci(),
708*4dc78e53SAndroid Build Coastguard Worker 		"We seem to not have iproute2, but we are in NLTST_IN_CI=1. This is fatal.");
709*4dc78e53SAndroid Build Coastguard Worker 
710*4dc78e53SAndroid Build Coastguard Worker 	printf("skip test due to missing iproute2%s%s%s\n", msg ? " (" : "",
711*4dc78e53SAndroid Build Coastguard Worker 	       msg ?: "", msg ? ")" : "");
712*4dc78e53SAndroid Build Coastguard Worker 	return true;
713*4dc78e53SAndroid Build Coastguard Worker }
714*4dc78e53SAndroid Build Coastguard Worker 
715*4dc78e53SAndroid Build Coastguard Worker /*****************************************************************************/
716*4dc78e53SAndroid Build Coastguard Worker 
_nltst_select_route_clear(NLTstSelectRoute * select_route)717*4dc78e53SAndroid Build Coastguard Worker void _nltst_select_route_clear(NLTstSelectRoute *select_route)
718*4dc78e53SAndroid Build Coastguard Worker {
719*4dc78e53SAndroid Build Coastguard Worker 	_nltst_assert_select_route(select_route);
720*4dc78e53SAndroid Build Coastguard Worker 
721*4dc78e53SAndroid Build Coastguard Worker 	_nl_clear_free(&select_route->addr);
722*4dc78e53SAndroid Build Coastguard Worker 	_nl_clear_free(&select_route->addr_pattern);
723*4dc78e53SAndroid Build Coastguard Worker }
724*4dc78e53SAndroid Build Coastguard Worker 
_nltst_select_route_cmp(const NLTstSelectRoute * select_route1,const NLTstSelectRoute * select_route2)725*4dc78e53SAndroid Build Coastguard Worker int _nltst_select_route_cmp(const NLTstSelectRoute *select_route1,
726*4dc78e53SAndroid Build Coastguard Worker 			    const NLTstSelectRoute *select_route2)
727*4dc78e53SAndroid Build Coastguard Worker {
728*4dc78e53SAndroid Build Coastguard Worker 	_NL_CMP_SELF(select_route1, select_route2);
729*4dc78e53SAndroid Build Coastguard Worker 	_NL_CMP_FIELD_STR0(select_route1, select_route2, addr);
730*4dc78e53SAndroid Build Coastguard Worker 	_NL_CMP_FIELD_STR0(select_route1, select_route2, addr_pattern);
731*4dc78e53SAndroid Build Coastguard Worker 	_NL_CMP_FIELD(select_route1, select_route2, addr_family);
732*4dc78e53SAndroid Build Coastguard Worker 	_NL_CMP_FIELD(select_route1, select_route2, ifindex);
733*4dc78e53SAndroid Build Coastguard Worker 	_NL_CMP_FIELD(select_route1, select_route2, plen);
734*4dc78e53SAndroid Build Coastguard Worker 	return 0;
735*4dc78e53SAndroid Build Coastguard Worker }
736*4dc78e53SAndroid Build Coastguard Worker 
_nltst_select_route_to_string(const NLTstSelectRoute * select_route)737*4dc78e53SAndroid Build Coastguard Worker char *_nltst_select_route_to_string(const NLTstSelectRoute *select_route)
738*4dc78e53SAndroid Build Coastguard Worker {
739*4dc78e53SAndroid Build Coastguard Worker 	char buf[1024];
740*4dc78e53SAndroid Build Coastguard Worker 	const char *family;
741*4dc78e53SAndroid Build Coastguard Worker 	char b_plen[100];
742*4dc78e53SAndroid Build Coastguard Worker 
743*4dc78e53SAndroid Build Coastguard Worker 	_nltst_assert_select_route(select_route);
744*4dc78e53SAndroid Build Coastguard Worker 
745*4dc78e53SAndroid Build Coastguard Worker 	if (select_route->addr_family == AF_INET)
746*4dc78e53SAndroid Build Coastguard Worker 		family = "4 ";
747*4dc78e53SAndroid Build Coastguard Worker 	else if (select_route->addr_family == AF_INET6)
748*4dc78e53SAndroid Build Coastguard Worker 		family = "6 ";
749*4dc78e53SAndroid Build Coastguard Worker 	else
750*4dc78e53SAndroid Build Coastguard Worker 		family = "";
751*4dc78e53SAndroid Build Coastguard Worker 
752*4dc78e53SAndroid Build Coastguard Worker 	b_plen[0] = '\0';
753*4dc78e53SAndroid Build Coastguard Worker 	if (select_route->plen != -1)
754*4dc78e53SAndroid Build Coastguard Worker 		_nltst_sprintf_arr(b_plen, "/%d", select_route->plen);
755*4dc78e53SAndroid Build Coastguard Worker 
756*4dc78e53SAndroid Build Coastguard Worker 	_nltst_sprintf_arr(buf,
757*4dc78e53SAndroid Build Coastguard Worker 			   "%s"
758*4dc78e53SAndroid Build Coastguard Worker 			   "%s"
759*4dc78e53SAndroid Build Coastguard Worker 			   "%s"
760*4dc78e53SAndroid Build Coastguard Worker 			   "",
761*4dc78e53SAndroid Build Coastguard Worker 			   family,
762*4dc78e53SAndroid Build Coastguard Worker 			   select_route->addr_pattern ?: select_route->addr,
763*4dc78e53SAndroid Build Coastguard Worker 			   b_plen);
764*4dc78e53SAndroid Build Coastguard Worker 	return _nltst_strdup(buf);
765*4dc78e53SAndroid Build Coastguard Worker }
766*4dc78e53SAndroid Build Coastguard Worker 
_nltst_select_route_parse(const char * str,NLTstSelectRoute * out_select_route)767*4dc78e53SAndroid Build Coastguard Worker void _nltst_select_route_parse(const char *str,
768*4dc78e53SAndroid Build Coastguard Worker 			       NLTstSelectRoute *out_select_route)
769*4dc78e53SAndroid Build Coastguard Worker {
770*4dc78e53SAndroid Build Coastguard Worker 	_nltst_auto_strfreev char **tokens0 = NULL;
771*4dc78e53SAndroid Build Coastguard Worker 	const char *const *tokens;
772*4dc78e53SAndroid Build Coastguard Worker 	int addr_family = AF_UNSPEC;
773*4dc78e53SAndroid Build Coastguard Worker 	int addr_family2 = AF_UNSPEC;
774*4dc78e53SAndroid Build Coastguard Worker 	NLTstIPAddr addr;
775*4dc78e53SAndroid Build Coastguard Worker 	int plen = -1;
776*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_free char *addr_free = NULL;
777*4dc78e53SAndroid Build Coastguard Worker 	const char *s_addr_pattern;
778*4dc78e53SAndroid Build Coastguard Worker 	const char *s_addr = NULL;
779*4dc78e53SAndroid Build Coastguard Worker 	const char *s;
780*4dc78e53SAndroid Build Coastguard Worker 	const char *s1;
781*4dc78e53SAndroid Build Coastguard Worker 
782*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_ptr_nonnull(str);
783*4dc78e53SAndroid Build Coastguard Worker 	_nltst_assert_select_route(out_select_route);
784*4dc78e53SAndroid Build Coastguard Worker 
785*4dc78e53SAndroid Build Coastguard Worker 	tokens0 = _nltst_strtokv(str);
786*4dc78e53SAndroid Build Coastguard Worker 	tokens = (const char *const *)tokens0;
787*4dc78e53SAndroid Build Coastguard Worker 
788*4dc78e53SAndroid Build Coastguard Worker 	s = tokens[0];
789*4dc78e53SAndroid Build Coastguard Worker 	if (!s)
790*4dc78e53SAndroid Build Coastguard Worker 		ck_abort_msg("invalid empty route pattern \"%s\"", str);
791*4dc78e53SAndroid Build Coastguard Worker 	if (_nl_streq(s, "4") || _nl_streq(s, "inet") ||
792*4dc78e53SAndroid Build Coastguard Worker 	    _nl_streq(s, "inet4")) {
793*4dc78e53SAndroid Build Coastguard Worker 		addr_family = AF_INET;
794*4dc78e53SAndroid Build Coastguard Worker 		tokens++;
795*4dc78e53SAndroid Build Coastguard Worker 	} else if (_nl_streq(s, "6") || _nl_streq(s, "inet6")) {
796*4dc78e53SAndroid Build Coastguard Worker 		addr_family = AF_INET6;
797*4dc78e53SAndroid Build Coastguard Worker 		tokens++;
798*4dc78e53SAndroid Build Coastguard Worker 	}
799*4dc78e53SAndroid Build Coastguard Worker 
800*4dc78e53SAndroid Build Coastguard Worker 	s_addr_pattern = tokens[0];
801*4dc78e53SAndroid Build Coastguard Worker 	if (!s_addr_pattern) {
802*4dc78e53SAndroid Build Coastguard Worker 		ck_abort_msg(
803*4dc78e53SAndroid Build Coastguard Worker 			"the route pattern \"%s\" is invalid and contains no destination address",
804*4dc78e53SAndroid Build Coastguard Worker 			str);
805*4dc78e53SAndroid Build Coastguard Worker 	}
806*4dc78e53SAndroid Build Coastguard Worker 	tokens++;
807*4dc78e53SAndroid Build Coastguard Worker 
808*4dc78e53SAndroid Build Coastguard Worker 	s = strchr(s_addr_pattern, '/');
809*4dc78e53SAndroid Build Coastguard Worker 	if (s) {
810*4dc78e53SAndroid Build Coastguard Worker 		long int plen2;
811*4dc78e53SAndroid Build Coastguard Worker 
812*4dc78e53SAndroid Build Coastguard Worker 		if (s == s_addr_pattern) {
813*4dc78e53SAndroid Build Coastguard Worker 			ck_abort_msg(
814*4dc78e53SAndroid Build Coastguard Worker 				"the route pattern \"%s\" contains no valid destination address",
815*4dc78e53SAndroid Build Coastguard Worker 				str);
816*4dc78e53SAndroid Build Coastguard Worker 		}
817*4dc78e53SAndroid Build Coastguard Worker 		addr_free = strndup(s_addr_pattern, s - s_addr_pattern);
818*4dc78e53SAndroid Build Coastguard Worker 		s_addr_pattern = addr_free;
819*4dc78e53SAndroid Build Coastguard Worker 		s++;
820*4dc78e53SAndroid Build Coastguard Worker 
821*4dc78e53SAndroid Build Coastguard Worker 		errno = 0;
822*4dc78e53SAndroid Build Coastguard Worker 		plen2 = strtol(s, (char **)&s1, 10);
823*4dc78e53SAndroid Build Coastguard Worker 		if (errno != 0 || s1[0] != '\0' || plen2 < 0 || plen2 > 128 ||
824*4dc78e53SAndroid Build Coastguard Worker 		    ((_nltst_str_find_first_not_from_charset(
825*4dc78e53SAndroid Build Coastguard Worker 			     s, "0123456789"))[0] != '\0')) {
826*4dc78e53SAndroid Build Coastguard Worker 			ck_abort_msg(
827*4dc78e53SAndroid Build Coastguard Worker 				"the route pattern \"%s\" contains no valid destination address",
828*4dc78e53SAndroid Build Coastguard Worker 				str);
829*4dc78e53SAndroid Build Coastguard Worker 		}
830*4dc78e53SAndroid Build Coastguard Worker 		plen = plen2;
831*4dc78e53SAndroid Build Coastguard Worker 	}
832*4dc78e53SAndroid Build Coastguard Worker 	if ((_nltst_str_find_first_not_from_charset(
833*4dc78e53SAndroid Build Coastguard Worker 		    s_addr_pattern, "abcdefABCDEF0123456789:.?*"))[0] != '\0') {
834*4dc78e53SAndroid Build Coastguard Worker 		ck_abort_msg(
835*4dc78e53SAndroid Build Coastguard Worker 			"the route pattern \"%s\" contains no valid destination address",
836*4dc78e53SAndroid Build Coastguard Worker 			str);
837*4dc78e53SAndroid Build Coastguard Worker 	}
838*4dc78e53SAndroid Build Coastguard Worker 	if (_nltst_inet_pton(addr_family, s_addr_pattern, &addr_family2,
839*4dc78e53SAndroid Build Coastguard Worker 			     &addr)) {
840*4dc78e53SAndroid Build Coastguard Worker 		free(addr_free);
841*4dc78e53SAndroid Build Coastguard Worker 		addr_free = _nltst_inet_ntop_dup(addr_family2, &addr);
842*4dc78e53SAndroid Build Coastguard Worker 		s_addr_pattern = addr_free;
843*4dc78e53SAndroid Build Coastguard Worker 		addr_family = addr_family2;
844*4dc78e53SAndroid Build Coastguard Worker 	} else {
845*4dc78e53SAndroid Build Coastguard Worker 		if (addr_family == AF_UNSPEC) {
846*4dc78e53SAndroid Build Coastguard Worker 			ck_abort_msg(
847*4dc78e53SAndroid Build Coastguard Worker 				"the route pattern \"%s\" contains a wild card address, it requires the address family",
848*4dc78e53SAndroid Build Coastguard Worker 				str);
849*4dc78e53SAndroid Build Coastguard Worker 		}
850*4dc78e53SAndroid Build Coastguard Worker 	}
851*4dc78e53SAndroid Build Coastguard Worker 
852*4dc78e53SAndroid Build Coastguard Worker 	ck_assert(addr_family == AF_INET || addr_family == AF_INET6);
853*4dc78e53SAndroid Build Coastguard Worker 
854*4dc78e53SAndroid Build Coastguard Worker 	if (plen > (addr_family == AF_INET ? 32 : 128)) {
855*4dc78e53SAndroid Build Coastguard Worker 		ck_abort_msg(
856*4dc78e53SAndroid Build Coastguard Worker 			"the route pattern \"%s\" contains no valid destination address (prefix length too large)",
857*4dc78e53SAndroid Build Coastguard Worker 			str);
858*4dc78e53SAndroid Build Coastguard Worker 	}
859*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_int_ge(plen, -1);
860*4dc78e53SAndroid Build Coastguard Worker 
861*4dc78e53SAndroid Build Coastguard Worker 	s = tokens[0];
862*4dc78e53SAndroid Build Coastguard Worker 	if (s) {
863*4dc78e53SAndroid Build Coastguard Worker 		ck_abort_msg("the route pattern \"%s\" contains extra tokens",
864*4dc78e53SAndroid Build Coastguard Worker 			     str);
865*4dc78e53SAndroid Build Coastguard Worker 	}
866*4dc78e53SAndroid Build Coastguard Worker 
867*4dc78e53SAndroid Build Coastguard Worker 	if (_nltst_inet_valid(addr_family, s_addr_pattern))
868*4dc78e53SAndroid Build Coastguard Worker 		_NL_SWAP(&s_addr, &s_addr_pattern);
869*4dc78e53SAndroid Build Coastguard Worker 
870*4dc78e53SAndroid Build Coastguard Worker 	_nltst_select_route_clear(out_select_route);
871*4dc78e53SAndroid Build Coastguard Worker 	memset(out_select_route, 0, sizeof(*out_select_route));
872*4dc78e53SAndroid Build Coastguard Worker 	*out_select_route = (NLTstSelectRoute){
873*4dc78e53SAndroid Build Coastguard Worker 		.addr_family = addr_family,
874*4dc78e53SAndroid Build Coastguard Worker 		.plen = plen,
875*4dc78e53SAndroid Build Coastguard Worker 		.ifindex = 0,
876*4dc78e53SAndroid Build Coastguard Worker 		.addr = s_addr ? strdup(s_addr) : NULL,
877*4dc78e53SAndroid Build Coastguard Worker 		.addr_pattern = s_addr_pattern ? strdup(s_addr_pattern) : NULL,
878*4dc78e53SAndroid Build Coastguard Worker 	};
879*4dc78e53SAndroid Build Coastguard Worker 	ck_assert(!s_addr || out_select_route->addr);
880*4dc78e53SAndroid Build Coastguard Worker 	ck_assert(!s_addr_pattern || out_select_route->addr_pattern);
881*4dc78e53SAndroid Build Coastguard Worker 	_nltst_assert_select_route(out_select_route);
882*4dc78e53SAndroid Build Coastguard Worker }
883*4dc78e53SAndroid Build Coastguard Worker 
_nltst_select_route_match(struct nl_object * route,const NLTstSelectRoute * select_route,bool do_assert)884*4dc78e53SAndroid Build Coastguard Worker bool _nltst_select_route_match(struct nl_object *route,
885*4dc78e53SAndroid Build Coastguard Worker 			       const NLTstSelectRoute *select_route,
886*4dc78e53SAndroid Build Coastguard Worker 			       bool do_assert)
887*4dc78e53SAndroid Build Coastguard Worker {
888*4dc78e53SAndroid Build Coastguard Worker 	struct nl_addr *addr;
889*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_route *route_;
890*4dc78e53SAndroid Build Coastguard Worker 	int i;
891*4dc78e53SAndroid Build Coastguard Worker 	char sbuf1[200];
892*4dc78e53SAndroid Build Coastguard Worker 
893*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_ptr_nonnull(route);
894*4dc78e53SAndroid Build Coastguard Worker 	ck_assert_str_eq(nl_object_get_type(route), "route/route");
895*4dc78e53SAndroid Build Coastguard Worker 
896*4dc78e53SAndroid Build Coastguard Worker 	if (!select_route)
897*4dc78e53SAndroid Build Coastguard Worker 		return true;
898*4dc78e53SAndroid Build Coastguard Worker 
899*4dc78e53SAndroid Build Coastguard Worker 	route_ = (struct rtnl_route *)route;
900*4dc78e53SAndroid Build Coastguard Worker 
901*4dc78e53SAndroid Build Coastguard Worker 	_nltst_assert_select_route(select_route);
902*4dc78e53SAndroid Build Coastguard Worker 
903*4dc78e53SAndroid Build Coastguard Worker #define _check(cond, msg, ...)                                                                                   \
904*4dc78e53SAndroid Build Coastguard Worker 	do {                                                                                                     \
905*4dc78e53SAndroid Build Coastguard Worker 		if (do_assert) {                                                                                 \
906*4dc78e53SAndroid Build Coastguard Worker 			_nl_auto_free char *s1 = NULL;                                                           \
907*4dc78e53SAndroid Build Coastguard Worker 			_nl_auto_free char *s2 = NULL;                                                           \
908*4dc78e53SAndroid Build Coastguard Worker                                                                                                                  \
909*4dc78e53SAndroid Build Coastguard Worker 			ck_assert_msg(                                                                           \
910*4dc78e53SAndroid Build Coastguard Worker 				(cond),                                                                          \
911*4dc78e53SAndroid Build Coastguard Worker 				"Checking condition \"%s\" for route \"%s\" (expected \"%s\") failed (msg: " msg \
912*4dc78e53SAndroid Build Coastguard Worker 				")",                                                                             \
913*4dc78e53SAndroid Build Coastguard Worker 				#cond, (s1 = _nltst_object_to_string(route)),                                    \
914*4dc78e53SAndroid Build Coastguard Worker 				(s2 = _nltst_select_route_to_string(                                             \
915*4dc78e53SAndroid Build Coastguard Worker 					 select_route)),                                                         \
916*4dc78e53SAndroid Build Coastguard Worker 				##__VA_ARGS__);                                                                  \
917*4dc78e53SAndroid Build Coastguard Worker 		} else if (cond) {                                                                               \
918*4dc78e53SAndroid Build Coastguard Worker 		} else {                                                                                         \
919*4dc78e53SAndroid Build Coastguard Worker 			return false;                                                                            \
920*4dc78e53SAndroid Build Coastguard Worker 		}                                                                                                \
921*4dc78e53SAndroid Build Coastguard Worker 	} while (0)
922*4dc78e53SAndroid Build Coastguard Worker 
923*4dc78e53SAndroid Build Coastguard Worker 	if (select_route->addr_family != AF_UNSPEC) {
924*4dc78e53SAndroid Build Coastguard Worker 		_check(rtnl_route_get_family(route_) ==
925*4dc78e53SAndroid Build Coastguard Worker 			       select_route->addr_family,
926*4dc78e53SAndroid Build Coastguard Worker 		       "mismatching address family");
927*4dc78e53SAndroid Build Coastguard Worker 	}
928*4dc78e53SAndroid Build Coastguard Worker 
929*4dc78e53SAndroid Build Coastguard Worker 	if (select_route->ifindex != 0) {
930*4dc78e53SAndroid Build Coastguard Worker 		struct nl_list_head *list;
931*4dc78e53SAndroid Build Coastguard Worker 		struct rtnl_nexthop *nh;
932*4dc78e53SAndroid Build Coastguard Worker 		size_t n;
933*4dc78e53SAndroid Build Coastguard Worker 		struct rtnl_nexthop *nh2;
934*4dc78e53SAndroid Build Coastguard Worker 
935*4dc78e53SAndroid Build Coastguard Worker 		list = rtnl_route_get_nexthops(route_);
936*4dc78e53SAndroid Build Coastguard Worker 		_check(list, "no nexthops for ifindex");
937*4dc78e53SAndroid Build Coastguard Worker 
938*4dc78e53SAndroid Build Coastguard Worker 		n = 0;
939*4dc78e53SAndroid Build Coastguard Worker 		nl_list_for_each_entry(nh, list, rtnh_list) {
940*4dc78e53SAndroid Build Coastguard Worker 			nh2 = nh;
941*4dc78e53SAndroid Build Coastguard Worker 			n++;
942*4dc78e53SAndroid Build Coastguard Worker 		}
943*4dc78e53SAndroid Build Coastguard Worker 		_check(n == 1, "expects one nexthop for ifindex but got %zu",
944*4dc78e53SAndroid Build Coastguard Worker 		       n);
945*4dc78e53SAndroid Build Coastguard Worker 		ck_assert_ptr_nonnull(nh2);
946*4dc78e53SAndroid Build Coastguard Worker 
947*4dc78e53SAndroid Build Coastguard Worker 		i = rtnl_route_nh_get_ifindex(nh2);
948*4dc78e53SAndroid Build Coastguard Worker 		_check(i == select_route->ifindex,
949*4dc78e53SAndroid Build Coastguard Worker 		       "route has unexpected ifindex %d for next hop", i);
950*4dc78e53SAndroid Build Coastguard Worker 	}
951*4dc78e53SAndroid Build Coastguard Worker 
952*4dc78e53SAndroid Build Coastguard Worker 	addr = rtnl_route_get_dst(route_);
953*4dc78e53SAndroid Build Coastguard Worker 
954*4dc78e53SAndroid Build Coastguard Worker 	if (addr) {
955*4dc78e53SAndroid Build Coastguard Worker 		if (select_route->addr_family != AF_UNSPEC) {
956*4dc78e53SAndroid Build Coastguard Worker 			_check(nl_addr_get_family(addr) ==
957*4dc78e53SAndroid Build Coastguard Worker 				       select_route->addr_family,
958*4dc78e53SAndroid Build Coastguard Worker 			       "unexecpted address family of dst");
959*4dc78e53SAndroid Build Coastguard Worker 		}
960*4dc78e53SAndroid Build Coastguard Worker 	}
961*4dc78e53SAndroid Build Coastguard Worker 
962*4dc78e53SAndroid Build Coastguard Worker 	if (select_route->plen != -1) {
963*4dc78e53SAndroid Build Coastguard Worker 		_check(addr, "missing address");
964*4dc78e53SAndroid Build Coastguard Worker 		_check(nl_addr_get_prefixlen(addr) ==
965*4dc78e53SAndroid Build Coastguard Worker 			       (unsigned)select_route->plen,
966*4dc78e53SAndroid Build Coastguard Worker 		       "unexpected prefix length");
967*4dc78e53SAndroid Build Coastguard Worker 	}
968*4dc78e53SAndroid Build Coastguard Worker 	if (select_route->addr || select_route->addr_pattern) {
969*4dc78e53SAndroid Build Coastguard Worker 		_check(addr, "missing address");
970*4dc78e53SAndroid Build Coastguard Worker 
971*4dc78e53SAndroid Build Coastguard Worker 		_nl_inet_ntop(nl_addr_get_family(addr),
972*4dc78e53SAndroid Build Coastguard Worker 			      nl_addr_get_binary_addr(addr), sbuf1);
973*4dc78e53SAndroid Build Coastguard Worker 
974*4dc78e53SAndroid Build Coastguard Worker 		ck_assert(strlen(sbuf1) > 0);
975*4dc78e53SAndroid Build Coastguard Worker 		ck_assert(strlen(sbuf1) < sizeof(sbuf1));
976*4dc78e53SAndroid Build Coastguard Worker 
977*4dc78e53SAndroid Build Coastguard Worker 		if (select_route->addr) {
978*4dc78e53SAndroid Build Coastguard Worker 			_check(_nl_streq(sbuf1, select_route->addr),
979*4dc78e53SAndroid Build Coastguard Worker 			       "unexpected address, \"%s\" does not match \"%s\"",
980*4dc78e53SAndroid Build Coastguard Worker 			       sbuf1, select_route->addr);
981*4dc78e53SAndroid Build Coastguard Worker 		}
982*4dc78e53SAndroid Build Coastguard Worker 		if (select_route->addr_pattern) {
983*4dc78e53SAndroid Build Coastguard Worker 			_check(fnmatch(select_route->addr_pattern, sbuf1, 0) ==
984*4dc78e53SAndroid Build Coastguard Worker 				       0,
985*4dc78e53SAndroid Build Coastguard Worker 			       "unexpected address, \"%s\" does not match pattern \"%s\"",
986*4dc78e53SAndroid Build Coastguard Worker 			       sbuf1, select_route->addr_pattern);
987*4dc78e53SAndroid Build Coastguard Worker 		}
988*4dc78e53SAndroid Build Coastguard Worker 	}
989*4dc78e53SAndroid Build Coastguard Worker 
990*4dc78e53SAndroid Build Coastguard Worker #undef _check
991*4dc78e53SAndroid Build Coastguard Worker 
992*4dc78e53SAndroid Build Coastguard Worker 	return false;
993*4dc78e53SAndroid Build Coastguard Worker }
994*4dc78e53SAndroid Build Coastguard Worker 
995*4dc78e53SAndroid Build Coastguard Worker /*****************************************************************************/
996*4dc78e53SAndroid Build Coastguard Worker 
_nltst_assert_route_list(struct nl_object * const * objs,ssize_t len,const char * const * expected_routes)997*4dc78e53SAndroid Build Coastguard Worker void _nltst_assert_route_list(struct nl_object *const *objs, ssize_t len,
998*4dc78e53SAndroid Build Coastguard Worker 			      const char *const *expected_routes)
999*4dc78e53SAndroid Build Coastguard Worker {
1000*4dc78e53SAndroid Build Coastguard Worker 	size_t l;
1001*4dc78e53SAndroid Build Coastguard Worker 	size_t i;
1002*4dc78e53SAndroid Build Coastguard Worker 
1003*4dc78e53SAndroid Build Coastguard Worker 	if (len < 0) {
1004*4dc78e53SAndroid Build Coastguard Worker 		l = 0;
1005*4dc78e53SAndroid Build Coastguard Worker 		if (objs) {
1006*4dc78e53SAndroid Build Coastguard Worker 			while (objs[l])
1007*4dc78e53SAndroid Build Coastguard Worker 				l++;
1008*4dc78e53SAndroid Build Coastguard Worker 		}
1009*4dc78e53SAndroid Build Coastguard Worker 	} else
1010*4dc78e53SAndroid Build Coastguard Worker 		l = len;
1011*4dc78e53SAndroid Build Coastguard Worker 
1012*4dc78e53SAndroid Build Coastguard Worker 	for (i = 0; i < l; i++) {
1013*4dc78e53SAndroid Build Coastguard Worker 		struct nl_object *route = objs[i];
1014*4dc78e53SAndroid Build Coastguard Worker 		_nltst_auto_clear_select_route NLTstSelectRoute select_route = {
1015*4dc78e53SAndroid Build Coastguard Worker 			0
1016*4dc78e53SAndroid Build Coastguard Worker 		};
1017*4dc78e53SAndroid Build Coastguard Worker 		_nl_auto_free char *s = _nltst_object_to_string(route);
1018*4dc78e53SAndroid Build Coastguard Worker 
1019*4dc78e53SAndroid Build Coastguard Worker 		if (!expected_routes[i]) {
1020*4dc78e53SAndroid Build Coastguard Worker 			ck_abort_msg(
1021*4dc78e53SAndroid Build Coastguard Worker 				"No more expected route, but have route %zu (of %zu) as %s",
1022*4dc78e53SAndroid Build Coastguard Worker 				i + 1, l, s);
1023*4dc78e53SAndroid Build Coastguard Worker 		}
1024*4dc78e53SAndroid Build Coastguard Worker 
1025*4dc78e53SAndroid Build Coastguard Worker 		_nltst_select_route_parse(expected_routes[i], &select_route);
1026*4dc78e53SAndroid Build Coastguard Worker 
1027*4dc78e53SAndroid Build Coastguard Worker 		_nltst_select_route_match(route, &select_route, true);
1028*4dc78e53SAndroid Build Coastguard Worker 	}
1029*4dc78e53SAndroid Build Coastguard Worker }
1030*4dc78e53SAndroid Build Coastguard Worker 
_nltst_assert_route_cache_v(struct nl_cache * cache,const char * const * expected_routes)1031*4dc78e53SAndroid Build Coastguard Worker void _nltst_assert_route_cache_v(struct nl_cache *cache,
1032*4dc78e53SAndroid Build Coastguard Worker 				 const char *const *expected_routes)
1033*4dc78e53SAndroid Build Coastguard Worker {
1034*4dc78e53SAndroid Build Coastguard Worker 	_nl_auto_free struct nl_object **objs = NULL;
1035*4dc78e53SAndroid Build Coastguard Worker 	size_t len;
1036*4dc78e53SAndroid Build Coastguard Worker 
1037*4dc78e53SAndroid Build Coastguard Worker 	ck_assert(cache);
1038*4dc78e53SAndroid Build Coastguard Worker 	ck_assert(expected_routes);
1039*4dc78e53SAndroid Build Coastguard Worker 
1040*4dc78e53SAndroid Build Coastguard Worker 	objs = _nltst_cache_get_all(cache, &len);
1041*4dc78e53SAndroid Build Coastguard Worker 
1042*4dc78e53SAndroid Build Coastguard Worker 	_nltst_assert_route_list(objs, len, expected_routes);
1043*4dc78e53SAndroid Build Coastguard Worker }
1044