1150043Smaxim/*- 2150043Smaxim * Copyright (C) 2005 The FreeBSD Project. All rights reserved. 3150043Smaxim * 4150043Smaxim * Redistribution and use in source and binary forms, with or without 5150043Smaxim * modification, are permitted provided that the following conditions 6150043Smaxim * are met: 7150043Smaxim * 1. Redistributions of source code must retain the above copyright 8150043Smaxim * notice, this list of conditions and the following disclaimer. 9150043Smaxim * 2. Redistributions in binary form must reproduce the above copyright 10150043Smaxim * notice, this list of conditions and the following disclaimer in the 11150043Smaxim * documentation and/or other materials provided with the distribution. 12150043Smaxim * 13150043Smaxim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14150043Smaxim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15150043Smaxim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16150043Smaxim * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17150043Smaxim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18150043Smaxim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19150043Smaxim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20150043Smaxim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21150043Smaxim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22150043Smaxim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23150043Smaxim * SUCH DAMAGE. 24150043Smaxim * 25150043Smaxim * $FreeBSD$ 26150043Smaxim */ 27150043Smaxim 28150043Smaxim#include <sys/types.h> 29150043Smaxim#include <sys/socket.h> 30150043Smaxim 31150043Smaxim#include <netinet/in.h> 32150043Smaxim#include <arpa/inet.h> 33150043Smaxim 34150043Smaxim#include <err.h> 35150043Smaxim#include <errno.h> 36150043Smaxim#include <stdio.h> 37150043Smaxim#include <string.h> 38150043Smaxim#include <unistd.h> 39150043Smaxim 40150043Smaximint 41150043Smaximmain(void) 42150043Smaxim{ 43150043Smaxim struct sockaddr_in sock; 44150043Smaxim socklen_t len; 45150043Smaxim int listen_sock, connect_sock; 46150043Smaxim u_short port; 47150043Smaxim 48150043Smaxim /* Shutdown(2) on an invalid file descriptor has to return EBADF. */ 49150043Smaxim if ((shutdown(listen_sock, SHUT_RDWR) != -1) && (errno != EBADF)) 50150043Smaxim errx(-1, "shutdown() for invalid file descriptor does not " 51150043Smaxim "return EBADF"); 52150043Smaxim 53150043Smaxim listen_sock = socket(PF_INET, SOCK_STREAM, 0); 54150043Smaxim if (listen_sock == -1) 55150043Smaxim errx(-1, 56150043Smaxim "socket(PF_INET, SOCK_STREAM, 0) for listen socket: %s", 57150043Smaxim strerror(errno)); 58150043Smaxim 59150043Smaxim bzero(&sock, sizeof(sock)); 60150043Smaxim sock.sin_len = sizeof(sock); 61150043Smaxim sock.sin_family = AF_INET; 62150043Smaxim sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 63150043Smaxim sock.sin_port = 0; 64150043Smaxim 65150043Smaxim if (bind(listen_sock, (struct sockaddr *)&sock, sizeof(sock)) < 0) 66150043Smaxim errx(-1, "bind(%s, %d) for listen socket: %s", 67150043Smaxim inet_ntoa(sock.sin_addr), sock.sin_port, strerror(errno)); 68150043Smaxim 69150043Smaxim len = sizeof(sock); 70150043Smaxim if (getsockname(listen_sock, (struct sockaddr *)&sock, &len) < 0) 71150043Smaxim errx(-1, "getsockname() for listen socket: %s", 72150043Smaxim strerror(errno)); 73150043Smaxim port = sock.sin_port; 74150043Smaxim 75150043Smaxim if (listen(listen_sock, -1) < 0) 76150043Smaxim errx(-1, "listen() for listen socket: %s", strerror(errno)); 77150043Smaxim 78150043Smaxim connect_sock = socket(PF_INET, SOCK_STREAM, 0); 79150043Smaxim if (connect_sock == -1) 80150043Smaxim errx(-1, "socket(PF_INET, SOCK_STREAM, 0) for connect " 81150043Smaxim "socket: %s", strerror(errno)); 82150043Smaxim 83150043Smaxim bzero(&sock, sizeof(sock)); 84150043Smaxim sock.sin_len = sizeof(sock); 85150043Smaxim sock.sin_family = AF_INET; 86150043Smaxim sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 87150043Smaxim sock.sin_port = port; 88150043Smaxim 89150043Smaxim if (connect(connect_sock, (struct sockaddr *)&sock, sizeof(sock)) < 0) 90150043Smaxim errx(-1, "connect() for connect socket: %s", strerror(errno)); 91150043Smaxim /* Try to pass an invalid flags. */ 92150043Smaxim if ((shutdown(connect_sock, SHUT_RD - 1) != -1) && (errno != EINVAL)) 93150043Smaxim errx(-1, "shutdown(SHUT_RD - 1) does not return EINVAL"); 94150043Smaxim if ((shutdown(connect_sock, SHUT_RDWR + 1) != -1) && (errno != EINVAL)) 95150043Smaxim errx(-1, "shutdown(SHUT_RDWR + 1) does not return EINVAL"); 96150043Smaxim 97150043Smaxim if (shutdown(connect_sock, SHUT_RD) < 0) 98150043Smaxim errx(-1, "shutdown(SHUT_RD) for connect socket: %s", 99150043Smaxim strerror(errno)); 100150043Smaxim if (shutdown(connect_sock, SHUT_WR) < 0) 101150043Smaxim errx(-1, "shutdown(SHUT_WR) for connect socket: %s", 102150043Smaxim strerror(errno)); 103150043Smaxim 104150043Smaxim close(connect_sock); 105150043Smaxim close(listen_sock); 106150043Smaxim 107150043Smaxim return (0); 108150043Smaxim} 109