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