accf_data_attach.c revision 147300
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: head/tools/regression/sockets/accf_data_attach/accf_data_attach.c 147300 2005-06-11 11:59:48Z maxim $
27132649Srwatson */
28132649Srwatson
29132649Srwatson#include <sys/types.h>
30132649Srwatson#include <sys/socket.h>
31132649Srwatson
32132649Srwatson#include <netinet/in.h>
33132649Srwatson
34132649Srwatson#include <err.h>
35132649Srwatson#include <errno.h>
36132649Srwatson#include <stdio.h>
37132649Srwatson#include <stdlib.h>
38132649Srwatson#include <string.h>
39132649Srwatson#include <unistd.h>
40132649Srwatson
41132649Srwatson#define	ACCF_NAME	"dataready"
42132649Srwatson
43132649Srwatson/*
44132649Srwatson * A number of small tests to confirm that attaching ACCF_DATA accept filters
45132649Srwatson * to inet4 ports works as expected.  We test:
46132649Srwatson *
47132649Srwatson * - That no accept filter is attached on a newly created socket.
48132649Srwatson * - That bind() has no affect on the accept filter state.
49132649Srwatson * - That we can't attach an accept filter to a socket that isn't in the
50132649Srwatson *   listen state.
51132649Srwatson * - That after we fail to attach the filter, querying the kernel shows no
52132649Srwatson *   filter attached.
53132649Srwatson * - That we can attach an accept filter to a socket that is in the listen
54132649Srwatson *   state.
55132649Srwatson * - That once an accept filter is attached, we can query to make sure it is
56132649Srwatson *   attached.
57147300Smaxim * - That once an accept filter is attached, we can remove it and query to
58147300Smaxim *   make sure it is removed.
59132649Srwatson */
60132649Srwatsonint
61132649Srwatsonmain(int argc, char *argv[])
62132649Srwatson{
63132649Srwatson	struct accept_filter_arg afa;
64132649Srwatson	struct sockaddr_in sin;
65132649Srwatson	socklen_t len;
66132649Srwatson	int lso, ret;
67132649Srwatson
68147300Smaxim	printf("1..11\n");
69137587Snik
70132649Srwatson	/*
71132649Srwatson	 * Step 0. Open socket().
72132649Srwatson	 */
73132649Srwatson	lso = socket(PF_INET, SOCK_STREAM, 0);
74132649Srwatson	if (lso == -1)
75137587Snik		errx(-1, "not ok 1 - socket: %s", strerror(errno));
76137587Snik	printf("ok 1 - socket\n");
77132649Srwatson
78132649Srwatson	/*
79132649Srwatson	 * Step 1. After socket().  Should return EINVAL, since no accept
80132649Srwatson	 * filter should be attached.
81132649Srwatson	 */
82132649Srwatson	bzero(&afa, sizeof(afa));
83132649Srwatson	len = sizeof(afa);
84132649Srwatson	ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len);
85136844Srwatson	if (ret != -1)
86137587Snik		errx(-1, "not ok 2 - getsockopt() after socket() succeeded");
87136844Srwatson	if (errno != EINVAL)
88137587Snik		errx(-1, "not ok 2 - getsockopt() after socket() failed with "
89136844Srwatson		    "%d (%s)", errno, strerror(errno));
90137587Snik	printf("ok 2 - getsockopt\n");
91132649Srwatson
92132649Srwatson	/*
93132649Srwatson	 * Step 2. Bind().  Ideally this will succeed.
94132649Srwatson	 */
95132649Srwatson	bzero(&sin, sizeof(sin));
96132649Srwatson	sin.sin_len = sizeof(sin);
97132649Srwatson	sin.sin_family = AF_INET;
98132649Srwatson	sin.sin_port = htons(8080);
99132649Srwatson	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
100132649Srwatson	if (bind(lso, (struct sockaddr *)&sin, sizeof(sin)) < 0)
101137587Snik		errx(-1, "not ok 3 - bind %s", strerror(errno));
102137587Snik	printf("ok 3 - bind\n");
103132649Srwatson
104132649Srwatson	/*
105132649Srwatson	 * Step 3: After bind().  getsockopt() should return EINVAL, since no
106132649Srwatson	 *  accept filter should be attached.
107132649Srwatson	 */
108132649Srwatson	len = sizeof(afa);
109132649Srwatson	ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len);
110136844Srwatson	if (ret != -1)
111137587Snik		errx(-1, "not ok 4 - getsockopt() after bind() succeeded");
112136844Srwatson	if (errno != EINVAL)
113137587Snik		errx(-1, "not ok 4 -  getsockopt() after bind() failed with %d (%s)",
114136844Srwatson		    errno, strerror(errno));
115137587Snik	printf("ok 4 - getsockopt\n");
116132649Srwatson
117132649Srwatson	/*
118132649Srwatson	 * Step 4: Setsockopt() before listen().  Should fail, since it's not
119132649Srwatson	 * yet a listen() socket.
120132649Srwatson	 */
121132649Srwatson	bzero(&afa, sizeof(afa));
122132649Srwatson	strcpy(afa.af_name, ACCF_NAME);
123132649Srwatson	ret = setsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa));
124136844Srwatson	if (ret == 0)
125137587Snik		errx(-1, "not ok 5 - setsockopt() before listen() succeeded");
126137587Snik	printf("ok 5 - setsockopt\n");
127132649Srwatson
128132649Srwatson	/*
129132649Srwatson	 * Step 5: Getsockopt() after pre-listen() setsockopt().  Should
130132649Srwatson	 * fail with EINVAL, since setsockopt() should have failed.
131132649Srwatson	 */
132132649Srwatson	len = sizeof(afa);
133132649Srwatson	ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len);
134136844Srwatson	if (ret == 0)
135137587Snik		errx(-1, "not ok 6 - getsockopt() after pre-listen() setsockopt() "
136136844Srwatson		    "succeeded");
137136844Srwatson	if (errno != EINVAL)
138137587Snik		errx(-1, "not ok 6 - pre-listen() getsockopt() failed with %d (%s)",
139136844Srwatson		    errno, strerror(errno));
140137587Snik	printf("ok 6 - getsockopt\n");
141132649Srwatson
142132649Srwatson	/*
143132649Srwatson	 * Step 6: listen().
144132649Srwatson	 */
145132649Srwatson	if (listen(lso, -1) < 0)
146137587Snik		errx(-1, "not ok 7 - listen: %s", strerror(errno));
147137587Snik	printf("ok 7 - listen\n");
148132649Srwatson
149132649Srwatson	/*
150147300Smaxim	 * Step 7: Getsockopt() after listen().  Should fail with EINVAL,
151147300Smaxim	 * since we have not installed accept filter yet.
152132649Srwatson	 */
153147300Smaxim	len = sizeof(afa);
154147300Smaxim	ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len);
155147300Smaxim	if (ret == 0)
156147300Smaxim		errx(-1, "not ok 8 - getsockopt() after listen() but before "
157147300Smaxim		    "setsockopt() succeeded");
158147300Smaxim	if (errno != EINVAL)
159147300Smaxim		errx(-1, "not ok 8 - getsockopt() after listen() but before "
160147300Smaxim		    "setsockopt() failed with %d (%s)", errno, strerror(errno));
161147300Smaxim	printf("ok 8 - getsockopt\n");
162147300Smaxim
163147300Smaxim	/*
164147300Smaxim	 * Step 8: After listen().  This call to setsockopt() should succeed.
165147300Smaxim	 */
166132649Srwatson	bzero(&afa, sizeof(afa));
167132649Srwatson	strcpy(afa.af_name, ACCF_NAME);
168132649Srwatson	ret = setsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa));
169136844Srwatson	if (ret != 0)
170147300Smaxim		errx(-1, "not ok 9 - setsockopt() after listen() failed with %d "
171136844Srwatson		    "(%s)", errno, strerror(errno));
172136844Srwatson	if (len != sizeof(afa))
173147300Smaxim		errx(-1, "not ok 9 - setsockopt() after listen() returned wrong "
174136844Srwatson		    "size (%d vs expected %d)", len, sizeof(afa));
175147300Smaxim	printf("ok 9 - setsockopt\n");
176132649Srwatson
177132649Srwatson	/*
178147300Smaxim	 * Step 9: After setsockopt().  Should succeed and identify
179132649Srwatson	 * ACCF_NAME.
180132649Srwatson	 */
181132649Srwatson	bzero(&afa, sizeof(afa));
182132649Srwatson	len = sizeof(afa);
183132649Srwatson	ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len);
184136844Srwatson	if (ret != 0)
185147300Smaxim		errx(-1, "not ok 10 - getsockopt() after listen() setsockopt() "
186136844Srwatson		    "failed with %d (%s)", errno, strerror(errno));
187136844Srwatson	if (len != sizeof(afa))
188147300Smaxim		errx(-1, "not ok 10 - getsockopt() after setsockopet()  after "
189136844Srwatson		    "listen() returned wrong size (got %d expected %d)", len,
190136844Srwatson		    sizeof(afa));
191136844Srwatson	if (strcmp(afa.af_name, ACCF_NAME) != 0)
192147300Smaxim		errx(-1, "not ok 10 - getsockopt() after setsockopt() after "
193136844Srwatson		    "listen() mismatch (got %s expected %s)", afa.af_name,
194136844Srwatson		    ACCF_NAME);
195147300Smaxim	printf("ok 10 - getsockopt\n");
196132649Srwatson
197147300Smaxim	/*
198147300Smaxim	 * Step 10: Remove accept filter.  After removing the accept filter
199147300Smaxim	 * getsockopt() should fail with EINVAL.
200147300Smaxim	 */
201147300Smaxim	ret = setsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, NULL, 0);
202147300Smaxim	if (ret != 0)
203147300Smaxim		errx(-1, "not ok 11 - setsockopt() after listen() "
204147300Smaxim		    "failed with %d (%s)", errno, strerror(errno));
205147300Smaxim	bzero(&afa, sizeof(afa));
206147300Smaxim	len = sizeof(afa);
207147300Smaxim	ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len);
208147300Smaxim	if (ret == 0)
209147300Smaxim		errx(-1, "not ok 11 - getsockopt() after removing "
210147300Smaxim		    "the accept filter returns valid accept filter %s",
211147300Smaxim		    afa.af_name);
212147300Smaxim	if (errno != EINVAL)
213147300Smaxim		errx(-1, "not ok 11 - getsockopt() after removing the accept"
214147300Smaxim		    "filter failed with %d (%s)", errno, strerror(errno));
215147300Smaxim	printf("ok 11 - setsockopt\n");
216147300Smaxim
217132649Srwatson	close(lso);
218132649Srwatson	return (0);
219132649Srwatson}
220