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

rpcapd: Link to shared library rather than statically #955

Open
netrounds-fredrik opened this issue Aug 3, 2020 · 16 comments
Open

rpcapd: Link to shared library rather than statically #955

netrounds-fredrik opened this issue Aug 3, 2020 · 16 comments

Comments

@netrounds-fredrik
Copy link

When compiling the rpcapd application on a UNIX system, libpcap is linked statically rather than dynamically (

target_link_libraries(rpcapd ${LIBRARY_NAME}_static
).

In a production environment you might want to use the existing libpcap installed on your system in order to get security updates from your Linux distro and to avoid having multiple binary copies of the library, so it would be good it it was possible to build rpcapd without static linking like you would normally build an application.

@guyharris
Copy link
Member

In a production environment you might want to use the existing libpcap installed on your system

Which sounds as if there should be a separate repository for rpcapd, so you can build it separately from libpcap.

@netrounds-fredrik
Copy link
Author

It would make sense to be able to build rpcapd separate from libpcap as they are not that tightly coupled from an API point of view. They can however still live in the same repo, just like libcurl and the curl command line tool do.

Is there a reason why rpcapd SHOULD link libpcap statically? There might be some low level dependency between them that I'm not aware of.

@mcr
Copy link
Member

mcr commented Aug 8, 2020 via email

@infrastation
Copy link
Member

Quite the opposite, libpcap does generate a .so by default because that is its main purpose.

Perhaps a good reason to link rpcapd statically for the time being is that rpcapd is still a work in progress and may depend on libpcap features that are still work in progress, so you can try today's rpcapd without introducing a bleeding edge today's version of a shared library into a working system.

Also there is a maintenance effort cost to having one more repository given the software needs to be portable and needs to have two build systems (autotools and CMake).

@netrounds-fredrik
Copy link
Author

From what I can see without digging too much into the details it doesn't seem to be too much work to make it possible to build rpcapd against a shared library, still in the same repo. Would you be interested in a PR for this once we get time to look into it?

@infrastation
Copy link
Member

Thank you for the offer. It would help to state the problem before working on the solution.

The current state is as follows. There is an rpcapd that is statically linked with libpcap.

A) If it comes from a system package (e.g. "libpcap-utils-static" or some such), it will be updated at the same time as the binary "libpcap" package, because both build from the "libpcap" source package.

B) Otherwise, if it comes from /usr/local as a result of a local source build and make install, after the packaged libpcap.so update it will continue use the compiled-in libpcap and will not have the bugfixes.

The proposed solution, as far as I can understand it, is as follows. There is an rpcapd that is dynamically linked with libpcap in the same build tree as libpcap.

C) If it comes from a system package, it will get the bugfixes during the libpcap binary package update. So C and A are same good.

D) Otherwise, if it comes from /usr/local as a result of a local source build, the libpcap with that it had built is in /usr/local too. After the packaged libpcap.so update the locally built rpcapd will still continue to use the locally built libpcap from /usr/local because that shared library directory has a priority over the directories where packaged shared libraries install the .so files (at least on some Linuxes). Also other software dynamically linked with the same soname will use the non-patched libpcap from /usr/local that the locally built rpcapd had installed. So D is worse than B.

Could you please describe the specific use case that you see and how the proposed change improves it?

@mcr
Copy link
Member

mcr commented Aug 11, 2020

If rpcapd is dynamically linked against libpcap, then it will likely use whatever libpcap.so that is in the system search path. That most likely is not the one in ../libpcap.so, so you will regularly be surprised.

@netrounds-fredrik
Copy link
Author

To my knowledge there are no distro that currently package rpcapd (checked Debian, Ubuntu, RHEL/Centos), scenario A/C doesn't really exist as of today. In scenario D I would only have rpcapd in /usr/local and let it use libpcap from the distro, and in that way get security updates for free. Then there might of course be important updates to rpcapd, but it's still less code to worry about.

Another good reason to link dynamically is because it's what you would expect. I can not come up with any project that has a library as well as an executable that does not link to the library dynamically when packaged for a distribution. See for example

You could have the exact same arguments about tcpdump. Why is that not linking libpcap statically?

If rpcapd is dynamically linked against libpcap, then it will likely use whatever libpcap.so that is in the system search path. That most likely is not the one in ../libpcap.so, so you will regularly be surprised.

Just as surprised as any other user of libpcap, so not too surprised I hope :)

@guyharris
Copy link
Member

To my knowledge there are no distro that currently package rpcapd (checked Debian, Ubuntu, RHEL/Centos), scenario A/C doesn't really exist as of today.

Currently true, but we should not assume it will remain true, or make it difficult for any OS that ships libpcap to ship rpcapd as well.

In scenario D I would only have rpcapd in /usr/local and let it use libpcap from the distro,

