вектор пакетов в libpcap - PullRequest
       16

вектор пакетов в libpcap

0 голосов
/ 03 ноября 2011

Я работаю с libpcap в c / c ++ и у меня есть проблема при вставке указателей в вектор. Это мой код:

    typedef vector <u_char *>vPack;
    ...
    vPack vect;
    ...
    if (pcap_dispatch (p, 0, &mycallback, (u_char *) &vect) < 0){
         cout << "Error" << endl;
          pcap_perror (p, prestr);
    }
    ....
    void mycallback (u_char * args, const struct pcap_pkthdr *pkthdr, const u_char * packet){
          u_char *pk;
          pk = (u_char *)packet;
          vPack *vec = (vPack *) args;
          vec[0].push_back(pk);
        }

Проблема в том, что элементы вставляются в одну и ту же ячейку памяти, а вектор всегда содержит один и тот же элемент. Есть предложения?

PD: извините за мой английский.

Ответы [ 4 ]

2 голосов
/ 03 ноября 2011

В mycallback аргумент packet является const u_char - буфером.Этот указатель указывает на внутренний буфер данных libpcap, который повторно используется для каждого пакета, который соответствует вашему фильтру (и вызывается ваш обратный вызов).Вы должны создать свой собственный буфер и скопировать в него пакетные данные.

Например:

u_char *b = malloc(pkthdr->caplen);
memcpy(b, pk, pkthdr->caplen);
vec[0].push_back(b);
1 голос
/ 03 ноября 2011

Вам необходимо скопировать данные в только что выделенный фрагмент памяти:

void mycallback (u_char * args, const struct pcap_pkthdr *pkthdr, const u_char * packet)
{
    u_char *pk = new u_char [pkthdr->caplen];
    memcpy(pk, packet, pkthdr->caplen);
    vPack *vec = (vPack *) args;
    vec->push_back(pk);
}

Однако есть важные вопросы, которые следует учитывать:

  • При уничтожении vector вынеобходимо перебрать каждый элемент и явно delete его, чтобы восстановить память.
  • Вы не знаете, долго ли каждый пакет находится в пределах vector.Вам действительно нужен класс, который хранит как данные, так и их длину, а затем хранит vector этих объектов.
0 голосов
/ 03 ноября 2011

расширение попытки Каррека!

struct packet_handler
{
  typedef std::vector<u_char> PacketType;
  typedef std::vector <PacketType> PacketBuffer;

  static void handler(u_char *user, const pcap_pkthdr *h, const u_char *bytes)
  {
    packet_handler* ph = reinterpret_cast<packet_handler*>(user);
    ph->handle(PacketType(bytes, bytes + h->caplen));
  }

  void handle(PacketType const& packet)
  {
    _packetBuffer.push_back(packet);
  }

  PacketBuffer _packetBuffer;
};

int main()
{
  packet_handler ph;
  // pass in the handler class as user data
  int result = pcap_dispatch(p, 0, packet_handler::handler, reinterpret_cast<uchar*>(&ph));
}
0 голосов
/ 03 ноября 2011

Какой беспорядок!Давайте создадим ответ C ++, используя документацию :

typedef std::vector <u_char*> VPack;

void handler(u_char *user, const pcap_pkthdr *h, const u_char *bytes)
{
  VPack & v = *reinterpret_cast<VPack*>(user);
  v.insert(v.end(), bytes, bytes + h->caplen);
}

int main()
{
  VPack v;
  // ... populate p ...
  int result = pcap_dispatch(p, 0, handler, reinterpret_cast<uchar*>(&v));
}

. Единственное, что заслуживает внимания, это то, что мы передаем указатель на v через аргумент user, поэтомусделать небезопасное приведение типов на обоих концах.Это просто отличительная черта использования функции обратного вызова C.

...