Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FreeBSD's PF has a new interface so leverage libpfctl to access it so… #4148

Merged
merged 1 commit into from Feb 7, 2024

Conversation

brd
Copy link
Contributor

@brd brd commented Nov 7, 2023

… the right interface is used depending on the version

I am interested in feedback if there is possibly a better way to do this.

ChangeLog: pf plugin: Support for libpfctl has been added.

@brd brd requested a review from a team as a code owner November 7, 2023 13:57
Copy link
Member

@octo octo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @brd, thanks for the contribution!

My overall concern is that this is making the code more complicated but doesn't provide additional utility. Is there anything that this new interface allows us to do that we were unable to do previously? If not, I think it would be preferable to keep the code simple.

src/pf.c Outdated Show resolved Hide resolved
@brd brd force-pushed the freebsd-pf branch 2 times, most recently from 36c20ee to 9ec1d73 Compare November 24, 2023 21:38
@brd
Copy link
Contributor Author

brd commented Nov 24, 2023

OK, I have split it into two separate functions, let me know what you think!

@octo octo added the bsd only label Nov 24, 2023
@octo
Copy link
Member

octo commented Nov 24, 2023

This looks much better now, thank you! I'm still not quite clean on why we need special code for FreeBSD if is does the exact same as the generic code. What's the benefit?

@brd
Copy link
Contributor Author

brd commented Nov 27, 2023

libpfctl is only for FreeBSD, as the interface to access pf info is changing over time.. it was ioctl, then nvlist, and now it is netlink. libpfctl abstracts that away so collectd does not need to have ifdef for the different versions of FreeBSD.

@octo
Copy link
Member

octo commented Nov 28, 2023

Thanks for the feedback. That does indeed sound like using an abstraction like libpfctl is useful.

The FreeBSD build currently fails with:

src/pf.c:39:10: fatal error: 'libpfctl.h' file not found
#include <libpfctl.h>
         ^~~~~~~~~~~~
1 error generated.

This is because:

  1. Our FreeBSD build instance does not yet have the libpfctl port installed. You can fix this by adding to the pkg_install_script step in .cirrus.yml.
  2. We need a check for this header file in the configure script. Search for net/pfvar.h in configure.ac to see how the decision to build the "pf" plugin is made right now. Then use HAVE_LIBPFCTL_H instead of __FreeBSD__ to chose which implementation to use.

I anticipate that the next issue is going to be a linker error because we need to link with libpfctl. This requires a check for the library with AC_CHECK_LIB in configure.ac and changes to the pf_la_LDFLAGS in Makefile.am.

@octo
Copy link
Member

octo commented Dec 21, 2023

Hi @brd, do you need any help making the above changes?

@octo octo added the Waiting for response - 1st time Waiting for contributor to respond - 1st call label Dec 21, 2023
@brd
Copy link
Contributor Author

brd commented Feb 3, 2024

@octo sorry for the delay, I kept meaning to get back to this and kept forgetting!

I am struggling with getting the configure script to work.. I tried this:

diff --git a/Makefile.am b/Makefile.am
index 1d3c69f2..71821bd0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1744,7 +1744,7 @@ endif
 if BUILD_PLUGIN_PF
 pkglib_LTLIBRARIES += pf.la
 pf_la_SOURCES = src/pf.c
-pf_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+pf_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(PF_LDFLAGS)
 endif
 
 if BUILD_PLUGIN_PINBA
diff --git a/configure.ac b/configure.ac
index 5383e3e2..f95fa1a4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -693,6 +693,9 @@ AC_CHECK_HEADERS([net/pfvar.h],
     # include <netinet/in.h>
     #endif
   ]]
+  AC_CHECK_LIB([libpfctl], [pfctl_status_counter],
+    PF_LDFLAGS="$PF_LDFLAGS -lpfctl"
+  )
 )

@octo
Copy link
Member

octo commented Feb 3, 2024

Hey @brd, no worries. I think the following should work. Note: it's untested!

diff --git a/Makefile.am b/Makefile.am
index 64c719c48..6b0e4b4ea 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1761,6 +1761,9 @@ if BUILD_PLUGIN_PF
 pkglib_LTLIBRARIES += pf.la
 pf_la_SOURCES = src/pf.c
 pf_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+if BUILD_WITH_LIBPFCTL
+pf_la_LDFLAGS += -lpfctl
+endif
 endif

 if BUILD_PLUGIN_PINBA
diff --git a/configure.ac b/configure.ac
index dad27f53b..ae77bf3b5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2040,6 +2040,13 @@ if test "x$with_kvm_openfiles" = "xyes"; then
   with_libkvm="yes"
 fi

