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 38static struct sockaddr_in server_addr; 39static struct sockaddr_in fsin1; 40static socklen_t sinlen; 41static socklen_t invalid_sinlen = -1; 42static int sv[2]; 43 44static void setup(void); 45static void setup2(int); 46static void setup3(int); 47static void setup4(int); 48static void cleanup(void); 49static void cleanup2(int); 50static void cleanup4(int); 51 52struct 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 80char *TCID = "getpeername01"; 81int TST_TOTAL = ARRAY_SIZE(test_cases); 82 83int 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 129static 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 140static void cleanup(void) 141{ 142} 143 144static void setup2(int i) 145{ 146 test_cases[i].sockfd = SAFE_OPEN(cleanup, "/dev/null", O_WRONLY, 0666); 147} 148 149static 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 if (bind(test_cases[i].sockfd, (struct sockaddr *)&server_addr, 157 sizeof(server_addr)) < 0) { 158 tst_brkm(TBROK | TERRNO, cleanup, 159 "socket bind failed for getpeername test %d", i); 160 } 161} 162 163static void setup4(int i) 164{ 165 if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) < 0) { 166 tst_brkm(TBROK | TERRNO, cleanup, 167 "socketpair failed for getpeername test %d", i); 168 } 169 test_cases[i].sockfd = sv[0]; 170} 171 172static void cleanup2(int i) 173{ 174 SAFE_CLOSE(cleanup, test_cases[i].sockfd); 175} 176 177static void cleanup4(int i) 178{ 179 SAFE_CLOSE(cleanup, sv[0]); 180 SAFE_CLOSE(cleanup, sv[1]); 181} 182