How to use libpcap to sniff on multiple devices? - libpcap

I am trying to create a sniffer that can sniff on multiple devices. In my code the program will receive a list of devices that a user wants to sniff on. I take the list of device and store it into an array that I use to loop through and pass along to a function that creates the pcap_t handle like the function below:
void *startPcapProcess(char * dev){
char errbuf[PCAP_ERRBUF_SIZE]; /* error buffer */
pcap_t *handle; /* packet capture handle */
/* filter expression [3] */
char filter_exp[] = "(dst port 53) and (udp[0xa] & 0x78 = 0x28)";
struct bpf_program fp; /* compiled filter program (expression) */
bpf_u_int32 mask; /* subnet mask */
bpf_u_int32 net; /* ip */
printf("%s","startPacketProcess called\n");
printf("Device sent to startPacketProcess: %s\n", dev);
/* get network number and mask associated with capture device */
if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) {
fprintf(stderr, "Couldn't get netmask for device %s: %s\n",
dev, errbuf);
net = 0;
mask = 0;
}
/* open capture device */
handle = pcap_open_live(dev, SNAP_LEN, 1, 1000, errbuf);
if (handle == NULL) {
fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf);
exit(EXIT_FAILURE);
}
/* make sure we're capturing on an Ethernet device [2] */
if (pcap_datalink(handle) != DLT_EN10MB) {
fprintf(stderr, "%s is not an Ethernet\n", dev);
exit(EXIT_FAILURE);
}
/* compile the filter expression */
if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
fprintf(stderr, "Couldn't parse filter %s: %s\n",
filter_exp, pcap_geterr(handle));
exit(EXIT_FAILURE);
}
/* apply the compiled filter */
if (pcap_setfilter(handle, &fp) == -1) {
fprintf(stderr, "Couldn't install filter %s: %s\n",
filter_exp, pcap_geterr(handle));
exit(EXIT_FAILURE);
}
pcap_freecode(&fp);
/* now we can set our callback function */
pcap_loop(handle, -1, process_packet, NULL);
printf("%s","End startPacketProcess call\n");
}
However, when I make a call to this function within my for loop it is only able to capture on one device since it seems to get stuck in the pcap_loop callback function. As a result of this I tried to do multi threading and the for loop that I use to pass in all the devices to open and capture to goes through the loop, but the pcap_loop callback function does not seem to execute. The following code shows my use of multi threading:
for (i = 0; i < numDevice; i++){
printf("Device returned by getDevices call: %s\n", deviceList[i]);
printf("%s","Entering for loop\n");
pthread_create(&tid, thAttr, startPacketProcess,(void*)deviceList[i]);
}
Does anyone know what I am doing wrong and can you provide me with suggestions on how to resolve this issue?
Thanks,
Linh

process_packet might be the problem. Try getting the packet in the thread context.
struct pcap_pkthdr *pkt_header;
u_char *pkt_data;
while ((retval = pcap_next_ex(mpPcap, &pkt_header, (const u_char **) &pkt_data)) >= 0) {
//Do Whatever
}

Have you tried using pcap_findalldevs() or pcap_findalldevs_ex()

Related

Use fread() to read binary file contents

I want to use fread to read a segment of a binary file. The binary content is 0xf3 0xf 0x1e 0xfa...
But I read and output from fread() 0xfffffff3 0xf... I want to know why 0xf3 becomes 0xfffffff3 0xf 0x1e 0xfffffffa...
My implementation code is as follows:
char movslq_inst[length];
/* Open the target_binary */
FILE * target_binary = fopen(target_path,"rb+");
/* Jump to target address */
if (fseek(target_binary, offset, SEEK_SET) != 0)
{
printf("Unable to seek file '%s' at offset '%i", target_path, offset);
exit(0);
}
/* Read the target bytes */
if (fread(movslq_inst, length, 1, target_binary) != 1)
{
printf("Unable to read file '%s'", target_path);
exit(0);
}
/* test examine */
printf("read content: \n");
for(int i = 0; i < length; i++)
{
printf("0x%x ",movslq_inst[i]);
}
printf("\n");
I worked it out. It should be unsigned char movslq_inst[length]; instead of
char movslq_inst[length];.

Why is cudaPointerGetAttributes() returning invalid argument for host pointer?

