Use fread() to read binary file contents - binary

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];.

Related

Trying to get an image to show up on an HTML file in a C web server

I'm trying to get more familiar with C by writing a web server, and I managed to get a method to create HTTP headers for html files yesterday but I have been unable to get images within that html file to load.
Right now I generate my header by opening the html file, and creating a file stream to write the start of the header, the size of it, and then I loop through the file to send each character to the stream. I them send that stream as a char pointer back to the main method which sends it as a response over the socket.
I'm imagining that there is some more work I need to do here, but I haven't been able to find a good solution or anything too helpful to point me in the right direction of how exactly to get it to display. I appreciate any responses/insight.
test.html
<!DOCTYPE html>
<html>
<head>
<title>Nick's test website</title>
</head>
<body>
<h1>Welcome to my website programmed from scratch in C</h1>
<p>I'm doing this project to practice C</p>
<table>
<tr>
<td>test1</td>
<td>test2</td>
<td>test2</td>
</tr>
</table>
<img src="pic.jpg"/>
</body>
</html>
headermaker.c
char * headermaker(char * file_name){
char ch;
FILE * fp;
fp = fopen(file_name, "r");
if(fp == NULL){
perror("Error while opening file.\n");
exit(-1);
}
//print/save size of file
fseek(fp, 0, SEEK_END);
int size = ftell(fp);
fseek(fp, 0, SEEK_SET);
printf("File size is %d\n", size);
//create filestream
FILE * stream;
char * buf;
size_t len;
stream = open_memstream(&buf, &len);
//start header
fprintf(stream, "HTTP/1.1 200 OK\\nDate: Sun, 28 Aug 2022 01:07:00 GMT\\nServer: Apache/2.2.14 (Win32)\\nLast-Modified: Sun, 28 Aug 2022 19:15:56 GMT\\nContent-Length: ");
fprintf(stream, "%d\n", size);
fprintf(stream, "Content-Type: text/html\n\n");
//loop through each character
while((ch = fgetc(fp)) != EOF)
fprintf(stream, "%c", ch);
fclose(stream);
fclose(fp);
return buf;
}
Using a modified version of provided code to setup a web server using netcat and needed to see explanation of how to send jpeg using netcat
./one | nc -l 45231 ; { ./two && cat pic.jpeg; } | nc -l 45231;
Chrome browser can open http://localhost:45231 and will show the web page with an image. Also, can observe the network request - response sequence using "View->Developer->Developer Tools".
The code was built like this:
gcc -DONE -o one main.c && gcc -DTWO -o two main.c
The modified code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
char * headermaker(char * file_name, char * content_type ){
char ch;
FILE * fp;
fp = fopen(file_name, "r");
if(fp == NULL){
perror("Error while opening file.\n");
exit(-1);
}
//print/save size of file
fseek(fp, 0, SEEK_END);
int size = ftell(fp);
fseek(fp, 0, SEEK_SET);
//printf("File size is %d\n", size);
//create filestream
FILE * stream;
char * buf;
size_t len;
stream = open_memstream(&buf, &len);
//start header
fprintf(stream, "HTTP/1.1 200 OK\n");
fprintf(stream, "Server: netcat!\n");
fprintf(stream, "Content-Type: %s\n",content_type);
fprintf(stream, "Content-Length: %d\n", size);
fprintf(stream, "\n");
//loop through each character
#ifdef ONE
while((ch = fgetc(fp)) != EOF)
fprintf(stream, "%c", ch);
#endif //#ifdef ONE
fclose(stream);
fclose(fp);
return buf;
}
int main( )
{
#ifdef ONE
char *buf = headermaker( "test.html", "text/html" );
printf( "%s", buf );
free(buf);
#endif //#ifdef ONE
#ifdef TWO
char *buf = headermaker( "pic.jpeg", "image/jpeg" );
printf( "%s", buf );
free(buf);
#endif //#ifdef TWO
return 0;
}
Another helpful debug tool was curl:
curl -vvv localhost:45231 > page.html
curl -vvv localhost:45231 > image.jpeg

Extract all URLs from HTML in C

