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