• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
111.Example Usage
112[source,c]
113-------------------------------------------------------------------------------
114
115#include <sys/socket.h>
116#include <netinet/in.h>
117
118#include "tst_test.h"
119#include "tst_safe_net.h"
120#include "tst_net.h"
121
122static int sockfd = -1;
123
124static void setup(void)
125{
126	struct sockaddr_in addr;
127
128	tst_init_sockaddr_inet_bin(&addr, INADDR_ANY, 0);
129	sockfd = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0);
130	SAFE_SETSOCKOPT_INT(sockfd, SOL_SOCKET, SO_SNDBUF, 4096);
131	SAFE_BIND(sockfd, (struct sockaddr *)&addr, sizeof(addr));
132	SAFE_LISTEN(sockfd, 8);
133}
134
135-------------------------------------------------------------------------------
136
1372 Configuring network devices
138-----------------------------
139
140+#include "tst_netdevice.h"+
141
142When opening a localhost socket isn't enough and the test needs special device
143or routing configuration, the netdevice library can create the required network
144setup without calling external programs. Internally, the netdevice functions
145use a rtnetlink socket to communicate with the kernel.
146
147All of these functions will call +tst_brk()+ on failure, unless stated
148otherwise. Error values described below are returned only during test cleanup
149stage.
150
1512.1 Network device management
152~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
153
154- +int NETDEV_INDEX_BY_NAME(const char *ifname)+ – Returns the device index for
155  the given device name, or -1 on error.
156
157- +int NETDEV_SET_STATE(const char *ifname, int up)+ – Enable or disable a
158  network device +ifname+. Returns 0 on success, -1 on error.
159
160- +int CREATE_VETH_PAIR(const char *ifname1, const char *ifname2)+ – Creates a
161  connected pair of virtual network devices with given device names. Returns 1
162  on success, 0 on error. Add +"CONFIG_VETH"+ to +test.needs_kconfigs+ if your
163  test calls this function.
164
165- +int NETDEV_ADD_DEVICE(const char *ifname, const char *devtype)+ - Creates
166  a new network device named +ifname+ of specified device type. Returns 1 on
167  success, 0 on error.
168
169- +int NETDEV_REMOVE_DEVICE(const char *ifname)+ – Removes network device
170  +ifname+. Returns 1 on success, 0 on error.
171
1722.2 Network address management
173~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
174
175- +int NETDEV_ADD_ADDRESS(const char \*ifname, unsigned int family, const void
176  *address, unsigned int prefix, size_t addrlen, unsigned int flags)+ – Adds
177  new address to network device +ifname+. This is a low-level function which
178  allows setting any type of address. You must specify the protocol +family+,
179  address length in bytes (+addrlen+) and network prefix length (+prefix+). The
180  +address+ itself must be in binary representation in network byte order. You
181  can also pass rtnetlink flags from the +IFA_F_*+ group. Returns 1 on success,
182  0 on error.
183
184- +int NETDEV_ADD_ADDRESS_INET(const char *ifname, in_addr_t address, unsigned
185  int prefix, unsigned int flags)+ – Adds new IPv4 address to network device
186  +ifname+. Parameters have the same meaning as in +NETDEV_ADD_ADDRESS()+.
187  Returns 1 on success, 0 on error.
188
189- +int NETDEV_REMOVE_ADDRESS(const char *ifname, unsigned int family, const
190  void *address, size_t addrlen)+ – Removes the specified address from network
191  device +ifname+. Parameters have the same meaning as in
192  +NETDEV_ADD_ADDRESS()+. Returns 1 on success, 0 on error.
193
194- +int NETDEV_REMOVE_ADDRESS_INET(const char *ifname, in_addr_t address)+ –
195  Removes specified IPv4 +address+ (in network byte order) from network device
196  +ifname+. Returns 1 on success, 0 on error.
197
1982.3 Network namespace device assignment
199~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
200
201WARNING: Moving a network device to another namespace will erase previous
202         configuration. Move the device to the correct namespace first, then
203         configure it.
204
205- +int NETDEV_CHANGE_NS_FD(const char *ifname, int nsfd)+ – Moves network
206  device +ifname+ to network namespace designated by open file descriptor
207  +nsfd+. Returns 1 on success, 0 on error.
208
209- +int NETDEV_CHANGE_NS_PID(const char *ifname, pid_t nspid)+ – Moves network
210  device +ifname+ to the network namespace currently used by process +nspid+.
211  Returns 1 on success, 0 on error.
212
2132.4 Routing table management
214~~~~~~~~~~~~~~~~~~~~~~~~~~~~
215
216- +int NETDEV_ADD_ROUTE(const char *ifname, unsigned int family, const void
217  *srcaddr, unsigned int srcprefix, size_t srclen, const void *dstaddr,
218  unsigned int dstprefix, size_t dstlen, const void *gateway, size_t
219  gatewaylen)+ – Adds new route to the main routing table. This is a low-level
220  function which allows creating routes for any protocol. You must specify the
221  protocol +family+ and either network device name +ifname+ or +gateway+
222  address. Both packet source address +srcaddr+ and destination address
223  +dstaddr+ are optional. You must also specify the corresponding length
224  and prefix argument for any address which is not +NULL+. All addresses must
225  be in binary representation in network byte order. Returns 1 on success,
226  0 on error.
227
228- +int NETDEV_ADD_ROUTE_INET(const char *ifname, in_addr_t srcaddr, unsigned
229  int srcprefix, in_addr_t dstaddr, unsigned int dstprefix, in_addr_t
230  gateway)+ – Adds new IPv4 route to the main routing table. Parameters have
231  the same meaning as in +NETDEV_ADD_ROUTE()+. If you do not want to set
232  explicit +gateway+ address, set it to 0. If the routing rule should ignore
233  the source or destination address, set the corresponding prefix argument
234  to 0. Returns 1 on success, 0 on error.
235
236- +int NETDEV_REMOVE_ROUTE(const char *ifname, unsigned int family, const void
237  *srcaddr, unsigned int srcprefix, size_t srclen, const void *dstaddr,
238  unsigned int dstprefix, size_t dstlen, const void *gateway, size_t
239  gatewaylen)+ – Removes a route from the main routing table. Parameters have
240  the same meaning as in +NETDEV_ADD_ROUTE()+. Returns 1 on success, 0 on
241  error.
242
243- +int NETDEV_REMOVE_ROUTE_INET(const char *ifname, in_addr_t srcaddr,
244  unsigned int srcprefix, in_addr_t dstaddr, unsigned int dstprefix, in_addr_t
245  gateway)+ – Removes IPv4 route from the main routing table. Parameters have
246  the same meaning as in +NETDEV_ADD_ROUTE_INET()+. Returns 1 on success,
247  0 on error.
248
249.Example Usage
250[source,c]
251-------------------------------------------------------------------------------
252#include <arpa/inet.h>
253#include <linux/if_addr.h>
254#include "tst_test.h"
255#include "tst_netdevice.h"
256
257...
258
259static void setup(void)
260{
261	CREATE_VETH_PAIR("ltp_veth1", "ltp_veth2");
262	NETDEV_ADD_ADDRESS_INET("ltp_veth2", htonl(DSTADDR), NETMASK,
263		IFA_F_NOPREFIXROUTE);
264	NETDEV_SET_STATE("ltp_veth2", 1);
265	NETDEV_ADD_ROUTE_INET("ltp_veth2", 0, 0, htonl(SRCNET), NETMASK, 0);
266
267	NETDEV_ADD_ADDRESS_INET("ltp_veth1", htonl(SRCADDR), NETMASK,
268		IFA_F_NOPREFIXROUTE);
269	NETDEV_SET_STATE("ltp_veth1", 1);
270	NETDEV_ADD_ROUTE_INET("ltp_veth1", 0, 0, htonl(DSTNET), NETMASK, 0);
271	...
272}
273-------------------------------------------------------------------------------
274
2753 rtnetlink API
276---------------
277
278+#include "tst_rtnetlink.h"+
279
280The rtnetlink library provides helper functions for constructing and sending
281arbitrary messages and parsing kernel responses.
282
283All of the functions below will call +tst_brk()+ on failure, unless stated
284otherwise. Error values described below are returned only during test cleanup
285stage.
286
2873.1 Data structures
288~~~~~~~~~~~~~~~~~~~
289
290[source,c]
291-------------------------------------------------------------------------------
292struct tst_rtnl_context;
293
294struct tst_rtnl_attr_list {
295	unsigned short type;
296	const void *data;
297	ssize_t len;
298	const struct tst_rtnl_attr_list *sublist;
299};
300
301struct tst_rtnl_message {
302	struct nlmsghdr *header;
303	struct nlmsgerr *err;
304	void *payload;
305	size_t payload_size;
306};
307-------------------------------------------------------------------------------
308
309+struct tst_rtnl_context+ is an opaque rtnetlink socket with buffer for
310constructing and sending arbitrary messages using the functions described
311below. Create a new context using +RTNL_CREATE_CONTEXT()+, then free it using
312+RTNL_DESTROY_CONTEXT()+ when you're done with it.
313
314+struct tst_rtnl_attr_list+ is a helper structure for defining complex
315rtnetlink message attribute payloads, including nested attribute lists. Every
316list and sublist defined using this structure is terminated by item with
317negative +len+.
318
319- +type+ is the attribute type that will be stored in +struct rtattr.rta_type+.
320
321- +data+ contains arbitrary attribute payload.
322
323- +len+ contains length of the +data+ attribute in bytes. If +data+ is +NULL+,
324  set +len+ to 0. The last item in a list or sublist must have negative length.
325
326- +sublist+ contains a nested attribute list which will be appended after
327  +data+ as part of the attribute payload. +struct rtattr.rta_len+ will be
328  calculated automatically with proper alignment, do _not_ add the sublist size
329  to the +len+ field. If you do not want to add nested attributes, set
330  +sublist+ to +NULL+.
331
332+struct tst_rtnl_message+ is a structure holding partially parsed rtnetlink
333messages received from the kernel. +RTNL_RECV()+ returns an array of these
334structures with the last item having +NULL+ in the +header+ field. Call
335+RTNL_FREE_MESSAGE()+ to free a message list returned by +RTNL_RECV()+.
336
337- +header+ is the netlink header structure of the message. +NULL+ in the header
338  field terminates a list of messages.
339
340- +err+ points to the payload of +NLMSG_ERROR+ messages. It is set to +NULL+
341  for all other message types.
342
343- +payload+ is a pointer to message data.
344
345- +payload_size+ is the length of +payload+ data in bytes.
346
3473.2 Sending and receiving messages
348~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
349
350- +struct tst_rtnl_context *RTNL_CREATE_CONTEXT(void)+ – Creates a new
351  rtnetlink communication context for use with the functions described below.
352  Returns +NULL+ on error.
353
354- +void RTNL_FREE_MESSAGE(struct tst_rtnl_message *msg)+ – Frees an array of
355  messages returned by +RTNL_RECV()+.
356
357- +void RTNL_DESTROY_CONTEXT(struct tst_rtnl_context *ctx)+ – Closes a
358  communication context created by +RTNL_CREATE_CONTEXT()+.
359
360- +int RTNL_SEND(struct tst_rtnl_context *ctx)+ – Sends all messages waiting
361  in +ctx+ buffer to the kernel. If there are multiple messages to send, a new
362  +NLMSG_DONE+ message will be added automatically. Returns the number of
363  bytes sent on success. Return 0 or negative value on error.
364
365- +int RTNL_SEND_VALIDATE(struct tst_rtnl_context *ctx)+ – Sends all messages
366  just like +RTNL_SEND()+, then receives the response from the kernel and
367  validates results of requests sent with the +NLM_F_ACK+ flag. This function
368  calls +tst_brk()+ as usual if communication fails but it will return error
369  status without terminating the test if one of the received messages contains
370  error code. See +RTNL_CHECK_ACKS()+ below for explanation of the return
371  value.
372
373- +int RTNL_WAIT(struct tst_rtnl_context *ctx)+ – Waits until data becomes
374  available to read from the rtnetlink socket (timeout: 1 second). Returns 1
375  if there is data to read, 0 on timeout or -1 on error.
376
377- +struct tst_rtnl_message *RTNL_RECV(struct tst_rtnl_context *ctx)+ – Receives
378  rtnetlink messages from the kernel. The messages are received in non-blocking
379  mode so calling +RTNL_WAIT()+ first is recommended. Returns an array of
380  partially parsed messages terminated by an item with +NULL+ in the +header+
381  field. On error or when there are no messages to receive, returns +NULL+.
382  Call +RTNL_FREE_MESSAGE()+ to free the returned data.
383
384- +int RTNL_CHECK_ACKS(struct tst_rtnl_context *ctx, struct tst_rtnl_message
385  *response)+ – Validate results of requests sent with the +NLM_F_ACK+ flag.
386  Do not call +RTNL_ADD_MESSAGE()+ between +RTNL_SEND()+ and
387  +RTNL_CHECK_ACKS()+ because it will reset the state of +ctx+ and prevent
388  result validation. Returns 1 if all messages sent with the +NLM_F_ACK+ flag
389  have a corresponding message in +response+ and the error code is 0. If any
390  of the expected response messages is missing, this function will call
391  +tst_brk()+ (or return 0 during test cleanup phase). If any of the response
392  messages has non-zero error code, this function will return 0 and store the
393  first non-zero error code in global variable +tst_rtnl_errno+ (sign-flipped
394  just like regular libc +errno+).
395
3963.3 Creating messages
397~~~~~~~~~~~~~~~~~~~~~
398
399- +int RTNL_ADD_MESSAGE(struct tst_rtnl_context *ctx, const struct nlmsghdr
400  *header, const void *payload, size_t payload_size)+ – Adds new rtnetlink
401  message to +ctx+ buffer. You need to provide message +header+ and optional
402  +payload+. +payload_size+ is the size of +payload+ data in bytes. If you
403  don't want to add any payload data, set +payload+ to +NULL+ and
404  +payload_size+ to 0. This function will automatically fill the +nlmsg_len+,
405  +nlmsg_seq+ and +nlmsg_pid+ fields of the new message header. You don't need
406  to set those. It'll also automatically add +NLM_F_MULTI+ flag when needed.
407  Returns 1 on success, 0 on error. Note that the first call of
408  +RTNL_ADD_MESSAGE()+ after +RTNL_SEND()+ will reset the state of +ctx+
409  and +RTNL_CHECK_ACKS()+ will not work correctly until the next +RTNL_SEND()+.
410
411- +int RTNL_ADD_ATTR(struct tst_rtnl_context *ctx, unsigned short type, const
412  void *data, unsigned short len)+ – Adds new attribute to the last message
413  in +ctx+ buffer. See +RTNL_ADD_MESSAGE()+. You need to provide attribute
414  +type+ which will be stored in +struct rtattr.rta_type+, optional payload
415  +data+ and payload size +len+ in bytes. If you don't want to add any payload,
416  set +data+ to +NULL+ and +len+ to 0. Returns 1 on success, 0 on error.
417
418- +int RTNL_ADD_ATTR_STRING(struct tst_rtnl_context *ctx, unsigned short type,
419  const char *data)+ – Adds new string attribute to the last message in +ctx+
420  buffer. Parameters and return value are the same as for +RTNL_ADD_ATTR()+,
421  except the payload length is calculated using +strlen()+.
422
423- +int RTNL_ADD_ATTR_LIST(struct tst_rtnl_context *ctx, const struct
424  tst_rtnl_attr_list *list)+ – Adds a list of attributes to the last message
425  in +ctx+ buffer. See description of +struct tst_rtnl_attr_list+ and
426  +RTNL_ADD_MESSAGE()+ above.  Returns the number of added attributes on
427  success (nested attributes are not counted), -1 on error.
428
429.Example Usage
430[source,c]
431-------------------------------------------------------------------------------
432#include <asm/types.h>
433#include <linux/netlink.h>
434#include <linux/rtnetlink.h>
435#include <sys/socket.h>
436#include <netinet/in.h>
437#include <arpa/inet.h>
438
439#include "tst_test.h"
440#include "tst_rtnetlink.h"
441#include "tst_netdevice.h"
442
443...
444
445void setup(void)
446{
447	struct tst_rtnl_context *ctx;
448	int index, ret;
449	in_addr_t addr;
450
451	struct nlmsghdr header = {
452		.nlmsg_type = RTM_NEWADDR,
453		.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE |
454			NLM_F_EXCL
455	};
456
457	struct ifaddrmsg info = {
458		.ifa_family = AF_INET,
459		.ifa_prefixlen = 24
460	};
461
462	index = NETDEV_INDEX_BY_NAME("ltp_veth1");
463	info.ifa_index = index;
464
465	ctx = RTNL_CREATE_CONTEXT();
466	RTNL_ADD_MESSAGE(ctx, &header, &info, sizeof(info));
467	addr = inet_addr("192.168.123.45");
468	RTNL_ADD_ATTR(ctx, IFA_LOCAL, &addr, sizeof(addr));
469	ret = RTNL_SEND_VALIDATE(ctx);
470	RTNL_DESTROY_CONTEXT(ctx);
471
472	if (!ret) {
473		tst_brk(TBROK, "Failed to set ltp_veth1 address");
474	}
475}
476-------------------------------------------------------------------------------
477