177c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes/* 277c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes * Check decoding of SO_LINGER socket option. 377c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes * 477c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes * Copyright (c) 2017 Dmitry V. Levin <ldv@altlinux.org> 577c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes * All rights reserved. 677c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes * 777c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes * Redistribution and use in source and binary forms, with or without 877c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes * modification, are permitted provided that the following conditions 977c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes * are met: 1077c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes * 1. Redistributions of source code must retain the above copyright 1177c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes * notice, this list of conditions and the following disclaimer. 1277c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes * 2. Redistributions in binary form must reproduce the above copyright 1377c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes * notice, this list of conditions and the following disclaimer in the 1477c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes * documentation and/or other materials provided with the distribution. 1577c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes * 3. The name of the author may not be used to endorse or promote products 1677c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes * derived from this software without specific prior written permission. 1777c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes * 1877c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1977c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2077c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2177c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2277c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2377c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2477c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2577c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2677c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2777c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2877c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes */ 2977c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes 3077c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes#include "tests.h" 3177c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes 3277c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes#include <stdio.h> 3377c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes#include <sys/socket.h> 3477c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes#include <unistd.h> 3577c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes 3677c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughesstatic const char *errstr; 3777c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes 3877c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughesstatic int 3977c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughesget_linger(int fd, void *val, socklen_t *len) 4077c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes{ 4177c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes int rc = getsockopt(fd, SOL_SOCKET, SO_LINGER, val, len); 4277c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes errstr = sprintrc(rc); 4377c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes return rc; 4477c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes} 4577c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes 4677c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughesstatic int 4777c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughesset_linger(int fd, void *val, socklen_t len) 4877c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes{ 4977c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes int rc = setsockopt(fd, SOL_SOCKET, SO_LINGER, val, len); 5077c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes errstr = sprintrc(rc); 5177c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes return rc; 5277c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes} 5377c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes 5477c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughesint 5577c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughesmain(void) 5677c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes{ 5777c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes TAIL_ALLOC_OBJECT_CONST_PTR(struct linger, linger); 5877c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes TAIL_ALLOC_OBJECT_CONST_PTR(socklen_t, len); 5977c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes int fd = socket(AF_UNIX, SOCK_STREAM, 0); 6077c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes if (fd < 0) 6177c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes perror_msg_and_skip("socket AF_UNIX SOCK_STREAM"); 6277c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes 6377c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes /* classic getsockopt */ 6477c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes *len = sizeof(*linger); 6577c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes get_linger(fd, linger, len); 6677c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes printf("getsockopt(%d, SOL_SOCKET, SO_LINGER, {l_onoff=%d, l_linger=%d}" 6777c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes ", [%d]) = %s\n", 6877c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes fd, linger->l_onoff, linger->l_linger, *len, errstr); 6977c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes 7077c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes /* classic setsockopt */ 7177c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes linger->l_onoff = -15; 7277c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes linger->l_linger = -42; 7377c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes set_linger(fd, linger, sizeof(*linger)); 7477c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes printf("setsockopt(%d, SOL_SOCKET, SO_LINGER, {l_onoff=%d, l_linger=%d}" 7577c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes ", %d) = %s\n", 7677c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes fd, linger->l_onoff, linger->l_linger, 7777c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes (unsigned int) sizeof(*linger), errstr); 7877c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes 7977c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes /* setsockopt with optlen larger than necessary */ 8077c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes set_linger(fd, linger, sizeof(*linger) + 1); 8177c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes printf("setsockopt(%d, SOL_SOCKET, SO_LINGER, {l_onoff=%d, l_linger=%d}" 8277c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes ", %d) = %s\n", 8377c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes fd, linger->l_onoff, linger->l_linger, 8477c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes (unsigned int) sizeof(*linger) + 1, errstr); 8577c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes 8677c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes /* setsockopt with optlen < 0 - EINVAL */ 8777c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes set_linger(fd, linger, -1U); 8877c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes printf("setsockopt(%d, SOL_SOCKET, SO_LINGER, %p, -1) = %s\n", 8977c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes fd, linger, errstr); 9077c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes 9177c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes /* setsockopt with optlen smaller than necessary - EINVAL */ 9277c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes set_linger(fd, linger, sizeof(linger->l_onoff)); 9377c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes printf("setsockopt(%d, SOL_SOCKET, SO_LINGER, %p, %d) = %s\n", 9477c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes fd, linger, (unsigned int) sizeof(linger->l_onoff), errstr); 9577c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes 9677c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes /* setsockopt optval EFAULT */ 9777c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes set_linger(fd, &linger->l_linger, sizeof(*linger)); 9877c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes printf("setsockopt(%d, SOL_SOCKET, SO_LINGER, %p, %d) = %s\n", 9977c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes fd, &linger->l_linger, (unsigned int) sizeof(*linger), errstr); 10077c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes 10177c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes /* getsockopt with optlen larger than necessary - shortened */ 10277c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes *len = sizeof(*linger) + 1; 10377c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes get_linger(fd, linger, len); 10477c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes printf("getsockopt(%d, SOL_SOCKET, SO_LINGER, {l_onoff=%d, l_linger=%d}" 10577c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes ", [%u->%d]) = %s\n", 10677c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes fd, linger->l_onoff, linger->l_linger, 10777c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes (unsigned int) sizeof(*linger) + 1, *len, errstr); 10877c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes 10977c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes /* getsockopt with optlen larger than usual - truncated to l_onoff */ 11077c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes *len = sizeof(linger->l_onoff); 11177c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes get_linger(fd, linger, len); 11277c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes printf("getsockopt(%d, SOL_SOCKET, SO_LINGER, {l_onoff=%d}" 11377c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes ", [%d]) = %s\n", 11477c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes fd, linger->l_onoff, *len, errstr); 11577c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes 11677c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes /* getsockopt with optlen larger than usual - truncated to raw */ 11777c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes *len = sizeof(*linger) - 1; 11877c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes get_linger(fd, linger, len); 11977c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes printf("getsockopt(%d, SOL_SOCKET, SO_LINGER, ", fd); 12077c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes print_quoted_hex(linger, *len); 12177c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes printf(", [%d]) = %s\n", *len, errstr); 12277c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes 12377c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes /* getsockopt optval EFAULT */ 12477c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes *len = sizeof(*linger); 12577c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes get_linger(fd, &linger->l_linger, len); 12677c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes printf("getsockopt(%d, SOL_SOCKET, SO_LINGER, %p, [%d]) = %s\n", 12777c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes fd, &linger->l_linger, *len, errstr); 12877c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes 12977c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes /* getsockopt optlen EFAULT */ 13077c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes get_linger(fd, linger, len + 1); 13177c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes printf("getsockopt(%d, SOL_SOCKET, SO_LINGER, %p, %p) = %s\n", 13277c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes fd, linger, len + 1, errstr); 13377c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes 13477c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes puts("+++ exited with 0 +++"); 13577c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes return 0; 13677c3ff8e0644f1e120e4b2ebc7222150b0446f3bElliott Hughes} 137