1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci 3f08c3bdfSopenharmony_ci/* 4f08c3bdfSopenharmony_ci * Copyright (C) 2008, Linux Foundation, 5f08c3bdfSopenharmony_ci * Copyright (c) 2020 Petr Vorel <petr.vorel@gmail.com> 6f08c3bdfSopenharmony_ci * written by Michael Kerrisk <mtk.manpages@gmail.com> 7f08c3bdfSopenharmony_ci * Initial Porting to LTP by Subrata <subrata@linux.vnet.ibm.com> 8f08c3bdfSopenharmony_ci */ 9f08c3bdfSopenharmony_ci 10f08c3bdfSopenharmony_ci#define _GNU_SOURCE 11f08c3bdfSopenharmony_ci#include <unistd.h> 12f08c3bdfSopenharmony_ci#include <sys/syscall.h> 13f08c3bdfSopenharmony_ci#include <sys/socket.h> 14f08c3bdfSopenharmony_ci#include <netinet/in.h> 15f08c3bdfSopenharmony_ci#include <stdlib.h> 16f08c3bdfSopenharmony_ci#include <stdio.h> 17f08c3bdfSopenharmony_ci#include <string.h> 18f08c3bdfSopenharmony_ci#include <errno.h> 19f08c3bdfSopenharmony_ci#include <linux/net.h> 20f08c3bdfSopenharmony_ci 21f08c3bdfSopenharmony_ci#include "tst_test.h" 22f08c3bdfSopenharmony_ci#include "lapi/fcntl.h" 23f08c3bdfSopenharmony_ci#include "lapi/syscalls.h" 24f08c3bdfSopenharmony_ci 25f08c3bdfSopenharmony_cistatic const char *variant_desc[] = { 26f08c3bdfSopenharmony_ci "libc accept4()", 27f08c3bdfSopenharmony_ci "__NR_accept4 syscall", 28f08c3bdfSopenharmony_ci "__NR_socketcall SYS_ACCEPT4 syscall"}; 29f08c3bdfSopenharmony_ci 30f08c3bdfSopenharmony_cistatic struct sockaddr_in *conn_addr, *accept_addr; 31f08c3bdfSopenharmony_cistatic int listening_fd; 32f08c3bdfSopenharmony_ci 33f08c3bdfSopenharmony_cistatic int socketcall_accept4(int fd, struct sockaddr *sockaddr, socklen_t 34f08c3bdfSopenharmony_ci *addrlen, int flags) 35f08c3bdfSopenharmony_ci{ 36f08c3bdfSopenharmony_ci long args[6]; 37f08c3bdfSopenharmony_ci 38f08c3bdfSopenharmony_ci args[0] = fd; 39f08c3bdfSopenharmony_ci args[1] = (long)sockaddr; 40f08c3bdfSopenharmony_ci args[2] = (long)addrlen; 41f08c3bdfSopenharmony_ci args[3] = flags; 42f08c3bdfSopenharmony_ci 43f08c3bdfSopenharmony_ci return tst_syscall(__NR_socketcall, SYS_ACCEPT4, args); 44f08c3bdfSopenharmony_ci} 45f08c3bdfSopenharmony_ci 46f08c3bdfSopenharmony_cistatic int create_listening_socket(void) 47f08c3bdfSopenharmony_ci{ 48f08c3bdfSopenharmony_ci struct sockaddr_in svaddr; 49f08c3bdfSopenharmony_ci int lfd; 50f08c3bdfSopenharmony_ci int optval; 51f08c3bdfSopenharmony_ci 52f08c3bdfSopenharmony_ci memset(&svaddr, 0, sizeof(struct sockaddr_in)); 53f08c3bdfSopenharmony_ci svaddr.sin_family = AF_INET; 54f08c3bdfSopenharmony_ci svaddr.sin_addr.s_addr = htonl(INADDR_ANY); 55f08c3bdfSopenharmony_ci svaddr.sin_port = 0; 56f08c3bdfSopenharmony_ci 57f08c3bdfSopenharmony_ci lfd = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0); 58f08c3bdfSopenharmony_ci 59f08c3bdfSopenharmony_ci optval = 1; 60f08c3bdfSopenharmony_ci SAFE_SETSOCKOPT(lfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); 61f08c3bdfSopenharmony_ci SAFE_BIND(lfd, (struct sockaddr *)&svaddr, sizeof(struct sockaddr_in)); 62f08c3bdfSopenharmony_ci SAFE_LISTEN(lfd, 5); 63f08c3bdfSopenharmony_ci 64f08c3bdfSopenharmony_ci return lfd; 65f08c3bdfSopenharmony_ci} 66f08c3bdfSopenharmony_ci 67f08c3bdfSopenharmony_cistatic void setup(void) 68f08c3bdfSopenharmony_ci{ 69f08c3bdfSopenharmony_ci socklen_t slen = sizeof(*conn_addr); 70f08c3bdfSopenharmony_ci 71f08c3bdfSopenharmony_ci tst_res(TINFO, "Testing variant: %s", variant_desc[tst_variant]); 72f08c3bdfSopenharmony_ci 73f08c3bdfSopenharmony_ci listening_fd = create_listening_socket(); 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ci memset(conn_addr, 0, sizeof(*conn_addr)); 76f08c3bdfSopenharmony_ci SAFE_GETSOCKNAME(listening_fd, (struct sockaddr *)conn_addr, &slen); 77f08c3bdfSopenharmony_ci conn_addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK); 78f08c3bdfSopenharmony_ci tst_res(TINFO, "server listening on: %d", ntohs(conn_addr->sin_port)); 79f08c3bdfSopenharmony_ci} 80f08c3bdfSopenharmony_ci 81f08c3bdfSopenharmony_cistatic void cleanup(void) 82f08c3bdfSopenharmony_ci{ 83f08c3bdfSopenharmony_ci SAFE_CLOSE(listening_fd); 84f08c3bdfSopenharmony_ci} 85f08c3bdfSopenharmony_ci 86f08c3bdfSopenharmony_cistatic struct test_case { 87f08c3bdfSopenharmony_ci int cloexec; 88f08c3bdfSopenharmony_ci int nonblock; 89f08c3bdfSopenharmony_ci} tcases[] = { 90f08c3bdfSopenharmony_ci { 0, 0 }, 91f08c3bdfSopenharmony_ci { SOCK_CLOEXEC, 0 }, 92f08c3bdfSopenharmony_ci { 0, SOCK_NONBLOCK }, 93f08c3bdfSopenharmony_ci { SOCK_CLOEXEC, SOCK_NONBLOCK }, 94f08c3bdfSopenharmony_ci}; 95f08c3bdfSopenharmony_ci 96f08c3bdfSopenharmony_cistatic void verify_accept4(unsigned int nr) 97f08c3bdfSopenharmony_ci{ 98f08c3bdfSopenharmony_ci struct test_case *tcase = &tcases[nr]; 99f08c3bdfSopenharmony_ci int flags = tcase->cloexec | tcase->nonblock; 100f08c3bdfSopenharmony_ci int connfd, acceptfd; 101f08c3bdfSopenharmony_ci int fdf, flf, fdf_pass, flf_pass, fd_cloexec, fd_nonblock; 102f08c3bdfSopenharmony_ci socklen_t addrlen; 103f08c3bdfSopenharmony_ci 104f08c3bdfSopenharmony_ci connfd = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0); 105f08c3bdfSopenharmony_ci SAFE_CONNECT(connfd, (struct sockaddr *)conn_addr, sizeof(*conn_addr)); 106f08c3bdfSopenharmony_ci addrlen = sizeof(*accept_addr); 107f08c3bdfSopenharmony_ci 108f08c3bdfSopenharmony_ci switch (tst_variant) { 109f08c3bdfSopenharmony_ci case 0: 110f08c3bdfSopenharmony_ci TEST(accept4(listening_fd, (struct sockaddr *)accept_addr, 111f08c3bdfSopenharmony_ci &addrlen, flags)); 112f08c3bdfSopenharmony_ci break; 113f08c3bdfSopenharmony_ci case 1: 114f08c3bdfSopenharmony_ci TEST(tst_syscall(__NR_accept4, listening_fd, 115f08c3bdfSopenharmony_ci (struct sockaddr *)accept_addr, 116f08c3bdfSopenharmony_ci &addrlen, flags)); 117f08c3bdfSopenharmony_ci break; 118f08c3bdfSopenharmony_ci case 2: 119f08c3bdfSopenharmony_ci TEST(socketcall_accept4(listening_fd, (struct sockaddr *)accept_addr, 120f08c3bdfSopenharmony_ci &addrlen, flags)); 121f08c3bdfSopenharmony_ci break; 122f08c3bdfSopenharmony_ci } 123f08c3bdfSopenharmony_ci 124f08c3bdfSopenharmony_ci if (TST_RET == -1) 125f08c3bdfSopenharmony_ci tst_brk(TBROK | TTERRNO, "accept4 failed"); 126f08c3bdfSopenharmony_ci 127f08c3bdfSopenharmony_ci acceptfd = TST_RET; 128f08c3bdfSopenharmony_ci 129f08c3bdfSopenharmony_ci /* Test to see if O_CLOEXEC is as expected */ 130f08c3bdfSopenharmony_ci fdf = SAFE_FCNTL(acceptfd, F_GETFD); 131f08c3bdfSopenharmony_ci fd_cloexec = !!(fdf & FD_CLOEXEC); 132f08c3bdfSopenharmony_ci fdf_pass = fd_cloexec == !!tcase->cloexec; 133f08c3bdfSopenharmony_ci if (!fdf_pass) { 134f08c3bdfSopenharmony_ci tst_res(TFAIL, "Close-on-exec flag mismatch, %d vs %d", 135f08c3bdfSopenharmony_ci fd_cloexec, !!tcase->cloexec); 136f08c3bdfSopenharmony_ci } 137f08c3bdfSopenharmony_ci 138f08c3bdfSopenharmony_ci /* Test to see if O_NONBLOCK is as expected */ 139f08c3bdfSopenharmony_ci flf = SAFE_FCNTL(acceptfd, F_GETFL); 140f08c3bdfSopenharmony_ci fd_nonblock = !!(flf & O_NONBLOCK); 141f08c3bdfSopenharmony_ci flf_pass = fd_nonblock == !!tcase->nonblock; 142f08c3bdfSopenharmony_ci if (!flf_pass) { 143f08c3bdfSopenharmony_ci tst_res(TFAIL, "nonblock flag mismatch, %d vs %d", 144f08c3bdfSopenharmony_ci fd_nonblock, !!tcase->nonblock); 145f08c3bdfSopenharmony_ci } 146f08c3bdfSopenharmony_ci 147f08c3bdfSopenharmony_ci SAFE_CLOSE(acceptfd); 148f08c3bdfSopenharmony_ci SAFE_CLOSE(connfd); 149f08c3bdfSopenharmony_ci 150f08c3bdfSopenharmony_ci if (fdf_pass && flf_pass) { 151f08c3bdfSopenharmony_ci tst_res(TPASS, "Close-on-exec %d, nonblock %d", 152f08c3bdfSopenharmony_ci fd_cloexec, fd_nonblock); 153f08c3bdfSopenharmony_ci } 154f08c3bdfSopenharmony_ci} 155f08c3bdfSopenharmony_ci 156f08c3bdfSopenharmony_cistatic struct tst_test test = { 157f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcases), 158f08c3bdfSopenharmony_ci .setup = setup, 159f08c3bdfSopenharmony_ci .cleanup = cleanup, 160f08c3bdfSopenharmony_ci .test_variants = ARRAY_SIZE(variant_desc), 161f08c3bdfSopenharmony_ci .test = verify_accept4, 162f08c3bdfSopenharmony_ci .bufs = (struct tst_buffers []) { 163f08c3bdfSopenharmony_ci {&conn_addr, .size = sizeof(*conn_addr)}, 164f08c3bdfSopenharmony_ci {&accept_addr, .size = sizeof(*accept_addr)}, 165f08c3bdfSopenharmony_ci {}, 166f08c3bdfSopenharmony_ci } 167f08c3bdfSopenharmony_ci}; 168