xref: /aosp_15_r20/external/ltp/lib/tst_netdevice.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) 2021 Linux Test Project
4*49cdfc7eSAndroid Build Coastguard Worker  */
5*49cdfc7eSAndroid Build Coastguard Worker 
6*49cdfc7eSAndroid Build Coastguard Worker #include <asm/types.h>
7*49cdfc7eSAndroid Build Coastguard Worker #include <linux/veth.h>
8*49cdfc7eSAndroid Build Coastguard Worker #include <sys/socket.h>
9*49cdfc7eSAndroid Build Coastguard Worker #include <net/if.h>
10*49cdfc7eSAndroid Build Coastguard Worker #include <linux/pkt_sched.h>
11*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/rtnetlink.h"
12*49cdfc7eSAndroid Build Coastguard Worker 
13*49cdfc7eSAndroid Build Coastguard Worker #define TST_NO_DEFAULT_MAIN
14*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
15*49cdfc7eSAndroid Build Coastguard Worker #include "tst_netlink.h"
16*49cdfc7eSAndroid Build Coastguard Worker #include "tst_netdevice.h"
17*49cdfc7eSAndroid Build Coastguard Worker 
create_request(const char * file,const int lineno,unsigned int type,unsigned int flags,const void * payload,size_t psize)18*49cdfc7eSAndroid Build Coastguard Worker static struct tst_netlink_context *create_request(const char *file,
19*49cdfc7eSAndroid Build Coastguard Worker 	const int lineno, unsigned int type, unsigned int flags,
20*49cdfc7eSAndroid Build Coastguard Worker 	const void *payload, size_t psize)
21*49cdfc7eSAndroid Build Coastguard Worker {
22*49cdfc7eSAndroid Build Coastguard Worker 	struct tst_netlink_context *ctx;
23*49cdfc7eSAndroid Build Coastguard Worker 	struct nlmsghdr header = {
24*49cdfc7eSAndroid Build Coastguard Worker 		.nlmsg_type = type,
25*49cdfc7eSAndroid Build Coastguard Worker 		.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags,
26*49cdfc7eSAndroid Build Coastguard Worker 	};
27*49cdfc7eSAndroid Build Coastguard Worker 
28*49cdfc7eSAndroid Build Coastguard Worker 	ctx = tst_netlink_create_context(file, lineno, NETLINK_ROUTE);
29*49cdfc7eSAndroid Build Coastguard Worker 
30*49cdfc7eSAndroid Build Coastguard Worker 	if (!ctx)
31*49cdfc7eSAndroid Build Coastguard Worker 		return NULL;
32*49cdfc7eSAndroid Build Coastguard Worker 
33*49cdfc7eSAndroid Build Coastguard Worker 	if (!tst_netlink_add_message(file, lineno, ctx, &header, payload,
34*49cdfc7eSAndroid Build Coastguard Worker 		psize)) {
35*49cdfc7eSAndroid Build Coastguard Worker 		tst_netlink_destroy_context(file, lineno, ctx);
36*49cdfc7eSAndroid Build Coastguard Worker 		return NULL;
37*49cdfc7eSAndroid Build Coastguard Worker 	}
38*49cdfc7eSAndroid Build Coastguard Worker 
39*49cdfc7eSAndroid Build Coastguard Worker 	return ctx;
40*49cdfc7eSAndroid Build Coastguard Worker }
41*49cdfc7eSAndroid Build Coastguard Worker 
tst_netdev_index_by_name(const char * file,const int lineno,const char * ifname)42*49cdfc7eSAndroid Build Coastguard Worker int tst_netdev_index_by_name(const char *file, const int lineno,
43*49cdfc7eSAndroid Build Coastguard Worker 	const char *ifname)
44*49cdfc7eSAndroid Build Coastguard Worker {
45*49cdfc7eSAndroid Build Coastguard Worker 	struct ifreq ifr;
46*49cdfc7eSAndroid Build Coastguard Worker 	int sock, ret;
47*49cdfc7eSAndroid Build Coastguard Worker 
48*49cdfc7eSAndroid Build Coastguard Worker 	if (strlen(ifname) >= IFNAMSIZ) {
49*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk_(file, lineno, TBROK,
50*49cdfc7eSAndroid Build Coastguard Worker 			"Network device name \"%s\" too long", ifname);
51*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
52*49cdfc7eSAndroid Build Coastguard Worker 	}
53*49cdfc7eSAndroid Build Coastguard Worker 
54*49cdfc7eSAndroid Build Coastguard Worker 	sock = safe_socket(file, lineno, NULL, AF_INET, SOCK_DGRAM, 0);
55*49cdfc7eSAndroid Build Coastguard Worker 
56*49cdfc7eSAndroid Build Coastguard Worker 	if (sock < 0)
57*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
58*49cdfc7eSAndroid Build Coastguard Worker 
59*49cdfc7eSAndroid Build Coastguard Worker 	strcpy(ifr.ifr_name, ifname);
60*49cdfc7eSAndroid Build Coastguard Worker 	ret = SAFE_IOCTL_(file, lineno, sock, SIOCGIFINDEX, &ifr);
61*49cdfc7eSAndroid Build Coastguard Worker 	safe_close(file, lineno, NULL, sock);
62*49cdfc7eSAndroid Build Coastguard Worker 
63*49cdfc7eSAndroid Build Coastguard Worker 	return ret ? -1 : ifr.ifr_ifindex;
64*49cdfc7eSAndroid Build Coastguard Worker }
65*49cdfc7eSAndroid Build Coastguard Worker 
tst_netdev_set_state(const char * file,const int lineno,const char * ifname,int up)66*49cdfc7eSAndroid Build Coastguard Worker int tst_netdev_set_state(const char *file, const int lineno,
67*49cdfc7eSAndroid Build Coastguard Worker 	const char *ifname, int up)
68*49cdfc7eSAndroid Build Coastguard Worker {
69*49cdfc7eSAndroid Build Coastguard Worker 	struct ifreq ifr;
70*49cdfc7eSAndroid Build Coastguard Worker 	int sock, ret;
71*49cdfc7eSAndroid Build Coastguard Worker 
72*49cdfc7eSAndroid Build Coastguard Worker 	if (strlen(ifname) >= IFNAMSIZ) {
73*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk_(file, lineno, TBROK,
74*49cdfc7eSAndroid Build Coastguard Worker 			"Network device name \"%s\" too long", ifname);
75*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
76*49cdfc7eSAndroid Build Coastguard Worker 	}
77*49cdfc7eSAndroid Build Coastguard Worker 
78*49cdfc7eSAndroid Build Coastguard Worker 	sock = safe_socket(file, lineno, NULL, AF_INET, SOCK_DGRAM, 0);
79*49cdfc7eSAndroid Build Coastguard Worker 
80*49cdfc7eSAndroid Build Coastguard Worker 	if (sock < 0)
81*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
82*49cdfc7eSAndroid Build Coastguard Worker 
83*49cdfc7eSAndroid Build Coastguard Worker 	strcpy(ifr.ifr_name, ifname);
84*49cdfc7eSAndroid Build Coastguard Worker 	ret = SAFE_IOCTL_(file, lineno, sock, SIOCGIFFLAGS, &ifr);
85*49cdfc7eSAndroid Build Coastguard Worker 
86*49cdfc7eSAndroid Build Coastguard Worker 	if (ret) {
87*49cdfc7eSAndroid Build Coastguard Worker 		safe_close(file, lineno, NULL, sock);
88*49cdfc7eSAndroid Build Coastguard Worker 		return ret;
89*49cdfc7eSAndroid Build Coastguard Worker 	}
90*49cdfc7eSAndroid Build Coastguard Worker 
91*49cdfc7eSAndroid Build Coastguard Worker 	if (up)
92*49cdfc7eSAndroid Build Coastguard Worker 		ifr.ifr_flags |= IFF_UP;
93*49cdfc7eSAndroid Build Coastguard Worker 	else
94*49cdfc7eSAndroid Build Coastguard Worker 		ifr.ifr_flags &= ~IFF_UP;
95*49cdfc7eSAndroid Build Coastguard Worker 
96*49cdfc7eSAndroid Build Coastguard Worker 	ret = SAFE_IOCTL_(file, lineno, sock, SIOCSIFFLAGS, &ifr);
97*49cdfc7eSAndroid Build Coastguard Worker 	safe_close(file, lineno, NULL, sock);
98*49cdfc7eSAndroid Build Coastguard Worker 
99*49cdfc7eSAndroid Build Coastguard Worker 	return ret;
100*49cdfc7eSAndroid Build Coastguard Worker }
101*49cdfc7eSAndroid Build Coastguard Worker 
tst_create_veth_pair(const char * file,const int lineno,int strict,const char * ifname1,const char * ifname2)102*49cdfc7eSAndroid Build Coastguard Worker int tst_create_veth_pair(const char *file, const int lineno, int strict,
103*49cdfc7eSAndroid Build Coastguard Worker 	const char *ifname1, const char *ifname2)
104*49cdfc7eSAndroid Build Coastguard Worker {
105*49cdfc7eSAndroid Build Coastguard Worker 	int ret;
106*49cdfc7eSAndroid Build Coastguard Worker 	struct ifinfomsg info = { .ifi_family = AF_UNSPEC };
107*49cdfc7eSAndroid Build Coastguard Worker 	struct tst_netlink_context *ctx;
108*49cdfc7eSAndroid Build Coastguard Worker 	struct tst_netlink_attr_list peerinfo[] = {
109*49cdfc7eSAndroid Build Coastguard Worker 		{IFLA_IFNAME, ifname2, strlen(ifname2) + 1, NULL},
110*49cdfc7eSAndroid Build Coastguard Worker 		{0, NULL, -1, NULL}
111*49cdfc7eSAndroid Build Coastguard Worker 	};
112*49cdfc7eSAndroid Build Coastguard Worker 	struct tst_netlink_attr_list peerdata[] = {
113*49cdfc7eSAndroid Build Coastguard Worker 		{VETH_INFO_PEER, &info, sizeof(info), peerinfo},
114*49cdfc7eSAndroid Build Coastguard Worker 		{0, NULL, -1, NULL}
115*49cdfc7eSAndroid Build Coastguard Worker 	};
116*49cdfc7eSAndroid Build Coastguard Worker 	struct tst_netlink_attr_list attrs[] = {
117*49cdfc7eSAndroid Build Coastguard Worker 		{IFLA_IFNAME, ifname1, strlen(ifname1) + 1, NULL},
118*49cdfc7eSAndroid Build Coastguard Worker 		{IFLA_LINKINFO, NULL, 0, (const struct tst_netlink_attr_list[]){
119*49cdfc7eSAndroid Build Coastguard Worker 			{IFLA_INFO_KIND, "veth", 4, NULL},
120*49cdfc7eSAndroid Build Coastguard Worker 			{IFLA_INFO_DATA, NULL, 0, peerdata},
121*49cdfc7eSAndroid Build Coastguard Worker 			{0, NULL, -1, NULL}
122*49cdfc7eSAndroid Build Coastguard Worker 		}},
123*49cdfc7eSAndroid Build Coastguard Worker 		{0, NULL, -1, NULL}
124*49cdfc7eSAndroid Build Coastguard Worker 	};
125*49cdfc7eSAndroid Build Coastguard Worker 
126*49cdfc7eSAndroid Build Coastguard Worker 	if (strlen(ifname1) >= IFNAMSIZ) {
127*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk_(file, lineno, TBROK,
128*49cdfc7eSAndroid Build Coastguard Worker 			"Network device name \"%s\" too long", ifname1);
129*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
130*49cdfc7eSAndroid Build Coastguard Worker 	}
131*49cdfc7eSAndroid Build Coastguard Worker 
132*49cdfc7eSAndroid Build Coastguard Worker 	if (strlen(ifname2) >= IFNAMSIZ) {
133*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk_(file, lineno, TBROK,
134*49cdfc7eSAndroid Build Coastguard Worker 			"Network device name \"%s\" too long", ifname2);
135*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
136*49cdfc7eSAndroid Build Coastguard Worker 	}
137*49cdfc7eSAndroid Build Coastguard Worker 
138*49cdfc7eSAndroid Build Coastguard Worker 	ctx = create_request(file, lineno, RTM_NEWLINK,
139*49cdfc7eSAndroid Build Coastguard Worker 		NLM_F_CREATE | NLM_F_EXCL, &info, sizeof(info));
140*49cdfc7eSAndroid Build Coastguard Worker 
141*49cdfc7eSAndroid Build Coastguard Worker 	if (!ctx)
142*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
143*49cdfc7eSAndroid Build Coastguard Worker 
144*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_rtnl_add_attr_list(file, lineno, ctx, attrs) != 2) {
145*49cdfc7eSAndroid Build Coastguard Worker 		tst_netlink_destroy_context(file, lineno, ctx);
146*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
147*49cdfc7eSAndroid Build Coastguard Worker 	}
148*49cdfc7eSAndroid Build Coastguard Worker 
149*49cdfc7eSAndroid Build Coastguard Worker 	ret = tst_netlink_send_validate(file, lineno, ctx);
150*49cdfc7eSAndroid Build Coastguard Worker 	tst_netlink_destroy_context(file, lineno, ctx);
151*49cdfc7eSAndroid Build Coastguard Worker 
152*49cdfc7eSAndroid Build Coastguard Worker 	if (strict && !ret) {
153*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk_(file, lineno, TBROK,
154*49cdfc7eSAndroid Build Coastguard Worker 			"Failed to create veth interfaces %s+%s: %s", ifname1,
155*49cdfc7eSAndroid Build Coastguard Worker 			ifname2, tst_strerrno(tst_netlink_errno));
156*49cdfc7eSAndroid Build Coastguard Worker 	}
157*49cdfc7eSAndroid Build Coastguard Worker 
158*49cdfc7eSAndroid Build Coastguard Worker 	return ret;
159*49cdfc7eSAndroid Build Coastguard Worker }
160*49cdfc7eSAndroid Build Coastguard Worker 
tst_netdev_add_device(const char * file,const int lineno,int strict,const char * ifname,const char * devtype)161*49cdfc7eSAndroid Build Coastguard Worker int tst_netdev_add_device(const char *file, const int lineno, int strict,
162*49cdfc7eSAndroid Build Coastguard Worker 	const char *ifname, const char *devtype)
163*49cdfc7eSAndroid Build Coastguard Worker {
164*49cdfc7eSAndroid Build Coastguard Worker 	int ret;
165*49cdfc7eSAndroid Build Coastguard Worker 	struct ifinfomsg info = { .ifi_family = AF_UNSPEC };
166*49cdfc7eSAndroid Build Coastguard Worker 	struct tst_netlink_context *ctx;
167*49cdfc7eSAndroid Build Coastguard Worker 	struct tst_netlink_attr_list attrs[] = {
168*49cdfc7eSAndroid Build Coastguard Worker 		{IFLA_IFNAME, ifname, strlen(ifname) + 1, NULL},
169*49cdfc7eSAndroid Build Coastguard Worker 		{IFLA_LINKINFO, NULL, 0, (const struct tst_netlink_attr_list[]){
170*49cdfc7eSAndroid Build Coastguard Worker 			{IFLA_INFO_KIND, devtype, strlen(devtype), NULL},
171*49cdfc7eSAndroid Build Coastguard Worker 			{0, NULL, -1, NULL}
172*49cdfc7eSAndroid Build Coastguard Worker 		}},
173*49cdfc7eSAndroid Build Coastguard Worker 		{0, NULL, -1, NULL}
174*49cdfc7eSAndroid Build Coastguard Worker 	};
175*49cdfc7eSAndroid Build Coastguard Worker 
176*49cdfc7eSAndroid Build Coastguard Worker 	if (strlen(ifname) >= IFNAMSIZ) {
177*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk_(file, lineno, TBROK,
178*49cdfc7eSAndroid Build Coastguard Worker 			"Network device name \"%s\" too long", ifname);
179*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
180*49cdfc7eSAndroid Build Coastguard Worker 	}
181*49cdfc7eSAndroid Build Coastguard Worker 
182*49cdfc7eSAndroid Build Coastguard Worker 	ctx = create_request(file, lineno, RTM_NEWLINK,
183*49cdfc7eSAndroid Build Coastguard Worker 		NLM_F_CREATE | NLM_F_EXCL, &info, sizeof(info));
184*49cdfc7eSAndroid Build Coastguard Worker 
185*49cdfc7eSAndroid Build Coastguard Worker 	if (!ctx)
186*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
187*49cdfc7eSAndroid Build Coastguard Worker 
188*49cdfc7eSAndroid Build Coastguard Worker 	if (tst_rtnl_add_attr_list(file, lineno, ctx, attrs) != 2) {
189*49cdfc7eSAndroid Build Coastguard Worker 		tst_netlink_destroy_context(file, lineno, ctx);
190*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
191*49cdfc7eSAndroid Build Coastguard Worker 	}
192*49cdfc7eSAndroid Build Coastguard Worker 
193*49cdfc7eSAndroid Build Coastguard Worker 	ret = tst_netlink_send_validate(file, lineno, ctx);
194*49cdfc7eSAndroid Build Coastguard Worker 	tst_netlink_destroy_context(file, lineno, ctx);
195*49cdfc7eSAndroid Build Coastguard Worker 
196*49cdfc7eSAndroid Build Coastguard Worker 	if (strict && !ret) {
197*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk_(file, lineno, TBROK,
198*49cdfc7eSAndroid Build Coastguard Worker 			"Failed to create %s device %s: %s", devtype, ifname,
199*49cdfc7eSAndroid Build Coastguard Worker 			tst_strerrno(tst_netlink_errno));
200*49cdfc7eSAndroid Build Coastguard Worker 	}
201*49cdfc7eSAndroid Build Coastguard Worker 
202*49cdfc7eSAndroid Build Coastguard Worker 	return ret;
203*49cdfc7eSAndroid Build Coastguard Worker }
204*49cdfc7eSAndroid Build Coastguard Worker 
tst_netdev_remove_device(const char * file,const int lineno,int strict,const char * ifname)205*49cdfc7eSAndroid Build Coastguard Worker int tst_netdev_remove_device(const char *file, const int lineno, int strict,
206*49cdfc7eSAndroid Build Coastguard Worker 	const char *ifname)
207*49cdfc7eSAndroid Build Coastguard Worker {
208*49cdfc7eSAndroid Build Coastguard Worker 	struct ifinfomsg info = { .ifi_family = AF_UNSPEC };
209*49cdfc7eSAndroid Build Coastguard Worker 	struct tst_netlink_context *ctx;
210*49cdfc7eSAndroid Build Coastguard Worker 	int ret;
211*49cdfc7eSAndroid Build Coastguard Worker 
212*49cdfc7eSAndroid Build Coastguard Worker 	if (strlen(ifname) >= IFNAMSIZ) {
213*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk_(file, lineno, TBROK,
214*49cdfc7eSAndroid Build Coastguard Worker 			"Network device name \"%s\" too long", ifname);
215*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
216*49cdfc7eSAndroid Build Coastguard Worker 	}
217*49cdfc7eSAndroid Build Coastguard Worker 
218*49cdfc7eSAndroid Build Coastguard Worker 	ctx = create_request(file, lineno, RTM_DELLINK, 0, &info, sizeof(info));
219*49cdfc7eSAndroid Build Coastguard Worker 
220*49cdfc7eSAndroid Build Coastguard Worker 	if (!ctx)
221*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
222*49cdfc7eSAndroid Build Coastguard Worker 
223*49cdfc7eSAndroid Build Coastguard Worker 	if (!tst_rtnl_add_attr_string(file, lineno, ctx, IFLA_IFNAME, ifname)) {
224*49cdfc7eSAndroid Build Coastguard Worker 		tst_netlink_destroy_context(file, lineno, ctx);
225*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
226*49cdfc7eSAndroid Build Coastguard Worker 	}
227*49cdfc7eSAndroid Build Coastguard Worker 
228*49cdfc7eSAndroid Build Coastguard Worker 	ret = tst_netlink_send_validate(file, lineno, ctx);
229*49cdfc7eSAndroid Build Coastguard Worker 	tst_netlink_destroy_context(file, lineno, ctx);
230*49cdfc7eSAndroid Build Coastguard Worker 
231*49cdfc7eSAndroid Build Coastguard Worker 	if (strict && !ret) {
232*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk_(file, lineno, TBROK,
233*49cdfc7eSAndroid Build Coastguard Worker 			"Failed to remove netdevice %s: %s", ifname,
234*49cdfc7eSAndroid Build Coastguard Worker 			tst_strerrno(tst_netlink_errno));
235*49cdfc7eSAndroid Build Coastguard Worker 	}
236*49cdfc7eSAndroid Build Coastguard Worker 
237*49cdfc7eSAndroid Build Coastguard Worker 	return ret;
238*49cdfc7eSAndroid Build Coastguard Worker }
239*49cdfc7eSAndroid Build Coastguard Worker 
modify_address(const char * file,const int lineno,int strict,unsigned int action,unsigned int nl_flags,const char * ifname,unsigned int family,const void * address,unsigned int prefix,size_t addrlen,uint32_t addr_flags)240*49cdfc7eSAndroid Build Coastguard Worker static int modify_address(const char *file, const int lineno, int strict,
241*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int action, unsigned int nl_flags, const char *ifname,
242*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int family, const void *address, unsigned int prefix,
243*49cdfc7eSAndroid Build Coastguard Worker 	size_t addrlen, uint32_t addr_flags)
244*49cdfc7eSAndroid Build Coastguard Worker {
245*49cdfc7eSAndroid Build Coastguard Worker 	struct tst_netlink_context *ctx;
246*49cdfc7eSAndroid Build Coastguard Worker 	int index, ret;
247*49cdfc7eSAndroid Build Coastguard Worker 	struct ifaddrmsg info = {
248*49cdfc7eSAndroid Build Coastguard Worker 		.ifa_family = family,
249*49cdfc7eSAndroid Build Coastguard Worker 		.ifa_prefixlen = prefix
250*49cdfc7eSAndroid Build Coastguard Worker 	};
251*49cdfc7eSAndroid Build Coastguard Worker 
252*49cdfc7eSAndroid Build Coastguard Worker 	index = tst_netdev_index_by_name(file, lineno, ifname);
253*49cdfc7eSAndroid Build Coastguard Worker 
254*49cdfc7eSAndroid Build Coastguard Worker 	if (index < 0) {
255*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk_(file, lineno, TBROK, "Interface %s not found", ifname);
256*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
257*49cdfc7eSAndroid Build Coastguard Worker 	}
258*49cdfc7eSAndroid Build Coastguard Worker 
259*49cdfc7eSAndroid Build Coastguard Worker 	info.ifa_index = index;
260*49cdfc7eSAndroid Build Coastguard Worker 	ctx = create_request(file, lineno, action, nl_flags, &info,
261*49cdfc7eSAndroid Build Coastguard Worker 		sizeof(info));
262*49cdfc7eSAndroid Build Coastguard Worker 
263*49cdfc7eSAndroid Build Coastguard Worker 	if (!ctx)
264*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
265*49cdfc7eSAndroid Build Coastguard Worker 
266*49cdfc7eSAndroid Build Coastguard Worker 	if (!tst_rtnl_add_attr(file, lineno, ctx, IFA_FLAGS, &addr_flags,
267*49cdfc7eSAndroid Build Coastguard Worker 		sizeof(uint32_t))) {
268*49cdfc7eSAndroid Build Coastguard Worker 		tst_netlink_destroy_context(file, lineno, ctx);
269*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
270*49cdfc7eSAndroid Build Coastguard Worker 	}
271*49cdfc7eSAndroid Build Coastguard Worker 
272*49cdfc7eSAndroid Build Coastguard Worker 	if (!tst_rtnl_add_attr(file, lineno, ctx, IFA_LOCAL, address,
273*49cdfc7eSAndroid Build Coastguard Worker 		addrlen)) {
274*49cdfc7eSAndroid Build Coastguard Worker 		tst_netlink_destroy_context(file, lineno, ctx);
275*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
276*49cdfc7eSAndroid Build Coastguard Worker 	}
277*49cdfc7eSAndroid Build Coastguard Worker 
278*49cdfc7eSAndroid Build Coastguard Worker 	ret = tst_netlink_send_validate(file, lineno, ctx);
279*49cdfc7eSAndroid Build Coastguard Worker 	tst_netlink_destroy_context(file, lineno, ctx);
280*49cdfc7eSAndroid Build Coastguard Worker 
281*49cdfc7eSAndroid Build Coastguard Worker 	if (strict && !ret) {
282*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk_(file, lineno, TBROK,
283*49cdfc7eSAndroid Build Coastguard Worker 			"Failed to modify %s network address: %s", ifname,
284*49cdfc7eSAndroid Build Coastguard Worker 			tst_strerrno(tst_netlink_errno));
285*49cdfc7eSAndroid Build Coastguard Worker 	}
286*49cdfc7eSAndroid Build Coastguard Worker 
287*49cdfc7eSAndroid Build Coastguard Worker 	return ret;
288*49cdfc7eSAndroid Build Coastguard Worker }
289*49cdfc7eSAndroid Build Coastguard Worker 
tst_netdev_add_address(const char * file,const int lineno,int strict,const char * ifname,unsigned int family,const void * address,unsigned int prefix,size_t addrlen,unsigned int flags)290*49cdfc7eSAndroid Build Coastguard Worker int tst_netdev_add_address(const char *file, const int lineno, int strict,
291*49cdfc7eSAndroid Build Coastguard Worker 	const char *ifname, unsigned int family, const void *address,
292*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int prefix, size_t addrlen, unsigned int flags)
293*49cdfc7eSAndroid Build Coastguard Worker {
294*49cdfc7eSAndroid Build Coastguard Worker 	return modify_address(file, lineno, strict, RTM_NEWADDR,
295*49cdfc7eSAndroid Build Coastguard Worker 		NLM_F_CREATE | NLM_F_EXCL, ifname, family, address, prefix,
296*49cdfc7eSAndroid Build Coastguard Worker 		addrlen, flags);
297*49cdfc7eSAndroid Build Coastguard Worker }
298*49cdfc7eSAndroid Build Coastguard Worker 
tst_netdev_add_address_inet(const char * file,const int lineno,int strict,const char * ifname,in_addr_t address,unsigned int prefix,unsigned int flags)299*49cdfc7eSAndroid Build Coastguard Worker int tst_netdev_add_address_inet(const char *file, const int lineno, int strict,
300*49cdfc7eSAndroid Build Coastguard Worker 	const char *ifname, in_addr_t address, unsigned int prefix,
301*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int flags)
302*49cdfc7eSAndroid Build Coastguard Worker {
303*49cdfc7eSAndroid Build Coastguard Worker 	return tst_netdev_add_address(file, lineno, strict, ifname, AF_INET,
304*49cdfc7eSAndroid Build Coastguard Worker 		&address, prefix, sizeof(address), flags);
305*49cdfc7eSAndroid Build Coastguard Worker }
306*49cdfc7eSAndroid Build Coastguard Worker 
tst_netdev_remove_address(const char * file,const int lineno,int strict,const char * ifname,unsigned int family,const void * address,size_t addrlen)307*49cdfc7eSAndroid Build Coastguard Worker int tst_netdev_remove_address(const char *file, const int lineno, int strict,
308*49cdfc7eSAndroid Build Coastguard Worker 	const char *ifname, unsigned int family, const void *address,
309*49cdfc7eSAndroid Build Coastguard Worker 	size_t addrlen)
310*49cdfc7eSAndroid Build Coastguard Worker {
311*49cdfc7eSAndroid Build Coastguard Worker 	return modify_address(file, lineno, strict, RTM_DELADDR, 0, ifname,
312*49cdfc7eSAndroid Build Coastguard Worker 		family, address, 0, addrlen, 0);
313*49cdfc7eSAndroid Build Coastguard Worker }
314*49cdfc7eSAndroid Build Coastguard Worker 
tst_netdev_remove_address_inet(const char * file,const int lineno,int strict,const char * ifname,in_addr_t address)315*49cdfc7eSAndroid Build Coastguard Worker int tst_netdev_remove_address_inet(const char *file, const int lineno,
316*49cdfc7eSAndroid Build Coastguard Worker 	int strict, const char *ifname, in_addr_t address)
317*49cdfc7eSAndroid Build Coastguard Worker {
318*49cdfc7eSAndroid Build Coastguard Worker 	return tst_netdev_remove_address(file, lineno, strict, ifname, AF_INET,
319*49cdfc7eSAndroid Build Coastguard Worker 		&address, sizeof(address));
320*49cdfc7eSAndroid Build Coastguard Worker }
321*49cdfc7eSAndroid Build Coastguard Worker 
change_ns(const char * file,const int lineno,int strict,const char * ifname,unsigned short attr,uint32_t value)322*49cdfc7eSAndroid Build Coastguard Worker static int change_ns(const char *file, const int lineno, int strict,
323*49cdfc7eSAndroid Build Coastguard Worker 	const char *ifname, unsigned short attr, uint32_t value)
324*49cdfc7eSAndroid Build Coastguard Worker {
325*49cdfc7eSAndroid Build Coastguard Worker 	struct ifinfomsg info = { .ifi_family = AF_UNSPEC };
326*49cdfc7eSAndroid Build Coastguard Worker 	struct tst_netlink_context *ctx;
327*49cdfc7eSAndroid Build Coastguard Worker 	int ret;
328*49cdfc7eSAndroid Build Coastguard Worker 
329*49cdfc7eSAndroid Build Coastguard Worker 	if (strlen(ifname) >= IFNAMSIZ) {
330*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk_(file, lineno, TBROK,
331*49cdfc7eSAndroid Build Coastguard Worker 			"Network device name \"%s\" too long", ifname);
332*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
333*49cdfc7eSAndroid Build Coastguard Worker 	}
334*49cdfc7eSAndroid Build Coastguard Worker 
335*49cdfc7eSAndroid Build Coastguard Worker 	ctx = create_request(file, lineno, RTM_NEWLINK, 0, &info, sizeof(info));
336*49cdfc7eSAndroid Build Coastguard Worker 
337*49cdfc7eSAndroid Build Coastguard Worker 	if (!ctx)
338*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
339*49cdfc7eSAndroid Build Coastguard Worker 
340*49cdfc7eSAndroid Build Coastguard Worker 	if (!tst_rtnl_add_attr_string(file, lineno, ctx, IFLA_IFNAME, ifname)) {
341*49cdfc7eSAndroid Build Coastguard Worker 		tst_netlink_destroy_context(file, lineno, ctx);
342*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
343*49cdfc7eSAndroid Build Coastguard Worker 	}
344*49cdfc7eSAndroid Build Coastguard Worker 
345*49cdfc7eSAndroid Build Coastguard Worker 	if (!tst_rtnl_add_attr(file, lineno, ctx, attr, &value,
346*49cdfc7eSAndroid Build Coastguard Worker 		sizeof(uint32_t))) {
347*49cdfc7eSAndroid Build Coastguard Worker 		tst_netlink_destroy_context(file, lineno, ctx);
348*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
349*49cdfc7eSAndroid Build Coastguard Worker 	}
350*49cdfc7eSAndroid Build Coastguard Worker 
351*49cdfc7eSAndroid Build Coastguard Worker 	ret = tst_netlink_send_validate(file, lineno, ctx);
352*49cdfc7eSAndroid Build Coastguard Worker 	tst_netlink_destroy_context(file, lineno, ctx);
353*49cdfc7eSAndroid Build Coastguard Worker 
354*49cdfc7eSAndroid Build Coastguard Worker 	if (strict && !ret) {
355*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk_(file, lineno, TBROK,
356*49cdfc7eSAndroid Build Coastguard Worker 			"Failed to move %s to another namespace: %s", ifname,
357*49cdfc7eSAndroid Build Coastguard Worker 			tst_strerrno(tst_netlink_errno));
358*49cdfc7eSAndroid Build Coastguard Worker 	}
359*49cdfc7eSAndroid Build Coastguard Worker 
360*49cdfc7eSAndroid Build Coastguard Worker 	return ret;
361*49cdfc7eSAndroid Build Coastguard Worker }
362*49cdfc7eSAndroid Build Coastguard Worker 
tst_netdev_change_ns_fd(const char * file,const int lineno,int strict,const char * ifname,int nsfd)363*49cdfc7eSAndroid Build Coastguard Worker int tst_netdev_change_ns_fd(const char *file, const int lineno, int strict,
364*49cdfc7eSAndroid Build Coastguard Worker 	const char *ifname, int nsfd)
365*49cdfc7eSAndroid Build Coastguard Worker {
366*49cdfc7eSAndroid Build Coastguard Worker 	return change_ns(file, lineno, strict, ifname, IFLA_NET_NS_FD, nsfd);
367*49cdfc7eSAndroid Build Coastguard Worker }
368*49cdfc7eSAndroid Build Coastguard Worker 
tst_netdev_change_ns_pid(const char * file,const int lineno,int strict,const char * ifname,pid_t nspid)369*49cdfc7eSAndroid Build Coastguard Worker int tst_netdev_change_ns_pid(const char *file, const int lineno, int strict,
370*49cdfc7eSAndroid Build Coastguard Worker 	const char *ifname, pid_t nspid)
371*49cdfc7eSAndroid Build Coastguard Worker {
372*49cdfc7eSAndroid Build Coastguard Worker 	return change_ns(file, lineno, strict, ifname, IFLA_NET_NS_PID, nspid);
373*49cdfc7eSAndroid Build Coastguard Worker }
374*49cdfc7eSAndroid Build Coastguard Worker 
modify_route(const char * file,const int lineno,int strict,unsigned int action,unsigned int flags,const char * ifname,unsigned int family,const void * srcaddr,unsigned int srcprefix,size_t srclen,const void * dstaddr,unsigned int dstprefix,size_t dstlen,const void * gateway,size_t gatewaylen)375*49cdfc7eSAndroid Build Coastguard Worker static int modify_route(const char *file, const int lineno, int strict,
376*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int action, unsigned int flags, const char *ifname,
377*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int family, const void *srcaddr, unsigned int srcprefix,
378*49cdfc7eSAndroid Build Coastguard Worker 	size_t srclen, const void *dstaddr, unsigned int dstprefix,
379*49cdfc7eSAndroid Build Coastguard Worker 	size_t dstlen, const void *gateway, size_t gatewaylen)
380*49cdfc7eSAndroid Build Coastguard Worker {
381*49cdfc7eSAndroid Build Coastguard Worker 	struct tst_netlink_context *ctx;
382*49cdfc7eSAndroid Build Coastguard Worker 	int ret;
383*49cdfc7eSAndroid Build Coastguard Worker 	int32_t index;
384*49cdfc7eSAndroid Build Coastguard Worker 	struct rtmsg info = {
385*49cdfc7eSAndroid Build Coastguard Worker 		.rtm_family = family,
386*49cdfc7eSAndroid Build Coastguard Worker 		.rtm_dst_len = dstprefix,
387*49cdfc7eSAndroid Build Coastguard Worker 		.rtm_src_len = srcprefix,
388*49cdfc7eSAndroid Build Coastguard Worker 		.rtm_table = RT_TABLE_MAIN,
389*49cdfc7eSAndroid Build Coastguard Worker 		.rtm_protocol = RTPROT_STATIC,
390*49cdfc7eSAndroid Build Coastguard Worker 		.rtm_type = RTN_UNICAST
391*49cdfc7eSAndroid Build Coastguard Worker 	};
392*49cdfc7eSAndroid Build Coastguard Worker 
393*49cdfc7eSAndroid Build Coastguard Worker 	if (!ifname && !gateway) {
394*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk_(file, lineno, TBROK,
395*49cdfc7eSAndroid Build Coastguard Worker 			"Interface name or gateway address required");
396*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
397*49cdfc7eSAndroid Build Coastguard Worker 	}
398*49cdfc7eSAndroid Build Coastguard Worker 
399*49cdfc7eSAndroid Build Coastguard Worker 	if (ifname && strlen(ifname) >= IFNAMSIZ) {
400*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk_(file, lineno, TBROK,
401*49cdfc7eSAndroid Build Coastguard Worker 			"Network device name \"%s\" too long", ifname);
402*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
403*49cdfc7eSAndroid Build Coastguard Worker 	}
404*49cdfc7eSAndroid Build Coastguard Worker 
405*49cdfc7eSAndroid Build Coastguard Worker 	if (ifname) {
406*49cdfc7eSAndroid Build Coastguard Worker 		index = tst_netdev_index_by_name(file, lineno, ifname);
407*49cdfc7eSAndroid Build Coastguard Worker 
408*49cdfc7eSAndroid Build Coastguard Worker 		if (index < 0)
409*49cdfc7eSAndroid Build Coastguard Worker 			return 0;
410*49cdfc7eSAndroid Build Coastguard Worker 	}
411*49cdfc7eSAndroid Build Coastguard Worker 
412*49cdfc7eSAndroid Build Coastguard Worker 	if (action == RTM_DELROUTE)
413*49cdfc7eSAndroid Build Coastguard Worker 		info.rtm_scope = RT_SCOPE_NOWHERE;
414*49cdfc7eSAndroid Build Coastguard Worker 	else
415*49cdfc7eSAndroid Build Coastguard Worker 		info.rtm_scope = RT_SCOPE_UNIVERSE;
416*49cdfc7eSAndroid Build Coastguard Worker 
417*49cdfc7eSAndroid Build Coastguard Worker 	ctx = create_request(file, lineno, action, flags, &info, sizeof(info));
418*49cdfc7eSAndroid Build Coastguard Worker 
419*49cdfc7eSAndroid Build Coastguard Worker 	if (!ctx)
420*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
421*49cdfc7eSAndroid Build Coastguard Worker 
422*49cdfc7eSAndroid Build Coastguard Worker 	if (srcaddr && !tst_rtnl_add_attr(file, lineno, ctx, RTA_SRC, srcaddr,
423*49cdfc7eSAndroid Build Coastguard Worker 		srclen)) {
424*49cdfc7eSAndroid Build Coastguard Worker 		tst_netlink_destroy_context(file, lineno, ctx);
425*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
426*49cdfc7eSAndroid Build Coastguard Worker 	}
427*49cdfc7eSAndroid Build Coastguard Worker 
428*49cdfc7eSAndroid Build Coastguard Worker 	if (dstaddr && !tst_rtnl_add_attr(file, lineno, ctx, RTA_DST, dstaddr,
429*49cdfc7eSAndroid Build Coastguard Worker 		dstlen)) {
430*49cdfc7eSAndroid Build Coastguard Worker 		tst_netlink_destroy_context(file, lineno, ctx);
431*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
432*49cdfc7eSAndroid Build Coastguard Worker 	}
433*49cdfc7eSAndroid Build Coastguard Worker 
434*49cdfc7eSAndroid Build Coastguard Worker 	if (gateway && !tst_rtnl_add_attr(file, lineno, ctx, RTA_GATEWAY,
435*49cdfc7eSAndroid Build Coastguard Worker 		gateway, gatewaylen)) {
436*49cdfc7eSAndroid Build Coastguard Worker 		tst_netlink_destroy_context(file, lineno, ctx);
437*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
438*49cdfc7eSAndroid Build Coastguard Worker 	}
439*49cdfc7eSAndroid Build Coastguard Worker 
440*49cdfc7eSAndroid Build Coastguard Worker 	if (ifname && !tst_rtnl_add_attr(file, lineno, ctx, RTA_OIF, &index,
441*49cdfc7eSAndroid Build Coastguard Worker 		sizeof(index))) {
442*49cdfc7eSAndroid Build Coastguard Worker 		tst_netlink_destroy_context(file, lineno, ctx);
443*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
444*49cdfc7eSAndroid Build Coastguard Worker 	}
445*49cdfc7eSAndroid Build Coastguard Worker 
446*49cdfc7eSAndroid Build Coastguard Worker 	ret = tst_netlink_send_validate(file, lineno, ctx);
447*49cdfc7eSAndroid Build Coastguard Worker 	tst_netlink_destroy_context(file, lineno, ctx);
448*49cdfc7eSAndroid Build Coastguard Worker 
449*49cdfc7eSAndroid Build Coastguard Worker 	if (strict && !ret) {
450*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk_(file, lineno, TBROK,
451*49cdfc7eSAndroid Build Coastguard Worker 			"Failed to modify network route: %s",
452*49cdfc7eSAndroid Build Coastguard Worker 			tst_strerrno(tst_netlink_errno));
453*49cdfc7eSAndroid Build Coastguard Worker 	}
454*49cdfc7eSAndroid Build Coastguard Worker 
455*49cdfc7eSAndroid Build Coastguard Worker 	return ret;
456*49cdfc7eSAndroid Build Coastguard Worker }
457*49cdfc7eSAndroid Build Coastguard Worker 
modify_route_inet(const char * file,const int lineno,int strict,unsigned int action,unsigned int flags,const char * ifname,in_addr_t srcaddr,unsigned int srcprefix,in_addr_t dstaddr,unsigned int dstprefix,in_addr_t gateway)458*49cdfc7eSAndroid Build Coastguard Worker static int modify_route_inet(const char *file, const int lineno, int strict,
459*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int action, unsigned int flags, const char *ifname,
460*49cdfc7eSAndroid Build Coastguard Worker 	in_addr_t srcaddr, unsigned int srcprefix, in_addr_t dstaddr,
461*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int dstprefix, in_addr_t gateway)
462*49cdfc7eSAndroid Build Coastguard Worker {
463*49cdfc7eSAndroid Build Coastguard Worker 	void *src = NULL, *dst = NULL, *gw = NULL;
464*49cdfc7eSAndroid Build Coastguard Worker 	size_t srclen = 0, dstlen = 0, gwlen = 0;
465*49cdfc7eSAndroid Build Coastguard Worker 
466*49cdfc7eSAndroid Build Coastguard Worker 	if (srcprefix) {
467*49cdfc7eSAndroid Build Coastguard Worker 		src = &srcaddr;
468*49cdfc7eSAndroid Build Coastguard Worker 		srclen = sizeof(srcaddr);
469*49cdfc7eSAndroid Build Coastguard Worker 	}
470*49cdfc7eSAndroid Build Coastguard Worker 
471*49cdfc7eSAndroid Build Coastguard Worker 	if (dstprefix) {
472*49cdfc7eSAndroid Build Coastguard Worker 		dst = &dstaddr;
473*49cdfc7eSAndroid Build Coastguard Worker 		dstlen = sizeof(dstaddr);
474*49cdfc7eSAndroid Build Coastguard Worker 	}
475*49cdfc7eSAndroid Build Coastguard Worker 
476*49cdfc7eSAndroid Build Coastguard Worker 	if (gateway) {
477*49cdfc7eSAndroid Build Coastguard Worker 		gw = &gateway;
478*49cdfc7eSAndroid Build Coastguard Worker 		gwlen = sizeof(gateway);
479*49cdfc7eSAndroid Build Coastguard Worker 	}
480*49cdfc7eSAndroid Build Coastguard Worker 
481*49cdfc7eSAndroid Build Coastguard Worker 	return modify_route(file, lineno, strict, action, flags, ifname,
482*49cdfc7eSAndroid Build Coastguard Worker 		AF_INET, src, srcprefix, srclen, dst, dstprefix, dstlen, gw,
483*49cdfc7eSAndroid Build Coastguard Worker 		gwlen);
484*49cdfc7eSAndroid Build Coastguard Worker }
485*49cdfc7eSAndroid Build Coastguard Worker 
tst_netdev_add_route(const char * file,const int lineno,int strict,const char * ifname,unsigned int family,const void * srcaddr,unsigned int srcprefix,size_t srclen,const void * dstaddr,unsigned int dstprefix,size_t dstlen,const void * gateway,size_t gatewaylen)486*49cdfc7eSAndroid Build Coastguard Worker int tst_netdev_add_route(const char *file, const int lineno, int strict,
487*49cdfc7eSAndroid Build Coastguard Worker 	const char *ifname, unsigned int family, const void *srcaddr,
488*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int srcprefix, size_t srclen, const void *dstaddr,
489*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int dstprefix, size_t dstlen, const void *gateway,
490*49cdfc7eSAndroid Build Coastguard Worker 	size_t gatewaylen)
491*49cdfc7eSAndroid Build Coastguard Worker {
492*49cdfc7eSAndroid Build Coastguard Worker 	return modify_route(file, lineno, strict, RTM_NEWROUTE,
493*49cdfc7eSAndroid Build Coastguard Worker 		NLM_F_CREATE | NLM_F_EXCL, ifname, family, srcaddr, srcprefix,
494*49cdfc7eSAndroid Build Coastguard Worker 		srclen, dstaddr, dstprefix, dstlen, gateway, gatewaylen);
495*49cdfc7eSAndroid Build Coastguard Worker }
496*49cdfc7eSAndroid Build Coastguard Worker 
tst_netdev_add_route_inet(const char * file,const int lineno,int strict,const char * ifname,in_addr_t srcaddr,unsigned int srcprefix,in_addr_t dstaddr,unsigned int dstprefix,in_addr_t gateway)497*49cdfc7eSAndroid Build Coastguard Worker int tst_netdev_add_route_inet(const char *file, const int lineno, int strict,
498*49cdfc7eSAndroid Build Coastguard Worker 	const char *ifname, in_addr_t srcaddr, unsigned int srcprefix,
499*49cdfc7eSAndroid Build Coastguard Worker 	in_addr_t dstaddr, unsigned int dstprefix, in_addr_t gateway)
500*49cdfc7eSAndroid Build Coastguard Worker {
501*49cdfc7eSAndroid Build Coastguard Worker 	return modify_route_inet(file, lineno, strict, RTM_NEWROUTE,
502*49cdfc7eSAndroid Build Coastguard Worker 		NLM_F_CREATE | NLM_F_EXCL, ifname, srcaddr, srcprefix, dstaddr,
503*49cdfc7eSAndroid Build Coastguard Worker 		dstprefix, gateway);
504*49cdfc7eSAndroid Build Coastguard Worker }
505*49cdfc7eSAndroid Build Coastguard Worker 
tst_netdev_remove_route(const char * file,const int lineno,int strict,const char * ifname,unsigned int family,const void * srcaddr,unsigned int srcprefix,size_t srclen,const void * dstaddr,unsigned int dstprefix,size_t dstlen,const void * gateway,size_t gatewaylen)506*49cdfc7eSAndroid Build Coastguard Worker int tst_netdev_remove_route(const char *file, const int lineno, int strict,
507*49cdfc7eSAndroid Build Coastguard Worker 	const char *ifname, unsigned int family, const void *srcaddr,
508*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int srcprefix, size_t srclen, const void *dstaddr,
509*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int dstprefix, size_t dstlen, const void *gateway,
510*49cdfc7eSAndroid Build Coastguard Worker 	size_t gatewaylen)
511*49cdfc7eSAndroid Build Coastguard Worker {
512*49cdfc7eSAndroid Build Coastguard Worker 	return modify_route(file, lineno, strict, RTM_DELROUTE, 0, ifname,
513*49cdfc7eSAndroid Build Coastguard Worker 		family, srcaddr, srcprefix, srclen, dstaddr, dstprefix, dstlen,
514*49cdfc7eSAndroid Build Coastguard Worker 		gateway, gatewaylen);
515*49cdfc7eSAndroid Build Coastguard Worker }
516*49cdfc7eSAndroid Build Coastguard Worker 
tst_netdev_remove_route_inet(const char * file,const int lineno,int strict,const char * ifname,in_addr_t srcaddr,unsigned int srcprefix,in_addr_t dstaddr,unsigned int dstprefix,in_addr_t gateway)517*49cdfc7eSAndroid Build Coastguard Worker int tst_netdev_remove_route_inet(const char *file, const int lineno,
518*49cdfc7eSAndroid Build Coastguard Worker 	int strict, const char *ifname, in_addr_t srcaddr,
519*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int srcprefix, in_addr_t dstaddr, unsigned int dstprefix,
520*49cdfc7eSAndroid Build Coastguard Worker 	in_addr_t gateway)
521*49cdfc7eSAndroid Build Coastguard Worker {
522*49cdfc7eSAndroid Build Coastguard Worker 	return modify_route_inet(file, lineno, strict, RTM_DELROUTE, 0, ifname,
523*49cdfc7eSAndroid Build Coastguard Worker 		srcaddr, srcprefix, dstaddr, dstprefix, gateway);
524*49cdfc7eSAndroid Build Coastguard Worker }
525*49cdfc7eSAndroid Build Coastguard Worker 
modify_qdisc(const char * file,const int lineno,int strict,const char * object,unsigned int action,unsigned int nl_flags,const char * ifname,unsigned int family,unsigned int parent,unsigned int handle,unsigned int info,const char * qd_kind,const struct tst_netlink_attr_list * config)526*49cdfc7eSAndroid Build Coastguard Worker static int modify_qdisc(const char *file, const int lineno, int strict,
527*49cdfc7eSAndroid Build Coastguard Worker 	const char *object, unsigned int action, unsigned int nl_flags,
528*49cdfc7eSAndroid Build Coastguard Worker 	const char *ifname, unsigned int family, unsigned int parent,
529*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int handle, unsigned int info, const char *qd_kind,
530*49cdfc7eSAndroid Build Coastguard Worker 	const struct tst_netlink_attr_list *config)
531*49cdfc7eSAndroid Build Coastguard Worker {
532*49cdfc7eSAndroid Build Coastguard Worker 	struct tst_netlink_context *ctx;
533*49cdfc7eSAndroid Build Coastguard Worker 	int ret;
534*49cdfc7eSAndroid Build Coastguard Worker 	struct tcmsg msg = {
535*49cdfc7eSAndroid Build Coastguard Worker 		.tcm_family = family,
536*49cdfc7eSAndroid Build Coastguard Worker 		.tcm_handle = handle,
537*49cdfc7eSAndroid Build Coastguard Worker 		.tcm_parent = parent,
538*49cdfc7eSAndroid Build Coastguard Worker 		.tcm_info = info
539*49cdfc7eSAndroid Build Coastguard Worker 	};
540*49cdfc7eSAndroid Build Coastguard Worker 
541*49cdfc7eSAndroid Build Coastguard Worker 	if (!qd_kind) {
542*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk_(file, lineno, TBROK,
543*49cdfc7eSAndroid Build Coastguard Worker 			"Queueing discipline name required");
544*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
545*49cdfc7eSAndroid Build Coastguard Worker 	}
546*49cdfc7eSAndroid Build Coastguard Worker 
547*49cdfc7eSAndroid Build Coastguard Worker 	if (ifname) {
548*49cdfc7eSAndroid Build Coastguard Worker 		msg.tcm_ifindex = tst_netdev_index_by_name(file, lineno,
549*49cdfc7eSAndroid Build Coastguard Worker 			ifname);
550*49cdfc7eSAndroid Build Coastguard Worker 
551*49cdfc7eSAndroid Build Coastguard Worker 		if (msg.tcm_ifindex < 0) {
552*49cdfc7eSAndroid Build Coastguard Worker 			tst_brk_(file, lineno, TBROK, "Interface %s not found",
553*49cdfc7eSAndroid Build Coastguard Worker 				ifname);
554*49cdfc7eSAndroid Build Coastguard Worker 			return 0;
555*49cdfc7eSAndroid Build Coastguard Worker 		}
556*49cdfc7eSAndroid Build Coastguard Worker 	}
557*49cdfc7eSAndroid Build Coastguard Worker 
558*49cdfc7eSAndroid Build Coastguard Worker 	ctx = create_request(file, lineno, action, nl_flags, &msg, sizeof(msg));
559*49cdfc7eSAndroid Build Coastguard Worker 
560*49cdfc7eSAndroid Build Coastguard Worker 	if (!ctx)
561*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
562*49cdfc7eSAndroid Build Coastguard Worker 
563*49cdfc7eSAndroid Build Coastguard Worker 	if (!tst_rtnl_add_attr_string(file, lineno, ctx, TCA_KIND, qd_kind)) {
564*49cdfc7eSAndroid Build Coastguard Worker 		tst_netlink_destroy_context(file, lineno, ctx);
565*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
566*49cdfc7eSAndroid Build Coastguard Worker 	}
567*49cdfc7eSAndroid Build Coastguard Worker 
568*49cdfc7eSAndroid Build Coastguard Worker 	if (config && !tst_rtnl_add_attr_list(file, lineno, ctx, config)) {
569*49cdfc7eSAndroid Build Coastguard Worker 		tst_netlink_destroy_context(file, lineno, ctx);
570*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
571*49cdfc7eSAndroid Build Coastguard Worker 	}
572*49cdfc7eSAndroid Build Coastguard Worker 
573*49cdfc7eSAndroid Build Coastguard Worker 	ret = tst_netlink_send_validate(file, lineno, ctx);
574*49cdfc7eSAndroid Build Coastguard Worker 	tst_netlink_destroy_context(file, lineno, ctx);
575*49cdfc7eSAndroid Build Coastguard Worker 
576*49cdfc7eSAndroid Build Coastguard Worker 	if (strict && !ret) {
577*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk_(file, lineno, TBROK,
578*49cdfc7eSAndroid Build Coastguard Worker 			"Failed to modify %s: %s", object,
579*49cdfc7eSAndroid Build Coastguard Worker 			tst_strerrno(tst_netlink_errno));
580*49cdfc7eSAndroid Build Coastguard Worker 	}
581*49cdfc7eSAndroid Build Coastguard Worker 
582*49cdfc7eSAndroid Build Coastguard Worker 	return ret;
583*49cdfc7eSAndroid Build Coastguard Worker }
584*49cdfc7eSAndroid Build Coastguard Worker 
tst_netdev_add_qdisc(const char * file,const int lineno,int strict,const char * ifname,unsigned int family,unsigned int parent,unsigned int handle,const char * qd_kind,const struct tst_netlink_attr_list * config)585*49cdfc7eSAndroid Build Coastguard Worker int tst_netdev_add_qdisc(const char *file, const int lineno, int strict,
586*49cdfc7eSAndroid Build Coastguard Worker 	const char *ifname, unsigned int family, unsigned int parent,
587*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int handle, const char *qd_kind,
588*49cdfc7eSAndroid Build Coastguard Worker 	const struct tst_netlink_attr_list *config)
589*49cdfc7eSAndroid Build Coastguard Worker {
590*49cdfc7eSAndroid Build Coastguard Worker 	return modify_qdisc(file, lineno, strict, "queueing discipline",
591*49cdfc7eSAndroid Build Coastguard Worker 		RTM_NEWQDISC, NLM_F_CREATE | NLM_F_EXCL, ifname, family,
592*49cdfc7eSAndroid Build Coastguard Worker 		parent, handle, 0, qd_kind, config);
593*49cdfc7eSAndroid Build Coastguard Worker }
594*49cdfc7eSAndroid Build Coastguard Worker 
tst_netdev_remove_qdisc(const char * file,const int lineno,int strict,const char * ifname,unsigned int family,unsigned int parent,unsigned int handle,const char * qd_kind)595*49cdfc7eSAndroid Build Coastguard Worker int tst_netdev_remove_qdisc(const char *file, const int lineno, int strict,
596*49cdfc7eSAndroid Build Coastguard Worker 	const char *ifname, unsigned int family, unsigned int parent,
597*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int handle, const char *qd_kind)
598*49cdfc7eSAndroid Build Coastguard Worker {
599*49cdfc7eSAndroid Build Coastguard Worker 	return modify_qdisc(file, lineno, strict, "queueing discipline",
600*49cdfc7eSAndroid Build Coastguard Worker 		RTM_DELQDISC, 0, ifname, family, parent, handle, 0, qd_kind,
601*49cdfc7eSAndroid Build Coastguard Worker 		NULL);
602*49cdfc7eSAndroid Build Coastguard Worker }
603*49cdfc7eSAndroid Build Coastguard Worker 
tst_netdev_add_traffic_class(const char * file,const int lineno,int strict,const char * ifname,unsigned int parent,unsigned int handle,const char * qd_kind,const struct tst_netlink_attr_list * config)604*49cdfc7eSAndroid Build Coastguard Worker int tst_netdev_add_traffic_class(const char *file, const int lineno,
605*49cdfc7eSAndroid Build Coastguard Worker 	int strict, const char *ifname, unsigned int parent,
606*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int handle, const char *qd_kind,
607*49cdfc7eSAndroid Build Coastguard Worker 	const struct tst_netlink_attr_list *config)
608*49cdfc7eSAndroid Build Coastguard Worker {
609*49cdfc7eSAndroid Build Coastguard Worker 	return modify_qdisc(file, lineno, strict, "traffic class",
610*49cdfc7eSAndroid Build Coastguard Worker 		RTM_NEWTCLASS, NLM_F_CREATE | NLM_F_EXCL, ifname, AF_UNSPEC,
611*49cdfc7eSAndroid Build Coastguard Worker 		parent, handle, 0, qd_kind, config);
612*49cdfc7eSAndroid Build Coastguard Worker }
613*49cdfc7eSAndroid Build Coastguard Worker 
tst_netdev_remove_traffic_class(const char * file,const int lineno,int strict,const char * ifname,unsigned int parent,unsigned int handle,const char * qd_kind)614*49cdfc7eSAndroid Build Coastguard Worker int tst_netdev_remove_traffic_class(const char *file, const int lineno,
615*49cdfc7eSAndroid Build Coastguard Worker 	int strict, const char *ifname, unsigned int parent,
616*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int handle, const char *qd_kind)
617*49cdfc7eSAndroid Build Coastguard Worker {
618*49cdfc7eSAndroid Build Coastguard Worker 	return modify_qdisc(file, lineno, strict, "traffic class",
619*49cdfc7eSAndroid Build Coastguard Worker 		RTM_DELTCLASS, 0, ifname, AF_UNSPEC, parent, handle, 0,
620*49cdfc7eSAndroid Build Coastguard Worker 		qd_kind, NULL);
621*49cdfc7eSAndroid Build Coastguard Worker }
622*49cdfc7eSAndroid Build Coastguard Worker 
tst_netdev_add_traffic_filter(const char * file,const int lineno,int strict,const char * ifname,unsigned int parent,unsigned int handle,unsigned int protocol,unsigned int priority,const char * f_kind,const struct tst_netlink_attr_list * config)623*49cdfc7eSAndroid Build Coastguard Worker int tst_netdev_add_traffic_filter(const char *file, const int lineno,
624*49cdfc7eSAndroid Build Coastguard Worker 	int strict, const char *ifname, unsigned int parent,
625*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int handle, unsigned int protocol, unsigned int priority,
626*49cdfc7eSAndroid Build Coastguard Worker 	const char *f_kind, const struct tst_netlink_attr_list *config)
627*49cdfc7eSAndroid Build Coastguard Worker {
628*49cdfc7eSAndroid Build Coastguard Worker 	return modify_qdisc(file, lineno, strict, "traffic filter",
629*49cdfc7eSAndroid Build Coastguard Worker 		RTM_NEWTFILTER, NLM_F_CREATE | NLM_F_EXCL, ifname, AF_UNSPEC,
630*49cdfc7eSAndroid Build Coastguard Worker 		parent, handle, TC_H_MAKE(priority << 16, htons(protocol)),
631*49cdfc7eSAndroid Build Coastguard Worker 		f_kind, config);
632*49cdfc7eSAndroid Build Coastguard Worker }
633*49cdfc7eSAndroid Build Coastguard Worker 
tst_netdev_remove_traffic_filter(const char * file,const int lineno,int strict,const char * ifname,unsigned int parent,unsigned int handle,unsigned int protocol,unsigned int priority,const char * f_kind)634*49cdfc7eSAndroid Build Coastguard Worker int tst_netdev_remove_traffic_filter(const char *file, const int lineno,
635*49cdfc7eSAndroid Build Coastguard Worker 	int strict, const char *ifname, unsigned int parent,
636*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int handle, unsigned int protocol, unsigned int priority,
637*49cdfc7eSAndroid Build Coastguard Worker 	const char *f_kind)
638*49cdfc7eSAndroid Build Coastguard Worker {
639*49cdfc7eSAndroid Build Coastguard Worker 	return modify_qdisc(file, lineno, strict, "traffic filter",
640*49cdfc7eSAndroid Build Coastguard Worker 		RTM_DELTFILTER, 0, ifname, AF_UNSPEC, parent, handle,
641*49cdfc7eSAndroid Build Coastguard Worker 		TC_H_MAKE(priority << 16, htons(protocol)), f_kind, NULL);
642*49cdfc7eSAndroid Build Coastguard Worker }
643