Home | History | Annotate | Download | only in getpeername
      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