I want to write a function that tells me if a pointer is a host or device pointer. This is essentially a wrapper around cudaPointerGetAttributes() that returns either 1 or 0 if the pointer is for the device or not.
What I can't understand is why cudaPointerGetAttributes fails my error checking by returning invalid argument when I'm testing a host pointer. An example is provided below.
#include <stdio.h>
#include <stdlib.h>
#define CUDA_ERROR_CHECK(fun) \
do{ \
cudaError_t err = fun; \
if(err != cudaSuccess) \
{ \
fprintf(stderr, "Cuda error %d %s:: %s\n", __LINE__, __func__, cudaGetErrorString(err)); \
exit(EXIT_FAILURE); \
} \
}while(0);
int is_device_pointer(const void *ptr)
{
int is_device_ptr = 0;
cudaPointerAttributes attributes;
CUDA_ERROR_CHECK(cudaPointerGetAttributes(&attributes, ptr));
if(attributes.devicePointer != NULL)
{
is_device_ptr = 1;
}
return is_device_ptr;
}
int main()
{
int *host_ptr, x = 0;
int is_dev_ptr;
host_ptr = &x;
int *dev_ptr;
cudaMalloc((void **)&dev_ptr, 16);
//is_dev_ptr = is_device_pointer((const void *)host_ptr); //Causes invalid argument
is_dev_ptr = is_device_pointer((const void *)dev_ptr); //Works
if(is_dev_ptr == 1)
{
fprintf(stdout, "Device pointer\n");
}
else
{
fprintf(stdout, "Not device Pointer\n");
}
CUDA_ERROR_CHECK(cudaFree((void *)dev_ptr));
CUDA_ERROR_CHECK(cudaDeviceReset());
return EXIT_SUCCESS;
}
This is expected behavior. cudaPointerGetAttributes can only introspect pointers that have been recorded in some fashion with the CUDA runtime API. Refer to the documentation:
If pointer was not allocated in, mapped by or registered with context supporting unified addressing cudaErrorInvalidValue is returned.
What this is saying is that the pointer must have been returned or passed through an API such as cudaMalloc, cudaMallocManaged, cudaHostRegister, etc. for it to be "recognized" by cudaPointerGetAttributes. You must be in a UVA regime, and you must have acquired the pointer using an appropriate method.
In your case, passing a bare host pointer this way doesn't meet the requirements spelled out in the documentation, so the error return is expected.
This particular error return code is a "non-sticky" CUDA error, meaning it can be cleared out via cudaGetLastError(). In my view, it should be safe to interpret this error return code as "this is an ordinary host pointer". But of course, if you pass a garbage value, or an unallocated pointer, you will get the same error code.

CUDA mapped memory: device -> host writes are not visible on host

