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