Tcp payload extraction and correct ip address - tcp

I'm trying to extract tcp payload from a packet , and here's a minimal case of capture callback:
void capture_callback (u_char *hdr , const struct pcap_pkthdr* pkthdr , const u_char* buff)
{
struct ether_header *eptr = (struct ether_header *) buff;
buff += sizeof (ether_header); /* jump over ethernet header: 14 bytes */
if ( ntohs (eptr->ether_type) == ETHERTYPE_IP )
{
struct ip *iph;
struct tcphdr *tcp_header;
iph = (struct ip *) buff;
buff += sizeof (ip); /* jump over ip header */
if ( iph->ip_p == IPPROTO_TCP )
{
tcp_header = (struct tcphdr *) buff;
buff += sizeof (tcphdr); /* jump over tcp header */
cout << inet_ntoa (iph->ip_src) << ":" << ntohs (tcp_header->th_sport) <<
" --> " << inet_ntoa(iph->ip_dst) << ":" << ntohs (tcp_header->th_dport) << endl;
}
}
}
But something went wrong here , source and destination IP address are the same.
And besides , how can i print out payload ? Since i can't just convert a unsigned char array to a char array explicitly, which ends on "\0" , it might get wrong.
192.168.56.1:48065 --> 192.168.56.1:80
192.168.56.80:80 --> 192.168.56.80:48065
EDIT
---------------------
THanks to Celeda , i solved the ip address issue by separating the call of inet_ntoa:
cout << "IP: " << inet_ntoa (iph->ip_src) << ":" << ntohs (tcp_header->th_sport) <<
" --> ";
cout << inet_ntoa(iph->ip_dst) << ":" << ntohs (tcp_header->th_dport) << endl;
And now the second part , i'm using:
cout << hex << buff << endl;
For HTTP protocol , and i'm not seeing anything like "GET /" , but multiple blank line
EDIT 2
--------------------------
I'm not so sure about TCP options for now , i'll check more documents about details ,
but for now this functions well.
if ( iph->ip_p == IPPROTO_TCP )
{
tcp_header = (struct tcphdr *) buff;
buff += tcp_header->th_off * 4;
cout << "IP: " << inet_ntoa (iph->ip_src) << ":" << ntohs (tcp_header->th_sport) <<
" --> ";
cout << inet_ntoa(iph->ip_dst) << ":" << ntohs (tcp_header->th_dport) << endl;
for ( int i = 0 ; i < iph->ip_len - iph->ip_off * 4; i ++ )
{
if ( isascii (buff[i]) )
{
cout << buff[i];
}
}
cout << endl << "-----------" << endl;
}

inet_ntoa() uses a static buffer. You are overwriting the buffer by calling it twice. Use inet_ntop() instead.
The payload might be binary data. How do you want to print it out? As a hex dump or something like that? Just look over the payload and print the bytes as hex one at a time for a simplistic hex dump. Or if you are sure that it's printable data you can dump it directly to the output with any function such as fwrite() that lets you specify the length of the string to write.
EDIT FOR ADDITIONAL INFORMATION IN THE QUESTION
The "extra characters" you see before the HTTP data sound like TCP options you are trying to interpret as payload data. Be sure to calculate the size of the TCP header correctly when you jump the buff pointer over it. It's 4 bytes * th_off. While you're at it, you should do the same for the IP header using ip_hl because the IP header is not always 20 bytes either.
Afterwards, the ending condition in your for loop is wrong. First, ip_off (the fragment offset) doesn't enter into it, and, second, both ip_hl and tcp_off are measured in units of 4 bytes, not in bytes.
Compare what you're getting with your code with how Wireshark decodes the same packet and you will be able to easily diagnose any further discrepancy.

Related

Tower of Hanoi recursion solution explanation

I have struggled with Tower of Hanoi problem for 3 months. Here's the simplest code I can find:
void moveDisk(int n, char from, char to, char buffer)
{
if(n == 1)
{
cout << "Move disk 1 from " << from << " to " << to << endl;
return;
}
moveDisk(n-1, from, buffer, to);
cout << "Move disk " << n << " from " << from << " to " << to << endl;
moveDisk(n-1, buffer, to, from);
}
int main()
{
moveDisk(3, 'A', 'C', 'B');
}
And it works perfectly well:
Move disk 1 from A to C
Move disk 2 from A to B
Move disk 1 from C to B
Move disk 3 from A to C
Move disk 1 from B to A
Move disk 2 from B to C
Move disk 1 from A to C
My biggest question is: Why it works?
I have done some research and they all say that: "Move the first n-1 disks to the 'buffer', then move the n disk to the 'to' stack and finally move the first n-1 disks to the 'to' stack. I understand the idea of it, but my question is: why writing the code that way works? Also: why do we need to print:
cout << "Move disk 1 from " << from << " to " << to << endl;
in the base case in order for it to work? If according to the idea above, why don't we just return when we hit the base case instead?
I tried to track the recursion by hand and the variable "from", "to", and "buffer" keep changing constantly - but somehow it works!
Please explain to me why?
Thank you!

How to efficiently deserialize nvp dictionary from std::string using boost