What I was trying to do is modifying a variable which resides in mapped memory that would cause the main program to exit.
But instead of this the main program keeps spinning on while (var == 0) ; line. I don't know how the new value could be flushed out so it would be visible on the host side too.
Btw. the variable is declared as volatile everywhere and I tried using the __threadfence_system() function with no success.
The host -> device direction works well.
System: Windows 7 x64, driver 358.50, GTX 560
Here is the piece of code that I can't get working:
static void handleCUDAError(cudaError_t err, const char *file, int line)
{
if (err != cudaSuccess) {
printf("%s in %s at line %d\n", cudaGetErrorString(err), file, line);
exit(EXIT_FAILURE);
}
}
#define CUDA_ERROR_CHECK(err) (handleCUDAError(err, __FILE__, __LINE__ ))
__global__ void echoKernel(volatile int* semaphore)
{
*semaphore = 1;
__threadfence_system();
}
int main()
{
CUDA_ERROR_CHECK(cudaSetDevice(0));
CUDA_ERROR_CHECK(cudaSetDeviceFlags(cudaDeviceMapHost));
volatile int var = 0;
volatile int *devptr;
CUDA_ERROR_CHECK(cudaHostRegister((int*)&var, sizeof (int), cudaHostRegisterMapped));
CUDA_ERROR_CHECK(cudaHostGetDevicePointer(&devptr, (int*)&var, 0));
echoKernel <<< 1, 1 >>> (devptr);
while (var == 0) ;
CUDA_ERROR_CHECK(cudaDeviceSynchronize());
CUDA_ERROR_CHECK(cudaHostUnregister((int*)&var));
CUDA_ERROR_CHECK(cudaDeviceReset());
return 0;
}
When I run your code on linux, it runs as-is without issue.
However on windows, there is a problem around WDDM command batching. In effect, your kernel does not launch and is not getting launched before you enter the while-loop that hangs.
The WDDM command queue is a queue of commands that will eventually go to the GPU device. Various events will cause this queue to be "flushed" and the contents to be delivered as a "batch" of commands to the GPU.
Various cuda runtime API calls may effectively force the "flushing" of the command queue, such as cudaDeviceSynchronize() or cudaMemcpy(). However after the kernel launch, you are not issuing any runtime API calls before entering your while-loop. As a result, in this scenario it seems that the kernel call is getting "stuck" in the queue and never "flushed".
You can work around this in a variety of ways, for example by recording an event after the launch of the kernel and then querying the status of that event. This will have the effect of flushing the queue, which will launch the kernel.
Here's an example modification of your code that works for me:
#include <stdio.h>
static void handleCUDAError(cudaError_t err, const char *file, int line)
{
if (err != cudaSuccess) {
printf("%s in %s at line %d\n", cudaGetErrorString(err), file, line);
exit(EXIT_FAILURE);
}
}
#define CUDA_ERROR_CHECK(err) (handleCUDAError(err, __FILE__, __LINE__ ))
__global__ void echoKernel(volatile int* semaphore)
{
*semaphore = 1;
__threadfence_system();
}
int main()
{
CUDA_ERROR_CHECK(cudaSetDevice(0));
CUDA_ERROR_CHECK(cudaSetDeviceFlags(cudaDeviceMapHost));
volatile int var = 0;
volatile int *devptr;
CUDA_ERROR_CHECK(cudaHostRegister((int*)&var, sizeof(int), cudaHostRegisterMapped));
CUDA_ERROR_CHECK(cudaHostGetDevicePointer(&devptr, (int*)&var, 0));
cudaEvent_t my_event;
CUDA_ERROR_CHECK(cudaEventCreate(&my_event));
echoKernel << < 1, 1 >> > (devptr);
CUDA_ERROR_CHECK(cudaEventRecord(my_event));
cudaEventQuery(my_event);
while (var == 0);
CUDA_ERROR_CHECK(cudaDeviceSynchronize());
CUDA_ERROR_CHECK(cudaHostUnregister((int*)&var));
CUDA_ERROR_CHECK(cudaDeviceReset());
return 0;
}
Tested on CUDA 7.5, Driver 358.50, Win7 x64 release project, GTX460M.
Note that we don't wrap the cudaEventQuery call in a standard error checker, because the expected behavior for it is to return a non-zero status when the event has not been completed yet.

capturing user data using pcap in c