That appears to call for an option to build and install only rpcapd, whether it's a separate repository and release tarball for rpcapd or configure-script and CMake options.

(A separate repository has the problem that there are both rpcap clients, such as the libpcap module for rpcap remote capture, and rpcap servers, such as rpcapd. Our implementations share some common headers and code.)

There's also scenario E, where you're building libpcap and rpcapd for testing and development purposes, so a dynamically-linked rpcapd would have to find the libpcap shared library/DLL in the build directory. That's not a top priority, but it'd be helpful if there was some way to make it work.

Another good reason to link dynamically is because it's what you would expect. I can not come up with any project that has a library as well as an executable that does not link to the library dynamically when packaged for a distribution. See for example

You could have the exact same arguments about tcpdump. Why is that not linking libpcap statically?

  1. It's a separate package; it's a program that happens to use libpcap, just as Wireshark is a program that happens to use libpcap. A user might just want to build and run the latest tcpdump with the system libpcap, and not want to bother building libpcap (if, for example, they don't care about additional capturing functionality in a newer libpcap release, they just want newer dissection capability in the newer tcpdump release). They're released as separate source tarballs and are in separate repositories.

  2. However, we have, at least when using autotools, a special hack for people who are building both libpcap and tcpdump and might not want to install either one, wherein tcpdump can link with a libpcap built in the ../libpcap-{version} directory; that links statically.

@netrounds-fredrik
Copy link
Author

netrounds-fredrik commented Aug 12, 2020

Perhaps a good reason to link rpcapd statically for the time being is that rpcapd is still a work in progress and may depend on libpcap features that are still work in progress, so you can try today's rpcapd without introducing a bleeding edge today's version of a shared library into a working system.

Yes, this is the only valid reason as I see it. However, from what I can see it's only the client side libpcap that need to expose the new APIs in pcap-new.c (pcap_findalldevs_ex, pcap_open, etc.) since rpcapd is only using the "standard" APIs (pcap_findalldevs, pcap_open_live, etc.).

@guyharris
Copy link
Member

guyharris commented Aug 12, 2020

Yes, this is the only valid reason as I see it. However, from what I can see it's only the client side libpcap that need to expose the new APIs in pcap-new.c (pcap_findalldevs_ex, pcap_open, etc.) since rpcapd is only using the "standard" APIs (pcap_findalldevs, pcap_open_live, etc.).

The "new" APIs defined in pcap-new.c are:

  • pcap_findalldevs_ex(), which is only for listing devices on a remote server, and rpcapd only lists devices local to the machine on which it's running;
  • pcap_open(), which is only needed for opening a device on a remote machine (there's nothing you can do with it for local devices that can't be done with pcap_create(), pcap_activate(), and other "standard" APIs, and there' nothing you can do with it for files that can't be done with pcap_open_offline()), and rpcapd only supports capturing on devices local to the machine on which it's running;
  • pcap_setsampling(), which is currently Windows-only (and it may even be WinPcap-only; I don't know whether Npcap supports it), and the rpcap protocol doesn't support using it;

so there's no need for rpcapd to use any of those APIs.

However, 1) new libpcap APIs won't be added in pcap-new.c (the name is historical, from WinPcap) and 2) newer versions of the protocol may mean that rpcapd will be using new APIs.

@netrounds-fredrik
Copy link
Author

There's also scenario E, where you're building libpcap and rpcapd for testing and development purposes

It could still be possible to build with static linking. I'm not even saying it can not still be the default option.

we should not ... make it difficult for any OS that ships libpcap to ship rpcapd as well.

... tcpdump. Why is that not linking libpcap statically?
It's a separate package; it's a program that happens to use libpcap

This was also my point with the examples of the other projects. They build a library and a program from the same repo, which are then distributed as separate packages in the distro. If rpcapd where to be distributed in Debian, it would probably be as a separate package that depends on the existing libpcap that is already in the distro.

@mcr
Copy link
Member

mcr commented Aug 12, 2020 via email

@infrastation
Copy link
Member

Is the consensus to leave this as it is now until dust settles in rpcapd?

@lukastribus
Copy link

I've filed a request to enable rpcap support in debians libpcap back in July:

https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=964985

@guyharris should the debian maintainer go ahead with adding --enable-remote or wait?

@netrounds-fredrik
Copy link
Author

I believe that this can be split up into two distinct parts. One is to build rpcapd without having to enable the experimental "remote" API in libpcap and the other is to make rpcapd link to libpcap dynamically.

I have made an attempt to show how this could be solved in these PRs:

  1. Add separate ENABLE_RPCAPD option to build rpcapd #961
  2. Add ENABLE_RPCAPD_DYNAMIC to make rpcapd link to libpcap shared library #962

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

5 participants