shutdown.c revision 150043
1174704Skmacy/*-
2174704Skmacy * Copyright (C) 2005 The FreeBSD Project.  All rights reserved.
3174704Skmacy *
4174704Skmacy * Redistribution and use in source and binary forms, with or without
5174704Skmacy * modification, are permitted provided that the following conditions
6174704Skmacy * are met:
7174704Skmacy * 1. Redistributions of source code must retain the above copyright
8174704Skmacy *    notice, this list of conditions and the following disclaimer.
9174704Skmacy * 2. Redistributions in binary form must reproduce the above copyright
10174704Skmacy *    notice, this list of conditions and the following disclaimer in the
11174704Skmacy *    documentation and/or other materials provided with the distribution.
12174704Skmacy *
13174704Skmacy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14174704Skmacy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15174704Skmacy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16174704Skmacy * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17174704Skmacy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18174704Skmacy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19174704Skmacy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20174704Skmacy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21174704Skmacy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22174704Skmacy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23174704Skmacy * SUCH DAMAGE.
24174704Skmacy *
25174704Skmacy * $FreeBSD: head/tools/regression/sockets/shutdown/shutdown.c 150043 2005-09-12 14:12:09Z maxim $
26174704Skmacy */
27174704Skmacy
28174704Skmacy#include <sys/types.h>
29174704Skmacy#include <sys/socket.h>
30174704Skmacy
31174704Skmacy#include <netinet/in.h>
32174704Skmacy#include <arpa/inet.h>
33174704Skmacy
34174704Skmacy#include <err.h>
35174704Skmacy#include <errno.h>
36174704Skmacy#include <stdio.h>
37174704Skmacy#include <string.h>
38174704Skmacy#include <unistd.h>
39174704Skmacy
40181803Sbzint
41174704Skmacymain(void)
42174704Skmacy{
43174704Skmacy	struct sockaddr_in sock;
44174704Skmacy	socklen_t len;
45174704Skmacy	int listen_sock, connect_sock;
46174704Skmacy	u_short port;
47174704Skmacy
48174704Skmacy	/* Shutdown(2) on an invalid file descriptor has to return EBADF. */
49174704Skmacy	if ((shutdown(listen_sock, SHUT_RDWR) != -1) && (errno != EBADF))
50174704Skmacy		errx(-1, "shutdown() for invalid file descriptor does not "
51174704Skmacy		    "return EBADF");
52174704Skmacy
53174704Skmacy	listen_sock = socket(PF_INET, SOCK_STREAM, 0);
54182591Skmacy	if (listen_sock == -1)
55182591Skmacy		errx(-1,
56174704Skmacy		    "socket(PF_INET, SOCK_STREAM, 0) for listen socket: %s",
57174704Skmacy		    strerror(errno));
58174704Skmacy
59174704Skmacy	bzero(&sock, sizeof(sock));
60174704Skmacy	sock.sin_len = sizeof(sock);
61174704Skmacy	sock.sin_family = AF_INET;
62174704Skmacy	sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
63174704Skmacy	sock.sin_port = 0;
64182591Skmacy
65182591Skmacy	if (bind(listen_sock, (struct sockaddr *)&sock, sizeof(sock)) < 0)
66182591Skmacy		errx(-1, "bind(%s, %d) for listen socket: %s",
67174704Skmacy		    inet_ntoa(sock.sin_addr), sock.sin_port, strerror(errno));
68174704Skmacy
69174704Skmacy	len = sizeof(sock);
70174704Skmacy	if (getsockname(listen_sock, (struct sockaddr *)&sock, &len) < 0)
71174704Skmacy		errx(-1, "getsockname() for listen socket: %s",
72182591Skmacy		    strerror(errno));
73174704Skmacy	port = sock.sin_port;
74174704Skmacy
75174704Skmacy	if (listen(listen_sock, -1) < 0)
76174704Skmacy		errx(-1, "listen() for listen socket: %s", strerror(errno));
77174704Skmacy
78174704Skmacy	/* Shutdown(2) on not connected socket has to return ENOTCONN. */
79174704Skmacy	if ((shutdown(listen_sock, SHUT_RDWR) != -1) && (errno != ENOTCONN))
80174704Skmacy		errx(-1, "shutdown(2) for not connected socket does not "
81174704Skmacy		    "return ENOTCONN");
82174704Skmacy	connect_sock = socket(PF_INET, SOCK_STREAM, 0);
83174704Skmacy	if (connect_sock == -1)
84174704Skmacy		errx(-1, "socket(PF_INET, SOCK_STREAM, 0) for connect "
85174704Skmacy		    "socket: %s", strerror(errno));
86174704Skmacy
87174704Skmacy	bzero(&sock, sizeof(sock));
88174704Skmacy	sock.sin_len = sizeof(sock);
89174704Skmacy	sock.sin_family = AF_INET;
90174704Skmacy	sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
91174704Skmacy	sock.sin_port = port;
92174704Skmacy
93174704Skmacy	if (connect(connect_sock, (struct sockaddr *)&sock, sizeof(sock)) < 0)
94174704Skmacy		errx(-1, "connect() for connect socket: %s", strerror(errno));
95174704Skmacy	/* Try to pass an invalid flags. */
96174704Skmacy	if ((shutdown(connect_sock, SHUT_RD - 1) != -1) && (errno != EINVAL))
97174704Skmacy		errx(-1, "shutdown(SHUT_RD - 1) does not return EINVAL");
98174704Skmacy	if ((shutdown(connect_sock, SHUT_RDWR + 1) != -1) && (errno != EINVAL))
99174704Skmacy		errx(-1, "shutdown(SHUT_RDWR + 1) does not return EINVAL");
100180648Skmacy
101180648Skmacy	if (shutdown(connect_sock, SHUT_RD) < 0)
102180648Skmacy		errx(-1, "shutdown(SHUT_RD) for connect socket: %s",
103180648Skmacy		    strerror(errno));
104180648Skmacy	if (shutdown(connect_sock, SHUT_WR) < 0)
105180648Skmacy		errx(-1, "shutdown(SHUT_WR) for connect socket: %s",
106180648Skmacy		    strerror(errno));
107180648Skmacy
108180648Skmacy	if ((shutdown(connect_sock, SHUT_RDWR) != -1) && (errno != ENOTCONN))
109180648Skmacy		errx(-1, "shutdown(2) for not connected socket does not "
110180648Skmacy		    "return ENOTCONN");
111181803Sbz	close(connect_sock);
112180674Skmacy	close(listen_sock);
113180648Skmacy
114181803Sbz	return (0);
115180648Skmacy}
116180648Skmacy