I wanted to send my own data size of 1024 bytes through a particular interface . Suppose we have two hosts , one is sending and another is receiving.
Receiving host is using pcap mechanism to receive the data from other host.As per my knowledge Pcap receives echo packets from interface.
Here i want my own data to be received. How can i achieve that ??? Im a beginner ,so please help me out how to deal with pcap.
Actually I want to receive all data into a host ,save it and later forward it to my actual destination.
Is it possible using pcap???
client:
import socket
import select
import sys
import time
import json
import os
import pickle
from time import sleep
c=1
while(c):
if os.path.exists('/home/mininet/save.txt'):
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
count=5
while (count):
f1=open("/home/mininet/save.txt","r")
d=f1.read()
f1.close()
if d.strip():
d=int(d)
f=open("/home/mininet/test1.txt", "rb")
l = f.read(1024)
s.sendto(l,("10.0.0.1",9999))
count=count-1
time.sleep(d)
c=0
s.close()
This is the client part and in server the corresponding program to receive these data..
First both client and server was connected with each other . Then that link is broken and placed a host in between them to monitor the traffic.
Each data should reach to that newly created host then that host redirect that data to the server. I wanted to achieve this using pcap.
Here is an example:
/*
* Use pcap_open_live() to open a packet capture device.
* Use pcap_dump() to output the packet capture data in
* binary format to a file for processing later.
*/
#include <unistd.h>
#include <stdio.h>
#include <pcap.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define IFSZ 16
#define FLTRSZ 120
#define MAXHOSTSZ 256
#define PCAP_SAVEFILE "./pcap_savefile"
extern char *inet_ntoa();
int
usage(char *progname)
{
printf("Usage: %s <interface> [<savefile name>]\n", basename(progname));
exit(11);
}
int
main(int argc, char **argv)
{
pcap_t *p; /* packet capture descriptor */
struct pcap_stat ps; /* packet statistics */
pcap_dumper_t *pd; /* pointer to the dump file */
char ifname[IFSZ]; /* interface name (such as "en0") */
char filename[80]; /* name of savefile for dumping packet data */
char errbuf[PCAP_ERRBUF_SIZE]; /* buffer to hold error text */
char lhost[MAXHOSTSZ]; /* local host name */
char fltstr[FLTRSZ]; /* bpf filter string */
char prestr[80]; /* prefix string for errors from pcap_perror */
struct bpf_program prog; /* compiled bpf filter program */
int optimize = 1; /* passed to pcap_compile to do optimization */
int snaplen = 80; /* amount of data per packet */
int promisc = 0; /* do not change mode; if in promiscuous */
/* mode, stay in it, otherwise, do not */
int to_ms = 1000; /* timeout, in milliseconds */
int count = 20; /* number of packets to capture */
u_int32 net = 0; /* network IP address */
u_int32 mask = 0; /* network address mask */
char netstr[INET_ADDRSTRLEN]; /* dotted decimal form of address */
char maskstr[INET_ADDRSTRLEN]; /* dotted decimal form of net mask */
int linktype = 0; /* data link type */
int pcount = 0; /* number of packets actually read */
/*
* For this program, the interface name must be passed to it on the
* command line. The savefile name may be optionally passed in
* as well. If no savefile name is passed in, "./pcap_savefile" is
* used. If there are no arguments, the program has been invoked
* incorrectly.
*/
if (argc < 2)
usage(argv[0]);
if (strlen(argv[1]) > IFSZ) {
fprintf(stderr, "Invalid interface name.\n");
exit(1);
}
strcpy(ifname, argv[1]);
/*
* If there is a second argument (the name of the savefile), save it in
* filename. Otherwise, use the default name.
*/
if (argc >= 3)
strcpy(filename,argv[2]);
else
strcpy(filename, PCAP_SAVEFILE);
/*
* Open the network device for packet capture. This must be called
* before any packets can be captured on the network device.
*/
if (!(p = pcap_open_live(ifname, snaplen, promisc, to_ms, errbuf))) {
fprintf(stderr, "Error opening interface %s: %s\n",
ifname, errbuf);
exit(2);
}
/*
* Look up the network address and subnet mask for the network device
* returned by pcap_lookupdev(). The network mask will be used later
* in the call to pcap_compile().
*/
if (pcap_lookupnet(ifname, &net, &mask, errbuf) < 0) {
fprintf(stderr, "Error looking up network: %s\n", errbuf);
exit(3);
}
/*
* Create the filter and store it in the string called 'fltstr.'
* Here, you want only incoming packets (destined for this host),
* which use port 69 (tftp), and originate from a host on the
* local network.
*/
/* First, get the hostname of the local system */
if (gethostname(lhost,sizeof(lhost)) < 0) {
fprintf(stderr, "Error getting hostname.\n");
exit(4);
}
/*
* Second, get the dotted decimal representation of the network address
* and netmask. These will be used as part of the filter string.
*/
inet_ntop(AF_INET, (char*) &net, netstr, sizeof netstr);
inet_ntop(AF_INET, (char*) &mask, maskstr, sizeof maskstr);
/* Next, put the filter expression into the fltstr string. */
sprintf(fltstr,"dst host %s and src net %s mask %s and udp port 69",
lhost, netstr, maskstr);
/*
* Compile the filter. The filter will be converted from a text
* string to a bpf program that can be used by the Berkely Packet
* Filtering mechanism. The fourth argument, optimize, is set to 1 so
* the resulting bpf program, prog, is compiled for better performance.
*/
if (pcap_compile(p,&prog,fltstr,optimize,mask) < 0) {
/*
* Print out appropriate text, followed by the error message
* generated by the packet capture library.
*/
fprintf(stderr, "Error compiling bpf filter on %s: %s\n",
ifname, pcap_geterr(p));
exit(5);
}
/*
* Load the compiled filter program into the packet capture device.
* This causes the capture of the packets defined by the filter
* program, prog, to begin.
*/
if (pcap_setfilter(p, &prog) < 0) {
/* Copy appropriate error text to prefix string, prestr */
sprintf(prestr, "Error installing bpf filter on interface %s",
ifname);
/*
* Print error to screen. The format will be the prefix string,
* created above, followed by the error message that the packet
* capture library generates.
*/
pcap_perror(p,prestr);
exit(6);
}
/*
* Open dump device for writing packet capture data. In this sample,
* the data will be written to a savefile. The name of the file is
* passed in as the filename string.
*/
if ((pd = pcap_dump_open(p,filename)) == NULL) {
/*
* Print out error message if pcap_dump_open failed. This will
* be the below message followed by the pcap library error text,
* obtained by pcap_geterr().
*/
fprintf(stderr,
"Error opening savefile \"%s\" for writing: %s\n",
filename, pcap_geterr(p));
exit(7);
}
/*
* Call pcap_dispatch() to read and process a maximum of count (20)
* packets. For each captured packet (a packet that matches the filter
* specified to pcap_compile()), pcap_dump() will be called to write
* the packet capture data (in binary format) to the savefile specified
* to pcap_dump_open(). Note that packet in this case may not be a
* complete packet. The amount of data captured per packet is
* determined by the snaplen variable which is passed to
* pcap_open_live().
*/
if ((pcount = pcap_dispatch(p, count, &pcap_dump, (char *)pd)) < 0) {
/*
* Print out appropriate text, followed by the error message
* generated by the packet capture library.
*/
sprintf(prestr,"Error reading packets from interface %s",
ifname);
pcap_perror(p,prestr);
exit(8);
}
printf("Packets received and successfully passed through filter: %d.\n",
pcount);
/*
* Get and print the link layer type for the packet capture device,
* which is the network device selected for packet capture.
*/
if (!(linktype = pcap_datalink(p))) {
fprintf(stderr,
"Error getting link layer type for interface %s",
ifname);
exit(9);
}
printf("The link layer type for packet capture device %s is: %d.\n",
ifname, linktype);
/*
* Get the packet capture statistics associated with this packet
* capture device. The values represent packet statistics from the time
* pcap_open_live() was called up until this call.
*/
if (pcap_stats(p, &ps) != 0) {
fprintf(stderr, "Error getting Packet Capture stats: %s\n",
pcap_geterr(p));
exit(10);
}
/* Print the statistics out */
printf("Packet Capture Statistics:\n");
printf("%d packets received by filter\n", ps.ps_recv);
printf("%d packets dropped by kernel\n", ps.ps_drop);
/*
* Close the savefile opened in pcap_dump_open().
*/
pcap_dump_close(pd);
/*
* Close the packet capture device and free the memory used by the
* packet capture descriptor.
*/
pcap_close(p);
}

