android13/external/ltp/testcases/kernel/syscalls/setsockopt/setsockopt01.c

109 lines
2.8 KiB
C

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) International Business Machines Corp., 2001
* 07/2001 John George
* Copyright (c) 2020 Martin Doucha <mdoucha@suse.cz>
*/
/*
* Test Description:
* Verify that setsockopt() returns the proper errno for various failure cases
*/
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include "tst_test.h"
static struct sockaddr_in addr;
static int optval;
static struct test_case { /* test case structure */
int domain; /* PF_INET, PF_UNIX, ... */
int type; /* SOCK_STREAM, SOCK_DGRAM ... */
int proto; /* protocol number (usually 0 = default) */
int level; /* IPPROTO_* */
int optname;
void *optval;
int optlen;
int experrno; /* expected errno */
char *desc;
} testcase_list[] = {
{-1, -1, -1, SOL_SOCKET, SO_OOBINLINE, &optval, sizeof(optval),
EBADF, "invalid file descriptor"},
{-1, -1, -1, SOL_SOCKET, SO_OOBINLINE, &optval, sizeof(optval),
ENOTSOCK, "non-socket file descriptor"},
{PF_INET, SOCK_STREAM, 0, SOL_SOCKET, SO_OOBINLINE, NULL,
sizeof(optval), EFAULT, "invalid option buffer"},
{PF_INET, SOCK_STREAM, 0, SOL_SOCKET, SO_OOBINLINE, &optval, 0,
EINVAL, "invalid optlen"},
{PF_INET, SOCK_STREAM, 0, 500, SO_OOBINLINE, &optval, sizeof(optval),
ENOPROTOOPT, "invalid level"},
{PF_INET, SOCK_STREAM, 0, IPPROTO_UDP, SO_OOBINLINE, &optval,
sizeof(optval), ENOPROTOOPT, "invalid option name (UDP)"},
{PF_INET, SOCK_STREAM, 0, IPPROTO_IP, -1, &optval, sizeof(optval),
ENOPROTOOPT, "invalid option name (IP)"},
{PF_INET, SOCK_STREAM, 0, IPPROTO_TCP, -1, &optval, sizeof(optval),
ENOPROTOOPT, "invalid option name (TCP)"}
};
static void setup(void)
{
/* initialize local sockaddr */
addr.sin_family = AF_INET;
addr.sin_port = 0;
addr.sin_addr.s_addr = INADDR_ANY;
}
static void run(unsigned int n)
{
struct test_case *tc = testcase_list + n;
int tmpfd, fd;
tst_res(TINFO, "Testing %s", tc->desc);
if (tc->domain == -1) {
tmpfd = fd = SAFE_OPEN("/dev/null", O_WRONLY);
} else {
tmpfd = fd = SAFE_SOCKET(tc->domain, tc->type, tc->proto);
SAFE_BIND(fd, (struct sockaddr *)&addr, sizeof(addr));
}
/* Use closed file descriptor rather than -1 */
if (tc->experrno == EBADF)
SAFE_CLOSE(tmpfd);
TEST(setsockopt(fd, tc->level, tc->optname, tc->optval, tc->optlen));
if (tc->experrno != EBADF)
SAFE_CLOSE(fd);
if (TST_RET == 0) {
tst_res(TFAIL, "setsockopt() succeeded unexpectedly");
return;
}
if (TST_RET != -1) {
tst_res(TFAIL | TTERRNO,
"Invalid setsockopt() return value %ld", TST_RET);
return;
}
if (TST_ERR != tc->experrno) {
tst_res(TFAIL | TTERRNO,
"setsockopt() returned unexpected error");
return;
}
tst_res(TPASS | TTERRNO, "setsockopt() returned the expected error");
}
static struct tst_test test = {
.test = run,
.tcnt = ARRAY_SIZE(testcase_list),
.setup = setup
};