Suppose I have a stringified representation of a name-value-pair dictionary with custom separators between names/values and name-value pairs, e.g. "foo:4|bar:-1" or "Alice=>cat;Bob=>dog".
It can be done with boost's split(), but I was curious if firstly, doing so isn't just reinventing the wheel, secondly, there are more efficient alternatives, like some customized deserialization.
Consider using Boost Spirit. Using the X3 version you'd write
const std::string input = "foo:4|bar:-1"; // or "Alice=>cat;Bob=>dog";
auto text = +~x3::char_(":|");
std::map<std::string, int> parsed;
if (parse(input.begin(), input.end(), (text >> ':' >> x3::int_) % '|', parsed)) {
std::cout << "parsed[bar]: " << parsed["bar"] << "\n";
}
Live On Coliru
The other form:
const std::string input = "Alice=>cat;Bob=>dog";
auto text = +(x3::char_ - ';' - "=>");
std::map<std::string, std::string> parsed;
if (parse(input.begin(), input.end(), (text >> "=>" >> text) % ';', parsed)) {
std::cout << "parsed[Bob]: " << parsed["Bob"] << "\n";
}
Live On Coliru

checking EOF on unix cp program

I'm writing a unix cp program, but I'm unclear about checking for EOF. The code I have is:
int main(int argc, const char * argv[]) {
int in, out;
char buf[BUFFER_SIZE];
if (argc != 3)
cout << "Error: incorrect number of params" << endl;
if ((in = open(argv[1], O_RDONLY, 0666)) == -1)
cout << "Error: cannot open input file" << endl;
if ((out = open(argv[2], O_WRONLY | O_CREAT, 0666)) == -1)
cout << "Cannot create output file" << endl;
else
while ((read(in, buf, BUFFER_SIZE)) != -1)
write(out, buf, BUFFER_SIZE);
return 0;
}
It reads and writes fine, but writes past EOF when writing the output file. So I get a couple lines of gibberish past the end of the file. Am I just not checking for EOF correctly? I appreciate the input.
You should read the man page for the read function.
On end-of-file, read returns 0. It returns -1 only if there's an error.
read can read fewer bytes than you asked to (and it must do so if there aren't that many bytes remaining to be read). Your write call assumes that read actually read BUFFER_SIZE bytes.
You need to save the result returned by read and write only that many bytes -- and you need to terminate the loop when read returns 0 (indicating end-of-file) or -1 (indicating an error). In the latter case, you should probably do something to handle the error, or at least inform the user.
Incidentally, you don't need the 0666 mode argument when calling open to open the file for reading; that applies only with O_CREAT. Since open is actually a variadic function (like printf), you don't have to supply all the arguments.
The man page is not clear on this point; it pretends that there are two different forms of the open function:
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
but in fact that's not legal in C. The POSIX description correctly shows the declaration as:
int open(const char *path, int oflag, ...);

Qt or OpenCV: print out the codec of a video file

I'd like to know how i can print out the codec of a video file after opening it with VideoCapture (on OSX or Ubuntu).
The file is correctly loaded and visualized by opencv inside a qt application.
QString filename = QFileDialog::getOpenFileName(...)
cout << filename.size() << endl; // size in byte
VideoCapture cap = VideoCapture(filename.toStdString());
cout << cap.get(CV_CAP_PROP_FRAME_HEIGHT) << endl; // print the height
cout << cap.get(CV_CAP_PROP_FPS) << endl; // print the fps
codec ??
Try
cap.get(CV_CAP_PROP_FOURCC);
to get the codec.
Edit:
I am not a C++ programmer, but this is what I found searching around to change it to a char array:
int ex = static_cast<int>(inputVideo.get(CV_CAP_PROP_FOURCC));
char EXT[] = {ex & 0XFF , (ex & 0XFF00) >> 8,(ex & 0XFF0000) >> 16,(ex & 0XFF000000) >> 24, 0};
See:
http://docs.opencv.org/doc/tutorials/highgui/video-write/video-write.html

QList memory deallocation

I'm trying to free memory after using QList, but it doesn't seem to work properly.
Here's my code:
QList<double> * myList;
myList = new QList<double>;
double myNumber;
cout << "CP1" << endl;
getchar(); // checkpoint 1
for (int i=0; i<1000000; i++)
{
myNumber = i;
myList->append(myNumber);
cout << myList->size() << endl;
}
cout << "CP2!" << endl;
getchar(); // checkpoint 2
for (int i=999999; i>0; i--)
{
myList->removeLast();
cout << myList->size() << endl;
}
cout << "CP3!" << endl;
getchar(); // checkpoint 3
delete myList;
cout << "CP4!" << endl;
getchar(); // checkpoint 4
Memory usage:
CP1: 460k
CP2:19996k
CP3:19996k
CP4:16088k
So it looks like despite removing of elements and deleting myList still large part of memory is being used. I believe there is a way to handle it but I can't find it.
Thanks in advance for any help.
Pawel
Memory manager is not required to release the memory your program has allocated. There are no problems in your deallocation.
QList is an array based list. The array expands automatically, but does not shrink automatically. Removing elements from the list does not affect the size of the array.
To trim the array down to the actual size, create a new QList and add the contents to it. Then delete the original list.
Unfortunately looks like there is no convenience method to do this, like the List.TrimExcess() in .NET.

Resources