1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2001 4f08c3bdfSopenharmony_ci * 07/2001 John George 5f08c3bdfSopenharmony_ci * Copyright (c) 2020 Martin Doucha <mdoucha@suse.cz> 6f08c3bdfSopenharmony_ci */ 7f08c3bdfSopenharmony_ci 8f08c3bdfSopenharmony_ci/* 9f08c3bdfSopenharmony_ci * Test Description: 10f08c3bdfSopenharmony_ci * Verify that setsockopt() returns the proper errno for various failure cases 11f08c3bdfSopenharmony_ci */ 12f08c3bdfSopenharmony_ci 13f08c3bdfSopenharmony_ci#include <unistd.h> 14f08c3bdfSopenharmony_ci#include <sys/types.h> 15f08c3bdfSopenharmony_ci#include <sys/socket.h> 16f08c3bdfSopenharmony_ci#include <sys/ioctl.h> 17f08c3bdfSopenharmony_ci#include <netinet/in.h> 18f08c3bdfSopenharmony_ci 19f08c3bdfSopenharmony_ci#include "tst_test.h" 20f08c3bdfSopenharmony_ci 21f08c3bdfSopenharmony_cistatic struct sockaddr_in addr; 22f08c3bdfSopenharmony_cistatic int optval; 23f08c3bdfSopenharmony_ci 24f08c3bdfSopenharmony_cistatic struct test_case { /* test case structure */ 25f08c3bdfSopenharmony_ci int domain; /* PF_INET, PF_UNIX, ... */ 26f08c3bdfSopenharmony_ci int type; /* SOCK_STREAM, SOCK_DGRAM ... */ 27f08c3bdfSopenharmony_ci int proto; /* protocol number (usually 0 = default) */ 28f08c3bdfSopenharmony_ci int level; /* IPPROTO_* */ 29f08c3bdfSopenharmony_ci int optname; 30f08c3bdfSopenharmony_ci void *optval; 31f08c3bdfSopenharmony_ci int optlen; 32f08c3bdfSopenharmony_ci int experrno; /* expected errno */ 33f08c3bdfSopenharmony_ci char *desc; 34f08c3bdfSopenharmony_ci} testcase_list[] = { 35f08c3bdfSopenharmony_ci {-1, -1, -1, SOL_SOCKET, SO_OOBINLINE, &optval, sizeof(optval), 36f08c3bdfSopenharmony_ci EBADF, "invalid file descriptor"}, 37f08c3bdfSopenharmony_ci {-1, -1, -1, SOL_SOCKET, SO_OOBINLINE, &optval, sizeof(optval), 38f08c3bdfSopenharmony_ci ENOTSOCK, "non-socket file descriptor"}, 39f08c3bdfSopenharmony_ci {PF_INET, SOCK_STREAM, 0, SOL_SOCKET, SO_OOBINLINE, NULL, 40f08c3bdfSopenharmony_ci sizeof(optval), EFAULT, "invalid option buffer"}, 41f08c3bdfSopenharmony_ci {PF_INET, SOCK_STREAM, 0, SOL_SOCKET, SO_OOBINLINE, &optval, 0, 42f08c3bdfSopenharmony_ci EINVAL, "invalid optlen"}, 43f08c3bdfSopenharmony_ci {PF_INET, SOCK_STREAM, 0, 500, SO_OOBINLINE, &optval, sizeof(optval), 44f08c3bdfSopenharmony_ci ENOPROTOOPT, "invalid level"}, 45f08c3bdfSopenharmony_ci {PF_INET, SOCK_STREAM, 0, IPPROTO_UDP, SO_OOBINLINE, &optval, 46f08c3bdfSopenharmony_ci sizeof(optval), ENOPROTOOPT, "invalid option name (UDP)"}, 47f08c3bdfSopenharmony_ci {PF_INET, SOCK_STREAM, 0, IPPROTO_IP, -1, &optval, sizeof(optval), 48f08c3bdfSopenharmony_ci ENOPROTOOPT, "invalid option name (IP)"}, 49f08c3bdfSopenharmony_ci {PF_INET, SOCK_STREAM, 0, IPPROTO_TCP, -1, &optval, sizeof(optval), 50f08c3bdfSopenharmony_ci ENOPROTOOPT, "invalid option name (TCP)"} 51f08c3bdfSopenharmony_ci}; 52f08c3bdfSopenharmony_ci 53f08c3bdfSopenharmony_cistatic void setup(void) 54f08c3bdfSopenharmony_ci{ 55f08c3bdfSopenharmony_ci /* initialize local sockaddr */ 56f08c3bdfSopenharmony_ci addr.sin_family = AF_INET; 57f08c3bdfSopenharmony_ci addr.sin_port = 0; 58f08c3bdfSopenharmony_ci addr.sin_addr.s_addr = INADDR_ANY; 59f08c3bdfSopenharmony_ci} 60f08c3bdfSopenharmony_ci 61f08c3bdfSopenharmony_cistatic void run(unsigned int n) 62f08c3bdfSopenharmony_ci{ 63f08c3bdfSopenharmony_ci struct test_case *tc = testcase_list + n; 64f08c3bdfSopenharmony_ci int tmpfd, fd; 65f08c3bdfSopenharmony_ci 66f08c3bdfSopenharmony_ci tst_res(TINFO, "Testing %s", tc->desc); 67f08c3bdfSopenharmony_ci 68f08c3bdfSopenharmony_ci if (tc->domain == -1) { 69f08c3bdfSopenharmony_ci tmpfd = fd = SAFE_OPEN("/dev/null", O_WRONLY); 70f08c3bdfSopenharmony_ci } else { 71f08c3bdfSopenharmony_ci tmpfd = fd = SAFE_SOCKET(tc->domain, tc->type, tc->proto); 72f08c3bdfSopenharmony_ci SAFE_BIND(fd, (struct sockaddr *)&addr, sizeof(addr)); 73f08c3bdfSopenharmony_ci } 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ci /* Use closed file descriptor rather than -1 */ 76f08c3bdfSopenharmony_ci if (tc->experrno == EBADF) 77f08c3bdfSopenharmony_ci SAFE_CLOSE(tmpfd); 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_ci TEST(setsockopt(fd, tc->level, tc->optname, tc->optval, tc->optlen)); 80f08c3bdfSopenharmony_ci 81f08c3bdfSopenharmony_ci if (tc->experrno != EBADF) 82f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 83f08c3bdfSopenharmony_ci 84f08c3bdfSopenharmony_ci if (TST_RET == 0) { 85f08c3bdfSopenharmony_ci tst_res(TFAIL, "setsockopt() succeeded unexpectedly"); 86f08c3bdfSopenharmony_ci return; 87f08c3bdfSopenharmony_ci } 88f08c3bdfSopenharmony_ci 89f08c3bdfSopenharmony_ci if (TST_RET != -1) { 90f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, 91f08c3bdfSopenharmony_ci "Invalid setsockopt() return value %ld", TST_RET); 92f08c3bdfSopenharmony_ci return; 93f08c3bdfSopenharmony_ci } 94f08c3bdfSopenharmony_ci 95f08c3bdfSopenharmony_ci if (TST_ERR != tc->experrno) { 96f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, 97f08c3bdfSopenharmony_ci "setsockopt() returned unexpected error"); 98f08c3bdfSopenharmony_ci return; 99f08c3bdfSopenharmony_ci } 100f08c3bdfSopenharmony_ci 101f08c3bdfSopenharmony_ci tst_res(TPASS | TTERRNO, "setsockopt() returned the expected error"); 102f08c3bdfSopenharmony_ci} 103f08c3bdfSopenharmony_ci 104f08c3bdfSopenharmony_cistatic struct tst_test test = { 105f08c3bdfSopenharmony_ci .test = run, 106f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(testcase_list), 107f08c3bdfSopenharmony_ci .setup = setup 108f08c3bdfSopenharmony_ci}; 109