On Apr 19, 2024, at 5:49 AM, Denis Ovsienko <de...@ovsienko.info> wrote:

> On Fri, 12 Apr 2024 18:49:05 -0700
> Guy Harris <ghar...@sonic.net> wrote:

        ...

> Since tcpdump is the reference implementation of a program that uses
> libpcap, it may be a good occasion to improve the solution space such
> that other software can copy something that works well in tcpdump.  It
> is not entirely obvious the LIBPCAP_HAVE_PCAP_xxxx macros would be worth
> the burden of maintenance, but the version macros should be a
> straightforward improvement, something such as:
> 
> #define PCAP_VERSION_MAJOR 1
> #define PCAP_VERSION_MINOR 11
> #define PCAP_VERSION_PATCHLEVEL 0
> #define PCAP_VERSION_AT_LEAST(a, b, c) ...
> 
> (The GCC and Clang version checks in compiler-tests.h would be examples
> of a good macro structure; Sun C, XL C and HP C version checks look
> unwieldy and error-prone).

Presumably meaning that we should export version information in the way GCC and 
Clang do, rather than in the ways that Sun/Oracle C, XL C and HP C do, the 
latter being why we have to go through all that extra pain (they provide a 
single #define with the version number components packed in it - or two 
different defines in different versions as XL C does - rather than separate 
#defines for major and minor versions, as GCC and Clang do).

> There could be a run-time check as well:
> 
> extern int pcap_version_at_least (unsigned char major, unsigned char
> minor, unsigned char patchlevel);

So how would that be used?

If a program is dynamically linked with libpcap, and includes calls to routines 
that were added in libpcap 1.12 or later, if you try to run it with libpcap 
1.11, the run-time linker will fail to load it, as some symbols requested by 
the executable won't be present in the library. The only OS on which this can 
be made to work is macOS, with its weak linking mechanism:

        
https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/DynamicLibraryDesignGuidelines.html

although Apple didn't set up the header file to weakly link symbols until Xcode 
15, and Sonoma was the first release built with Xcode 15, so I think the first 
OS in which you can arrange that the run-time linker not fail would be Sonoma.

With the macOS scheme, there are *run-time* checks for the OS version you're 
running on, although Apple have done rather a crap job of documenting the 
mechanism, especially as used in C and C++ code, where it's done with the 
__builtin_available() pseudo-function, e.g.:

        if (__builtin_available(macOS 10.12, *)) {
                if (clock_gettime(CLOCK_REALTIME, &value) == 0) {
                        printf("Realtime seconds: %ld\n", value.tv_sec);
                }
        } else {
                // clock_gettime not available!
                return 1;
        }

as per

        https://epir.at/2019/10/30/api-availability-and-target-conditionals/

If you *don't* do the check, you'll get, I think, a run-time failure if you try 
to call a routine that's not available; there's a compiler option, 
-Wunguarded-availability, to produce a warning if you make a call to a routine 
that's not available on the minimum-targeted OS version.

16-bit Windows also supported that - in the same way that macOS used to do it, 
with "the pointer to the function is NULL if a weakly-linked symbol isn't 
available" - but they decided that was too ugly, and got rid of it in 32-bit 
and 64-bit Windows:

        https://devblogs.microsoft.com/oldnewthing/20160317-00/?p=93173

Apple probably also decided it was too ugly, and added __builtin_available() 
(and Objective-C @available, and something similar for Swift) as well as the 
compiler warning.

The Microsoft blog post indicates how you do this in Windows, namely by loading 
the library at run time with LoadLibrary() and attempting to get pointers to 
individual routines with GetProcAddress() and testing if the result is NULL; 
the same thing can be done on UN*Xes with dlopen() and dlsym().

But *all* of those require either run-time checks for a particular OS version 
in macOS, in cases where you're using the libpcap that comes with macOS, or 
require loading the library at run time, finding particular routines at run 
time, and checking at run time whether the routine was found.

> The latter could be available via a build helper binary, such as (using
> the binary operators from test(1) and version-aware comparison):
> 
> pcap-version -ge 1 # same as 1 0 0
> pcap-version -ge 1 10 # same as 1 10 0
> pcap-version -ne 1 10 4
> pcap-version -eq 1 10 4
> pcap-version -ge 1 9 1 && pcap-version -le 1 9 3

So would this be used in a Makefile/configure script/CMakeFile.txt/etc. to 
check whether the libpcap on the system is sufficiently recent to include the 
routines your program needs, and fail if it isn't?

>> Is there any reason not to require libpcap 1.0 or later?  If there
>> is, is there any reason not to require libpcap 0.7 or later?
> 
> Such use cases may exist, but I am not aware of any.

So my inclination would be to require libpcap 1.0 for tcpdump 5.0.

_______________________________________________
tcpdump-workers mailing list -- tcpdump-workers@lists.tcpdump.org
To unsubscribe send an email to tcpdump-workers-le...@lists.tcpdump.org
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to