+AC_CHECK_HEADERS([libpfctl.h])
+AC_CHECK_LIB([libpfctl], [pfctl_status_counter],
+  [with_libpfctl="yes"],
+  [with_libpfctl="no"]
+)
+AM_CONDITIONAL([BUILD_WITH_LIBPFCTL], [test "x$with_libpfctl" = "xyes"])
+
 # --with-cuda {{{
 AC_ARG_WITH([cuda],
   [AS_HELP_STRING([--with-cuda@<:@=PREFIX@:>@], [Path to cuda.])],
diff --git a/src/pf.c b/src/pf.c
index 9681d366a..2dbcd31cc 100644
--- a/src/pf.c
+++ b/src/pf.c
@@ -36,6 +36,10 @@

 #include <net/pfvar.h>

+#if HAVE_LIBPFCTL_H
+#include <libpfctl.h>
+#endif
+
 #ifndef FCNT_NAMES
 #if FCNT_MAX != 3
 #error "Unexpected value for FCNT_MAX"

@brd
Copy link
Contributor Author

brd commented Feb 6, 2024

Hi @octo I think I got it working right.. have a look and let me know what you think.

Copy link
Member

@octo octo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks much better, thank you @brd! Once we fix the AC_CHECK_HEADERS check this is good to go.

configure.ac Outdated
Comment on lines 2043 to 2050
AC_CHECK_HEADERS([libpfctl.h], [], [],
[
#include <sys/queue.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <net/if.h>
#include <net/pfvar.h>
])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check is inconsequential: neither the success nor the failure case have any side effects.

Option 1: If you simplify this to

AC_CHECK_HEADERS([libpfctl.h])

then autoconf's default behavior will be active, which will create a HAVE_LIBPFCTL_H define if the header is present. You can use it instead of __FreeBSD__ in the .c file.

Option 2: In the unlikely case that you have to specify the other headers, skipping the arguments entirely will trigger the default behavior (I think):

AC_CHECK_HEADERS([libpfctl.h],,, # <-- empty arguments
[
  #include <sys/queue.h>
  #include <sys/types.h>
  #include <netinet/in.h>
  #include <net/if.h>
  #include <net/pfvar.h>
])

Option 3: remove entirely.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Case in point, the build currently fails with:

src/pf.c:39:10: fatal error: 'libpfctl.h' file not found
#include <libpfctl.h>
         ^~~~~~~~~~~~
1 error generated.
--- src/pf.lo ---
*** [src/pf.lo] Error code 1

This is despite the configure script technically checking for the header's existence:

checking for libpfctl.h... no
checking for pfctl_status_counter in -llibpfctl... no

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, the build works for me where I have libpfctl present:

checking for libpfctl.h... yes
checking for pfctl_status_counter in -lpfctl... yes

I had to add the other includes so that the test worked.. but if we don't need it, I am happy to remove it.

Where are you seeing that build failure? It looks like the checks on this PR are successful?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see some failed checks below. The detailed view of the FreeBSD one is here: https://cirrus-ci.com/task/6128106226843648

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, thank you! I am not very familiar with the github actions and didn't see where I could get that detail.. the in github link didn't show any errors, just looked like it built successfully.

In the FreeBSD port, we set CPPFLAGS= -I/usr/local/include :
https://cgit.freebsd.org/ports/tree/net-mgmt/collectd5/Makefile#n84

Looks like that is needed in the .cirrus.yml...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, that doesn't seem to be working according to the config.log

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a typo in the flag definition (CPPLAGS instead of CPPFLAGS).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We definitely need HAVE_LIBPFCTL_H and cannot rely on __FreeBSD__, see comment below. Please try if

AC_CHECK_HEADERS([libpfctl.h])

works, that would be the easiest.

Comment on lines +85 to +87
int fd;

fd = open(pf_device, O_RDONLY);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional coding style improvement.

Suggested change
int fd;
fd = open(pf_device, O_RDONLY);
int fd = open(pf_device, O_RDONLY);

.cirrus.yml Outdated Show resolved Hide resolved
configure.ac Outdated Show resolved Hide resolved
Copy link
Member

@octo octo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The build succeeds now. The remaining issue is in src/ras.c which is unrelated.

src/pf.c Outdated Show resolved Hide resolved
configure.ac Outdated
Comment on lines 2043 to 2050
AC_CHECK_HEADERS([libpfctl.h], [], [],
[
#include <sys/queue.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <net/if.h>
#include <net/pfvar.h>
])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We definitely need HAVE_LIBPFCTL_H and cannot rely on __FreeBSD__, see comment below. Please try if

AC_CHECK_HEADERS([libpfctl.h])

works, that would be the easiest.

… the right interface is used depending on the version
@brd
Copy link
Contributor Author

brd commented Feb 7, 2024

I think that addresses all the build issues.. I kept the #includes for the AC_CHECK_HEADERS since the test failed for me without them.

@octo octo added the Feature label Feb 7, 2024
Copy link
Member

@octo octo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks @brd!

@octo octo merged commit 9473060 into collectd:main Feb 7, 2024
23 of 24 checks passed
@brd
Copy link
Contributor Author

brd commented Feb 7, 2024

Thank you for all your help! It is much appreciated

@octo
Copy link
Member

octo commented Feb 7, 2024

@brd You're very welcome. Thanks for your contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bsd only Feature Waiting for response - 1st time Waiting for contributor to respond - 1st call
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants