]> git.ipfire.org Git - thirdparty/public-inbox.git/commitdiff
daemon: enable SO_ACCEPTFILTER on NetBSD
authorEric Wong <e@80x24.org>
Tue, 3 Oct 2023 09:26:01 +0000 (09:26 +0000)
committerEric Wong <e@80x24.org>
Tue, 3 Oct 2023 10:16:11 +0000 (10:16 +0000)
NetBSD 5.0+ has accept filter support from FreeBSD; and I
I think we can assume all NetBSD is 5.0+ (released in 2009)
nowadays if we're already depending on Perl 5.12 from 2010.

lib/PublicInbox/Daemon.pm
lib/PublicInbox/TestCommon.pm
t/httpd-corner.t
t/httpd-https.t
t/httpd.t
t/imapd-tls.t
t/nntpd-tls.t
t/pop3d.t

index 078831530598f1060828e4d90971a98e837e7c11..7546105e4d5c801bb4cbd3c753ec03cec8432735 100644 (file)
@@ -641,7 +641,7 @@ sub defer_accept ($$) {
                my $sec = unpack('i', $x);
                return if $sec > 0; # systemd users may set a higher value
                setsockopt($s, IPPROTO_TCP, $TCP_DEFER_ACCEPT, 1);
-       } elsif ($^O eq 'freebsd') {
+       } elsif ($^O =~ /\A(?:freebsd|netbsd)\z/) {
                my $x = getsockopt($s, SOL_SOCKET, $SO_ACCEPTFILTER);
                return if defined $x; # don't change if set
                my $accf_arg = pack('a16a240', $af_name, '');
index 2c38500cdf1e32d6a40ba2e24938f9fe81f4a1e3..7d0eb2c4bcaae9b04780f11ea3a3f1b3dfba0f3a 100644 (file)
@@ -133,6 +133,15 @@ my %IPv6_VERSION = (
        'Net::POP3' => 2.32,
 );
 
+sub need_accept_filter ($) {
+       my ($af) = @_;
+       return if $^O eq 'netbsd'; # since NetBSD 5.0
+       skip 'SO_ACCEPTFILTER is FreeBSD/NetBSD-only' if $^O ne 'freebsd';
+       state $tried = {};
+       ($tried->{$af} //= system("kldstat -m $af >/dev/null")) and
+               skip "$af not loaded: kldload $af";
+}
+
 sub require_mods {
        my @mods = @_;
        my $maybe = pop @mods if $mods[-1] =~ /\A[0-9]+\z/;
@@ -166,6 +175,9 @@ sub require_mods {
                                push @need, $msg;
                                next;
                        }
+               } elsif ($mod =~ /\A\+(accf_.*)\z/) {
+                       need_accept_filter($1);
+                       next
                } elsif (index($mod, '||') >= 0) { # "Foo||Bar"
                        my $ok;
                        for my $m (split(/\Q||\E/, $mod)) {
index 7600c2b955f27b067d29328d3843832920b56506..aab3635cc8a3c198612dc1f331b36dec32eef77e 100644 (file)
@@ -3,8 +3,9 @@
 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
 # note: our HTTP server should be standalone and capable of running
 # generic PSGI/Plack apps.
-use strict; use v5.10.1; use PublicInbox::TestCommon;
+use v5.12; use PublicInbox::TestCommon;
 use Time::HiRes qw(gettimeofday tv_interval);
+use autodie qw(getsockopt setsockopt);
 use PublicInbox::Spawn qw(spawn popen_rd);
 require_mods(qw(Plack::Util Plack::Builder HTTP::Date HTTP::Status));
 use PublicInbox::SHA qw(sha1_hex);
@@ -26,20 +27,21 @@ my @zmods = qw(PublicInbox::GzipFilter IO::Uncompress::Gunzip);
 # Make sure we don't clobber socket options set by systemd or similar
 # using socket activation:
 my ($defer_accept_val, $accf_arg, $TCP_DEFER_ACCEPT);
-if ($^O eq 'linux') {
+SKIP: {
+       skip 'TCP_DEFER_ACCEPT is Linux-only' if $^O ne 'linux';
        $TCP_DEFER_ACCEPT = eval { Socket::TCP_DEFER_ACCEPT() } // 9;
-       setsockopt($sock, IPPROTO_TCP, $TCP_DEFER_ACCEPT, 5) or die;
+       setsockopt($sock, IPPROTO_TCP, $TCP_DEFER_ACCEPT, 5);
        my $x = getsockopt($sock, IPPROTO_TCP, $TCP_DEFER_ACCEPT);
-       defined $x or die "getsockopt: $!";
        $defer_accept_val = unpack('i', $x);
-       if ($defer_accept_val <= 0) {
-               die "unexpected TCP_DEFER_ACCEPT value: $defer_accept_val";
-       }
-} elsif ($^O eq 'freebsd' && system('kldstat -m accf_data >/dev/null') == 0) {
+       ok($defer_accept_val > 0, 'TCP_DEFER_ACCEPT val non-zero') or
+               xbail "unexpected TCP_DEFER_ACCEPT value: $defer_accept_val";
+}
+SKIP: {
+       require_mods '+accf_data';
        require PublicInbox::Daemon;
        my $var = $PublicInbox::Daemon::SO_ACCEPTFILTER;
        $accf_arg = pack('a16a240', 'dataready', '');
-       setsockopt($sock, SOL_SOCKET, $var, $accf_arg) or die "setsockopt: $!";
+       setsockopt($sock, SOL_SOCKET, $var, $accf_arg);
 }
 
 sub unix_server ($) {
@@ -625,15 +627,14 @@ SKIP: {
 SKIP: {
        skip 'TCP_DEFER_ACCEPT is Linux-only', 1 if $^O ne 'linux';
        my $var = $TCP_DEFER_ACCEPT;
-       defined(my $x = getsockopt($sock, IPPROTO_TCP, $var)) or die;
+       my $x = getsockopt($sock, IPPROTO_TCP, $var);
        is(unpack('i', $x), $defer_accept_val,
                'TCP_DEFER_ACCEPT unchanged if previously set');
 };
 SKIP: {
-       skip 'SO_ACCEPTFILTER is FreeBSD-only', 1 if $^O ne 'freebsd';
-       skip 'accf_data not loaded: kldload accf_data' if !defined $accf_arg;
+       require_mods '+accf_data';
        my $var = $PublicInbox::Daemon::SO_ACCEPTFILTER;
-       defined(my $x = getsockopt($sock, SOL_SOCKET, $var)) or die;
+       my $x = getsockopt($sock, SOL_SOCKET, $var);
        is($x, $accf_arg, 'SO_ACCEPTFILTER unchanged if previously set');
 };
 
index b0cd7eab51d4719321f954730843585a4bfdc1fb..bf0861238f15eb04f43832b0820fe147ab8f7a40 100644 (file)
@@ -102,10 +102,7 @@ for my $args (
                ok(unpack('i', $x) > 0, 'TCP_DEFER_ACCEPT set on https');
        };
        SKIP: {
-               skip 'SO_ACCEPTFILTER is FreeBSD-only', 2 if $^O ne 'freebsd';
-               if (system('kldstat -m accf_data >/dev/null')) {
-                       skip 'accf_data not loaded? kldload accf_data', 2;
-               }
+               require_mods '+accf_data';
                require PublicInbox::Daemon;
                ok(defined($PublicInbox::Daemon::SO_ACCEPTFILTER),
                        'SO_ACCEPTFILTER defined');
index aa60121031419d49b6ca1b2ab66ed5b90ff3c542..0421c7eac720ccd448df64828469cd92a8739a7c 100644 (file)
--- a/t/httpd.t
+++ b/t/httpd.t
@@ -104,10 +104,7 @@ SKIP: {
        ok(unpack('i', $x) > 0, 'TCP_DEFER_ACCEPT set');
 };
 SKIP: {
-       skip 'SO_ACCEPTFILTER is FreeBSD-only', 1 if $^O ne 'freebsd';
-       if (system('kldstat -m accf_http >/dev/null') != 0) {
-               skip 'accf_http not loaded: kldload accf_http', 1;
-       }
+       require_mods '+accf_http';
        require PublicInbox::Daemon;
        ok(defined($PublicInbox::Daemon::SO_ACCEPTFILTER),
                'SO_ACCEPTFILTER defined');
index e432ef075313161f97a67bf3a0837d758c4f6c67..b95085a29e4d1b9230fdeedb0ad78e8cc80b9abd 100644 (file)
@@ -181,10 +181,7 @@ for my $args (
                is(unpack('i', $x), 0, 'TCP_DEFER_ACCEPT is 0 on plain IMAP');
        };
        SKIP: {
-               skip 'SO_ACCEPTFILTER is FreeBSD-only', 2 if $^O ne 'freebsd';
-               if (system('kldstat -m accf_data >/dev/null')) {
-                       skip 'accf_data not loaded? kldload accf_data', 2;
-               }
+               require_mods '+accf_data';
                require PublicInbox::Daemon;
                my $x = getsockopt($imaps, SOL_SOCKET,
                                $PublicInbox::Daemon::SO_ACCEPTFILTER);
index 21377fc0f858b6a7af76b96b11bd39f5ecfa4488..cf3c95c96127aafc37c7048eb444d339fb0a3e5d 100644 (file)
@@ -175,10 +175,7 @@ for my $args (
                is(unpack('i', $x), 0, 'TCP_DEFER_ACCEPT is 0 on plain NNTP');
        };
        SKIP: {
-               skip 'SO_ACCEPTFILTER is FreeBSD-only', 2 if $^O ne 'freebsd';
-               if (system('kldstat -m accf_data >/dev/null')) {
-                       skip 'accf_data not loaded? kldload accf_data', 2;
-               }
+               require_mods '+accf_data';
                require PublicInbox::Daemon;
                my $x = getsockopt($nntps, SOL_SOCKET,
                                $PublicInbox::Daemon::SO_ACCEPTFILTER);
index 2a7a7c3fdaf04097f72526e12d427bd34122f320..fce4a78803670a5c2d9b782b1633f6e2b4a05a24 100644 (file)
--- a/t/pop3d.t
+++ b/t/pop3d.t
@@ -268,9 +268,7 @@ EOF
                is(unpack('i', $x), 0, 'TCP_DEFER_ACCEPT is 0 on plain POP3');
        };
        SKIP: {
-               skip 'SO_ACCEPTFILTER is FreeBSD-only', 2 if $^O ne 'freebsd';
-               system('kldstat -m accf_data >/dev/null') and
-                       skip 'accf_data not loaded? kldload accf_data', 2;
+               require_mods '+accf_data';
                require PublicInbox::Daemon;
                my $x = getsockopt($pop3s, SOL_SOCKET,
                                $PublicInbox::Daemon::SO_ACCEPTFILTER);