1 /* 2 * 3 * Copyright (c) International Business Machines Corp., 2001 4 * 07/2001 Ported by Wayne Boyer 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 14 * the GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21 /* 22 * Verify that getpeername() returns the proper errno for various failure cases 23 */ 24 25 #include <stdio.h> 26 #include <unistd.h> 27 #include <errno.h> 28 #include <fcntl.h> 29 #include <sys/types.h> 30 #include <sys/socket.h> 31 #include <sys/signal.h> 32 #include <sys/ioctl.h> 33 #include <netinet/in.h> 34 35 #include "test.h" 36 #include "safe_macros.h" 37 38 static struct sockaddr_in server_addr; 39 static struct sockaddr_in fsin1; 40 static socklen_t sinlen; 41 static socklen_t invalid_sinlen = -1; 42 static int sv[2]; 43 44 static void setup(void); 45 static void setup2(int); 46 static void setup3(int); 47 static void setup4(int); 48 static void cleanup(void); 49 static void cleanup2(int); 50 static void cleanup4(int); 51 52 struct test_case_t { 53 int sockfd; 54 struct sockaddr *sockaddr; 55 socklen_t *addrlen; 56 int expretval; 57 int experrno; 58 void (*setup) (int); 59 void (*cleanup) (int); 60 char *name; 61 } test_cases[] = { 62 {-1, (struct sockaddr *)&fsin1, &sinlen, -1, EBADF, NULL, NULL, 63 "EBADF"}, 64 {-1, (struct sockaddr *)&fsin1, &sinlen, -1, ENOTSOCK, setup2, cleanup2, 65 "ENOTSOCK"}, 66 {-1, (struct sockaddr *)&fsin1, &sinlen, -1, ENOTCONN, setup3, cleanup2, 67 "ENOTCONN"}, 68 {-1, (struct sockaddr *)&fsin1, &invalid_sinlen, -1, EINVAL, setup4, 69 cleanup4, "EINVAL"}, 70 #ifndef UCLINUX 71 {-1, (struct sockaddr *)-1, &sinlen, -1, EFAULT, setup4, cleanup4, 72 "EFAULT"}, 73 {-1, (struct sockaddr *)&fsin1, NULL, -1, EFAULT, setup4, 74 cleanup4, "EFAULT"}, 75 {-1, (struct sockaddr *)&fsin1, (socklen_t *)1, -1, EFAULT, setup4, 76 cleanup4, "EFAULT"}, 77 #endif 78 }; 79 80 char *TCID = "getpeername01"; 81 int TST_TOTAL = ARRAY_SIZE(test_cases); 82 83 int main(int argc, char *argv[]) 84 { 85 int lc; 86 int i; 87 88 tst_parse_opts(argc, argv, NULL, NULL); 89 90 setup(); 91 92 for (lc = 0; TEST_LOOPING(lc); ++lc) { 93 94 tst_count = 0; 95 96 for (i = 0; i < TST_TOTAL; ++i) { 97 98 if (test_cases[i].setup != NULL) 99 test_cases[i].setup(i); 100 101 TEST(getpeername(test_cases[i].sockfd, 102 test_cases[i].sockaddr, 103 test_cases[i].addrlen)); 104 105 if (TEST_RETURN == test_cases[i].expretval && 106 TEST_ERRNO == test_cases[i].experrno) { 107 tst_resm(TPASS, 108 "test getpeername() %s successful", 109 test_cases[i].name); 110 } else { 111 tst_resm(TFAIL, 112 "test getpeername() %s failed; " 113 "returned %ld (expected %d), errno %d " 114 "(expected %d)", test_cases[i].name, 115 TEST_RETURN, test_cases[i].expretval, 116 TEST_ERRNO, test_cases[i].experrno); 117 } 118 119 if (test_cases[i].cleanup != NULL) 120 test_cases[i].cleanup(i); 121 } 122 } 123 124 cleanup(); 125 126 tst_exit(); 127 } 128 129 static void setup(void) 130 { 131 TEST_PAUSE; 132 133 server_addr.sin_family = AF_INET; 134 server_addr.sin_port = 0; 135 server_addr.sin_addr.s_addr = INADDR_ANY; 136 137 sinlen = sizeof(fsin1); 138 } 139 140 static void cleanup(void) 141 { 142 } 143 144 static void setup2(int i) 145 { 146 test_cases[i].sockfd = SAFE_OPEN(cleanup, "/dev/null", O_WRONLY, 0666); 147 } 148 149 static void setup3(int i) 150 { 151 test_cases[i].sockfd = socket(PF_INET, SOCK_STREAM, 0); 152 if (test_cases[i].sockfd < 0) { 153 tst_brkm(TBROK | TERRNO, cleanup, 154 "socket setup failed for getpeername test %d", i); 155 } 156 SAFE_BIND(cleanup, test_cases[i].sockfd, 157 (struct sockaddr *)&server_addr, sizeof(server_addr)); 158 } 159 160 static void setup4(int i) 161 { 162 if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) < 0) { 163 tst_brkm(TBROK | TERRNO, cleanup, 164 "socketpair failed for getpeername test %d", i); 165 } 166 test_cases[i].sockfd = sv[0]; 167 } 168 169 static void cleanup2(int i) 170 { 171 SAFE_CLOSE(cleanup, test_cases[i].sockfd); 172 } 173 174 static void cleanup4(int i) 175 { 176 SAFE_CLOSE(cleanup, sv[0]); 177 SAFE_CLOSE(cleanup, sv[1]); 178 } 179