cudaHostRegister fails with 'invalid argument' error even with page-aligned memory

I have allocated page-aligned memory on host using posix_memalign. The call to posix_memalign does not return any error. However, using this pointer as argument to cudaHostRegister gives me an 'invalid argument' error. What could be the issue?
CUDA API version: 4.0
gcc version: 4.4.5
GPU compute capability: 2.0
The memory allocation is done in the application code, and a pointer is passed to a library routine.
Application code snippet:
if(posix_memalign((void **)&h_A, getpagesize(), n * n * sizeof(float))) {
printf("Error allocating aligned memory for A\n");
return 1;
}
Shared library code snippet:
if((ret = cudaSetDeviceFlags(cudaDeviceMapHost)) != cudaSuccess) {
fprintf(stderr, "Error setting device flag: %s\n",
cudaGetErrorString(ret));
return NULL;
}
if((ret = cudaHostRegister(h_A, n2 * sizeof(float),
cudaHostRegisterMapped)) != cudaSuccess) {
fprintf(stderr, "Error registering page-locked memory for A: %s\n",
cudaGetErrorString(ret));
return NULL;
}
I cannot reproduce this. If I take the code snippets you supplied and make them into a minimal executable:
#include <unistd.h>
#include <stdlib.h>
#include <malloc.h>
#include <stdio.h>
int main(void)
{
const int n2 = 100 * 100;
float *h_A;
cudaError_t ret;
if(posix_memalign((void **)&h_A, getpagesize(), n2 * sizeof(float))) {
printf("Error allocating aligned memory for A\n");
return -1;
}
if((ret = cudaSetDeviceFlags(cudaDeviceMapHost)) != cudaSuccess) {
fprintf(stderr, "Error setting device flag: %s\n",
cudaGetErrorString(ret));
return -1;
}
if((ret = cudaHostRegister(h_A, n2 * sizeof(float),
cudaHostRegisterMapped)) != cudaSuccess) {
fprintf(stderr, "Error registering page-locked memory for A: %s\n",
cudaGetErrorString(ret));
return -1;
}
return 0;
}
it compiles and runs without error under both CUDA 4.2 and CUDA 5.0 on a 64 bit linux host with the 304.54 driver. I would, therefore, conclude that either you have a broken CUDA installation or your code has a problem somewhere you haven't shown us.
Perhaps you can compile and run this code exactly as I posted and see what happens. If it works, it might help narrow down what it is that might be going wrong here.