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