how to reassemble tcp and decode http info in c code? - c

I am working with libpcap to check http info. libpcap can not reassemble tcp segment.
there are many corner cases to deal manually. I also read wireshark source code. It's too big.
Does have any open source code can reassemble tcp and disect http data in c?

Have hacked code of driftnet, tcpflow, pcap etc. earlier.
tcpflow can re-assemble dumps from ie tcpdump. A "typical" chain of work could be:
$ tcpdump -nnieth0 -w dump.raw
# dump dum dump
$ mkdir tmp && cd tmp
tmp/$ tcpflow -r ../dump.raw
# This joins the transfers into separate files
# Now one can investigate each transfere from those separate files
# Next join them to one:
tmp/$ cat * > ../dump.flow
tmp/$ cd ..
# Extract some data
$ foremost -i dump.flow
Believe you can find some useful lines in the source-code for these.
Else:
A HTTP parsing library: HTTP Parser

Easiest way to do this is download wireshark software open pcap file or live capture it. after that right click any packet and go to "follow tcp stream"...you will see your http data in opened window.
If you want to build a program from scratch.-
A pcap file structure for tcp transaction is something like this:
[pcap_file_header]
for each packet
[pcap_packet] --this contains packet len info
[ip_header]----usually of size 20 or more
[tcp_header]--usually of size 20 or more
[packet] ---len stored in pcap packet header
Now to read the info, first get your pcap file in stream pointer.
Read packet file header(google for various type of struct)
start a loop
for each packet
read pcap_phdr from file or stream
add offset of ip_hdr length and tcp hdr length
for example pointer=pointer+20(for ip)+20(for tcp)
the pointer should be pointing to your data
so just give read pcap_phdr.caplen amount of byte and print it character by character.

The smallest TCP/IP stack I know of, which is open source is uIP but it is a bit odd, as it is designed for extremely small systems (microcontrollers)
Another small Open Source TCP/IP stack, which is a bit more traditional is lwIP

Related

how to fix 'invalid argument' for ioctl requests to block device

I'm writing a small c program to make tape status and seek requests via
ioctl(int fd, long int request, &io_buf)
but after trial and plenty of error, ioctl is returning -1 with the errno message "Invalid Argument"
I'm on Linux and running my program as sudo. The device I want to issue requests to is an optical drive, connected via SCSI. I've tried tape status and seek requests by passing requests (MTIOCGET or MTIOCTOP, respectively) to ioctl.
Code snippet for tape status function where fd is the file descriptor of the device returned by open() and mtgetbuf is an instance of the mtget struct from sys/mtio.h
stat = ioctl(fd, MTIOCGET, &mtgetbuf);
if (stat == -1)
{
perror("error on ioctl MTIOCGET request: ")
return EXIT_FAILURE;
}
Similar code snippet for seek tape function except mtopbuf is an instance of the mtop structure and MTSEEK is the defined op code for the seek operation, also in sys/mtio.h
mtopbuf.mt_op = MTSEEK;
stat = ioctl(fd, MTIOCTOP, &mtopbuf);
if (stat == -1)
{
perror("error on ioctl MTIOCGET request: ")
return EXIT_FAILURE;
}
Instead of invalid argument error messages and a return of -1, I would have expected a successful return from ioctl and the respective structure instances, mtgetbuf and mtopbuf, to have their members populated with data provided by the device.
I.e. A successful ioctl() command with the MTIOCGET request would return into the mtgetbuf mt_type member a value of either MT_ISSCSI1, MT_ISSCSI2, or MT_ISUNKNOWN (I don't believe it is any of the other defined values for other vendor-specific devices).
Note: I'm aware of the linux/mtio.h header file and I have tried including that in place of sys/mtio.h but the outcome is the same.
I've recently had success issuing requests to a block device using the SCSI Generic Linux driver (SG). There are three header files (below) that have provided op codes, structures used to pass and retrieve data from the device, among other information.
SCSI SG Header files:
/usr/include/scsi/scsi.h
/usr/include/scsi/scsi_ioctl.h
/usr/include/scsi/sg.h
A combination of online resources were instrumental in understanding how to package, send, and receive requests:
1) The TLDP SCSI Generic (sg) HOW-TO guide is a font of information on communicating to SCSI devices via the SG driver. A link to it is provided here. It explains in detail various commands that can be issued, how to package the commands by creating an instance of the sg_io_hdr_t structure, as well as a programming example to send a SCSI INQUIRY command which returns basic vendor information of the device. There are also status and sense codes for error handling and understanding unsuccessful SCSI requests.
2) Seagate's SCSI Command Reference Manual was helpful at times to understand the structure of bytes/bits in a SCSI command. Typically the op code occupied the first byte and the remaining bytes were zeros. The op codes in this reference manual were defined between those three header files mentioned above.
I have been able to send successful INQUIRY and GET_SG_VERSION_NUMBER requests and most likely have been able to send SEEK(6), READ_CAPACITY(10), and REZERO_UNIT commands. I say most likely because -1/errno values are not being returned and no information is being passed back into the sense buffer which is an indication of warnings/errors (either SCSI, host adapter, or driver status codes).
Hope this answers OPs question.

