t_listen.c revision 276478
1241823Smarcel/* $NetBSD: t_listen.c,v 1.4 2012/03/18 07:00:52 jruoho Exp $ */ 2242710Ssjg/* 3242710Ssjg * Copyright (c) 2007 The NetBSD Foundation, Inc. 4242710Ssjg * All rights reserved. 5242710Ssjg * 6242710Ssjg * Redistribution and use in source and binary forms, with or without 7242710Ssjg * modification, are permitted provided that the following conditions 8242710Ssjg * are met: 9242710Ssjg * 1. Redistributions of source code must retain the above copyright 10242710Ssjg * notice, this list of conditions and the following disclaimer. 11242710Ssjg * 2. Redistributions in binary form must reproduce the above copyright 12242710Ssjg * notice, this list of conditions and the following disclaimer in the 13242710Ssjg * documentation and/or other materials provided with the distribution. 14242710Ssjg * 15242710Ssjg * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 16241823Smarcel * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 17242710Ssjg * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18241823Smarcel * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19258095Ssjg * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 20258095Ssjg * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21258095Ssjg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 22241823Smarcel * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23242710Ssjg * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 24242710Ssjg * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25290870Sngie * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26298012Sngie * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27304144Sbdrewery */ 28304144Sbdrewery 29242710Ssjg#include <atf-c.h> 30272055Sngie#include <err.h> 31272055Sngie#include <errno.h> 32272055Sngie#include <fcntl.h> 33272055Sngie#include <string.h> 34272055Sngie#include <unistd.h> 35272055Sngie 36258095Ssjg#include <arpa/inet.h> 37346919Sngie#include <netinet/in.h> 38346919Sngie 39346919Sngie#ifdef __FreeBSD__ 40346919Sngie#include <sys/socket.h> 41346919Sngie#endif 42258095Ssjg 43249770Ssjgstatic const char *path = "listen"; 44242710Ssjg 45241823SmarcelATF_TC_WITH_CLEANUP(listen_err); 46296553SbdreweryATF_TC_HEAD(listen_err, tc) 47296553Sbdrewery{ 48296553Sbdrewery atf_tc_set_md_var(tc, "descr", 49296553Sbdrewery "Checks errors from listen(2) (PR standards/46150)"); 50296553Sbdrewery} 51296553Sbdrewery 52296553SbdreweryATF_TC_BODY(listen_err, tc) 53296553Sbdrewery{ 54296553Sbdrewery static const size_t siz = sizeof(struct sockaddr_in); 55296553Sbdrewery struct sockaddr_in sina, sinb; 56296553Sbdrewery int fda, fdb, fdc; 57296553Sbdrewery 58241823Smarcel (void)memset(&sina, 0, sizeof(struct sockaddr_in)); 59296553Sbdrewery (void)memset(&sinb, 0, sizeof(struct sockaddr_in)); 60241823Smarcel 61242710Ssjg sina.sin_family = AF_INET; 62289289Sbdrewery sina.sin_port = htons(31522); 63296121Sbdrewery sina.sin_addr.s_addr = inet_addr("127.0.0.1"); 64288158Sbdrewery 65296121Sbdrewery sinb.sin_family = AF_INET; 66241823Smarcel sinb.sin_port = htons(31522); 67296553Sbdrewery sinb.sin_addr.s_addr = inet_addr("127.0.0.1"); 68296122Sbdrewery 69296555Sbdrewery fda = socket(AF_INET, SOCK_STREAM, 0); 70296555Sbdrewery fdb = socket(AF_INET, SOCK_STREAM, 0); 71296555Sbdrewery fdc = open("listen", O_RDWR | O_CREAT, 0600); 72296555Sbdrewery 73296555Sbdrewery ATF_REQUIRE(fda >= 0 && fdb >= 0 && fdc >= 0); 74296555Sbdrewery ATF_REQUIRE_ERRNO(ENOTSOCK, listen(fdc, 1) == -1); 75296555Sbdrewery 76296555Sbdrewery (void)close(fdc); 77296555Sbdrewery (void)unlink(path); 78241823Smarcel 79288158Sbdrewery ATF_REQUIRE(bind(fda, (struct sockaddr *)&sina, siz) == 0); 80241823Smarcel ATF_REQUIRE(listen(fda, 1) == 0); 81288158Sbdrewery 82274079Sngie /* 83296122Sbdrewery * According to IEEE Std 1003.1-2008: if the socket is 84296122Sbdrewery * already connected, the call should fail with EINVAL. 85296000Sbdrewery */ 86296000Sbdrewery ATF_REQUIRE(connect(fdb, (struct sockaddr *)&sinb, siz) == 0); 87288158Sbdrewery ATF_REQUIRE_ERRNO(EINVAL, listen(fdb, 1) == -1); 88288158Sbdrewery 89288158Sbdrewery (void)close(fda); 90274079Sngie (void)close(fdb); 91274079Sngie 92242710Ssjg ATF_REQUIRE_ERRNO(EBADF, connect(fdb, 93258095Ssjg (struct sockaddr *)&sinb, siz) == -1); 94241823Smarcel} 95318332Sbdrewery 96289286SbdreweryATF_TC_CLEANUP(listen_err, tc) 97289286Sbdrewery{ 98289286Sbdrewery (void)unlink(path); 99289286Sbdrewery} 100242710Ssjg 101289286SbdreweryATF_TC(listen_low_port); 102289286SbdreweryATF_TC_HEAD(listen_low_port, tc) 103289286Sbdrewery{ 104289286Sbdrewery atf_tc_set_md_var(tc, "descr", "Does low-port allocation work?"); 105289286Sbdrewery atf_tc_set_md_var(tc, "require.user", "root"); 106289286Sbdrewery} 107289286Sbdrewery 108289286SbdreweryATF_TC_BODY(listen_low_port, tc) 109289286Sbdrewery{ 110291340Sbdrewery int sd, val; 111291340Sbdrewery 112291340Sbdrewery sd = socket(AF_INET, SOCK_STREAM, 0); 113291338Sbdrewery 114318332Sbdrewery val = IP_PORTRANGE_LOW; 115318332Sbdrewery if (setsockopt(sd, IPPROTO_IP, IP_PORTRANGE, &val, 116318332Sbdrewery sizeof(val)) == -1) 117318332Sbdrewery atf_tc_fail("setsockopt failed: %s", strerror(errno)); 118318332Sbdrewery 119318332Sbdrewery if (listen(sd, 5) == -1) { 120318332Sbdrewery int serrno = errno; 121318332Sbdrewery atf_tc_fail("listen failed: %s%s", 122318332Sbdrewery strerror(serrno), 123318332Sbdrewery serrno != EACCES ? "" : 124335643Sbdrewery " (see http://mail-index.netbsd.org/" 125335643Sbdrewery "source-changes/2007/12/16/0011.html)"); 126335643Sbdrewery } 127335643Sbdrewery 128335643Sbdrewery close(sd); 129335643Sbdrewery} 130335643Sbdrewery 131335643SbdreweryATF_TP_ADD_TCS(tp) 132335643Sbdrewery{ 133335643Sbdrewery 134318332Sbdrewery ATF_TP_ADD_TC(tp, listen_err); 135318332Sbdrewery ATF_TP_ADD_TC(tp, listen_low_port); 136318332Sbdrewery 137289286Sbdrewery return 0; 138289286Sbdrewery} 139289286Sbdrewery