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