How to read and write concurrently a pcap file in c

I have 2 programs written in C, one program writes to the pcap file and the second program reads from it at the same time.For writing ,I am using the following code
while(j < 100000)
{
pcount = pcap_dispatch(p,2000,&pcap_dump,(u_char *)pd);
j = j+pcount;
printf("Got %d packets , total packets %d\n",pcount,j);
}
And for decoding the packets, I am using the following code
while( (returnValue=pcap_next_ex(pcap,&header,&data)) >= 0)
{
printf("Packet # %d ",++packetCount);
printf("return value %d\n",returnValue);
}
When i run the program separately i.e when I stop writing to the pcap file, It decodes the packets perfectly. But when I run both the programs at the same time, the decoder does not decode all the packets. If i get 100 packets, the decoder will show only 50-60 decoded packets.
Any help will be appreciated.
In my opinion, reader's file is not getting updated as soon as the writer writes in the pcap file. This might be due to the reason that reader's file pointer is not refreshed i.e its reading the non updated version of file.
Hope it will help you.
This is what pipes are for. I suggest something like
pcap_writer -w - | tee permanent-file.pcap | pcap_reader -r -
where pcap_writer and pcap_reader are your programs. This way you create something that can be combined in a different manner, if wanted.

Running C code using FastCGI & NGINX

