1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com> 4f08c3bdfSopenharmony_ci */ 5f08c3bdfSopenharmony_ci 6f08c3bdfSopenharmony_ci/*\ 7f08c3bdfSopenharmony_ci * [Description] 8f08c3bdfSopenharmony_ci * 9f08c3bdfSopenharmony_ci * Verify that epoll receives EPOLLRDHUP event when we hang a reading 10f08c3bdfSopenharmony_ci * half-socket we are polling on. 11f08c3bdfSopenharmony_ci */ 12f08c3bdfSopenharmony_ci 13f08c3bdfSopenharmony_ci#include "tst_test.h" 14f08c3bdfSopenharmony_ci#include "tst_net.h" 15f08c3bdfSopenharmony_ci#include "tst_epoll.h" 16f08c3bdfSopenharmony_ci 17f08c3bdfSopenharmony_cistatic int epfd; 18f08c3bdfSopenharmony_cistatic int sockfd_client; 19f08c3bdfSopenharmony_cistatic int sockfd_server; 20f08c3bdfSopenharmony_cistatic in_port_t *sock_port; 21f08c3bdfSopenharmony_ci 22f08c3bdfSopenharmony_cistatic void create_server(void) 23f08c3bdfSopenharmony_ci{ 24f08c3bdfSopenharmony_ci int sockfd_server; 25f08c3bdfSopenharmony_ci socklen_t len; 26f08c3bdfSopenharmony_ci struct sockaddr_in serv_addr; 27f08c3bdfSopenharmony_ci struct sockaddr_in sin; 28f08c3bdfSopenharmony_ci 29f08c3bdfSopenharmony_ci tst_init_sockaddr_inet_bin(&serv_addr, INADDR_ANY, 0); 30f08c3bdfSopenharmony_ci 31f08c3bdfSopenharmony_ci sockfd_server = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0); 32f08c3bdfSopenharmony_ci SAFE_BIND(sockfd_server, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); 33f08c3bdfSopenharmony_ci SAFE_LISTEN(sockfd_server, 10); 34f08c3bdfSopenharmony_ci 35f08c3bdfSopenharmony_ci len = sizeof(sin); 36f08c3bdfSopenharmony_ci memset(&sin, 0, sizeof(struct sockaddr_in)); 37f08c3bdfSopenharmony_ci SAFE_GETSOCKNAME(sockfd_server, (struct sockaddr *)&sin, &len); 38f08c3bdfSopenharmony_ci 39f08c3bdfSopenharmony_ci *sock_port = ntohs(sin.sin_port); 40f08c3bdfSopenharmony_ci 41f08c3bdfSopenharmony_ci tst_res(TINFO, "Listening on port %d", *sock_port); 42f08c3bdfSopenharmony_ci 43f08c3bdfSopenharmony_ci TST_CHECKPOINT_WAKE_AND_WAIT(0); 44f08c3bdfSopenharmony_ci 45f08c3bdfSopenharmony_ci SAFE_CLOSE(sockfd_server); 46f08c3bdfSopenharmony_ci} 47f08c3bdfSopenharmony_ci 48f08c3bdfSopenharmony_cistatic void run(void) 49f08c3bdfSopenharmony_ci{ 50f08c3bdfSopenharmony_ci struct sockaddr_in client_addr; 51f08c3bdfSopenharmony_ci struct epoll_event evt_req; 52f08c3bdfSopenharmony_ci struct epoll_event evt_rec; 53f08c3bdfSopenharmony_ci int ret; 54f08c3bdfSopenharmony_ci 55f08c3bdfSopenharmony_ci if (!SAFE_FORK()) { 56f08c3bdfSopenharmony_ci create_server(); 57f08c3bdfSopenharmony_ci return; 58f08c3bdfSopenharmony_ci } 59f08c3bdfSopenharmony_ci 60f08c3bdfSopenharmony_ci TST_CHECKPOINT_WAIT(0); 61f08c3bdfSopenharmony_ci 62f08c3bdfSopenharmony_ci tst_res(TINFO, "Connecting to port %d", *sock_port); 63f08c3bdfSopenharmony_ci 64f08c3bdfSopenharmony_ci sockfd_client = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0); 65f08c3bdfSopenharmony_ci 66f08c3bdfSopenharmony_ci tst_init_sockaddr_inet(&client_addr, "127.0.0.1", *sock_port); 67f08c3bdfSopenharmony_ci 68f08c3bdfSopenharmony_ci SAFE_CONNECT(sockfd_client, 69f08c3bdfSopenharmony_ci (struct sockaddr *)&client_addr, 70f08c3bdfSopenharmony_ci sizeof(client_addr)); 71f08c3bdfSopenharmony_ci 72f08c3bdfSopenharmony_ci tst_res(TINFO, "Polling on socket"); 73f08c3bdfSopenharmony_ci 74f08c3bdfSopenharmony_ci epfd = SAFE_EPOLL_CREATE1(0); 75f08c3bdfSopenharmony_ci evt_req.events = EPOLLRDHUP; 76f08c3bdfSopenharmony_ci SAFE_EPOLL_CTL(epfd, EPOLL_CTL_ADD, sockfd_client, &evt_req); 77f08c3bdfSopenharmony_ci 78f08c3bdfSopenharmony_ci tst_res(TINFO, "Hang socket"); 79f08c3bdfSopenharmony_ci 80f08c3bdfSopenharmony_ci TST_EXP_PASS_SILENT(shutdown(sockfd_client, SHUT_RD)); 81f08c3bdfSopenharmony_ci ret = SAFE_EPOLL_WAIT(epfd, &evt_rec, 1, 2000); 82f08c3bdfSopenharmony_ci if (ret != 1) { 83f08c3bdfSopenharmony_ci tst_res(TFAIL, "Wrong number of events reported %i", ret); 84f08c3bdfSopenharmony_ci goto exit; 85f08c3bdfSopenharmony_ci } 86f08c3bdfSopenharmony_ci 87f08c3bdfSopenharmony_ci if (evt_rec.events & EPOLLRDHUP) 88f08c3bdfSopenharmony_ci tst_res(TPASS, "Received EPOLLRDHUP"); 89f08c3bdfSopenharmony_ci else 90f08c3bdfSopenharmony_ci tst_res(TFAIL, "EPOLLRDHUP has not been received"); 91f08c3bdfSopenharmony_ci 92f08c3bdfSopenharmony_ciexit: 93f08c3bdfSopenharmony_ci SAFE_CLOSE(epfd); 94f08c3bdfSopenharmony_ci SAFE_CLOSE(sockfd_client); 95f08c3bdfSopenharmony_ci 96f08c3bdfSopenharmony_ci TST_CHECKPOINT_WAKE(0); 97f08c3bdfSopenharmony_ci} 98f08c3bdfSopenharmony_ci 99f08c3bdfSopenharmony_cistatic void setup(void) 100f08c3bdfSopenharmony_ci{ 101f08c3bdfSopenharmony_ci sock_port = SAFE_MMAP(NULL, sizeof(in_port_t), PROT_READ | PROT_WRITE, 102f08c3bdfSopenharmony_ci MAP_SHARED | MAP_ANONYMOUS, -1, 0); 103f08c3bdfSopenharmony_ci} 104f08c3bdfSopenharmony_ci 105f08c3bdfSopenharmony_cistatic void cleanup(void) 106f08c3bdfSopenharmony_ci{ 107f08c3bdfSopenharmony_ci if (sock_port) 108f08c3bdfSopenharmony_ci SAFE_MUNMAP(sock_port, sizeof(in_port_t)); 109f08c3bdfSopenharmony_ci 110f08c3bdfSopenharmony_ci if (fcntl(sockfd_client, F_GETFD) > 0) 111f08c3bdfSopenharmony_ci SAFE_CLOSE(sockfd_client); 112f08c3bdfSopenharmony_ci 113f08c3bdfSopenharmony_ci if (fcntl(sockfd_server, F_GETFD) > 0) 114f08c3bdfSopenharmony_ci SAFE_CLOSE(sockfd_server); 115f08c3bdfSopenharmony_ci 116f08c3bdfSopenharmony_ci if (fcntl(epfd, F_GETFD) > 0) 117f08c3bdfSopenharmony_ci SAFE_CLOSE(epfd); 118f08c3bdfSopenharmony_ci} 119f08c3bdfSopenharmony_ci 120f08c3bdfSopenharmony_cistatic struct tst_test test = { 121f08c3bdfSopenharmony_ci .setup = setup, 122f08c3bdfSopenharmony_ci .cleanup = cleanup, 123f08c3bdfSopenharmony_ci .test_all = run, 124f08c3bdfSopenharmony_ci .forks_child = 1, 125f08c3bdfSopenharmony_ci .needs_checkpoints = 1, 126f08c3bdfSopenharmony_ci}; 127