问题
I'm working with libpcap in c / c + + and I have a problem when inserting pointers in a vector. This is my code:
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);
}
The problem is that the elements are inserted in the same memory location, and the vector always contains the same element. Any suggestions?
PD: sorry for my english.
回答1:
extending Karrek's attempt!
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));
}
回答2:
In mycallback
the argument packet
is a const u_char
- buffer. This pointer points to an libpcap-internal data buffer which is reused for every packet which has matched your filter (and your callback is called). You have to create your own buffer and copy the packet-data into it.
For example:
u_char *b = malloc(pkthdr->caplen);
memcpy(b, pk, pkthdr->caplen);
vec[0].push_back(b);
回答3:
You have to copy the data to a freshly allocated piece of memory:
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);
}
However there are important issues to consider:
- When destroying your
vector
you must iterate through each element and explicitlydelete
it, in order to recover memory. - You don't know long each packet is within the
vector
. You really need a class that stores both the data and its length and then store avector
of these objects instead.
回答4:
What a mess! Let's make a C++ answer, using the documentation:
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));
}
The only noteworth point here is that we pass a pointer to v
through the user
argument, so we have to do some type-unsafe casting on both ends. That's just the hallmark of using a C callback function, though.
来源:https://stackoverflow.com/questions/7994083/vector-of-packets-in-libpcap