I am trying to run C code using FastCGI and NGINX. Right now, after following all the steps in this website: http://chriswu.me/blog/writing-hello-world-in-fcgi-with-c-plus-plus/
I am at the step where I am about to spawn-fcgi. However, the system that I must use is a 32 bit system where commands such as sudo apt-get install are not supported. I tried copying over the spawn-fcgi binary from my 64 bit system and tried using that like this: ./spawn-fcgi -p 8000 -n hello_world command but it is giving me an error saying it cannot execute the binary file (I'm assuming it is because I am for sure on a 32 bit system when trying to use it). In fact, when I executed file spawn-fcgi it told me that it was a 64-bit LSB executable, and as I am running it on a 32-bit system, that's why the "Cannot execute binary file" error is there.
What I'm wondering is if there is anyway I could run a C script using FASTCGI without calling on spawn-fcgi or cgi-fcgi or if there is anyway I could use somehow get these binaries in 32-bit. I tried searching online for 32-bit downloads of FASTCGI but it seems like fastcgi.com is broken as I am unable to access the website.
Please let me know if I've left out any crucial information and I'll be glad to provide it. Thanks!
By using the API provided by <fcgiapp.h> header, you can specify the socket details, which spawning via external means does for you.
You can get a TCP socket file descriptor like this:
int sockfd = FCGX_OpenSocket("127.0.0.1:9000", 100);
...or using Unix sockets:
int sockfd = FCGX_OpenSocket("/var/run/fcgi.sock", 100);
With the socket you can then:
FCGX_Request req;
FCGX_InitRequest(&req, sockfd, 0);
while (FCGX_Accept_r(&req) >= 0) {
FCGX_FPrintF(req.out, "Content-Type: text/html\n\n");
FCGX_FPrintF(req.out, "hello world");
FCGX_Finish_r(&req);
}
Once you compile, you can execute the binary directly without using spawn-fcgi or cgi-fcgi.

blocking pcap and multiple I/O `select `

I want to use pcap to capture packets
and then send the captured packets to another host
my source code snippets are like:
for(;;){
pcap_packet = pcap_next(pcap_handler, &pcap_header);
if(pcap_packet !=NULL)
printf("capture a packet with length of %d\n", pcap_header.len);
// send the packet as payload to the sender, excluding the Ethernet Header
n = send(sd_proxy, pcap_packet+ETHERNET_HDR_LEN, pcap_header.len-ETHERNET_HDR_LEN, 0);
if(n<0){
shutdown(connfd, SHUT_RDWR);
close(connfd);
break;
} new
}
so basically, I want program to be blocked by the pcap_next, once a
the socket sd_proxy establishes a TCP connection with the other host,
if the other host initiate an active TCP close, I want to detect this
active close. Ideally, I should use a select and a n=recv(rd_fd, ...)
if the other host initiates a active close, select will notice there is something with rd_fd and then I see whether 'n=0' or not.
but with pcap, select can't cooperate with pcap
so how to finish my task?
thanks!
select can't cooperate with pcap
Why not? Have you tried using pcap_get_selectable_fd() on pcap_handler and adding the resulting file descriptor to the file descriptor set in your select() call?
You're working on Linux, so that should Just Work.
(If you were running on a system that uses BPF, such as *BSD or OS X, you might have problems with this, at least with older versions of those OSes; various *BSDs have had their select-with-BPF bugs fixed for a while; on OS X, I fixed it in Lion, so it could have problems on Snow Leopard and earlier.)

Creating a pcap file

I need to save UDP packets to a file and would like to use the pcap format to reuse the various tools available (wireshark, tcpdump, ...).
There are some information in this thread but I can't find how to write the global file header 'struct pcap_file_header'.
pcap_t* pd = pcap_open_dead(DLT_RAW, 65535);
pcap_dumper_t* pdumper = pcap_dump_open(pd, filename);
struct pcap_file_header file_hdr;
file_hdr.magic_number = 0xa1b2c3d4;
file_hdr.version_major = 2;
file_hdr.version_minor = 4;
file_hdr.thiszone = 0;
file_hdr.sigfigs = 0;
file_hdr.snaplen = 65535;
file_hdr.linktype = 1;
// How do I write file_hdr to m_pdumper?
while( (len = recvmsg(sd, &msg_hdr, 0)) > 0 )
pcap_dump((u_char*)m_pdumper, &m_pcap_pkthdr, (const u_char*)&data);
How should I write the global file header?
If there is no specific pcap function available, how can I retrieve the file descriptor to insert the header using write()?
You shouldn't need to write that header, pcap_open_dead should do it for you. You only need to fill out and write that header yourself if you want to write the file directly instead of using pcap_dump and friends. There's an example here of a trivial program write out a pcap file with those functions.
original answer, concerning writing the file directly:
I can't remember exactly how this works, but I wrote a patch to redir a while ago that would write out pcap files, you may be able to use it as an example.
You can find it attached to this debian bug. (bug link fixed.)
Some of it is for faking the ethernet and IP headers, and may not be applicable as you're using pcap_dump_open and pcap_dump where as the patch linked above writes out the pcap file without using any libraries, but I'll leave this here anyway in case it helps.
If you are interested in UDP and TCP only, you should use DLT_EN10MB instead of DLT_RAW ( cf pcap_open_dead to simulate full UDP packets capture ).
It is much better when editing in WireShak.

Resources