summaryrefslogtreecommitdiff
path: root/contrib/apr/network_io/unix/sockopt.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/apr/network_io/unix/sockopt.c')
-rw-r--r--contrib/apr/network_io/unix/sockopt.c29
1 files changed, 25 insertions, 4 deletions
diff --git a/contrib/apr/network_io/unix/sockopt.c b/contrib/apr/network_io/unix/sockopt.c
index 3fc932f42f5e..7b67c2ec13a1 100644
--- a/contrib/apr/network_io/unix/sockopt.c
+++ b/contrib/apr/network_io/unix/sockopt.c
@@ -381,12 +381,33 @@ apr_status_t apr_gethostname(char *buf, apr_int32_t len, apr_pool_t *cont)
}
#if APR_HAS_SO_ACCEPTFILTER
-apr_status_t apr_socket_accept_filter(apr_socket_t *sock, char *name,
- char *args)
+apr_status_t apr_socket_accept_filter(apr_socket_t *sock, char *nonconst_name,
+ char *nonconst_args)
{
+ /* these should have been const; act like they are */
+ const char *name = nonconst_name;
+ const char *args = nonconst_args;
+
struct accept_filter_arg af;
- strncpy(af.af_name, name, 16);
- strncpy(af.af_arg, args, 256 - 16);
+ socklen_t optlen = sizeof(af);
+
+ /* FreeBSD returns an error if the filter is already set; ignore
+ * this call if we previously set it to the same value.
+ */
+ if ((getsockopt(sock->socketdes, SOL_SOCKET, SO_ACCEPTFILTER,
+ &af, &optlen)) == 0) {
+ if (!strcmp(name, af.af_name) && !strcmp(args, af.af_arg)) {
+ return APR_SUCCESS;
+ }
+ }
+
+ /* Uhh, at least in FreeBSD 9 the fields are declared as arrays of
+ * these lengths; did sizeof not work in some ancient release?
+ *
+ * FreeBSD kernel sets the last byte to a '\0'.
+ */
+ apr_cpystrn(af.af_name, name, 16);
+ apr_cpystrn(af.af_arg, args, 256 - 16);
if ((setsockopt(sock->socketdes, SOL_SOCKET, SO_ACCEPTFILTER,
&af, sizeof(af))) < 0) {