1f08c3bdfSopenharmony_ciLTP C Test Network API
2f08c3bdfSopenharmony_ci======================
3f08c3bdfSopenharmony_ci
4f08c3bdfSopenharmony_ciNOTE: See also
5f08c3bdfSopenharmony_ci      https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines[Test Writing Guidelines],
6f08c3bdfSopenharmony_ci      https://github.com/linux-test-project/ltp/wiki/C-Test-Case-Tutorial[C Test Case Tutorial],
7f08c3bdfSopenharmony_ci      https://github.com/linux-test-project/ltp/wiki/C-Test-API[C Test API],
8f08c3bdfSopenharmony_ci      https://github.com/linux-test-project/ltp/wiki/Shell-Test-API[Shell Test API].
9f08c3bdfSopenharmony_ci
10f08c3bdfSopenharmony_ciLTP library includes helper functions for configuring sockets and setting up
11f08c3bdfSopenharmony_cinetwork devices.
12f08c3bdfSopenharmony_ci
13f08c3bdfSopenharmony_ci1 Configuring sockets
14f08c3bdfSopenharmony_ci---------------------
15f08c3bdfSopenharmony_ci
16f08c3bdfSopenharmony_ci1.1 Safe syscall variants
17f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~
18f08c3bdfSopenharmony_ci
19f08c3bdfSopenharmony_ci+#include "tst_safe_net.h"+
20f08c3bdfSopenharmony_ci
21f08c3bdfSopenharmony_ciMost common standard syscalls and libc functions for configuring sockets have a
22f08c3bdfSopenharmony_ci"safe" variant in LTP library which will call +tst_brk()+ if the underlying
23f08c3bdfSopenharmony_cisystem function fails. See
24f08c3bdfSopenharmony_cihttps://github.com/linux-test-project/ltp/wiki/C-Test-API[C Test API]. The
25f08c3bdfSopenharmony_cisafe function names are in uppercase with the +SAFE_+ prefix (e.g. the safe
26f08c3bdfSopenharmony_civariant of +socket()+ is called +SAFE_SOCKET()+). For most safe functions, the
27f08c3bdfSopenharmony_ciparameters and return type are identical to the standard system function:
28f08c3bdfSopenharmony_ci
29f08c3bdfSopenharmony_ci- +SAFE_SOCKET()+
30f08c3bdfSopenharmony_ci- +SAFE_SOCKETPAIR()+
31f08c3bdfSopenharmony_ci- +SAFE_GETSOCKOPT()+
32f08c3bdfSopenharmony_ci- +SAFE_SETSOCKOPT()+
33f08c3bdfSopenharmony_ci- +SAFE_BIND()+
34f08c3bdfSopenharmony_ci- +SAFE_LISTEN()+
35f08c3bdfSopenharmony_ci- +SAFE_ACCEPT()+
36f08c3bdfSopenharmony_ci- +SAFE_CONNECT()+
37f08c3bdfSopenharmony_ci- +SAFE_GETSOCKNAME()+
38f08c3bdfSopenharmony_ci- +SAFE_GETHOSTNAME()+
39f08c3bdfSopenharmony_ci- +SAFE_GETADDRINFO()+
40f08c3bdfSopenharmony_ci
41f08c3bdfSopenharmony_ciA few safe functions have extra parameters for quick return value validation.
42f08c3bdfSopenharmony_ciThe ellipsis (+...+) represents the standard parameters of the underlying system
43f08c3bdfSopenharmony_cifunction:
44f08c3bdfSopenharmony_ci
45f08c3bdfSopenharmony_ci* +SAFE_SEND(char strict, ...)+
46f08c3bdfSopenharmony_ci* +SAFE_SENDTO(char strict, ...)+
47f08c3bdfSopenharmony_ci** If +strict+ is non-zero, the return value must be equal to the data length
48f08c3bdfSopenharmony_ci   argument. Otherwise the test will fail and exit.
49f08c3bdfSopenharmony_ci
50f08c3bdfSopenharmony_ci* +SAFE_SENDMSG(size_t msg_len, ...)+
51f08c3bdfSopenharmony_ci* +SAFE_RECV(size_t msg_len, ...)+
52f08c3bdfSopenharmony_ci* +SAFE_RECVMSG(size_t msg_len, ...)+
53f08c3bdfSopenharmony_ci** If +msg_len+ is non-zero, the return value must be equal to the +msg_len+
54f08c3bdfSopenharmony_ci   argument. Otherwise the test will fail and exit.
55f08c3bdfSopenharmony_ci
56f08c3bdfSopenharmony_ciThere are also some custom functions for simpler configuration and queries:
57f08c3bdfSopenharmony_ci
58f08c3bdfSopenharmony_ci- +int SAFE_SETSOCKOPT_INT(int sockfd, int level, int optname, int value)+ –
59f08c3bdfSopenharmony_ci  Simple setsockopt() variant for passing integers by value.
60f08c3bdfSopenharmony_ci
61f08c3bdfSopenharmony_ci- +int TST_GETSOCKPORT(int sockfd)+ – Get port number (in host byte order) of a
62f08c3bdfSopenharmony_ci  bound socket.
63f08c3bdfSopenharmony_ci
64f08c3bdfSopenharmony_ci- +unsigned short TST_GET_UNUSED_PORT(int family, int type)+ – Get a random
65f08c3bdfSopenharmony_ci  port number (in network byte order) which is currently closed for the given
66f08c3bdfSopenharmony_ci  socket family and type. Note that another application may open the port while
67f08c3bdfSopenharmony_ci  the test is still running. The test user is responsible for setting up test
68f08c3bdfSopenharmony_ci  environment without such interference.
69f08c3bdfSopenharmony_ci
70f08c3bdfSopenharmony_ci1.2 Address conversion functions
71f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
72f08c3bdfSopenharmony_ci
73f08c3bdfSopenharmony_ci+#include "tst_net.h"+
74f08c3bdfSopenharmony_ci
75f08c3bdfSopenharmony_ciLTP library also provides helper functions for quick initialization of socket
76f08c3bdfSopenharmony_ciaddress structures:
77f08c3bdfSopenharmony_ci
78f08c3bdfSopenharmony_ci- +void tst_get_in_addr(const char *ip_str, struct in_addr *ip)+ – Convert
79f08c3bdfSopenharmony_ci  human-readable IPv4 address string +ip_str+ to binary representation in
80f08c3bdfSopenharmony_ci  network byte order. The converted value will be stored in the second argument.
81f08c3bdfSopenharmony_ci
82f08c3bdfSopenharmony_ci- +void tst_get_in6_addr(const char *ip_str, struct in6_addr *ip6)+ – Convert
83f08c3bdfSopenharmony_ci  human-readable IPv6 address string +ip_str+ to binary representation in
84f08c3bdfSopenharmony_ci  network byte order. The converted value will be stored in the second argument.
85f08c3bdfSopenharmony_ci
86f08c3bdfSopenharmony_ci- +socklen_t tst_get_connect_address(int sock, struct sockaddr_storage *addr)+ –
87f08c3bdfSopenharmony_ci  Find the address which can be used to send data to bound socket +sock+ from
88f08c3bdfSopenharmony_ci  another socket. The address will be stored in the second argument. This
89f08c3bdfSopenharmony_ci  function automatically converts wildcard bind address to localhost. Returns
90f08c3bdfSopenharmony_ci  size of the address in bytes.
91f08c3bdfSopenharmony_ci
92f08c3bdfSopenharmony_ci- +void tst_init_sockaddr_inet(struct sockaddr_in *sa, const char *ip_str,
93f08c3bdfSopenharmony_ci  uint16_t port)+ – Initialize socket address structure +sa+ using
94f08c3bdfSopenharmony_ci  human-readable IPv4 address +ip_str+ and port number +port+ in host byte
95f08c3bdfSopenharmony_ci  order.
96f08c3bdfSopenharmony_ci
97f08c3bdfSopenharmony_ci- +void tst_init_sockaddr_inet_bin(struct sockaddr_in *sa, uint32_t ip_val,
98f08c3bdfSopenharmony_ci  uint16_t port)+ – Initialize socket address structure +sa+ using binary IPv4
99f08c3bdfSopenharmony_ci  address +ip_val+ and port number +port+, both in host byte order.
100f08c3bdfSopenharmony_ci
101f08c3bdfSopenharmony_ci- +void tst_init_sockaddr_inet6(struct sockaddr_in6 *sa, const char *ip_str,
102f08c3bdfSopenharmony_ci  uint16_t port)+ – Initialize socket address structure +sa+ using
103f08c3bdfSopenharmony_ci  human-readable IPv6 address +ip_str+ and port number +port+ in host byte
104f08c3bdfSopenharmony_ci  order.
105f08c3bdfSopenharmony_ci
106f08c3bdfSopenharmony_ci- +void tst_init_sockaddr_inet6_bin(struct sockaddr_in6 *sa, const struct
107f08c3bdfSopenharmony_ci  in6_addr *ip_val, uint16_t port)+ – Initialize socket address structure +sa+
108f08c3bdfSopenharmony_ci  using binary IPv6 address +ip_val+ and port number +port+, both in host byte
109f08c3bdfSopenharmony_ci  order.
110f08c3bdfSopenharmony_ci
111f08c3bdfSopenharmony_ci.Example Usage
112f08c3bdfSopenharmony_ci[source,c]
113f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
114f08c3bdfSopenharmony_ci
115f08c3bdfSopenharmony_ci#include <sys/socket.h>
116f08c3bdfSopenharmony_ci#include <netinet/in.h>
117f08c3bdfSopenharmony_ci
118f08c3bdfSopenharmony_ci#include "tst_test.h"
119f08c3bdfSopenharmony_ci#include "tst_safe_net.h"
120f08c3bdfSopenharmony_ci#include "tst_net.h"
121f08c3bdfSopenharmony_ci
122f08c3bdfSopenharmony_cistatic int sockfd = -1;
123f08c3bdfSopenharmony_ci
124f08c3bdfSopenharmony_cistatic void setup(void)
125f08c3bdfSopenharmony_ci{
126f08c3bdfSopenharmony_ci	struct sockaddr_in addr;
127f08c3bdfSopenharmony_ci
128f08c3bdfSopenharmony_ci	tst_init_sockaddr_inet_bin(&addr, INADDR_ANY, 0);
129f08c3bdfSopenharmony_ci	sockfd = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0);
130f08c3bdfSopenharmony_ci	SAFE_SETSOCKOPT_INT(sockfd, SOL_SOCKET, SO_SNDBUF, 4096);
131f08c3bdfSopenharmony_ci	SAFE_BIND(sockfd, (struct sockaddr *)&addr, sizeof(addr));
132f08c3bdfSopenharmony_ci	SAFE_LISTEN(sockfd, 8);
133f08c3bdfSopenharmony_ci}
134f08c3bdfSopenharmony_ci
135f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
136f08c3bdfSopenharmony_ci
137f08c3bdfSopenharmony_ci2 Configuring network devices
138f08c3bdfSopenharmony_ci-----------------------------
139f08c3bdfSopenharmony_ci
140f08c3bdfSopenharmony_ci+#include "tst_netdevice.h"+
141f08c3bdfSopenharmony_ci
142f08c3bdfSopenharmony_ciWhen opening a localhost socket isn't enough and the test needs special device
143f08c3bdfSopenharmony_cior routing configuration, the netdevice library can create the required network
144f08c3bdfSopenharmony_cisetup without calling external programs. Internally, the netdevice functions
145f08c3bdfSopenharmony_ciuse a rtnetlink socket to communicate with the kernel.
146f08c3bdfSopenharmony_ci
147f08c3bdfSopenharmony_ciAll of these functions will call +tst_brk()+ on failure, unless stated
148f08c3bdfSopenharmony_ciotherwise. Error values described below are returned only during test cleanup
149f08c3bdfSopenharmony_cistage.
150f08c3bdfSopenharmony_ci
151f08c3bdfSopenharmony_ci2.1 Network device management
152f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
153f08c3bdfSopenharmony_ci
154f08c3bdfSopenharmony_ci- +int NETDEV_INDEX_BY_NAME(const char *ifname)+ – Returns the device index for
155f08c3bdfSopenharmony_ci  the given device name, or -1 on error.
156f08c3bdfSopenharmony_ci
157f08c3bdfSopenharmony_ci- +int NETDEV_SET_STATE(const char *ifname, int up)+ – Enable or disable a
158f08c3bdfSopenharmony_ci  network device +ifname+. Returns 0 on success, -1 on error.
159f08c3bdfSopenharmony_ci
160f08c3bdfSopenharmony_ci- +int CREATE_VETH_PAIR(const char *ifname1, const char *ifname2)+ – Creates a
161f08c3bdfSopenharmony_ci  connected pair of virtual network devices with given device names. Returns 1
162f08c3bdfSopenharmony_ci  on success, 0 on error. Add +"CONFIG_VETH"+ to +test.needs_kconfigs+ if your
163f08c3bdfSopenharmony_ci  test calls this function.
164f08c3bdfSopenharmony_ci
165f08c3bdfSopenharmony_ci- +int NETDEV_ADD_DEVICE(const char *ifname, const char *devtype)+ - Creates
166f08c3bdfSopenharmony_ci  a new network device named +ifname+ of specified device type. Returns 1 on
167f08c3bdfSopenharmony_ci  success, 0 on error.
168f08c3bdfSopenharmony_ci
169f08c3bdfSopenharmony_ci- +int NETDEV_REMOVE_DEVICE(const char *ifname)+ – Removes network device
170f08c3bdfSopenharmony_ci  +ifname+. Returns 1 on success, 0 on error.
171f08c3bdfSopenharmony_ci
172f08c3bdfSopenharmony_ci2.2 Network address management
173f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
174f08c3bdfSopenharmony_ci
175f08c3bdfSopenharmony_ci- +int NETDEV_ADD_ADDRESS(const char \*ifname, unsigned int family, const void
176f08c3bdfSopenharmony_ci  *address, unsigned int prefix, size_t addrlen, unsigned int flags)+ – Adds
177f08c3bdfSopenharmony_ci  new address to network device +ifname+. This is a low-level function which
178f08c3bdfSopenharmony_ci  allows setting any type of address. You must specify the protocol +family+,
179f08c3bdfSopenharmony_ci  address length in bytes (+addrlen+) and network prefix length (+prefix+). The
180f08c3bdfSopenharmony_ci  +address+ itself must be in binary representation in network byte order. You
181f08c3bdfSopenharmony_ci  can also pass rtnetlink flags from the +IFA_F_*+ group. Returns 1 on success,
182f08c3bdfSopenharmony_ci  0 on error.
183f08c3bdfSopenharmony_ci
184f08c3bdfSopenharmony_ci- +int NETDEV_ADD_ADDRESS_INET(const char *ifname, in_addr_t address, unsigned
185f08c3bdfSopenharmony_ci  int prefix, unsigned int flags)+ – Adds new IPv4 address to network device
186f08c3bdfSopenharmony_ci  +ifname+. Parameters have the same meaning as in +NETDEV_ADD_ADDRESS()+.
187f08c3bdfSopenharmony_ci  Returns 1 on success, 0 on error.
188f08c3bdfSopenharmony_ci
189f08c3bdfSopenharmony_ci- +int NETDEV_REMOVE_ADDRESS(const char *ifname, unsigned int family, const
190f08c3bdfSopenharmony_ci  void *address, size_t addrlen)+ – Removes the specified address from network
191f08c3bdfSopenharmony_ci  device +ifname+. Parameters have the same meaning as in
192f08c3bdfSopenharmony_ci  +NETDEV_ADD_ADDRESS()+. Returns 1 on success, 0 on error.
193f08c3bdfSopenharmony_ci
194f08c3bdfSopenharmony_ci- +int NETDEV_REMOVE_ADDRESS_INET(const char *ifname, in_addr_t address)+ –
195f08c3bdfSopenharmony_ci  Removes specified IPv4 +address+ (in network byte order) from network device
196f08c3bdfSopenharmony_ci  +ifname+. Returns 1 on success, 0 on error.
197f08c3bdfSopenharmony_ci
198f08c3bdfSopenharmony_ci2.3 Network namespace device assignment
199f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
200f08c3bdfSopenharmony_ci
201f08c3bdfSopenharmony_ciWARNING: Moving a network device to another namespace will erase previous
202f08c3bdfSopenharmony_ci         configuration. Move the device to the correct namespace first, then
203f08c3bdfSopenharmony_ci         configure it.
204f08c3bdfSopenharmony_ci
205f08c3bdfSopenharmony_ci- +int NETDEV_CHANGE_NS_FD(const char *ifname, int nsfd)+ – Moves network
206f08c3bdfSopenharmony_ci  device +ifname+ to network namespace designated by open file descriptor
207f08c3bdfSopenharmony_ci  +nsfd+. Returns 1 on success, 0 on error.
208f08c3bdfSopenharmony_ci
209f08c3bdfSopenharmony_ci- +int NETDEV_CHANGE_NS_PID(const char *ifname, pid_t nspid)+ – Moves network
210f08c3bdfSopenharmony_ci  device +ifname+ to the network namespace currently used by process +nspid+.
211f08c3bdfSopenharmony_ci  Returns 1 on success, 0 on error.
212f08c3bdfSopenharmony_ci
213f08c3bdfSopenharmony_ci2.4 Routing table management
214f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~
215f08c3bdfSopenharmony_ci
216f08c3bdfSopenharmony_ci- +int NETDEV_ADD_ROUTE(const char *ifname, unsigned int family, const void
217f08c3bdfSopenharmony_ci  *srcaddr, unsigned int srcprefix, size_t srclen, const void *dstaddr,
218f08c3bdfSopenharmony_ci  unsigned int dstprefix, size_t dstlen, const void *gateway, size_t
219f08c3bdfSopenharmony_ci  gatewaylen)+ – Adds new route to the main routing table. This is a low-level
220f08c3bdfSopenharmony_ci  function which allows creating routes for any protocol. You must specify the
221f08c3bdfSopenharmony_ci  protocol +family+ and either network device name +ifname+ or +gateway+
222f08c3bdfSopenharmony_ci  address. Both packet source address +srcaddr+ and destination address
223f08c3bdfSopenharmony_ci  +dstaddr+ are optional. You must also specify the corresponding length
224f08c3bdfSopenharmony_ci  and prefix argument for any address which is not +NULL+. All addresses must
225f08c3bdfSopenharmony_ci  be in binary representation in network byte order. Returns 1 on success,
226f08c3bdfSopenharmony_ci  0 on error.
227f08c3bdfSopenharmony_ci
228f08c3bdfSopenharmony_ci- +int NETDEV_ADD_ROUTE_INET(const char *ifname, in_addr_t srcaddr, unsigned
229f08c3bdfSopenharmony_ci  int srcprefix, in_addr_t dstaddr, unsigned int dstprefix, in_addr_t
230f08c3bdfSopenharmony_ci  gateway)+ – Adds new IPv4 route to the main routing table. Parameters have
231f08c3bdfSopenharmony_ci  the same meaning as in +NETDEV_ADD_ROUTE()+. If you do not want to set
232f08c3bdfSopenharmony_ci  explicit +gateway+ address, set it to 0. If the routing rule should ignore
233f08c3bdfSopenharmony_ci  the source or destination address, set the corresponding prefix argument
234f08c3bdfSopenharmony_ci  to 0. Returns 1 on success, 0 on error.
235f08c3bdfSopenharmony_ci
236f08c3bdfSopenharmony_ci- +int NETDEV_REMOVE_ROUTE(const char *ifname, unsigned int family, const void
237f08c3bdfSopenharmony_ci  *srcaddr, unsigned int srcprefix, size_t srclen, const void *dstaddr,
238f08c3bdfSopenharmony_ci  unsigned int dstprefix, size_t dstlen, const void *gateway, size_t
239f08c3bdfSopenharmony_ci  gatewaylen)+ – Removes a route from the main routing table. Parameters have
240f08c3bdfSopenharmony_ci  the same meaning as in +NETDEV_ADD_ROUTE()+. Returns 1 on success, 0 on
241f08c3bdfSopenharmony_ci  error.
242f08c3bdfSopenharmony_ci
243f08c3bdfSopenharmony_ci- +int NETDEV_REMOVE_ROUTE_INET(const char *ifname, in_addr_t srcaddr,
244f08c3bdfSopenharmony_ci  unsigned int srcprefix, in_addr_t dstaddr, unsigned int dstprefix, in_addr_t
245f08c3bdfSopenharmony_ci  gateway)+ – Removes IPv4 route from the main routing table. Parameters have
246f08c3bdfSopenharmony_ci  the same meaning as in +NETDEV_ADD_ROUTE_INET()+. Returns 1 on success,
247f08c3bdfSopenharmony_ci  0 on error.
248f08c3bdfSopenharmony_ci
249f08c3bdfSopenharmony_ci.Example Usage
250f08c3bdfSopenharmony_ci[source,c]
251f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
252f08c3bdfSopenharmony_ci#include <arpa/inet.h>
253f08c3bdfSopenharmony_ci#include <linux/if_addr.h>
254f08c3bdfSopenharmony_ci#include "tst_test.h"
255f08c3bdfSopenharmony_ci#include "tst_netdevice.h"
256f08c3bdfSopenharmony_ci
257f08c3bdfSopenharmony_ci...
258f08c3bdfSopenharmony_ci
259f08c3bdfSopenharmony_cistatic void setup(void)
260f08c3bdfSopenharmony_ci{
261f08c3bdfSopenharmony_ci	CREATE_VETH_PAIR("ltp_veth1", "ltp_veth2");
262f08c3bdfSopenharmony_ci	NETDEV_ADD_ADDRESS_INET("ltp_veth2", htonl(DSTADDR), NETMASK,
263f08c3bdfSopenharmony_ci		IFA_F_NOPREFIXROUTE);
264f08c3bdfSopenharmony_ci	NETDEV_SET_STATE("ltp_veth2", 1);
265f08c3bdfSopenharmony_ci	NETDEV_ADD_ROUTE_INET("ltp_veth2", 0, 0, htonl(SRCNET), NETMASK, 0);
266f08c3bdfSopenharmony_ci
267f08c3bdfSopenharmony_ci	NETDEV_ADD_ADDRESS_INET("ltp_veth1", htonl(SRCADDR), NETMASK,
268f08c3bdfSopenharmony_ci		IFA_F_NOPREFIXROUTE);
269f08c3bdfSopenharmony_ci	NETDEV_SET_STATE("ltp_veth1", 1);
270f08c3bdfSopenharmony_ci	NETDEV_ADD_ROUTE_INET("ltp_veth1", 0, 0, htonl(DSTNET), NETMASK, 0);
271f08c3bdfSopenharmony_ci	...
272f08c3bdfSopenharmony_ci}
273f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
274f08c3bdfSopenharmony_ci
275f08c3bdfSopenharmony_ci3 rtnetlink API
276f08c3bdfSopenharmony_ci---------------
277f08c3bdfSopenharmony_ci
278f08c3bdfSopenharmony_ci+#include "tst_rtnetlink.h"+
279f08c3bdfSopenharmony_ci
280f08c3bdfSopenharmony_ciThe rtnetlink library provides helper functions for constructing and sending
281f08c3bdfSopenharmony_ciarbitrary messages and parsing kernel responses.
282f08c3bdfSopenharmony_ci
283f08c3bdfSopenharmony_ciAll of the functions below will call +tst_brk()+ on failure, unless stated
284f08c3bdfSopenharmony_ciotherwise. Error values described below are returned only during test cleanup
285f08c3bdfSopenharmony_cistage.
286f08c3bdfSopenharmony_ci
287f08c3bdfSopenharmony_ci3.1 Data structures
288f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~
289f08c3bdfSopenharmony_ci
290f08c3bdfSopenharmony_ci[source,c]
291f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
292f08c3bdfSopenharmony_cistruct tst_rtnl_context;
293f08c3bdfSopenharmony_ci
294f08c3bdfSopenharmony_cistruct tst_rtnl_attr_list {
295f08c3bdfSopenharmony_ci	unsigned short type;
296f08c3bdfSopenharmony_ci	const void *data;
297f08c3bdfSopenharmony_ci	ssize_t len;
298f08c3bdfSopenharmony_ci	const struct tst_rtnl_attr_list *sublist;
299f08c3bdfSopenharmony_ci};
300f08c3bdfSopenharmony_ci
301f08c3bdfSopenharmony_cistruct tst_rtnl_message {
302f08c3bdfSopenharmony_ci	struct nlmsghdr *header;
303f08c3bdfSopenharmony_ci	struct nlmsgerr *err;
304f08c3bdfSopenharmony_ci	void *payload;
305f08c3bdfSopenharmony_ci	size_t payload_size;
306f08c3bdfSopenharmony_ci};
307f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
308f08c3bdfSopenharmony_ci
309f08c3bdfSopenharmony_ci+struct tst_rtnl_context+ is an opaque rtnetlink socket with buffer for
310f08c3bdfSopenharmony_ciconstructing and sending arbitrary messages using the functions described
311f08c3bdfSopenharmony_cibelow. Create a new context using +RTNL_CREATE_CONTEXT()+, then free it using
312f08c3bdfSopenharmony_ci+RTNL_DESTROY_CONTEXT()+ when you're done with it.
313f08c3bdfSopenharmony_ci
314f08c3bdfSopenharmony_ci+struct tst_rtnl_attr_list+ is a helper structure for defining complex
315f08c3bdfSopenharmony_cirtnetlink message attribute payloads, including nested attribute lists. Every
316f08c3bdfSopenharmony_cilist and sublist defined using this structure is terminated by item with
317f08c3bdfSopenharmony_cinegative +len+.
318f08c3bdfSopenharmony_ci
319f08c3bdfSopenharmony_ci- +type+ is the attribute type that will be stored in +struct rtattr.rta_type+.
320f08c3bdfSopenharmony_ci
321f08c3bdfSopenharmony_ci- +data+ contains arbitrary attribute payload.
322f08c3bdfSopenharmony_ci
323f08c3bdfSopenharmony_ci- +len+ contains length of the +data+ attribute in bytes. If +data+ is +NULL+,
324f08c3bdfSopenharmony_ci  set +len+ to 0. The last item in a list or sublist must have negative length.
325f08c3bdfSopenharmony_ci
326f08c3bdfSopenharmony_ci- +sublist+ contains a nested attribute list which will be appended after
327f08c3bdfSopenharmony_ci  +data+ as part of the attribute payload. +struct rtattr.rta_len+ will be
328f08c3bdfSopenharmony_ci  calculated automatically with proper alignment, do _not_ add the sublist size
329f08c3bdfSopenharmony_ci  to the +len+ field. If you do not want to add nested attributes, set
330f08c3bdfSopenharmony_ci  +sublist+ to +NULL+.
331f08c3bdfSopenharmony_ci
332f08c3bdfSopenharmony_ci+struct tst_rtnl_message+ is a structure holding partially parsed rtnetlink
333f08c3bdfSopenharmony_cimessages received from the kernel. +RTNL_RECV()+ returns an array of these
334f08c3bdfSopenharmony_cistructures with the last item having +NULL+ in the +header+ field. Call
335f08c3bdfSopenharmony_ci+RTNL_FREE_MESSAGE()+ to free a message list returned by +RTNL_RECV()+.
336f08c3bdfSopenharmony_ci
337f08c3bdfSopenharmony_ci- +header+ is the netlink header structure of the message. +NULL+ in the header
338f08c3bdfSopenharmony_ci  field terminates a list of messages.
339f08c3bdfSopenharmony_ci
340f08c3bdfSopenharmony_ci- +err+ points to the payload of +NLMSG_ERROR+ messages. It is set to +NULL+
341f08c3bdfSopenharmony_ci  for all other message types.
342f08c3bdfSopenharmony_ci
343f08c3bdfSopenharmony_ci- +payload+ is a pointer to message data.
344f08c3bdfSopenharmony_ci
345f08c3bdfSopenharmony_ci- +payload_size+ is the length of +payload+ data in bytes.
346f08c3bdfSopenharmony_ci
347f08c3bdfSopenharmony_ci3.2 Sending and receiving messages
348f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
349f08c3bdfSopenharmony_ci
350f08c3bdfSopenharmony_ci- +struct tst_rtnl_context *RTNL_CREATE_CONTEXT(void)+ – Creates a new
351f08c3bdfSopenharmony_ci  rtnetlink communication context for use with the functions described below.
352f08c3bdfSopenharmony_ci  Returns +NULL+ on error.
353f08c3bdfSopenharmony_ci
354f08c3bdfSopenharmony_ci- +void RTNL_FREE_MESSAGE(struct tst_rtnl_message *msg)+ – Frees an array of
355f08c3bdfSopenharmony_ci  messages returned by +RTNL_RECV()+.
356f08c3bdfSopenharmony_ci
357f08c3bdfSopenharmony_ci- +void RTNL_DESTROY_CONTEXT(struct tst_rtnl_context *ctx)+ – Closes a
358f08c3bdfSopenharmony_ci  communication context created by +RTNL_CREATE_CONTEXT()+.
359f08c3bdfSopenharmony_ci
360f08c3bdfSopenharmony_ci- +int RTNL_SEND(struct tst_rtnl_context *ctx)+ – Sends all messages waiting
361f08c3bdfSopenharmony_ci  in +ctx+ buffer to the kernel. If there are multiple messages to send, a new
362f08c3bdfSopenharmony_ci  +NLMSG_DONE+ message will be added automatically. Returns the number of
363f08c3bdfSopenharmony_ci  bytes sent on success. Return 0 or negative value on error.
364f08c3bdfSopenharmony_ci
365f08c3bdfSopenharmony_ci- +int RTNL_SEND_VALIDATE(struct tst_rtnl_context *ctx)+ – Sends all messages
366f08c3bdfSopenharmony_ci  just like +RTNL_SEND()+, then receives the response from the kernel and
367f08c3bdfSopenharmony_ci  validates results of requests sent with the +NLM_F_ACK+ flag. This function
368f08c3bdfSopenharmony_ci  calls +tst_brk()+ as usual if communication fails but it will return error
369f08c3bdfSopenharmony_ci  status without terminating the test if one of the received messages contains
370f08c3bdfSopenharmony_ci  error code. See +RTNL_CHECK_ACKS()+ below for explanation of the return
371f08c3bdfSopenharmony_ci  value.
372f08c3bdfSopenharmony_ci
373f08c3bdfSopenharmony_ci- +int RTNL_WAIT(struct tst_rtnl_context *ctx)+ – Waits until data becomes
374f08c3bdfSopenharmony_ci  available to read from the rtnetlink socket (timeout: 1 second). Returns 1
375f08c3bdfSopenharmony_ci  if there is data to read, 0 on timeout or -1 on error.
376f08c3bdfSopenharmony_ci
377f08c3bdfSopenharmony_ci- +struct tst_rtnl_message *RTNL_RECV(struct tst_rtnl_context *ctx)+ – Receives
378f08c3bdfSopenharmony_ci  rtnetlink messages from the kernel. The messages are received in non-blocking
379f08c3bdfSopenharmony_ci  mode so calling +RTNL_WAIT()+ first is recommended. Returns an array of
380f08c3bdfSopenharmony_ci  partially parsed messages terminated by an item with +NULL+ in the +header+
381f08c3bdfSopenharmony_ci  field. On error or when there are no messages to receive, returns +NULL+.
382f08c3bdfSopenharmony_ci  Call +RTNL_FREE_MESSAGE()+ to free the returned data.
383f08c3bdfSopenharmony_ci
384f08c3bdfSopenharmony_ci- +int RTNL_CHECK_ACKS(struct tst_rtnl_context *ctx, struct tst_rtnl_message
385f08c3bdfSopenharmony_ci  *response)+ – Validate results of requests sent with the +NLM_F_ACK+ flag.
386f08c3bdfSopenharmony_ci  Do not call +RTNL_ADD_MESSAGE()+ between +RTNL_SEND()+ and
387f08c3bdfSopenharmony_ci  +RTNL_CHECK_ACKS()+ because it will reset the state of +ctx+ and prevent
388f08c3bdfSopenharmony_ci  result validation. Returns 1 if all messages sent with the +NLM_F_ACK+ flag
389f08c3bdfSopenharmony_ci  have a corresponding message in +response+ and the error code is 0. If any
390f08c3bdfSopenharmony_ci  of the expected response messages is missing, this function will call
391f08c3bdfSopenharmony_ci  +tst_brk()+ (or return 0 during test cleanup phase). If any of the response
392f08c3bdfSopenharmony_ci  messages has non-zero error code, this function will return 0 and store the
393f08c3bdfSopenharmony_ci  first non-zero error code in global variable +tst_rtnl_errno+ (sign-flipped
394f08c3bdfSopenharmony_ci  just like regular libc +errno+).
395f08c3bdfSopenharmony_ci
396f08c3bdfSopenharmony_ci3.3 Creating messages
397f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~
398f08c3bdfSopenharmony_ci
399f08c3bdfSopenharmony_ci- +int RTNL_ADD_MESSAGE(struct tst_rtnl_context *ctx, const struct nlmsghdr
400f08c3bdfSopenharmony_ci  *header, const void *payload, size_t payload_size)+ – Adds new rtnetlink
401f08c3bdfSopenharmony_ci  message to +ctx+ buffer. You need to provide message +header+ and optional
402f08c3bdfSopenharmony_ci  +payload+. +payload_size+ is the size of +payload+ data in bytes. If you
403f08c3bdfSopenharmony_ci  don't want to add any payload data, set +payload+ to +NULL+ and
404f08c3bdfSopenharmony_ci  +payload_size+ to 0. This function will automatically fill the +nlmsg_len+,
405f08c3bdfSopenharmony_ci  +nlmsg_seq+ and +nlmsg_pid+ fields of the new message header. You don't need
406f08c3bdfSopenharmony_ci  to set those. It'll also automatically add +NLM_F_MULTI+ flag when needed.
407f08c3bdfSopenharmony_ci  Returns 1 on success, 0 on error. Note that the first call of
408f08c3bdfSopenharmony_ci  +RTNL_ADD_MESSAGE()+ after +RTNL_SEND()+ will reset the state of +ctx+
409f08c3bdfSopenharmony_ci  and +RTNL_CHECK_ACKS()+ will not work correctly until the next +RTNL_SEND()+.
410f08c3bdfSopenharmony_ci
411f08c3bdfSopenharmony_ci- +int RTNL_ADD_ATTR(struct tst_rtnl_context *ctx, unsigned short type, const
412f08c3bdfSopenharmony_ci  void *data, unsigned short len)+ – Adds new attribute to the last message
413f08c3bdfSopenharmony_ci  in +ctx+ buffer. See +RTNL_ADD_MESSAGE()+. You need to provide attribute
414f08c3bdfSopenharmony_ci  +type+ which will be stored in +struct rtattr.rta_type+, optional payload
415f08c3bdfSopenharmony_ci  +data+ and payload size +len+ in bytes. If you don't want to add any payload,
416f08c3bdfSopenharmony_ci  set +data+ to +NULL+ and +len+ to 0. Returns 1 on success, 0 on error.
417f08c3bdfSopenharmony_ci
418f08c3bdfSopenharmony_ci- +int RTNL_ADD_ATTR_STRING(struct tst_rtnl_context *ctx, unsigned short type,
419f08c3bdfSopenharmony_ci  const char *data)+ – Adds new string attribute to the last message in +ctx+
420f08c3bdfSopenharmony_ci  buffer. Parameters and return value are the same as for +RTNL_ADD_ATTR()+,
421f08c3bdfSopenharmony_ci  except the payload length is calculated using +strlen()+.
422f08c3bdfSopenharmony_ci
423f08c3bdfSopenharmony_ci- +int RTNL_ADD_ATTR_LIST(struct tst_rtnl_context *ctx, const struct
424f08c3bdfSopenharmony_ci  tst_rtnl_attr_list *list)+ – Adds a list of attributes to the last message
425f08c3bdfSopenharmony_ci  in +ctx+ buffer. See description of +struct tst_rtnl_attr_list+ and
426f08c3bdfSopenharmony_ci  +RTNL_ADD_MESSAGE()+ above.  Returns the number of added attributes on
427f08c3bdfSopenharmony_ci  success (nested attributes are not counted), -1 on error.
428f08c3bdfSopenharmony_ci
429f08c3bdfSopenharmony_ci.Example Usage
430f08c3bdfSopenharmony_ci[source,c]
431f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
432f08c3bdfSopenharmony_ci#include <asm/types.h>
433f08c3bdfSopenharmony_ci#include <linux/netlink.h>
434f08c3bdfSopenharmony_ci#include <linux/rtnetlink.h>
435f08c3bdfSopenharmony_ci#include <sys/socket.h>
436f08c3bdfSopenharmony_ci#include <netinet/in.h>
437f08c3bdfSopenharmony_ci#include <arpa/inet.h>
438f08c3bdfSopenharmony_ci
439f08c3bdfSopenharmony_ci#include "tst_test.h"
440f08c3bdfSopenharmony_ci#include "tst_rtnetlink.h"
441f08c3bdfSopenharmony_ci#include "tst_netdevice.h"
442f08c3bdfSopenharmony_ci
443f08c3bdfSopenharmony_ci...
444f08c3bdfSopenharmony_ci
445f08c3bdfSopenharmony_civoid setup(void)
446f08c3bdfSopenharmony_ci{
447f08c3bdfSopenharmony_ci	struct tst_rtnl_context *ctx;
448f08c3bdfSopenharmony_ci	int index, ret;
449f08c3bdfSopenharmony_ci	in_addr_t addr;
450f08c3bdfSopenharmony_ci
451f08c3bdfSopenharmony_ci	struct nlmsghdr header = {
452f08c3bdfSopenharmony_ci		.nlmsg_type = RTM_NEWADDR,
453f08c3bdfSopenharmony_ci		.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE |
454f08c3bdfSopenharmony_ci			NLM_F_EXCL
455f08c3bdfSopenharmony_ci	};
456f08c3bdfSopenharmony_ci
457f08c3bdfSopenharmony_ci	struct ifaddrmsg info = {
458f08c3bdfSopenharmony_ci		.ifa_family = AF_INET,
459f08c3bdfSopenharmony_ci		.ifa_prefixlen = 24
460f08c3bdfSopenharmony_ci	};
461f08c3bdfSopenharmony_ci
462f08c3bdfSopenharmony_ci	index = NETDEV_INDEX_BY_NAME("ltp_veth1");
463f08c3bdfSopenharmony_ci	info.ifa_index = index;
464f08c3bdfSopenharmony_ci
465f08c3bdfSopenharmony_ci	ctx = RTNL_CREATE_CONTEXT();
466f08c3bdfSopenharmony_ci	RTNL_ADD_MESSAGE(ctx, &header, &info, sizeof(info));
467f08c3bdfSopenharmony_ci	addr = inet_addr("192.168.123.45");
468f08c3bdfSopenharmony_ci	RTNL_ADD_ATTR(ctx, IFA_LOCAL, &addr, sizeof(addr));
469f08c3bdfSopenharmony_ci	ret = RTNL_SEND_VALIDATE(ctx);
470f08c3bdfSopenharmony_ci	RTNL_DESTROY_CONTEXT(ctx);
471f08c3bdfSopenharmony_ci
472f08c3bdfSopenharmony_ci	if (!ret) {
473f08c3bdfSopenharmony_ci		tst_brk(TBROK, "Failed to set ltp_veth1 address");
474f08c3bdfSopenharmony_ci	}
475f08c3bdfSopenharmony_ci}
476f08c3bdfSopenharmony_ci-------------------------------------------------------------------------------
477