Modify HuffmanTree.java and HuffmanNode.java to allow the user to se.pdf
part2
1. #include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pcap.h>
#include <signal.h>
#include <time.h>
#define ETHERNET_HEADER_SIZE 14
#define INTERNET_HEADER_SIZE 20
#define TCP_HEADER_SIZE 20
char **hosts; // unique host space //
int *visits; // visit count space //
int sent = 0; // bytes sent //
int received = 0; // bytes received //
int k = 0; // unique host count //
int size = 20; // the size of our current host space //
int depth = 25; // the depth of our current host space //
int y = 0; // page counter //
time_t start; // start time of our program //
time_t end; // end time of our program //
double timer; // store the time our program ran //
struct internet_header // define the structure of the internet header
as given in the specification //
{
unsigned char version:4;
unsigned char IHL:4;
char type;
unsigned char length[2];
unsigned char identification[2];
unsigned char flags:3;
unsigned short fragment:13;
char time;
char proto;
unsigned char checksum[2];
unsigned char source[4];
unsigned char dest[4];
};
struct tcp_header // define all parts of tcp layer, without taking the
data into consideration //
{
unsigned short source;
unsigned short dest;
unsigned long sequence;
unsigned long acknowledge;
unsigned char offset:4;
unsigned char reserved:6;
unsigned char flags1:1;
unsigned char flags2:1;
unsigned char flags3:1;
unsigned char flags4:1;
2. unsigned char flags5:1;
unsigned char flags6:1;
unsigned short window;
unsigned short checksum;
unsigned short pointer;
};
int tcp_test(const unsigned char *data_packet) // test if our input
packet is a tcp packet, using 1 as a true value if it is //
{
const struct internet_header *iheader;
iheader = (const struct internet_header *)data_packet;
if((iheader->proto) == 6)
{
return 1;
}
else
return 0;
}
int port_test(const unsigned char *data_packet) // test if our input
packet is sent through port 80, using 1 as a value if it is received,
using 2 as a value if it is sent and 0 if it uses another port //
{
const struct tcp_header *theader;
theader = (const struct tcp_header *)data_packet;
int i = ntohs(theader->source);
int j = ntohs(theader->dest);
if (i == 80)
{
return 1;
}
if (j == 80)
{
return 2;
}
else
{
return 0;
}
}
void expand() // expand our packet by increasing the number of
unique hosts we have available to us //
{
char **temp = realloc(hosts, (2*size)*sizeof(char*)); // reallocate
hosts to a new space of double the size //
int i;
if(temp != NULL)
3. {
hosts = temp; // if the reallocation is complete we reassign hosts
//
} else perror("Failed to reallocate memory");
for(i = size; i < (2*size); i++)
{
hosts[i] = calloc(depth, sizeof(char)); // zero all of our new
created char spaces //
}
int *tmp = realloc(visits, (2*size)*sizeof(int)); // reallocate
visits to a new space of double the size //
if(tmp != NULL)
{
visits = tmp; // if reallocation is complete we reassign visits //
} else perror("Failed to reallocate memory");
size = (2*size); // we have doubled the size of our unique hosts
space //
}
void extend()
{
int i;
int j;
for(i = 0; i < k; i++)
{
char *temp = realloc(hosts[i], (2*depth)*sizeof(char)); // for
each char space, pointed to by i, reallocate the chars to a new space
of double the size //
if(temp != NULL)
{
hosts[i] = temp; // if reallocation is complete we reassign the
hosts space //
}
else perror("Failed to reallocate memory");
}
for(i = k; i < size; i++)
{
hosts[i] = calloc((2*depth),sizeof(char)); // zero all of our non-
complete and empty char spaces using calloc //
}
depth = (2*depth); // we have doubled the depth of our host space
depth //
}
4. void find_host(const unsigned char *data, int length) // find the host
name in our data packet //
{
unsigned char byte;
unsigned int i,j,x;
j = 0;
if(length > 3) // if packet is large enough to submit to our tests
//
{
for(i = 0; i < (length-4); i++) // iterate i until we cannot
consider the next 5 characters //
{
if(((int)data[i] == 72) && ((int)data[i+1] == 111) &&
((int)data[i+2] == 115) && ((int)data[i+3] == 116) && ((int)data[i+4]
== 58)) // if we find the ascii representation of 'Host:'
{
y++; // we have a new host, address found, so we know we have a
new page connection. Iterate y, our page counter //
if(k >= size) // if we have a unique host that exceeds our host
space, expand the host space before we add the value //
{
expand();
}
if(k == 0) // if this is our first entry, input the host without
tests //
{
do
{
byte = data[i + 6 + j];;
hosts[k][j] = byte; // store the char form of our host in our
host space //
j++;
if(j >= depth) // if we have a host name exceeding the depth
of our host space, we extend the depth //
{
extend();
j = 0; // to ensure the data is not lost from this
incomplete form being reallocated, we zero the entire entry and start
again by resetting j //
}
} while((int)data[i + 6 + j] != 10); // when we find the space
character at the end of the host name, stop adding to the host space
//
visits[k] = 1; // set visits for this host to 1 //
k++; // increase number of unique hosts //
}
else
{
x = match(data,i); // search for the value of a match to the
host name, if one exists //
5. if(x < (k+1)) // if we have found a valid host point, we have a
match //
{
visits[x] = visits[x] + 1; // at the match point, increase
our number of visits by one //
}
else // if no match has been found //
{
do
{
byte = data[i + 6 + j];
hosts[k][j] = byte; // store the char form of our host in
our host space //
j++;
if(j >= depth) // if we have a host name exceeding the
depth of our host space, we extend the depth //
{
extend();
j = 0; // to ensure the data is not lost from this
incomplete form being reallocated, we zero the entire entry and start
again by resetting j //
}
} while((int)data[i + 6 + j] != 10); // when we find the
space character at the end of the host name, stop adding to the host
space //
visits[k] = 1; // set visits for this host to 1 //
k++; // increase number of unique hosts //
}
}
}
}
}
}
int match(const unsigned char *data, int position) // test if we find
a match for the host name //
{
unsigned char byte;
int j,i,x;
int *test = calloc(k,sizeof(int)); // set an array to represent each
unique host, defaulted to zero using calloc //
for(i = 0; i < k; i++) // test for each of our unique hosts //
{
j = 0;
x = 0;
do
{
byte = data[position + 6 + j]; // iterate across our input host
name //
j++;
6. if(hosts[i][x] != byte) // if we find a difference between the
host name at i and our input host name, set the test value at i to 1
//
{
test[i] = 1;
}
x++;
} while(((int)data[position + 6 + j] != 10) && (x < depth)); //
continue until we hit the space value at the end of the host name //
}
for(i = 0; i < k; i++)
{
if(test[i] == 0) // if we have gone through test without setting
the value to 1, no difference has been found and we have a match at
poistion i //
{
return i;
}
}
return k+1; // if no match is found, return k+1, clearly an invalid
value for i //
}
void sig_handler (int sig) // defines the conditions when ctrl+c is
caught in main //
{
double i;
int j;
int x;
int q;
int act;
printf("nUnique hosts visited : %dn", k);
printf("Pages visited : %dn", y);
printf("Bytes received: %d bytesn", received);
printf("Bytes sent: %d bytesn", sent);
end = time(NULL); // time the end of our program, when ctrl+c is
caught //
timer = (double)(end - start); // our total time is time elapsed
between start and end //
i = (received) / (1024 * timer); // download bandwidth is recieved
per second across our program time //
printf("Average download bandwidth: %d KB/sn", (int)i);
i = (sent) / (1024 * timer); // upload bandwidth is sent per second
across program time //
printf("Average upload bandwidth: %d KB/sn", (int)i);
printf("Top 5 hosts: n");
if(k < 5) // if we haven't found 5 unique hosts, we have a maximum
value of the number of unique hosts found //
{
7. act = k;
}
else // if we have 5 or more unique hosts, we set our maximum value
to 5 //
{
act = 5;
}
for( j = 0; j < act; j++) // we find our top visits for our maximum
value //
{
q = 0;
for( x = 1; x < k; x++) // iterate across our list until we are
out of unique hosts to test //
{
if(visits[x] > visits[q]) // if we find a value with more visits
later in the list, we set this as our current high value, defined to
be q //
{
q = x;
}
}
visits[q] = 0; // we zero this value to ensure it is not picked
again //
x = 0; // reset x to start iteration later on //
printf("t");
while(hosts[q][x] != 0) // until we hit a value that is unchanged,
set to zero by our inital calloc call //
{
printf("%c", hosts[q][x]);// print the name of the most visited
host found //
x++;
}
printf("n");
}
free(hosts); // free the memory from both of hosts and visits upon
exit //
free(visits);
exit(0); // exit the program //
}
int* build_visits() // build our visits array //
{
int *tmp = (int*) calloc(20, sizeof(int));
return tmp;
}
char** build_hosts() // build our hosts array //
{
int i;
8. char **tmp = (char**) calloc(20, sizeof(char*));
for (i = 0; i < size; i++)
{
tmp[i] = (char*) calloc(25, sizeof(char)); // at each pointer in
*tmp, create an array of chars //
}
return tmp;
}
int main(int argc, char *argv[])
{
struct pcap_pkthdr header;
const unsigned char *packet;
char errbuf[PCAP_ERRBUF_SIZE];
char *device;
pcap_t *pcap_handle;
int i;
start = time(NULL); // take our start time //
device = pcap_lookupdev(errbuf); // lookup a device to sniff //
visits = build_visits(); // build our visits array //
hosts = build_hosts(); // build our hosts array //
if (device == NULL) perror("pcap_lookupdev failed");
printf("Sniffing on device %sn", device);
pcap_handle = pcap_open_live(device, 4096, 1, 0, errbuf); // open
the connection to the device //
if (pcap_handle == NULL) perror("pcap_open_live failed");
signal(SIGINT, sig_handler); // search for our ctrl+c call,
deferring to sig_handler when we receive it //
while (1) {
packet = pcap_next(pcap_handle, &header);// continue to move along
the packets in consideration //
if((tcp_test(packet + ETHERNET_HEADER_SIZE)) == 1) // if we have a
tcp packet from our test defined above //
{
if((port_test(packet + ETHERNET_HEADER_SIZE +
INTERNET_HEADER_SIZE)) == 2) // if we have sent the packet //
{
sent = sent + header.len; // increase the number of bytes sent //
find_host(packet + ETHERNET_HEADER_SIZE + INTERNET_HEADER_SIZE +
TCP_HEADER_SIZE, header.len - ETHERNET_HEADER_SIZE -
INTERNET_HEADER_SIZE - TCP_HEADER_SIZE); // find the host of our sent
packet //
}
else if((port_test(packet + ETHERNET_HEADER_SIZE +
INTERNET_HEADER_SIZE)) == 1) // if packet has been received //