Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 11 Jun 2005 02:36:41 -0700
From:      Alfred Perlstein <alfred@freebsd.org>
To:        Maxim Konovalov <maxim@macomnet.ru>
Cc:        freebsd-net@freebsd.org, Igor Sysoev <is@rambler-co.ru>, rwatson@freebsd.org
Subject:   Re: setsockopt() can not remove the accept filter
Message-ID:  <20050611093640.GB17867@elvis.mu.org>
In-Reply-To: <20050611111530.I5448@mp2.macomnet.net>
References:  <20050611020140.R27835@is.park.rambler.ru> <20050611111530.I5448@mp2.macomnet.net>

next in thread | previous in thread | raw e-mail | index | archive | help
Looks cool.  Can you commit it?  Or should I?

* Maxim Konovalov <maxim@macomnet.ru> [050611 00:25] wrote:
> [ CC'ed rwatson ]
> 
> On Sat, 11 Jun 2005, 02:12+0400, Igor Sysoev wrote:
> 
> > Hi,
> >
> > man setsockopt(2) states that "passing in an optval of NULL will remove
> > the filter", however, setsockopt() always return EINVAL in this case,
> > because do_setopt_accept_filter() removes the filter if sopt == NULL, but
> > not if sopt->val == NULL.  The fix is easy:
> >
> > -        if (sopt == NULL) {
> > +        if (sopt == NULL || sopt->val == NULL) {
> 
> Yep, your observation is correct.  The second (mis)feature:
> getsockopt(SO_ACCEPTFILTER) always returns success on listen socket
> even we didn't install accept filter on the socket.
> 
> I extended the regression test for accept filter for these bugs.
> That makes the name of the test misleading though because now it tests
> detach case as well.
> 
> Index: sys/kern/uipc_accf.c
> ===================================================================
> RCS file: /home/ncvs/src/sys/kern/uipc_accf.c,v
> retrieving revision 1.18
> diff -u -p -r1.18 uipc_accf.c
> --- sys/kern/uipc_accf.c	12 Mar 2005 12:57:17 -0000	1.18
> +++ sys/kern/uipc_accf.c	11 Jun 2005 06:53:47 -0000
> @@ -176,8 +176,10 @@ do_getopt_accept_filter(struct socket *s
>  		error = EINVAL;
>  		goto out;
>  	}
> -	if ((so->so_options & SO_ACCEPTFILTER) == 0)
> +	if ((so->so_options & SO_ACCEPTFILTER) == 0) {
> +		error = EINVAL;
>  		goto out;
> +	}
>  	strcpy(afap->af_name, so->so_accf->so_accept_filter->accf_name);
>  	if (so->so_accf->so_accept_filter_str != NULL)
>  		strcpy(afap->af_arg, so->so_accf->so_accept_filter_str);
> @@ -200,7 +202,7 @@ do_setopt_accept_filter(struct socket *s
>  	/*
>  	 * Handle the simple delete case first.
>  	 */
> -	if (sopt == NULL) {
> +	if (sopt == NULL || sopt->sopt_val == NULL) {
>  		SOCK_LOCK(so);
>  		if ((so->so_options & SO_ACCEPTCONN) == 0) {
>  			SOCK_UNLOCK(so);
> Index: tools/regression/sockets/accf_data_attach/accf_data_attach.c
> ===================================================================
> RCS file: /home/ncvs/src/tools/regression/sockets/accf_data_attach/accf_data_attach.c,v
> retrieving revision 1.3
> diff -u -p -r1.3 accf_data_attach.c
> --- tools/regression/sockets/accf_data_attach/accf_data_attach.c	11 Nov 2004 19:47:53 -0000	1.3
> +++ tools/regression/sockets/accf_data_attach/accf_data_attach.c	11 Jun 2005 07:06:41 -0000
> @@ -54,6 +54,8 @@
>   *   state.
>   * - That once an accept filter is attached, we can query to make sure it is
>   *   attached.
> + * - That once an accept filter is attached, we can remove it and query to
> + *   make sure it is removed.
>   */
>  int
>  main(int argc, char *argv[])
> @@ -145,38 +147,72 @@ main(int argc, char *argv[])
>  	printf("ok 7 - listen\n");
> 
>  	/*
> -	 * Step 7: After listen().  This call to setsockopt() should succeed.
> +	 * Step 7: Getsockopt() after listen().  Should fail with EINVAL,
> +	 * since we have not installed accept filter yep.
> +	 */
> +	len = sizeof(afa);
> +	ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len);
> +	if (ret == 0)
> +		errx(-1, "not ok 8 - getsockopt() after listen() but before "
> +		    "setsockopt() succeeded");
> +	if (errno != EINVAL)
> +		errx(-1, "not ok 8 - getsockopt() after listen() but before "
> +		    "setsockopt() failed with %d (%s)", errno, strerror(errno));
> +	printf("ok 8 - getsockopt\n");
> +
> +	/*
> +	 * Step 8: After listen().  This call to setsockopt() should succeed.
>  	 */
>  	bzero(&afa, sizeof(afa));
>  	strcpy(afa.af_name, ACCF_NAME);
>  	ret = setsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa));
>  	if (ret != 0)
> -		errx(-1, "not ok 8 - setsockopt() after listen() failed with %d "
> +		errx(-1, "not ok 9 - setsockopt() after listen() failed with %d "
>  		    "(%s)", errno, strerror(errno));
>  	if (len != sizeof(afa))
> -		errx(-1, "not ok 8 - setsockopt() after listen() returned wrong "
> +		errx(-1, "not ok 9 - setsockopt() after listen() returned wrong "
>  		    "size (%d vs expected %d)", len, sizeof(afa));
> -	printf("ok 8 - setsockopt\n");
> +	printf("ok 9 - setsockopt\n");
> 
>  	/*
> -	 * Step 8: After setsockopt().  Should succeed and identify
> +	 * Step 9: After setsockopt().  Should succeed and identify
>  	 * ACCF_NAME.
>  	 */
>  	bzero(&afa, sizeof(afa));
>  	len = sizeof(afa);
>  	ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len);
>  	if (ret != 0)
> -		errx(-1, "not ok 9 - getsockopt() after listen() setsockopt() "
> +		errx(-1, "not ok 10 - getsockopt() after listen() setsockopt() "
>  		    "failed with %d (%s)", errno, strerror(errno));
>  	if (len != sizeof(afa))
> -		errx(-1, "not ok 9 - getsockopt() after setsockopet()  after "
> +		errx(-1, "not ok 10 - getsockopt() after setsockopet()  after "
>  		    "listen() returned wrong size (got %d expected %d)", len,
>  		    sizeof(afa));
>  	if (strcmp(afa.af_name, ACCF_NAME) != 0)
> -		errx(-1, "not ok 9 - getsockopt() after setsockopt() after "
> +		errx(-1, "not ok 10 - getsockopt() after setsockopt() after "
>  		    "listen() mismatch (got %s expected %s)", afa.af_name,
>  		    ACCF_NAME);
> -	printf("ok 9 - getsockopt\n");
> +	printf("ok 10 - getsockopt\n");
> +
> +	/*
> +	 * Step 10: Remove accept filter.  After removing the accept filter
> +	 * getsockopt() should fail with EINVAL.
> +	 */
> +	ret = setsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, NULL, 0);
> +	if (ret != 0)
> +		errx(-1, "not ok 11 - setsockopt() after listen() "
> +		    "failed with %d (%s)", errno, strerror(errno));
> +	bzero(&afa, sizeof(afa));
> +	len = sizeof(afa);
> +	ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len);
> +	if (ret == 0)
> +		errx(-1, "not ok 11 - getsockopt() after removing "
> +		    "the accept filter returns valid accept filter %s",
> +		    afa.af_name);
> +	if (errno != EINVAL)
> +		errx(-1, "not ok 11 - getsockopt() after removing the accept"
> +		    "filter failed with %d (%s)", errno, strerror(errno));
> +	printf("ok 11 - setsockopt\n");
> 
>  	close(lso);
>  	return (0);
> %%%
> 
> -- 
> Maxim Konovalov

-- 
- Alfred Perlstein
- email: bright@mu.org cell: 408-480-4684



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20050611093640.GB17867>