From e19354d350d845ff51a2cdbf2f7f177e641d873d Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Sat, 8 Jul 2017 14:57:44 +0000 Subject: [PATCH] tests: check decoding of SO_LINGER socket option * tests/so_linger.c: New file. * tests/gen_tests.in (so_linger): New entry. * tests/pure_executables.list: Add so_linger. * tests/.gitignore: Likewise. --- tests/.gitignore | 1 + tests/gen_tests.in | 1 + tests/pure_executables.list | 1 + tests/so_linger.c | 131 ++++++++++++++++++++++++++++++++++++ 4 files changed, 134 insertions(+) create mode 100644 tests/so_linger.c diff --git a/tests/.gitignore b/tests/.gitignore index 62de90b5..55528882 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -348,6 +348,7 @@ sigprocmask sigreturn sigsuspend sleep +so_linger socketcall splice stack-fcall diff --git a/tests/gen_tests.in b/tests/gen_tests.in index 57fd5fd9..d352e896 100644 --- a/tests/gen_tests.in +++ b/tests/gen_tests.in @@ -299,6 +299,7 @@ sigpending -a15 sigprocmask -a34 sigreturn -esignal='!USR1' sigsuspend -a19 -esignal=none +so_linger -e trace=getsockopt,setsockopt socketcall -a20 splice stat -a32 -v -P stat.sample -P /dev/full diff --git a/tests/pure_executables.list b/tests/pure_executables.list index 033208e6..390a40e2 100755 --- a/tests/pure_executables.list +++ b/tests/pure_executables.list @@ -287,6 +287,7 @@ sigpending sigprocmask sigreturn sigsuspend +so_linger socketcall splice stat diff --git a/tests/so_linger.c b/tests/so_linger.c new file mode 100644 index 00000000..8f106349 --- /dev/null +++ b/tests/so_linger.c @@ -0,0 +1,131 @@ +/* + * Check decoding of SO_LINGER socket option. + * + * Copyright (c) 2017 Dmitry V. Levin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "tests.h" + +#include +#include +#include + +static const char *errstr; + +static int +get_linger(int fd, void *val, socklen_t *len) +{ + int rc = getsockopt(fd, SOL_SOCKET, SO_LINGER, val, len); + errstr = sprintrc(rc); + return rc; +} + +static int +set_linger(int fd, void *val, socklen_t len) +{ + int rc = setsockopt(fd, SOL_SOCKET, SO_LINGER, val, len); + errstr = sprintrc(rc); + return rc; +} + +int +main(void) +{ + TAIL_ALLOC_OBJECT_CONST_PTR(struct linger, linger); + TAIL_ALLOC_OBJECT_CONST_PTR(socklen_t, len); + int fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) + perror_msg_and_skip("socket AF_UNIX SOCK_STREAM"); + + /* classic getsockopt */ + *len = sizeof(*linger); + get_linger(fd, linger, len); + printf("getsockopt(%d, SOL_SOCKET, SO_LINGER, {l_onoff=%d, l_linger=%d}" + ", [%d]) = %s\n", + fd, linger->l_onoff, linger->l_linger, *len, errstr); + + /* classic setsockopt */ + linger->l_onoff = -15; + linger->l_linger = -42; + set_linger(fd, linger, sizeof(*linger)); + printf("setsockopt(%d, SOL_SOCKET, SO_LINGER, {l_onoff=%d, l_linger=%d}" + ", %d) = %s\n", + fd, linger->l_onoff, linger->l_linger, + (unsigned int) sizeof(*linger), errstr); + + /* setsockopt with optlen larger than necessary */ + set_linger(fd, linger, sizeof(*linger) + 1); + printf("setsockopt(%d, SOL_SOCKET, SO_LINGER, {l_onoff=%d, l_linger=%d}" + ", %d) = %s\n", + fd, linger->l_onoff, linger->l_linger, + (unsigned int) sizeof(*linger) + 1, errstr); + + /* setsockopt with optlen smaller than necessary - EINVAL */ + set_linger(fd, linger, sizeof(linger->l_onoff)); + printf("setsockopt(%d, SOL_SOCKET, SO_LINGER, %p, %d) = %s\n", + fd, linger, (unsigned int) sizeof(linger->l_onoff), errstr); + + /* setsockopt optval EFAULT */ + set_linger(fd, &linger->l_linger, sizeof(*linger)); + printf("setsockopt(%d, SOL_SOCKET, SO_LINGER, %p, %d) = %s\n", + fd, &linger->l_linger, (unsigned int) sizeof(*linger), errstr); + + /* getsockopt with optlen larger than necessary - shortened */ + *len = sizeof(*linger) + 1; + get_linger(fd, linger, len); + printf("getsockopt(%d, SOL_SOCKET, SO_LINGER, {l_onoff=%d, l_linger=%d}" + ", [%u->%d]) = %s\n", + fd, linger->l_onoff, linger->l_linger, + (unsigned int) sizeof(*linger) + 1, *len, errstr); + + /* getsockopt with optlen larger than usual - truncated to l_onoff */ + *len = sizeof(linger->l_onoff); + get_linger(fd, linger, len); + printf("getsockopt(%d, SOL_SOCKET, SO_LINGER, {l_onoff=%d}" + ", [%d]) = %s\n", + fd, linger->l_onoff, *len, errstr); + + /* getsockopt with optlen larger than usual - truncated to raw */ + *len = sizeof(*linger) - 1; + get_linger(fd, linger, len); + printf("getsockopt(%d, SOL_SOCKET, SO_LINGER, ", fd); + print_quoted_hex(linger, *len); + printf(", [%d]) = %s\n", *len, errstr); + + /* getsockopt optval EFAULT */ + *len = sizeof(*linger); + get_linger(fd, &linger->l_linger, len); + printf("getsockopt(%d, SOL_SOCKET, SO_LINGER, %p, [%d]) = %s\n", + fd, &linger->l_linger, *len, errstr); + + /* getsockopt optlen EFAULT */ + get_linger(fd, linger, len + 1); + printf("getsockopt(%d, SOL_SOCKET, SO_LINGER, %p, %p) = %s\n", + fd, linger, len + 1, errstr); + + puts("+++ exited with 0 +++"); + return 0; +} -- 2.40.0