accf_data_attach.c revision 294303
166458Sdfr/*-
266458Sdfr * Copyright (c) 2004 Robert N. M. Watson
366458Sdfr * All rights reserved.
466458Sdfr *
566458Sdfr * Redistribution and use in source and binary forms, with or without
666458Sdfr * modification, are permitted provided that the following conditions
766458Sdfr * are met:
866458Sdfr * 1. Redistributions of source code must retain the above copyright
966458Sdfr *    notice, this list of conditions and the following disclaimer.
1066458Sdfr * 2. Redistributions in binary form must reproduce the above copyright
1166458Sdfr *    notice, this list of conditions and the following disclaimer in the
1266458Sdfr *    documentation and/or other materials provided with the distribution.
1366458Sdfr *
1466458Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1566458Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1666458Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1766458Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1866458Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1966458Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2066458Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2166458Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2266458Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2366458Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2466458Sdfr * SUCH DAMAGE.
2566458Sdfr *
2666458Sdfr * $FreeBSD: stable/10/tools/regression/sockets/accf_data_attach/accf_data_attach.c 294303 2016-01-19 01:38:06Z ngie $
2766458Sdfr */
2866458Sdfr
2971785Speter#include <sys/types.h>
3066458Sdfr#include <sys/module.h>
3166458Sdfr#include <sys/socket.h>
3266458Sdfr
3366458Sdfr#include <netinet/in.h>
3466458Sdfr
3566458Sdfr#include <err.h>
3666458Sdfr#include <errno.h>
3766458Sdfr#include <stdio.h>
3866458Sdfr#include <stdlib.h>
3966458Sdfr#include <string.h>
4066458Sdfr#include <unistd.h>
41205713Smarcel
4266458Sdfr#define	ACCF_NAME	"dataready"
4366458Sdfr
44143796Siedowse/*
4592843Salfred * A number of small tests to confirm that attaching ACCF_DATA accept filters
46143796Siedowse * to inet4 ports works as expected.  We test:
4766458Sdfr *
48143796Siedowse * - That no accept filter is attached on a newly created socket.
49143796Siedowse * - That bind() has no affect on the accept filter state.
50143796Siedowse * - That we can't attach an accept filter to a socket that isn't in the
51143796Siedowse *   listen state.
52143796Siedowse * - That after we fail to attach the filter, querying the kernel shows no
53143796Siedowse *   filter attached.
5471785Speter * - That we can attach an accept filter to a socket that is in the listen
5566458Sdfr *   state.
5666458Sdfr * - That once an accept filter is attached, we can query to make sure it is
5766458Sdfr *   attached.
5866458Sdfr * - That once an accept filter is attached, we can remove it and query to
5966458Sdfr *   make sure it is removed.
6066458Sdfr */
6166458Sdfrint
6266458Sdfrmain(void)
63143796Siedowse{
64143796Siedowse	struct accept_filter_arg afa;
65146794Smarcel	struct sockaddr_in sin;
66146794Smarcel	socklen_t len;
67143796Siedowse	int lso, ret;
68143796Siedowse
69143796Siedowse	/* XXX: PLAIN_TEST_REQUIRE_MODULE "backport" for stable/9 */
7066458Sdfr	const char *_mod_name = "accf_data";
7166458Sdfr
72146791Smarcel	if (modfind(_mod_name) == -1) {
7366458Sdfr		printf("1..0 # SKIP - module %s could not be resolved: %s\n",
7466458Sdfr		    _mod_name, strerror(errno));
7566458Sdfr		_exit(0);
7666458Sdfr	}
7766458Sdfr	/* XXX: PLAIN_TEST_REQUIRE_MODULE for stable/9 */
7871785Speter
7966458Sdfr	printf("1..11\n");
8066458Sdfr
8166458Sdfr	/*
82143796Siedowse	 * Step 0. Open socket().
8366458Sdfr	 */
84143796Siedowse	lso = socket(PF_INET, SOCK_STREAM, 0);
85143796Siedowse	if (lso == -1)
86143796Siedowse		errx(-1, "not ok 1 - socket: %s", strerror(errno));
87143796Siedowse	printf("ok 1 - socket\n");
88205713Smarcel
8966458Sdfr	/*
90205726Smarcel	 * Step 1. After socket().  Should return EINVAL, since no accept
91205713Smarcel	 * filter should be attached.
9266458Sdfr	 */
9366458Sdfr	bzero(&afa, sizeof(afa));
94	len = sizeof(afa);
95	ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len);
96	if (ret != -1)
97		errx(-1, "not ok 2 - getsockopt() after socket() succeeded");
98	if (errno != EINVAL)
99		errx(-1, "not ok 2 - getsockopt() after socket() failed with "
100		    "%d (%s)", errno, strerror(errno));
101	printf("ok 2 - getsockopt\n");
102
103	/*
104	 * Step 2. Bind().  Ideally this will succeed.
105	 */
106	bzero(&sin, sizeof(sin));
107	sin.sin_len = sizeof(sin);
108	sin.sin_family = AF_INET;
109	sin.sin_port = htons(8080);
110	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
111	if (bind(lso, (struct sockaddr *)&sin, sizeof(sin)) < 0)
112		errx(-1, "not ok 3 - bind %s", strerror(errno));
113	printf("ok 3 - bind\n");
114
115	/*
116	 * Step 3: After bind().  getsockopt() should return EINVAL, since no
117	 *  accept filter should be attached.
118	 */
119	len = sizeof(afa);
120	ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len);
121	if (ret != -1)
122		errx(-1, "not ok 4 - getsockopt() after bind() succeeded");
123	if (errno != EINVAL)
124		errx(-1, "not ok 4 -  getsockopt() after bind() failed with %d (%s)",
125		    errno, strerror(errno));
126	printf("ok 4 - getsockopt\n");
127
128	/*
129	 * Step 4: Setsockopt() before listen().  Should fail, since it's not
130	 * yet a listen() socket.
131	 */
132	bzero(&afa, sizeof(afa));
133	strncpy(afa.af_name, ACCF_NAME, sizeof(afa.af_name));
134	ret = setsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa));
135	if (ret == 0)
136		errx(-1, "not ok 5 - setsockopt() before listen() succeeded");
137	printf("ok 5 - setsockopt\n");
138
139	/*
140	 * Step 5: Getsockopt() after pre-listen() setsockopt().  Should
141	 * fail with EINVAL, since setsockopt() should have failed.
142	 */
143	len = sizeof(afa);
144	ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len);
145	if (ret == 0)
146		errx(-1, "not ok 6 - getsockopt() after pre-listen() setsockopt() "
147		    "succeeded");
148	if (errno != EINVAL)
149		errx(-1, "not ok 6 - pre-listen() getsockopt() failed with %d (%s)",
150		    errno, strerror(errno));
151	printf("ok 6 - getsockopt\n");
152
153	/*
154	 * Step 6: listen().
155	 */
156	if (listen(lso, -1) < 0)
157		errx(-1, "not ok 7 - listen: %s", strerror(errno));
158	printf("ok 7 - listen\n");
159
160	/*
161	 * Step 7: Getsockopt() after listen().  Should fail with EINVAL,
162	 * since we have not installed accept filter yet.
163	 */
164	len = sizeof(afa);
165	ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len);
166	if (ret == 0)
167		errx(-1, "not ok 8 - getsockopt() after listen() but before "
168		    "setsockopt() succeeded");
169	if (errno != EINVAL)
170		errx(-1, "not ok 8 - getsockopt() after listen() but before "
171		    "setsockopt() failed with %d (%s)", errno, strerror(errno));
172	printf("ok 8 - getsockopt\n");
173
174	/*
175	 * Step 8: After listen().  This call to setsockopt() should succeed.
176	 */
177	bzero(&afa, sizeof(afa));
178	strncpy(afa.af_name, ACCF_NAME, sizeof(afa.af_name));
179	ret = setsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa));
180	if (ret != 0)
181		errx(-1, "not ok 9 - setsockopt() after listen() failed with %d "
182		    "(%s)", errno, strerror(errno));
183	printf("ok 9 - setsockopt\n");
184
185	/*
186	 * Step 9: After setsockopt().  Should succeed and identify
187	 * ACCF_NAME.
188	 */
189	bzero(&afa, sizeof(afa));
190	len = sizeof(afa);
191	ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len);
192	if (ret != 0)
193		errx(-1, "not ok 10 - getsockopt() after listen() setsockopt() "
194		    "failed with %d (%s)", errno, strerror(errno));
195	if (len != sizeof(afa))
196		errx(-1, "not ok 10 - getsockopt() after setsockopet()  after "
197		    "listen() returned wrong size (got %d expected %zd)", len,
198		    sizeof(afa));
199	if (strcmp(afa.af_name, ACCF_NAME) != 0)
200		errx(-1, "not ok 10 - getsockopt() after setsockopt() after "
201		    "listen() mismatch (got %s expected %s)", afa.af_name,
202		    ACCF_NAME);
203	printf("ok 10 - getsockopt\n");
204
205	/*
206	 * Step 10: Remove accept filter.  After removing the accept filter
207	 * getsockopt() should fail with EINVAL.
208	 */
209	ret = setsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, NULL, 0);
210	if (ret != 0)
211		errx(-1, "not ok 11 - setsockopt() after listen() "
212		    "failed with %d (%s)", errno, strerror(errno));
213	bzero(&afa, sizeof(afa));
214	len = sizeof(afa);
215	ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len);
216	if (ret == 0)
217		errx(-1, "not ok 11 - getsockopt() after removing "
218		    "the accept filter returns valid accept filter %s",
219		    afa.af_name);
220	if (errno != EINVAL)
221		errx(-1, "not ok 11 - getsockopt() after removing the accept"
222		    "filter failed with %d (%s)", errno, strerror(errno));
223	printf("ok 11 - setsockopt\n");
224
225	close(lso);
226	return (0);
227}
228