对“pcap_init”的未定义引用 - Libpcap

Undefined Reference to `pcap_init' - Libpcap

我目前正在尝试使用 libpcap 设置一个简单的数据包嗅探器,但由于这个链接器错误而面临很多困惑。

我从 github (1.11.0-PRE-GIT) 克隆了最新版本,并成功完成了安装说明中概述的配置、制作和安装步骤。

我的脚本如下:

#include <iostream>
#include <pcap/pcap.h>
#include <string>
#include <cstdlib>


using namespace std;

int main(int argc, char *argv[])
{
    //Set up error buffer
    char errbuf[PCAP_ERRBUF_SIZE];

    // Check Libpcap version number
    cout << pcap_lib_version() << endl << endl;

    //Initialize the library for local charactr encoding         
    pcap_init(PCAP_CHAR_ENC_LOCAL, errbuf);
    
    return 0;
}

但是当我尝试使用下面的命令进行编译时出现错误:

g++ csniff.cc -o csniff -lpcap

/usr/bin/ld: /tmp/ccAPLFoh.o: in function `main':
csniff.cc:(.text+0x79): undefined reference to `pcap_init'
collect2: error: ld returned 1 exit status

我还检查了 usr/include 和 usr/local/include 中的 pcap.h 文件,它们都包含 pcap_init 函数的原型,如下所示:

#define PCAP_CHAR_ENC_LOCAL 0x00000000U /* strings are in the local 
character encoding */
#define PCAP_CHAR_ENC_UTF_8 0x00000001U /* strings are in UTF-8 */

PCAP_AVAILABLE_1_10
PCAP_API int    pcap_init(unsigned int, char *);

不过我注意到的一件事是,当我用 pcap_init 注释掉该行并使用脚本打印我得到的版本号时

libpcap version 1.9.1 (with TPACKET_V3)

如有指点,将不胜感激!

编辑:运行 Ubuntu 20.04.3 LTS

您的操作系统已经带有 libpcap - 版本 1.9.1。大多数 Linux 发行版都这样做,*BSD、macOS 和一些商业 UN*Xes 也是如此。

你编译安装了更新版本的libpcap,所以你有两个版本的库文件——系统自带的1.9.1,在系统库目录下,因为它自带OS, 而1.11.0-PRE-GIT 和你编译安装的,大概在/usr/local/lib.

您在 /usr/local/include/pcap 中还有 一个 版本的 libpcap header 文件 - 1.11.0-PRE-GIT 版本,因为你安装了它。你 没有 有 header 文件的 1.9.1 版本,因为,像许多 Linux 发行版一样,一个单独的“开发”包必须安装在为了获取 header 个文件。

当你编译你的程序时,你没有告诉它在哪里寻找 header 文件或库。它在 /usr/local/include/pcap 中找到 header 文件 - 即 1.11.0-PRE-GIT header 文件 - 并在系统库目录中找到库 - 即 1.9. 1 个图书馆。

这会导致问题,因为 header 文件包含 pcap_init() 的声明,因此编译器不会打印关于 pcap_init() 未被声明的警告,而是库文件不包含 pcap_init() 函数,所以 linker 打印了一个关于 pcap_init() not being found in libpcap.

的错误

删除对 pcap_init() 的调用意味着 linker 没有尝试寻找 pcap_init(),因此没有失败。

如果您没有构建和安装 libpcap 1.11.0-PRE-GIT,并且您已经安装了 libpcap-dev 软件包,您的系统将具有 headers 和库1.9.1,并编译你的程序 - 没有 pcap_init() 的调用 - 会找到 1.9.1 的 headers,所以它可以编译,并且1.9.1 的库,所以它将 link.

但是,如果您想使用 1.11.0-PRE-GIT 构建,则需要告诉编译器在哪里可以找到这些库;您可能还必须告诉它在哪里可以找到 headers.

如果你没有安装 libpcap-dev 包,那么你不需要告诉它在哪里可以找到 headers,因为它会找到 1.11.0-PRE-GIT 你安装的;但是,如果安装了 libpcap-dev 包 ,您可能必须将标志 -I /usr/local/include 添加到编译器命令,以确保它找到 headers 在 /usr/local/include 而不是系统包含目录。

为了确保它找到 1.11.0-PRE-GIT 版本的库,您还必须将标志 -L /usr/local/lib 添加到编译器命令 - 或者设置 LD_LIBRARY_PATH 以便 linker 找到 1.11.0-PRE-GIT 版本。

如果您使用 1.11.0-PRE-GIT 构建,则可以使用 pcap_init()。你不需要使用pcap_init(),除非你想运行某些UN*X上的程序 Windows 并且您希望所有字符串都采用 UTF-8(在 Windows 上,默认情况下,字符串将被视为在“本地代码页”中)。引用 pcap_init() 手册页的描述部分:

   pcap_init()  is  used  to  initialize the Packet Capture library.  opts
   specifies options for the library; currently, the options are:

   PCAP_CHAR_ENC_LOCAL
          Treat all strings supplied as arguments, and return all  strings
          to the caller, as being in the local character encoding.

   PCAP_CHAR_ENC_UTF_8
          Treat  all strings supplied as arguments, and return all strings
          to the caller, as being in UTF‐8.

   On UNIX‐like systems, the local character encoding  is  assumed  to  be
   UTF‐8, so no character encoding transformations are done.

   On Windows, the local character encoding is the local ANSI code page.

   If pcap_init() is not called, strings are treated as being in the local
   ANSI code page on Windows, pcap_lookupdev(3PCAP) will succeed if  there
   is  a  device  on  which  to  capture,  and pcap_create(3PCAP) makes an
   attempt to check whether the string passed as an argument is a UTF‐16LE
   string  ‐  note that this attempt is unsafe, as it may run past the end
   of the string ‐ to handle pcap_lookupdev() returning a UTF‐16LE string.
   Programs   that   don’t  call  pcap_init()  should,  on  Windows,  call
   pcap_wsockinit() to  initialize  Winsock;  this  is  not  necessary  if
   pcap_init() is called, as pcap_init() will initialize Winsock itself on
   Windows.