tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: accept_filter, accf_http, setsockopt and the EINVAL error



On Thu June 25 2009 02:27:57 Iain Hibbert wrote:
> On Wed, 24 Jun 2009, Sverre Froyen wrote:
> > (1) It seems to me that adding the "httpready" filter a second time is
> > not really an error and I'm wondering if setsockopt could be modified to
> > silently ignore the second attempt.
>
> I see the following code in kern/uipc_accf.c
>
>       /*
>        * Require a listen socket; don't try to replace an existing filter
>        * without first removing it.
>        */
>       solock(so);
>       if ((so->so_options & SO_ACCEPTCONN) == 0 || so->so_accf != NULL) {
>               error = EINVAL;
>               goto out;
>       }
>
> which seems to imply that the behaviour you see is purposeful..  does
> FreeBSD allow implicit replacement of the filter?

FreeBSD's code is identical.  Despite that fact, I've attached a patch that 
makes setsockopt silently ignore the second call.  Please note that I do not 
allow replacing a filter with a different type, only adding the same type 
twice.

Regards,

Sverre




Index: src/sys/kern/uipc_accf.c
===================================================================
RCS file: /cvsroot/src/sys/kern/uipc_accf.c,v
retrieving revision 1.8
diff -b -u -r1.8 uipc_accf.c
--- src/sys/kern/uipc_accf.c    20 Nov 2008 10:00:54 -0000      1.8
+++ src/sys/kern/uipc_accf.c    26 Jun 2009 19:56:52 -0000
@@ -328,16 +328,30 @@
        }
 
        /*
-        * Require a listen socket; don't try to replace an existing filter
-        * without first removing it.
+        * Require a listen socket.
         */
+       if ((so->so_options & SO_ACCEPTCONN) == 0) {
        solock(so);
-       if ((so->so_options & SO_ACCEPTCONN) == 0 || so->so_accf != NULL) {
                error = EINVAL;
                goto out;
        }
 
        /*
+        * Don't try to replace an existing filter with a new type
+        * without first removing it.
+        */
+       if (so->so_accf != NULL) {
+               if (so->so_accf->so_accept_filter == NULL ||
+                   strcmp(so->so_accf->so_accept_filter->accf_name,
+                   afa.af_name) != 0)
+                       error = EINVAL;
+               solock(so);
+               goto out;
+       }
+
+       solock(so);
+
+       /*
         * Invoke the accf_create() method of the filter if required.  The
         * socket lock is held over this call, so create methods for filters
         * shouldn't block.


Home | Main Index | Thread Index | Old Index