static void server_init(void) { struct addrinfo hints; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; if (getaddrinfo(NULL, tcp_port, &hints, &local_addrinfo) != 0) tst_brkm(TBROK | TERRNO, cleanup, "getaddrinfo failed"); /* IPv6 socket is also able to access IPv4 protocol stack */ sfd = SAFE_SOCKET(cleanup, AF_INET6, SOCK_STREAM, 0); tst_resm(TINFO, "assigning a name to the server socket..."); if (!local_addrinfo) tst_brkm(TBROK, cleanup, "failed to get the address"); SAFE_BIND(cleanup, sfd, local_addrinfo->ai_addr, local_addrinfo->ai_addrlen); freeaddrinfo(local_addrinfo); const int flag = 1; setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)); if (fastopen_api == TFO_ENABLED) { if (setsockopt(sfd, IPPROTO_TCP, TCP_FASTOPEN, &tfo_queue_size, sizeof(tfo_queue_size)) == -1) tst_brkm(TBROK, cleanup, "Can't set TFO sock. options"); } SAFE_LISTEN(cleanup, sfd, max_queue_len); tst_resm(TINFO, "Listen on the socket '%d', port '%s'", sfd, tcp_port); }
static int read_iface_prefix(const char *ip_str, int is_ipv6) { uint8_t family = is_ipv6 ? AF_INET6 : AF_INET; char buf[16384]; unsigned int len; struct { struct nlmsghdr nlhdr; struct ifaddrmsg addrmsg; } msg; struct nlmsghdr *retmsg; int sock = SAFE_SOCKET(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); memset(&msg, 0, sizeof(msg)); msg.nlhdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); msg.nlhdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT; msg.nlhdr.nlmsg_type = RTM_GETADDR; msg.addrmsg.ifa_family = family; SAFE_SEND(1, sock, &msg, msg.nlhdr.nlmsg_len, 0); len = recv(sock, buf, sizeof(buf), 0); retmsg = (struct nlmsghdr *)buf; while NLMSG_OK(retmsg, len) { char ifname[IFNAMSIZ]; struct ifaddrmsg *retaddr; struct rtattr *retrta; char pradd[128]; int attlen; retaddr = (struct ifaddrmsg *)NLMSG_DATA(retmsg); retrta = (struct rtattr *)IFA_RTA(retaddr); attlen = IFA_PAYLOAD(retmsg); while RTA_OK(retrta, attlen) { if (retrta->rta_type == IFA_ADDRESS) { inet_ntop(family, RTA_DATA(retrta), pradd, sizeof(pradd)); if_indextoname(retaddr->ifa_index, ifname); if (!strcmp(pradd, ip_str)) { prefix = retaddr->ifa_prefixlen; iface = strdup(ifname); return 0; } } retrta = RTA_NEXT(retrta, attlen); } retmsg = NLMSG_NEXT(retmsg, len); } return -1; }
static int create_skbuf(unsigned int sizeof_priv) { int ver = TPACKET_V3; struct tpacket_req3 req = {}; req.tp_block_size = pgsz; req.tp_block_nr = 2; req.tp_frame_size = req.tp_block_size; req.tp_frame_nr = req.tp_block_nr; req.tp_retire_blk_tov = 100; req.tp_sizeof_priv = sizeof_priv; sk = SAFE_SOCKET(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); TEST(setsockopt(sk, SOL_PACKET, PACKET_VERSION, &ver, sizeof(ver))); if (TST_RET && TST_ERR == EINVAL) tst_brk(TCONF | TTERRNO, "TPACKET_V3 not supported"); if (TST_RET) tst_brk(TBROK | TTERRNO, "setsockopt(sk, SOL_PACKET, PACKET_VERSION, TPACKET_V3)"); return setsockopt(sk, SOL_PACKET, PACKET_RX_RING, &req, sizeof(req)); }
static void verify_recvmsg(void) { struct sockaddr_in6 addr_init = { .sin6_family = AF_INET6, .sin6_port = htons(0), .sin6_addr = IN6ADDR_LOOPBACK_INIT, }; struct sockaddr_in6 addr_r, addr_w, addr_f; socklen_t addrlen_r, addrlen_w; struct iovec iov = { .iov_base = buff, .iov_len = sizeof(buff), }; struct msghdr msghdr = { .msg_name = &addr_f, .msg_namelen = sizeof(addr_f), .msg_iov = &iov, .msg_iovlen = 1, .msg_control = NULL, .msg_controllen = 0, .msg_flags = 0, }; int R; sdr = SAFE_SOCKET(PF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_IP); SAFE_BIND(sdr, (struct sockaddr*)&addr_init, sizeof(addr_init)); addrlen_r = sizeof(addr_r); SAFE_GETSOCKNAME(sdr, (struct sockaddr*)&addr_r, &addrlen_r); sdw = SAFE_SOCKET(PF_INET6, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_IP); SAFE_BIND(sdw, (struct sockaddr*)&addr_init, sizeof(addr_init)); addrlen_w = sizeof(addr_w); SAFE_GETSOCKNAME(sdw, (struct sockaddr*)&addr_w, &addrlen_w); R = sendto(sdw, msg, msglen, 0, (struct sockaddr*)&addr_r, addrlen_r); if (R < 0) tst_brk(TBROK | TERRNO, "sendto()"); R = recvmsg(sdr, &msghdr, MSG_PEEK); if (R < 0) { tst_res(TFAIL | TERRNO, "recvmsg(..., MSG_PEEK)"); return; } tst_res(TINFO, "received %d bytes", R); if ((R == bufflen) && !memcmp(msg, buff, R)) tst_res(TPASS, "recvmsg(..., MSG_PEEK) works fine"); else tst_res(TPASS, "recvmsg(..., MSG_PEEK) failed"); SAFE_CLOSE(sdw); SAFE_CLOSE(sdr); } static void cleanup(void) { if (sdw > 0 && close(sdw)) tst_res(TWARN | TERRNO, "close(sdw) failed"); if (sdr > 0 && close(sdr)) tst_res(TWARN | TERRNO, "close(sdr) failed"); } static struct tst_test test = { .tid = "recvmsg02", .min_kver = "2.6.27", .test_all = verify_recvmsg, .cleanup = cleanup, };