1132649Srwatson/*- 2132649Srwatson * Copyright (c) 2004 Robert N. M. Watson 3132649Srwatson * All rights reserved. 4132649Srwatson * 5132649Srwatson * Redistribution and use in source and binary forms, with or without 6132649Srwatson * modification, are permitted provided that the following conditions 7132649Srwatson * are met: 8132649Srwatson * 1. Redistributions of source code must retain the above copyright 9132649Srwatson * notice, this list of conditions and the following disclaimer. 10132649Srwatson * 2. Redistributions in binary form must reproduce the above copyright 11132649Srwatson * notice, this list of conditions and the following disclaimer in the 12132649Srwatson * documentation and/or other materials provided with the distribution. 13132649Srwatson * 14132649Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15132649Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16132649Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17132649Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18132649Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19132649Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20132649Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21132649Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22132649Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23132649Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24132649Srwatson * SUCH DAMAGE. 25132649Srwatson * 26132649Srwatson * $FreeBSD$ 27132649Srwatson */ 28132649Srwatson 29132649Srwatson#include <sys/types.h> 30294103Sngie#include <sys/module.h> 31132649Srwatson#include <sys/socket.h> 32132649Srwatson 33132649Srwatson#include <netinet/in.h> 34132649Srwatson 35132649Srwatson#include <err.h> 36132649Srwatson#include <errno.h> 37132649Srwatson#include <stdio.h> 38132649Srwatson#include <stdlib.h> 39132649Srwatson#include <string.h> 40132649Srwatson#include <unistd.h> 41132649Srwatson 42132649Srwatson#define ACCF_NAME "dataready" 43132649Srwatson 44132649Srwatson/* 45132649Srwatson * A number of small tests to confirm that attaching ACCF_DATA accept filters 46132649Srwatson * to inet4 ports works as expected. We test: 47132649Srwatson * 48132649Srwatson * - That no accept filter is attached on a newly created socket. 49132649Srwatson * - That bind() has no affect on the accept filter state. 50132649Srwatson * - That we can't attach an accept filter to a socket that isn't in the 51132649Srwatson * listen state. 52132649Srwatson * - That after we fail to attach the filter, querying the kernel shows no 53132649Srwatson * filter attached. 54132649Srwatson * - That we can attach an accept filter to a socket that is in the listen 55132649Srwatson * state. 56132649Srwatson * - That once an accept filter is attached, we can query to make sure it is 57132649Srwatson * attached. 58147300Smaxim * - That once an accept filter is attached, we can remove it and query to 59147300Smaxim * make sure it is removed. 60132649Srwatson */ 61132649Srwatsonint 62281355Sngiemain(void) 63132649Srwatson{ 64132649Srwatson struct accept_filter_arg afa; 65132649Srwatson struct sockaddr_in sin; 66132649Srwatson socklen_t len; 67132649Srwatson int lso, ret; 68132649Srwatson 69294103Sngie /* XXX: PLAIN_TEST_REQUIRE_MODULE "backport" for stable/9 */ 70294103Sngie const char *_mod_name = "accf_data"; 71294103Sngie 72294103Sngie if (modfind(_mod_name) == -1) { 73294103Sngie printf("1..0 # SKIP - module %s could not be resolved: %s\n", 74294103Sngie _mod_name, strerror(errno)); 75294103Sngie _exit(0); 76294103Sngie } 77294103Sngie /* XXX: PLAIN_TEST_REQUIRE_MODULE for stable/9 */ 78294103Sngie 79147300Smaxim printf("1..11\n"); 80137587Snik 81132649Srwatson /* 82132649Srwatson * Step 0. Open socket(). 83132649Srwatson */ 84132649Srwatson lso = socket(PF_INET, SOCK_STREAM, 0); 85132649Srwatson if (lso == -1) 86137587Snik errx(-1, "not ok 1 - socket: %s", strerror(errno)); 87137587Snik printf("ok 1 - socket\n"); 88132649Srwatson 89132649Srwatson /* 90132649Srwatson * Step 1. After socket(). Should return EINVAL, since no accept 91132649Srwatson * filter should be attached. 92132649Srwatson */ 93132649Srwatson bzero(&afa, sizeof(afa)); 94132649Srwatson len = sizeof(afa); 95132649Srwatson ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len); 96136844Srwatson if (ret != -1) 97137587Snik errx(-1, "not ok 2 - getsockopt() after socket() succeeded"); 98136844Srwatson if (errno != EINVAL) 99137587Snik errx(-1, "not ok 2 - getsockopt() after socket() failed with " 100136844Srwatson "%d (%s)", errno, strerror(errno)); 101137587Snik printf("ok 2 - getsockopt\n"); 102132649Srwatson 103132649Srwatson /* 104132649Srwatson * Step 2. Bind(). Ideally this will succeed. 105132649Srwatson */ 106132649Srwatson bzero(&sin, sizeof(sin)); 107132649Srwatson sin.sin_len = sizeof(sin); 108132649Srwatson sin.sin_family = AF_INET; 109132649Srwatson sin.sin_port = htons(8080); 110132649Srwatson sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 111132649Srwatson if (bind(lso, (struct sockaddr *)&sin, sizeof(sin)) < 0) 112137587Snik errx(-1, "not ok 3 - bind %s", strerror(errno)); 113137587Snik printf("ok 3 - bind\n"); 114132649Srwatson 115132649Srwatson /* 116132649Srwatson * Step 3: After bind(). getsockopt() should return EINVAL, since no 117132649Srwatson * accept filter should be attached. 118132649Srwatson */ 119132649Srwatson len = sizeof(afa); 120132649Srwatson ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len); 121136844Srwatson if (ret != -1) 122137587Snik errx(-1, "not ok 4 - getsockopt() after bind() succeeded"); 123136844Srwatson if (errno != EINVAL) 124137587Snik errx(-1, "not ok 4 - getsockopt() after bind() failed with %d (%s)", 125136844Srwatson errno, strerror(errno)); 126137587Snik printf("ok 4 - getsockopt\n"); 127132649Srwatson 128132649Srwatson /* 129132649Srwatson * Step 4: Setsockopt() before listen(). Should fail, since it's not 130132649Srwatson * yet a listen() socket. 131132649Srwatson */ 132132649Srwatson bzero(&afa, sizeof(afa)); 133294103Sngie strncpy(afa.af_name, ACCF_NAME, sizeof(afa.af_name)); 134132649Srwatson ret = setsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa)); 135136844Srwatson if (ret == 0) 136137587Snik errx(-1, "not ok 5 - setsockopt() before listen() succeeded"); 137137587Snik printf("ok 5 - setsockopt\n"); 138132649Srwatson 139132649Srwatson /* 140132649Srwatson * Step 5: Getsockopt() after pre-listen() setsockopt(). Should 141132649Srwatson * fail with EINVAL, since setsockopt() should have failed. 142132649Srwatson */ 143132649Srwatson len = sizeof(afa); 144132649Srwatson ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len); 145136844Srwatson if (ret == 0) 146137587Snik errx(-1, "not ok 6 - getsockopt() after pre-listen() setsockopt() " 147136844Srwatson "succeeded"); 148136844Srwatson if (errno != EINVAL) 149137587Snik errx(-1, "not ok 6 - pre-listen() getsockopt() failed with %d (%s)", 150136844Srwatson errno, strerror(errno)); 151137587Snik printf("ok 6 - getsockopt\n"); 152132649Srwatson 153132649Srwatson /* 154132649Srwatson * Step 6: listen(). 155132649Srwatson */ 156132649Srwatson if (listen(lso, -1) < 0) 157137587Snik errx(-1, "not ok 7 - listen: %s", strerror(errno)); 158137587Snik printf("ok 7 - listen\n"); 159132649Srwatson 160132649Srwatson /* 161147300Smaxim * Step 7: Getsockopt() after listen(). Should fail with EINVAL, 162147300Smaxim * since we have not installed accept filter yet. 163132649Srwatson */ 164147300Smaxim len = sizeof(afa); 165147300Smaxim ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len); 166147300Smaxim if (ret == 0) 167147300Smaxim errx(-1, "not ok 8 - getsockopt() after listen() but before " 168147300Smaxim "setsockopt() succeeded"); 169147300Smaxim if (errno != EINVAL) 170147300Smaxim errx(-1, "not ok 8 - getsockopt() after listen() but before " 171147300Smaxim "setsockopt() failed with %d (%s)", errno, strerror(errno)); 172147300Smaxim printf("ok 8 - getsockopt\n"); 173147300Smaxim 174147300Smaxim /* 175147300Smaxim * Step 8: After listen(). This call to setsockopt() should succeed. 176147300Smaxim */ 177132649Srwatson bzero(&afa, sizeof(afa)); 178294103Sngie strncpy(afa.af_name, ACCF_NAME, sizeof(afa.af_name)); 179132649Srwatson ret = setsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa)); 180136844Srwatson if (ret != 0) 181147300Smaxim errx(-1, "not ok 9 - setsockopt() after listen() failed with %d " 182136844Srwatson "(%s)", errno, strerror(errno)); 183147300Smaxim printf("ok 9 - setsockopt\n"); 184132649Srwatson 185132649Srwatson /* 186147300Smaxim * Step 9: After setsockopt(). Should succeed and identify 187132649Srwatson * ACCF_NAME. 188132649Srwatson */ 189132649Srwatson bzero(&afa, sizeof(afa)); 190132649Srwatson len = sizeof(afa); 191132649Srwatson ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len); 192136844Srwatson if (ret != 0) 193147300Smaxim errx(-1, "not ok 10 - getsockopt() after listen() setsockopt() " 194136844Srwatson "failed with %d (%s)", errno, strerror(errno)); 195136844Srwatson if (len != sizeof(afa)) 196147300Smaxim errx(-1, "not ok 10 - getsockopt() after setsockopet() after " 197197432Sjhb "listen() returned wrong size (got %d expected %zd)", len, 198136844Srwatson sizeof(afa)); 199136844Srwatson if (strcmp(afa.af_name, ACCF_NAME) != 0) 200147300Smaxim errx(-1, "not ok 10 - getsockopt() after setsockopt() after " 201136844Srwatson "listen() mismatch (got %s expected %s)", afa.af_name, 202136844Srwatson ACCF_NAME); 203147300Smaxim printf("ok 10 - getsockopt\n"); 204132649Srwatson 205147300Smaxim /* 206147300Smaxim * Step 10: Remove accept filter. After removing the accept filter 207147300Smaxim * getsockopt() should fail with EINVAL. 208147300Smaxim */ 209147300Smaxim ret = setsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, NULL, 0); 210147300Smaxim if (ret != 0) 211147300Smaxim errx(-1, "not ok 11 - setsockopt() after listen() " 212147300Smaxim "failed with %d (%s)", errno, strerror(errno)); 213147300Smaxim bzero(&afa, sizeof(afa)); 214147300Smaxim len = sizeof(afa); 215147300Smaxim ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len); 216147300Smaxim if (ret == 0) 217147300Smaxim errx(-1, "not ok 11 - getsockopt() after removing " 218147300Smaxim "the accept filter returns valid accept filter %s", 219147300Smaxim afa.af_name); 220147300Smaxim if (errno != EINVAL) 221147300Smaxim errx(-1, "not ok 11 - getsockopt() after removing the accept" 222147300Smaxim "filter failed with %d (%s)", errno, strerror(errno)); 223147300Smaxim printf("ok 11 - setsockopt\n"); 224147300Smaxim 225132649Srwatson close(lso); 226132649Srwatson return (0); 227132649Srwatson} 228