1 /* 2 * Copyright (c) 2021 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29 #include <sys/socket.h> 30 #include <sys/sysctl.h> 31 #include <sys/time.h> 32 33 #include <darwintest.h> 34 35 T_DECL(so_linger_negative, "SO_LINGER negative") 36 { 37 int s = -1; 38 T_ASSERT_POSIX_SUCCESS(s = socket(AF_LOCAL, SOCK_DGRAM, 0), "socket(AF_LOCAL, SOCK_DGRAM)"); 39 40 struct linger set_l = {}; 41 set_l.l_onoff = 1; 42 set_l.l_linger = -1; 43 T_LOG("l_linger %d", set_l.l_linger); 44 T_ASSERT_POSIX_SUCCESS(setsockopt(s, SOL_SOCKET, SO_LINGER, 45 &set_l, sizeof(struct linger)), 46 "setsockopt SO_LINGER"); 47 48 struct linger get_l = {}; 49 socklen_t len = sizeof(struct linger); 50 T_ASSERT_POSIX_SUCCESS(getsockopt(s, SOL_SOCKET, SO_LINGER, 51 &get_l, &len), 52 "getsockopt SO_LINGER"); 53 54 T_EXPECT_EQ(set_l.l_linger, get_l.l_linger, 55 "SO_LINGER negative l_linger %d == %d", set_l.l_linger, get_l.l_linger); 56 } 57 58 T_DECL(so_linger_overflow, "SO_LINGER overflow") 59 { 60 int s = -1; 61 T_ASSERT_POSIX_SUCCESS(s = socket(AF_LOCAL, SOCK_DGRAM, 0), "socket(AF_LOCAL, SOCK_DGRAM)"); 62 63 struct linger set_l = {}; 64 set_l.l_onoff = 1; 65 set_l.l_linger = SHRT_MAX + 1; 66 T_LOG("l_linger %d", set_l.l_linger); 67 T_ASSERT_POSIX_SUCCESS(setsockopt(s, SOL_SOCKET, SO_LINGER, 68 &set_l, sizeof(struct linger)), 69 "setsockopt SO_LINGER"); 70 71 struct linger get_l = {}; 72 socklen_t len = sizeof(struct linger); 73 T_ASSERT_POSIX_SUCCESS(getsockopt(s, SOL_SOCKET, SO_LINGER, 74 &get_l, &len), 75 "getsockopt SO_LINGER"); 76 77 /* 78 * Test passes based on the knowledge that l_linger is stored 79 * as a short signed integer 80 */ 81 T_EXPECT_EQ((short)set_l.l_linger, (short)get_l.l_linger, 82 "SO_LINGER overflow l_linger (short) %d == (short) %d", 83 set_l.l_linger, get_l.l_linger); 84 } 85 86 T_DECL(so_linger_500, "SO_LINGER 500") 87 { 88 int s = -1; 89 T_ASSERT_POSIX_SUCCESS(s = socket(AF_LOCAL, SOCK_DGRAM, 0), "socket(AF_LOCAL, SOCK_DGRAM)"); 90 91 struct clockinfo clkinfo; 92 size_t oldlen = sizeof(struct clockinfo); 93 T_ASSERT_POSIX_SUCCESS(sysctlbyname("kern.clockrate", &clkinfo, &oldlen, NULL, 0), 94 "sysctlbyname(kern.clockrate)"); 95 96 struct linger set_l = {}; 97 set_l.l_onoff = 1; 98 set_l.l_linger = 500; 99 100 T_ASSERT_POSIX_SUCCESS(setsockopt(s, SOL_SOCKET, SO_LINGER, 101 &set_l, sizeof(struct linger)), 102 "setsockopt SO_LINGER"); 103 104 struct linger get_l = {}; 105 socklen_t len = sizeof(struct linger); 106 T_ASSERT_POSIX_SUCCESS(getsockopt(s, SOL_SOCKET, SO_LINGER, 107 &get_l, &len), 108 "getsockopt SO_LINGER"); 109 110 T_EXPECT_EQ(set_l.l_linger, get_l.l_linger, 111 "SO_LINGER 500 l_linger %d == %d", set_l.l_linger, get_l.l_linger); 112 } 113 114 T_DECL(so_linger_sec_negative, "SO_LINGER_SEC negative") 115 { 116 int s = -1; 117 T_ASSERT_POSIX_SUCCESS(s = socket(AF_LOCAL, SOCK_DGRAM, 0), "socket(AF_LOCAL, SOCK_DGRAM)"); 118 119 struct clockinfo clkinfo; 120 size_t oldlen = sizeof(struct clockinfo); 121 T_ASSERT_POSIX_SUCCESS(sysctlbyname("kern.clockrate", &clkinfo, &oldlen, NULL, 0), 122 "sysctlbyname(kern.clockrate)"); 123 124 struct linger set_l = {}; 125 set_l.l_onoff = 1; 126 set_l.l_linger = -1; 127 T_LOG("l_linger %d * clkinfo.hz %d = %d", set_l.l_linger, clkinfo.hz, (set_l.l_linger * clkinfo.hz)); 128 129 T_ASSERT_POSIX_SUCCESS(setsockopt(s, SOL_SOCKET, SO_LINGER_SEC, 130 &set_l, sizeof(struct linger)), 131 "setsockopt SO_LINGER_SEC"); 132 133 struct linger get_l = {}; 134 socklen_t len = sizeof(struct linger); 135 T_ASSERT_POSIX_SUCCESS(getsockopt(s, SOL_SOCKET, SO_LINGER_SEC, 136 &get_l, &len), 137 "getsockopt SO_LINGER_SEC"); 138 139 T_EXPECT_EQ(set_l.l_linger, get_l.l_linger, 140 "SO_LINGER_SEC negative l_linger %d == %d", set_l.l_linger, get_l.l_linger); 141 } 142 143 T_DECL(so_linger_sec_5_seconds, "SO_LINGER_SEC 5 seconds") 144 { 145 int s = -1; 146 T_ASSERT_POSIX_SUCCESS(s = socket(AF_LOCAL, SOCK_DGRAM, 0), "socket(AF_LOCAL, SOCK_DGRAM)"); 147 148 struct clockinfo clkinfo; 149 size_t oldlen = sizeof(struct clockinfo); 150 T_ASSERT_POSIX_SUCCESS(sysctlbyname("kern.clockrate", &clkinfo, &oldlen, NULL, 0), 151 "sysctlbyname(kern.clockrate)"); 152 153 struct linger set_l = {}; 154 set_l.l_onoff = 1; 155 set_l.l_linger = 5; 156 T_LOG("l_linger %d * clkinfo.hz %d = %d", set_l.l_linger, clkinfo.hz, (set_l.l_linger * clkinfo.hz)); 157 158 T_ASSERT_POSIX_SUCCESS(setsockopt(s, SOL_SOCKET, SO_LINGER_SEC, 159 &set_l, sizeof(struct linger)), 160 "setsockopt SO_LINGER_SEC"); 161 162 struct linger get_l = {}; 163 socklen_t len = sizeof(struct linger); 164 T_ASSERT_POSIX_SUCCESS(getsockopt(s, SOL_SOCKET, SO_LINGER_SEC, 165 &get_l, &len), 166 "getsockopt SO_LINGER_SEC"); 167 168 T_EXPECT_EQ(set_l.l_linger, get_l.l_linger, 169 "SO_LINGER_SEC 5 seconds l_linger %d == %d", set_l.l_linger, get_l.l_linger); 170 } 171