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 rtnetlink 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 rtnetlink API
278---------------
279
280+#include "tst_rtnetlink.h"+
281
282The rtnetlink 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_rtnl_context;
295
296struct tst_rtnl_attr_list {
297	unsigned short type;
298	const void *data;
299	ssize_t len;
300	const struct tst_rtnl_attr_list *sublist;
301};
302
303struct tst_rtnl_message {
304	struct nlmsghdr *header;
305	struct nlmsgerr *err;
306	void *payload;
307	size_t payload_size;
308};
309-------------------------------------------------------------------------------
310
311+struct tst_rtnl_context+ is an opaque rtnetlink socket with buffer for
312constructing and sending arbitrary messages using the functions described
313below. Create a new context using +RTNL_CREATE_CONTEXT()+, then free it using
314+RTNL_DESTROY_CONTEXT()+ when you're done with it.
315
316+struct tst_rtnl_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 rtattr.rta_type+.
322
323- +data+ contains arbitrary attribute payload.
324
325- +len+ contains length of the +data+ attribute in bytes. If +data+ is +NULL+,
326  set +len+ to 0. The last item in a list or sublist must have negative length.
327
328- +sublist+ contains a nested attribute list which will be appended after
329  +data+ as part of the attribute payload. +struct rtattr.rta_len+ will be
330  calculated automatically with proper alignment, do _not_ add the sublist size
331  to the +len+ field. If you do not want to add nested attributes, set
332  +sublist+ to +NULL+.
333
334+struct tst_rtnl_message+ is a structure holding partially parsed rtnetlink
335messages received from the kernel. +RTNL_RECV()+ returns an array of these
336structures with the last item having +NULL+ in the +header+ field. Call
337+RTNL_FREE_MESSAGE()+ to free a message list returned by +RTNL_RECV()+.
338
339- +header+ is the netlink header structure of the message. +NULL+ in the header
340  field terminates a list of messages.
341
342- +err+ points to the payload of +NLMSG_ERROR+ messages. It is set to +NULL+
343  for all other message types.
344
345- +payload+ is a pointer to message data.
346
347- +payload_size+ is the length of +payload+ data in bytes.
348
3493.2 Sending and receiving messages
350~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
351
352- +struct tst_rtnl_context *RTNL_CREATE_CONTEXT(void)+ – Creates a new
353  rtnetlink communication context for use with the functions described below.
354  Returns +NULL+ on error.
355
356- +void RTNL_FREE_MESSAGE(struct tst_rtnl_message *msg)+ – Frees an array of
357  messages returned by +RTNL_RECV()+.
358
359- +void RTNL_DESTROY_CONTEXT(struct tst_rtnl_context *ctx)+ – Closes a
360  communication context created by +RTNL_CREATE_CONTEXT()+.
361
362- +int RTNL_SEND(struct tst_rtnl_context *ctx)+ – Sends all messages waiting
363  in +ctx+ buffer to the kernel. If there are multiple messages to send, a new
364  +NLMSG_DONE+ message will be added automatically. Returns the number of
365  bytes sent on success. Return 0 or negative value on error.
366
367- +int RTNL_SEND_VALIDATE(struct tst_rtnl_context *ctx)+ – Sends all messages
368  just like +RTNL_SEND()+, then receives the response from the kernel and
369  validates results of requests sent with the +NLM_F_ACK+ flag. This function
370  calls +tst_brk()+ as usual if communication fails but it will return error
371  status without terminating the test if one of the received messages contains
372  error code. See +RTNL_CHECK_ACKS()+ below for explanation of the return
373  value.
374
375- +int RTNL_WAIT(struct tst_rtnl_context *ctx)+ – Waits until data becomes
376  available to read from the rtnetlink socket (timeout: 1 second). Returns 1
377  if there is data to read, 0 on timeout or -1 on error.
378
379- +struct tst_rtnl_message *RTNL_RECV(struct tst_rtnl_context *ctx)+ – Receives
380  rtnetlink messages from the kernel. The messages are received in non-blocking
381  mode so calling +RTNL_WAIT()+ first is recommended. Returns an array of
382  partially parsed messages terminated by an item with +NULL+ in the +header+
383  field. On error or when there are no messages to receive, returns +NULL+.
384  Call +RTNL_FREE_MESSAGE()+ to free the returned data.
385
386- +int RTNL_CHECK_ACKS(struct tst_rtnl_context *ctx, struct tst_rtnl_message
387  *response)+ – Validate results of requests sent with the +NLM_F_ACK+ flag.
388  Do not call +RTNL_ADD_MESSAGE()+ between +RTNL_SEND()+ and
389  +RTNL_CHECK_ACKS()+ because it will reset the state of +ctx+ and prevent
390  result validation. Returns 1 if all messages sent with the +NLM_F_ACK+ flag
391  have a corresponding message in +response+ and the error code is 0. If any
392  of the expected response messages is missing, this function will call
393  +tst_brk()+ (or return 0 during test cleanup phase). If any of the response
394  messages has non-zero error code, this function will return 0 and store the
395  first non-zero error code in global variable +tst_rtnl_errno+ (sign-flipped
396  just like regular libc +errno+).
397
3983.3 Creating messages
399~~~~~~~~~~~~~~~~~~~~~
400
401- +int RTNL_ADD_MESSAGE(struct tst_rtnl_context *ctx, const struct nlmsghdr
402  *header, const void *payload, size_t payload_size)+ – Adds new rtnetlink
403  message to +ctx+ buffer. You need to provide message +header+ and optional
404  +payload+. +payload_size+ is the size of +payload+ data in bytes. If you
405  don't want to add any payload data, set +payload+ to +NULL+ and
406  +payload_size+ to 0. This function will automatically fill the +nlmsg_len+,
407  +nlmsg_seq+ and +nlmsg_pid+ fields of the new message header. You don't need
408  to set those. It'll also automatically add +NLM_F_MULTI+ flag when needed.
409  Returns 1 on success, 0 on error. Note that the first call of
410  +RTNL_ADD_MESSAGE()+ after +RTNL_SEND()+ will reset the state of +ctx+
411  and +RTNL_CHECK_ACKS()+ will not work correctly until the next +RTNL_SEND()+.
412
413- +int RTNL_ADD_ATTR(struct tst_rtnl_context *ctx, unsigned short type, const
414  void *data, unsigned short len)+ – Adds new attribute to the last message
415  in +ctx+ buffer. See +RTNL_ADD_MESSAGE()+. You need to provide attribute
416  +type+ which will be stored in +struct rtattr.rta_type+, optional payload
417  +data+ and payload size +len+ in bytes. If you don't want to add any payload,
418  set +data+ to +NULL+ and +len+ to 0. Returns 1 on success, 0 on error.
419
420- +int RTNL_ADD_ATTR_STRING(struct tst_rtnl_context *ctx, unsigned short type,
421  const char *data)+ – Adds new string attribute to the last message in +ctx+
422  buffer. Parameters and return value are the same as for +RTNL_ADD_ATTR()+,
423  except the payload length is calculated using +strlen()+.
424
425- +int RTNL_ADD_ATTR_LIST(struct tst_rtnl_context *ctx, const struct
426  tst_rtnl_attr_list *list)+ – Adds a list of attributes to the last message
427  in +ctx+ buffer. See description of +struct tst_rtnl_attr_list+ and
428  +RTNL_ADD_MESSAGE()+ above.  Returns the number of added attributes on
429  success (nested attributes are not counted), -1 on error.
430
431Example Usage
432+++++++++++++
433[source,c]
434-------------------------------------------------------------------------------
435#include <asm/types.h>
436#include <linux/netlink.h>
437#include <linux/rtnetlink.h>
438#include <sys/socket.h>
439#include <netinet/in.h>
440#include <arpa/inet.h>
441
442#include "tst_test.h"
443#include "tst_rtnetlink.h"
444#include "tst_netdevice.h"
445
446...
447
448void setup(void)
449{
450	struct tst_rtnl_context *ctx;
451	int index, ret;
452	in_addr_t addr;
453
454	struct nlmsghdr header = {
455		.nlmsg_type = RTM_NEWADDR,
456		.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE |
457			NLM_F_EXCL
458	};
459
460	struct ifaddrmsg info = {
461		.ifa_family = AF_INET,
462		.ifa_prefixlen = 24
463	};
464
465	index = NETDEV_INDEX_BY_NAME("ltp_veth1");
466	info.ifa_index = index;
467
468	ctx = RTNL_CREATE_CONTEXT();
469	RTNL_ADD_MESSAGE(ctx, &header, &info, sizeof(info));
470	addr = inet_addr("192.168.123.45");
471	RTNL_ADD_ATTR(ctx, IFA_LOCAL, &addr, sizeof(addr));
472	ret = RTNL_SEND_VALIDATE(ctx);
473	RTNL_DESTROY_CONTEXT(ctx);
474
475	if (!ret) {
476		tst_brk(TBROK, "Failed to set ltp_veth1 address");
477	}
478}
479-------------------------------------------------------------------------------
480