How can I extract all URLs in a HTML using C standard library?
I am trying to deal with it using sscanf(), but the valgrind gives error (and I am even not sure if the code can meet my requirement after debugging successfully, so if there are other ways, please tell me). I stored the html content in a string pointer, there are multiple URLs (including absolute URL and relative URL, e.g.http://www.google.com, //www.google.com, /a.html, a.html and so on) in it. I want to extract them one by one and store them separately into another string pointer.
I am also thinking about using strstr(), but then I have no idea about how to get the second url.
My code (I skip the assert here) using sscanf:
int
main(int argc, char* argv[]) {
char *remain_html = (char *)malloc(sizeof(char) * 1001);
char *url = (char *)malloc(sizeof(char) * 101);
char *html = "navigation"
"search";
printf("html: %s\n\n", html);
sscanf(html, "<a href=\"%s", remain_html);
printf("after first href tag: %s\n\n", remain_html);
sscanf(remain_html, "%s\">", url);
printf("first web: %s\n\n", url);
sscanf(remain_html, "<a href=\"%s", remain_html);
printf("after second href tag: %s\n\n", remain_html);
free(remain_html);
free(url);
}
The valgrind gives: Conditional jump or move depends on uninitialised value(s).
If anybody could help, thank you so much!
valgrind warn you about non initialized data (used in test), considering your program only does sscanf and printf that means you very probably have a problem with your scanf
if I change a little your program to print the result of sscanf, so show much elements it get :
int
main(int argc, char* argv[]) {
char *remain_html = (char *)malloc(sizeof(char) * 1001);
char *url = (char *)malloc(sizeof(char) * 101);
char *html = "<A class=\"mw-jump-link\" HREF=\"#mw-head\">Jump to navigation</a>"
"<a class=\"mw-jump-link\" href=\"#p-search\">Jump to search</a>";
printf("html: %s\n\n", html);
printf("%d\n", sscanf(html, "<a href=\"%s", remain_html));
printf("after first href tag: %s\n\n", remain_html);
printf("%d\n", sscanf(remain_html, "%s\">", url));
printf("first web: %s\n\n", url);
printf("%d\n", sscanf(remain_html, "<a href=\"%s", remain_html));
printf("after second href tag: %s\n\n", remain_html);
free(remain_html);
free(url);
}
the execution is :
pi#raspberrypi:/tmp $ ./a.out
html: <A class="mw-jump-link" HREF="#mw-head">Jump to navigation</a><a class="mw-jump-link" href="#p-search">Jump to search</a>
0
after first href tag:
-1
first web:
-1
after second href tag:
pi#raspberrypi:/tmp $
so the first scanf got nothing (0 element), that means it does not set remain_html and that one is non initialized when it is used by the next sscanf with an undefined behavior
Because of the format
"<a href=\"%s"
the first sscanf waits for a string starting by
<a href="
but html starts by
<A class=
which is different, so it stop from the second character and does not set remain_html
To use sscanf is not the right way, search for the prefix <a href=" may be in uppercase for instance using strcasestr, then extract the URL up to the closing "
Example :
#include <stdio.h>
#include <string.h>
#include <ctype.h>
/* in case you do not have that function */
char * strcasestr(char * haystack, char *needle)
{
while (*haystack) {
char * ha = haystack;
char * ne = needle;
while (tolower(*ha) == tolower(*ne)) {
if (!*++ne)
return haystack;
ha += 1;
}
haystack += 1;
}
return NULL;
}
int main(int argc, char* argv[]) {
char *html = "navigation"
"search";
char * begin = html;
char * end;
printf("html: %s\n", html);
while ((begin = strcasestr(begin, "<a href=\"")) != NULL) {
begin += 9; /* bypass the header */
end = strchr(begin, '"');
if (end != NULL) {
printf("found '%.*s'\n", (int) (end - begin), begin);
begin = end + 1;
}
else {
puts("invalid url");
return -1;
}
}
}
Compilation and execution :
pi#raspberrypi:/tmp $ gcc -Wall a.c
pi#raspberrypi:/tmp $ ./a.out
html: navigationsearch
found 'http://www.google.com'
found '/a.html'
pi#raspberrypi:/tmp $
Note I know the second parameter of strcasestr is in lower case so it is useless to do do tolower(*ne) and *ne is enough, but I given a definition of the function out of the current context

Encode an image as a base64 string in MATLAB

Currently, I have an image stored as an MxNx3 uint8 array in MATLAB. However, I need to embed it in an HTML document, and I can't include the image separately.
Instead, I've decided to try and encode the image as a base64 string. However, I can't seem to find a way to encode the image as a string without having to first save the image to disk. I tried looking into writebmp and the like, but I can't seem to get it to work.
I'd really rather not write the image to a file, just to read it back using fread. The computer I'm using has very low Disk I/O, so that will take way too long.
Any help would be appreciated!
Edit:
I looked here, but that errors in R2018b due to "no method found". When I linearize the image, the returned string is incorrect
From an image matrix to HTML
1 Convert the image to the bytes of a BMP
function [header] = writeBMP(IM)
header = uint8([66;77;118;5;0;0;0;0;0;0;54;0;0;0;40;0;0;0;21;0;0;0;21;0;0;0;1;0;24;0;0;0;0;0;64;5;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0]);
IMr = IM(:,:,1);
IMg = IM(:,:,2);
IMb = IM(:,:,3);clear IM;
IM(:,:,1)=IMb';
IM(:,:,2)=IMg';
IM(:,:,3)=IMr';
IM(:,:,:)=IM(:,end:-1:1,:);
[i,j,~]=size(IM);
header(19:22) = typecast(int32(i),'uint8'); %width
header(23:26) = typecast(int32(j),'uint8'); %height
IM = permute(IM,[3,1,2]);
IM = reshape(IM,[i*3,j]);
W = double(i)*3;
W = ceil(W/4)*4;
IM(3*i+1:W,:)=0; %padd zeros
IM = IM(:); %linear
header(35:38) = typecast(uint32(length(IM)),'uint8'); %datasize
header = [header;IM];
header(3:6) = typecast(uint32(length(header)),'uint8'); %filesize
end
You can also look into ...\toolbox\matlab\imagesci\private\writebmp.m for a more detailed example.
2 Encode the bytes to base64 characters
This is best done in a mex-file.
Save this code as encodeB64.c and run mex encodeB64.c
/*==========================================================
* encodeB64.c - converts a byte vector to base64
*
* The calling syntax is:
*
* [B] = encodeB64(B)
*
* input: - B : vector of uint8
*
* output: - B : vector of base64 char
*
* This is a MEX-file for MATLAB.
*
*========================================================*/
#include "mex.h"
/* The computational routine */
void Convert(unsigned char *in, unsigned char *out,unsigned long Nin, unsigned long Nout)
{
int temp;
static unsigned char alphabet[64] = {65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,48,49,50,51,52,53,54,55,56,57,43,47};
for (int i=0;i<(Nin-2);i+=3){
temp = in[i+2] | (int)in[i+1]<<8 | (int)in[i]<<16;
for (int j=0;j<4;j++){
out[3+(i/3)*4-j] = alphabet[(temp >> (j*6)) & 0x3f];
}
}
if (Nin%3==1){
temp = (int)in[Nin-1]<<16;
out[Nout-1] = 61;
out[Nout-2] = 61;
out[Nout-3] = alphabet[(temp >> 12) & 0x3f];
out[Nout-4] = alphabet[(temp >> 18) & 0x3f];
}
if (Nin%3==2){
temp = in[Nin-1]<<8 | (int)in[Nin-2]<<16;
out[Nout-1] = 61;
out[Nout-2] = alphabet[(temp >> 6) & 0x3f];
out[Nout-3] = alphabet[(temp >> 12) & 0x3f];
out[Nout-4] = alphabet[(temp >> 18) & 0x3f];
}
}
/* The gateway function */
void mexFunction( int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[])
{
unsigned char *InputV; /* input vector 1*/
unsigned char *OutputV; /* output vector 1*/
unsigned long Nin;
unsigned long Nout;
/* check for proper number of arguments */
if(nrhs!=1) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nrhs","One inputs required.");
}
if(nlhs!=1) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nlhs","One output required.");
}
/* make sure the first input argument is scalar integer*/
if( !mxIsClass(prhs[0],"uint8") || mxGetNumberOfElements(prhs[0]) == 1 || mxGetN(prhs[0]) != 1) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notRowInteger","Input one must be uint8 column vector.");
}
/* get the value of the scalar input */
InputV = mxGetPr(prhs[0]);
Nin = mxGetM(prhs[0]); /*number of input bytes */
Nout = 4*((Nin+2)/3);
/* create the output matrix */
plhs[0] = mxCreateNumericMatrix((mwSize)Nout,1,mxUINT8_CLASS,mxREAL);
/* get a pointer to the real data in the output matrix */
OutputV = (unsigned char *) mxGetData(plhs[0]);
/* call the computational routine */
Convert(InputV,OutputV,Nin,Nout);
}
To test it you can run
T = randi(255,[2^28,1],'uint8'); %250MB random data
tic;Res=encodeB64(T);t=toc %convert
(length(T)/2^20) / t %read in MB/s
(length(Res)/2^20) / t %write in MB/s
My result:
read: 467 MB/s write: 623 MB/s
3 Put it all together and test
file = 'test.html';
fid = fopen(file,'wt');
fwrite(fid,sprintf('<html>\n<header> </header>\n<body>\n'));
fwrite(fid,sprintf('<p>%s</p>\n','Show the Matlab demo image street1.jpg'));
IM = imread('street1.jpg');figure(1);clf;image(IM);
B = writeBMP(IM);
str = encodeB64(B);
fwrite(fid,sprintf('<img src="data:image/bmp;base64,%s"/>\n',str));
fwrite(fid,sprintf('</body>\n</html>'));
fclose(fid);
this should generate a 1,229,008 byte HTML file with an image encoded.

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);
}

How to use libpcap to sniff on multiple devices?

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()