#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;
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)
{
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 //
}
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 //
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++;
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 //
{
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;
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 //
{
received = received + header.len; // increase number of bytes
received //
}
}
}
}

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; unsignedchar 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 unsignedchar *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 //
  • 9.
    { received = received+ header.len; // increase number of bytes received // } } } }