//*****************************************************************************
//
// Program: vip -- Programming Project 3
//
// Author: Travis Dillon
//
// Class: CS 444
// Email: tdillon@ace.cs.ohiou.edu
//
// Description: This is the virtual ip program, it first finds the IP address
// of all it's interfaces using RARP. Then it sits and waits on
// ARP and ICMP requests, and sends ARP and ICMP replies.
//
// Date: January 25, 2005
//
//*****************************************************************************
#include <stdlib.h>
#include <iostream.h>
#include <vrouter.h>
#include <time.h>
#define DEFAULT_GROUP 6
#define BUFFER_SIZE 512
#define INTERFACE_NAME_LENGTH 100
#define MAX_NUM_INTERFACES 4
#define RARP_MAX_WAIT 10
#define RARP_MAX_REQUEST 10
using namespace std;
typedef unsigned char u_char;
typedef struct _Ethernet
{
unsigned char destination[7];
unsigned char source[7];
unsigned char type[3];
}Ethernet;
void option_h();
void option_l(lanlist* all_lans);
void option_g(int argc, char** argv, unsigned& group, int& i);
void make_rarp_packet(const bool& debug_on, INTERFACE** ifaces, _lan* lan_ptr,
lanlist* all_lans);
void get_ip(const bool& debug_on, INTERFACE** ifaces, _lan* lan_ptr,
int msec_maxwait, int num_request, lanlist* all_lans,
char ip_array[MAX_NUM_INTERFACES][4], const int& b);
void show_ip(const bool& debug_on, const char read_buf[]);
void analyze_packet(const bool& debug_on, char buf[], const int& packet_size,
char ip_array[MAX_NUM_INTERFACES][4], lanlist* all_lans,
INTERFACE** ifaces, const size_t& c);
void make_arp_packet(const bool& debug_on, char buf[],
char ip_array[MAX_NUM_INTERFACES][4], const size_t& f,
lanlist* all_lans, INTERFACE** ifaces);
void make_icmp_packet(const bool& debug_on, char buf[], const int& packet_size,
char ip_array[MAX_NUM_INTERFACES][4], const size_t& f,
lanlist* all_lans, INTERFACE** ifaces);
void print_arp_packet(const char buf[]);
void print_icmp_echo(char buf[], const int& packet_size);
int main(int argc, char *argv[])
{
int i, msec_maxwait(RARP_MAX_WAIT), num_request(RARP_MAX_REQUEST);
int packet_size;
char buf[BUFFER_SIZE], ip_array[MAX_NUM_INTERFACES][4];
unsigned group = DEFAULT_GROUP;
bool debug_on = false;
lanlist* all_lans = whichlans();
_lan* lan_ptr = all_lans -> lan;
INTERFACE* ifaces[MAX_NUM_INTERFACES];
if(all_lans == NULL)
{
cerr << "whichlans() failed and returned NULL\n";
exit(EXIT_FAILURE);
}
for(i=1; i < argc; ++i) //parse the command line
{
if(argv[i][0] != '-') //at this point an argument must have a '-'
{
cout << "Invalid option - \"" << argv[i] << "\".\n";
option_h();
}
switch(argv[i][1])
{
case 'd': debug_on = true; break;
case 'l': option_l(all_lans); break;
case 'g': option_g(argc, argv, group, i); break;
case 'h': option_h(); break;
default:
{
cout << "Invalid option - \"" << argv[i] << "\".\n";
option_h();
break;
}
}
}
for(size_t j(0); j < MAX_NUM_INTERFACES; ++j) //open all interfaces
{
if(lan_ptr == NULL) ifaces[j] = NULL;
else
{
if(debug_on) cout << "main openinterface with j = " << j << endl;
ifaces[j] = openinterface(lan_ptr -> lname, group);
if(debug_on) cout << "main open " << lan_ptr -> lname << endl;
lan_ptr = lan_ptr -> next;
}
}
if(debug_on) cout << "main group = " << group << endl;
lan_ptr = all_lans -> lan;
for(int b(0); b < all_lans -> cnt; ++b) //show IPs of all interfaces
{
if(debug_on) cout << "main get_ip() for " << lan_ptr -> lname << endl;
get_ip(debug_on, ifaces, lan_ptr, msec_maxwait,
num_request, all_lans, ip_array, b);
lan_ptr = lan_ptr -> next;
}
//This block of code is modeled after the code Dr. Ostermann sent us in the
//Vbridge options email.
while(true) //let vip run
{
blockforpacket(ifaces); //wait until we have a packet somewhere
for(size_t c(0); ifaces[c] != NULL; ++c) //look for the packet
{
if(checkforpacket(ifaces[c])) //check all interfaces for packets
{
packet_size = readpacket(ifaces[c], buf, BUFFER_SIZE); //get packet
if(debug_on) cout << "main packet_size = " << packet_size << endl;
if(packet_size == -1)
{
cerr << "readpacket failed.\n";
exit(EXIT_FAILURE);
}
analyze_packet(debug_on, buf, packet_size, ip_array,
all_lans, ifaces, c); //process the packet
}
}
}
for(size_t j(0); ifaces[j] != NULL; ++j) closeinterface(ifaces[j]);
exit(EXIT_SUCCESS);
}
//****************************************************************************
//
// Function: option_h
//
// Purpose: If the -h flag is given in the command line or someone enters
// an invalid command argument, this will print out options.
//
// Parameters: none
//
// Calls: exit
//
//****************************************************************************
void option_h()
{
cout << "-d To print debugging information.\n"
<< "-l List all interfaces and exit.\n"
<< "-g NUM Use group NUM. If NUM is ommitted then "
<< DEFAULT_GROUP << " will be used.\n"
<< "-h Print a quick summary of the command line arguments"
<< " and exit.\n";
exit(EXIT_SUCCESS);
}
//****************************************************************************
//
// Function: option_l
//
// Purpose: If the -l flag is given in the command line this will print
// all the names and addresses of network devices on a computer.
//
// Parameters: all_lans - linked list that holds all network addresses and
// names of them on the computer
//
// Calls: exit
//
//****************************************************************************
void option_l(lanlist* all_lans)
{
_lan* lan_ptr = all_lans -> lan;
for(int j(0); j < all_lans -> cnt; ++j)
{
cout << "name = " << lan_ptr -> lname << endl;
cout << "addr = " << lan_ptr -> hwaddr << endl << endl;
lan_ptr = lan_ptr -> next;
}
exit(EXIT_SUCCESS);
}
//****************************************************************************
//
// Function: option_g
//
// Purpose: If the -g NUM flag is given in the command line this will
// change the group to NUM as long as NUM is in [0, 63]
//
// Parameters: argc - number of command line arguments
// argv - the commmand line arguments
// i - position in the command line arguments
//
// Calls: none
//
//****************************************************************************
void option_g(int argc, char** argv, unsigned& group, int& i)
{
if(i < argc - 1 && argv[i + 1][0] != char(45))
{ //true if -g isn't last command and -g has numbers after it
group = argv[++i][0] - 48; //ascii for zero is 48
if(argv[i][1] != '\0') //true if the group is greater than ten
{
group = (group * 10) + (argv[i][1] - 48);
if(argv[i][2] != '\0') //true if the group is greater than 99
{
cout << "INVALID group number. Defaulting to "
<< DEFAULT_GROUP << ".\n";
group = DEFAULT_GROUP;
}
}
}
if(group > 63) //valid range of group numbers is 0 - 63
{
cout << "INVALID group number. Defaulting to " << DEFAULT_GROUP << ".\n";
group = DEFAULT_GROUP;
}
}
//****************************************************************************
//
// Function: make_rarp_packet
//
// Purpose: Create a RARP packet to find out current interfaces IP address.
//
// Parameters: debug_on - debugging information flag
// ifaces - handle to the interfaces
// lan_ptr - pointer to the current interface
// all_lans - linked list that holds all network addresses and
// names of them on the computer
//
// Calls: writepacket, strncmp
//
//****************************************************************************
void make_rarp_packet(const bool& debug_on, INTERFACE** ifaces, _lan* lan_ptr,
lanlist* all_lans)
{
char buf[BUFFER_SIZE];
int tens, ones, hex_to_dec(1),g(6);
_lan* temp_lan_ptr = all_lans -> lan;
size_t t;
for(size_t w(0); lan_ptr -> hwaddr[w] != '\0'; ++w)
{ //this creates the source, next 6 octets of buffer
tens = lan_ptr -> hwaddr[w];
ones = lan_ptr -> hwaddr[w + 1];
tens = ((tens > 57) ? (tens -= 87) : (tens -= 48));
ones = ((ones > 57) ? (ones -= 87) : (ones -= 48));
hex_to_dec = 16 * tens + ones;
buf[g - 6] = char(255); //ethernet broadcast
buf[g++] = hex_to_dec; //my hw address is the source
w += 2;
}
buf[12] = char(128); //RARP type code is 8035 hex
buf[13] = char(53); //RARP type code is 8035 hex
if(debug_on)
{
cout << "make_rarp_packet RARP type code = " << std::hex
<< u_char(buf[12]) * 256 + u_char(buf[13]) << std::dec << endl;
}
//this is Hardware address space "Ethernet"
buf[14] = char(0);
buf[15] = char(1); //from RFC 903 example
//this is Protocol address space "IP"
buf[16] = char(8);
buf[17] = char(0); //from RFC 903 example
//this is byte length of each hardware address
buf[18] = char(6); //from lecture notes
//this is byte length of each protocol address
buf[19] = char(4); //from lecture notes
//this is opcode
buf[20] = char(0);
buf[21] = char(3); //request reverse
//this is hardware address of the sender
buf[22] = buf[6]; //length is from buf[18]
buf[23] = buf[7];
buf[24] = buf[8];
buf[25] = buf[9];
buf[26] = buf[10];
buf[27] = buf[11];
//this is source protocol address, but undefined for request reverse
buf[28] = char(0); //length is from buf[19]
buf[29] = char(0);
buf[30] = char(0);
buf[31] = char(0);
//this will be the hardware address of the destination
buf[32] = buf[22]; //length and data are same as buf[22 - 27]
buf[33] = buf[23];
buf[34] = buf[24];
buf[35] = buf[25];
buf[36] = buf[26];
buf[37] = buf[27];
//this is target protocol address, but undefined for request reverse
buf[38] = char(); //length and data is same as buf[28 - 31]
buf[39] = char();
buf[40] = char();
buf[41] = char();
buf[42] = '\0';
if(debug_on) cout << "make_rarp_packet writepacket() to "
<< lan_ptr -> lname << endl;
for(t = 0; strncmp(lan_ptr -> lname, temp_lan_ptr -> lname, 6) != 0 &&
t <= MAX_NUM_INTERFACES; ++t) temp_lan_ptr = temp_lan_ptr -> next;
if(t == MAX_NUM_INTERFACES)
{
cerr << "ERROR IN make_rarp_packet" << endl;
exit(EXIT_FAILURE);
}
else writepacket(ifaces[t], buf, 42);
if(debug_on) cout << "make_rarp_packet the RARP packet i'm sending\n";
if(debug_on) print_arp_packet(buf);
}
//****************************************************************************
//
// Function: get_ip
//
// Purpose: Obtain the ip for the current interface.
//
// Parameters: debug_on - debugging information flag
// ifaces - handle to the interfaces
// lan_ptr - pointer to the current interface
// msec_maxwait - how long to wait for each packet
// num_request - how many times to check for packet
// all_lans - linked list that holds all network addresses and
// names of them on the computer
// ip_array - array holding ip addresses of all interfaces
// b - index into current interface
//
// Calls: make_rarp_packet, blockforpacket_timeout, checkforpacket,
// readpacket, show_ip
//
//****************************************************************************
void get_ip(const bool& debug_on, INTERFACE** ifaces, _lan* lan_ptr,
int msec_maxwait, int num_request, lanlist* all_lans,
char ip_array[MAX_NUM_INTERFACES][4], const int& b)
{
int packet_size;
char read_buf[BUFFER_SIZE];
if(debug_on) cout << "get_ip calling make_rarp_packet for "
<< lan_ptr -> lname << endl;
make_rarp_packet(debug_on, ifaces, lan_ptr, all_lans);
if(debug_on) cout << "get_ip blocking for packet on "
<< lan_ptr -> lname << endl;
while(!blockforpacket_timeout(ifaces, msec_maxwait) && num_request > 0)
{ //this checks 10 times for a packet over 20 seconds
msec_maxwait *= 2; //start at 10 milliseconds, double after each failure
if(debug_on) cout << "vip: RARP response wait interval (" << msec_maxwait
<< " ms) EXIT when " << num_request << " reaches 0!"
<< endl;
--num_request; //try 10 times
}
if(num_request > 0)
{
if(debug_on) cout << "get_ip checking for packet on "
<< lan_ptr -> lname << endl;
if(checkforpacket(ifaces[b])) //check current interface for packet
{
if(debug_on) cout << "get_ip found packet on "
<< lan_ptr -> lname << endl;
packet_size = readpacket(ifaces[b], read_buf, BUFFER_SIZE);
if(debug_on)
{
cout << "get_ip RARP reply on " << lan_ptr -> lname << endl;
print_arp_packet(read_buf);
}
if(packet_size == -1)
{
cerr << "readpacket failed.\n";
exit(EXIT_FAILURE);
}
}
else
{
if(debug_on) cout << "get_ip no packet found on "
<< lan_ptr -> lname << endl;
}
}
else
{
cerr << "RARP REQUEST WAS NOT RETURNED. EXITING" << endl;
if(debug_on) cout << "get_ip num_request = 0 no packet received" << endl;
exit(EXIT_FAILURE);
}
cout << "IP address of " << lan_ptr -> lname << " is ";
show_ip(debug_on, read_buf);
for(size_t e(0); e < 4; ++e)
{
ip_array[b][e] = read_buf[e + 38]; //copy the ip to ip_array
}
}
//****************************************************************************
//
// Function: show_ip
//
// Purpose: Print out the ip address
//
// Parameters: debug_on - debugging information flag
// read_buf - the packet that was read in or created
//
// Calls: none
//
//****************************************************************************
void show_ip(const bool& debug_on, const char read_buf[])
{
//the last field is the ip address
for(size_t g(38); g < 42; ++g)
{
cout << size_t(u_char(read_buf[g]));
if(g != 41) cout << '.';
else cout << endl;
}
//this is opcode, should be 4
if(debug_on) cout << "show_ip " << size_t(read_buf[20])
<< size_t(read_buf[21]) << " is the opcode" << endl;
}
//****************************************************************************
//
// Function: analyze_packet
//
// Purpose: Check an ip packet for arp and icmp, and process it.
// These algorithms were given in the assignment.
//
// Parameters: debug_on - debugging information flag
// buf - the packet that was read in or created
// packet_size - num bytes of packet
// ip_array - array of ip addresses for all interfaces
// all_lans - linked list that holds all network addresses and
// names of them on the computer
// ifaces - handle to the interfaces
// c - index of which interface we are on
//
// Calls: make_arp_packet, print_arp_packet, make_icmp_packet,
// print_icmp_echo
//
//****************************************************************************
void analyze_packet(const bool& debug_on, char buf[], const int& packet_size,
char ip_array[MAX_NUM_INTERFACES][4], lanlist* all_lans,
INTERFACE** ifaces, const size_t& c)
{
size_t f;
_lan* temp_lan_ptr = all_lans -> lan;
int tens, ones, hex_to_dec(1);
bool ethernet_broadcast = false, type_ip, type_rarp, type_arp, arp_request,
my_ip = false, ethernet_match = false, icmp_echo = false;
for(size_t d(0); d < 6; ++d)
{
ethernet_broadcast = (u_char(buf[d]) == u_char(255)) ? true : false;
if(!ethernet_broadcast)
{
if(debug_on)
{
cout << "analyze_packet this is not an ETHERNET broadcast packet"
<< endl;
}
break;
}
}
//ip is type 800 hex
type_ip = (buf[12] == char(8) && buf[13] == char(0)) ? true : false;
//rarp is type 8035 hex
type_rarp = (buf[12] == char(128) && buf[13] == char(53)) ? true : false;
//arp is type 0806 hex
type_arp = (buf[12] == char(8) && buf[13] == char(6)) ? true : false;
//arp request if opcode is 3
arp_request = (buf[20] == char(0) && buf[21] == char(3)) ? true : false;
if(debug_on && type_arp)
{
cout << "analyze_packet this is the ARP packet i received" << endl;
print_arp_packet(buf);
}
if(debug_on && type_ip)
{
cout << "analyze_packet this is the IP packet i received" << endl;
print_icmp_echo(buf, packet_size);
}
for(f = 0; int(f) < all_lans -> cnt; ++f)
{ //this check is to see if the ip address target is ''me''
for(size_t g(0); g < 4; ++g)
{
my_ip = (ip_array[f][g] == buf[g + 38]) ? true : false;
if(!my_ip) goto skip; //try next ip in ip_array
if(my_ip && g == 3) goto next; //this ip matches the request
}
skip:;
}
next:;
if(type_arp && ethernet_broadcast && my_ip)
{ //ethernet type code is arp, ethernet destination is broadcast, and
//the target ip is mine.
if(debug_on) cout << "analyze_packet this ARP packet is for me" << endl;
make_arp_packet(debug_on, buf, ip_array, c, all_lans, ifaces);
return;
}
my_ip = false;
for(size_t z(0); z < c; ++z) temp_lan_ptr = temp_lan_ptr -> next;
for(size_t z(0); z < 6; ++z)
{
tens = temp_lan_ptr -> hwaddr[3*z];
ones = temp_lan_ptr -> hwaddr[3*z + 1];
tens = ((tens > 57) ? (tens -= 87) : (tens -= 48));
ones = ((ones > 57) ? (ones -= 87) : (ones -= 48));
hex_to_dec = 16 * tens + ones;
ethernet_match = (hex_to_dec == int(u_char(buf[z]))) ? true : false;
if(!ethernet_match) break;
}
for(f = 0; int(f) < all_lans -> cnt; ++f)
{ //this check is to see if the ip address target is ''me''
for(size_t g(0); g < 4; ++g)
{
my_ip = (ip_array[f][g] == buf[g + 30]) ? true : false;
if(!my_ip) goto skip2; //try next ip in ip_array
if(my_ip && g == 3) goto next2; //this ip matches the request
}
skip2:;
}
next2:;
icmp_echo = (buf[34] == char(8)) ? true : false; //echo request is 8
if(ethernet_match && type_ip && my_ip && icmp_echo)
{
if(debug_on) cout << "analyze_packet this is ICMP packet for me" << endl;
make_icmp_packet(debug_on, buf, packet_size, ip_array, c,
all_lans, ifaces);
return;
}
if(debug_on) cout << "analyze_packet this packet was not valid" << endl;
}
//****************************************************************************
//
// Function: make_arp_packet
//
// Purpose: Creates an ARP packet to serve as a reply to the HW addr request
//
// Parameters: debug_on - debugging information flag
// buf - the packet that was read in or created
// ip_array - array of ip addresses for all interfaces
// f -
// all_lans - linked list that holds all network addresses and
// names of them on the computer
// ifaces - handle to all interfaces
//
// Calls: writepacket
//
//****************************************************************************
void make_arp_packet(const bool& debug_on, char buf[],
char ip_array[MAX_NUM_INTERFACES][4], const size_t& f,
lanlist* all_lans, INTERFACE** ifaces)
{
char new_buf[43];
_lan* lan_ptr = all_lans -> lan;
int tens, ones, hex_to_dec(1), g(6);
for(size_t k(0); k < f; ++k) lan_ptr = lan_ptr -> next;
for(size_t g(0); g < 6; ++g)
{ //destination for reply is source of request
new_buf[g] = buf[g + 6];
}
for(size_t w(0); lan_ptr -> hwaddr[w] != '\0'; ++w)
{ //my ETHERNET ADDRESS, next 6 octets of buffer
tens = lan_ptr -> hwaddr[w];
ones = lan_ptr -> hwaddr[w + 1];
tens = ((tens > 57) ? (tens -= 87) : (tens -= 48));
ones = ((ones > 57) ? (ones -= 87) : (ones -= 48));
hex_to_dec = 16 * tens + ones;
new_buf[g++] = hex_to_dec;
w += 2;
}
new_buf[12] = char(8); //ARP type code is 806 hex
new_buf[13] = char(6); //ARP type code is 806 hex
//Hardware address space "Ethernet"
new_buf[14] = char(0);
new_buf[15] = char(1); //from RFC 903 example
//Protocol address space "IP"
new_buf[16] = char(8);
new_buf[17] = char(0); //from RFC 903 example
//tbyte length of each hardware address
new_buf[18] = char(6); //from lecture notes
//byte length of each protocol address
new_buf[19] = char(4); //from lecture notes
//opcode
new_buf[20] = char(0);
new_buf[21] = char(2); //reply to ARP request
//my ETHERNET address
new_buf[22] = new_buf[6];
new_buf[23] = new_buf[7];
new_buf[24] = new_buf[8];
new_buf[25] = new_buf[9];
new_buf[26] = new_buf[10];
new_buf[27] = new_buf[11];
//my IP address
//get the correct ip for multi interface machines
for(size_t z(0); z < 4; ++z) new_buf[z + 28] = ip_array[f][z];
//hardware address of the target
new_buf[32] = new_buf[0];
new_buf[33] = new_buf[1];
new_buf[34] = new_buf[2];
new_buf[35] = new_buf[3];
new_buf[36] = new_buf[4];
new_buf[37] = new_buf[5];
//this is target protocol address
new_buf[38] = buf[28];
new_buf[39] = buf[29];
new_buf[40] = buf[30];
new_buf[41] = buf[31];
new_buf[42] = '\0';
_lan* temp_lan_ptr = all_lans -> lan;
for(size_t k(0); k < f; ++k) temp_lan_ptr = temp_lan_ptr -> next;
if(debug_on) cout << "make_arp_packet writepacket() to "
<< temp_lan_ptr -> lname << endl
<< "make_arp_packet this is the ARP packet i'm sending"
<< endl;
if(debug_on) print_arp_packet(new_buf);
writepacket(ifaces[f], new_buf, 42);
}
//****************************************************************************
//
// Function: make_icmp_packet
//
// Purpose: Creates an ICMP packet to serve as a reply to the ping request
//
// Parameters: debug_on - debugging information flag
// buf - the packet that was read in or created
// packet_size - num of bytes of current packet
// ip_array - array of ip addresses for all interfaces
// f - index into ifaces of current interface
// all_lans - linked list that holds all network addresses and
// names of them on the computer
// ifaces - handles to the interfaces
//
// Calls: print_icmp_echo, writepacket, vchksum
//
//****************************************************************************
void make_icmp_packet(const bool& debug_on, char buf[], const int& packet_size,
char ip_array[MAX_NUM_INTERFACES][4], const size_t& f,
lanlist* all_lans, INTERFACE** ifaces)
{
char new_buf[packet_size];
_lan* lan_ptr = all_lans -> lan;
int tens, ones, hex_to_dec(1), g(6);
u_short temp_check_sum;
for(size_t k(0); k < f; ++k) lan_ptr = lan_ptr -> next;
//ETHERNET HEADER
for(size_t g(0); g < 6; ++g)
{ //destination for reply is source of request
new_buf[g] = buf[g + 6];
}
for(size_t w(0); lan_ptr -> hwaddr[w] != '\0'; ++w)
{ //my ETHERNET ADDRESS, next 6 octets of buffer
tens = lan_ptr -> hwaddr[w];
ones = lan_ptr -> hwaddr[w + 1];
tens = ((tens > 57) ? (tens -= 87) : (tens -= 48));
ones = ((ones > 57) ? (ones -= 87) : (ones -= 48));
hex_to_dec = 16 * tens + ones;
new_buf[g++] = hex_to_dec;
w += 2;
}
new_buf[12] = char(8); //ICMP is IP type code is 800 hex
new_buf[13] = char(0); //ICMP is IP type code is 800 hex
//IP HEADER
for(size_t x(14); x < 24; ++x) new_buf[x] = buf[x]; //copy beginning
new_buf[24] = new_buf[25] = char(0); //initialize checksum to 0x00
for(size_t x(26); x < 30; ++x) new_buf[x] = buf[x + 4]; //swap IPs
for(size_t x(30); x < 34; ++x) new_buf[x] = buf[x - 4];
temp_check_sum = vchksum(&(new_buf[14]), 20); //calculate checksum
memcpy(&new_buf[24], &temp_check_sum, sizeof(temp_check_sum)); //update
if(debug_on) cout << "make_icmp_packet IP vchksum = "
<< vchksum(&(new_buf[14]),20) << endl; //should be 0 now
//ICMP HEADER
new_buf[34] = char(0); //ICMP ECHO REPLY
new_buf[35] = char(0); //ICMP code = 0
new_buf[36] = char(0); //checksum has to be 0 before it is set
new_buf[37] = char(0); //checksum has to be 0 before it is set
new_buf[38] = buf[38]; //identifier stays the same
new_buf[39] = buf[39]; //identifier stays the same
new_buf[40] = buf[40]; //sequence number stays the same
new_buf[41] = buf[41]; //sequence number stays the same
//copy original data
for(int v(42); v < packet_size; ++v) new_buf[v] = buf[v];
//deal with the checksum
temp_check_sum = vchksum(&(new_buf[34]), 64); //run vchksum over entire icmp
memcpy(&new_buf[36], &temp_check_sum, sizeof(temp_check_sum));
if(debug_on) cout << "make_icmp_packet ICMP vchksum = "
<< vchksum(&(new_buf[34]),64) << endl
<< "make_icmp_packet the ICMP packet i'm sending\n";
if(debug_on) print_icmp_echo(new_buf, packet_size);
writepacket(ifaces[f], new_buf, packet_size);
}
//****************************************************************************
//
// Function: print_arp_packet
//
// Purpose: This will print out the ARP request and the ARP reply packets.
//
// Parameters: buf - the packet that was read in or created
//
// Calls: none
//
//****************************************************************************
void print_arp_packet(const char buf[])
{
//ETHERNET HEADER
cout << " ETHERNET HEADER CONTENTS" << endl << " destination ";
for(size_t a(0); a < 6; ++a)
{
if(size_t(u_char(buf[a])) < 16) cout << '0';
cout << std::hex << size_t(u_char(buf[a])) << std::dec; //output in hex
if(a != 5) cout << ":";
}
cout << endl << " source ";
for(size_t a(6); a < 12; ++a)
{
if(size_t(u_char(buf[a])) < 16) cout << '0';
cout << std::hex << size_t(u_char(buf[a])) << std::dec; //output in hex
if(a != 11) cout << ":";
}
cout << endl << " type "
<< std::hex << u_char(buf[12]) * 256 + u_char(buf[13])
//ARP FRAME CONTENTS
<< std::dec << endl << " ARP FRAME CONTENTS" << endl
<< " hardware address space " << size_t(u_char(buf[14]))
<< size_t(u_char(buf[15])) << endl << " protocol address space "
<< size_t(u_char(buf[16])) << size_t(u_char(buf[17])) << endl
<< " byte length of HWADDR " << size_t(u_char(buf[18])) << endl
<< " byte length of PRADDR " << size_t(u_char(buf[19])) << endl
<< " opcode " << size_t(u_char(buf[20]))
<< size_t(u_char(buf[21])) << endl << " sender ethernet ";
for(size_t a(22); a < 28; ++a)
{
if(size_t(u_char(buf[a])) < 16) cout << '0';
cout << std::hex << size_t(u_char(buf[a])) << std::dec; //output in hex
if(a != 27) cout << ":";
}
cout << endl << " sender ip ";
for(size_t a(28); a < 32; ++a)
{
cout << size_t(u_char(buf[a])) << std::dec; //output in hex
if(a != 31) cout << '.';
}
cout << endl << " target ethernet ";
for(size_t a(32); a < 38; ++a)
{
if(size_t(u_char(buf[a])) < 16) cout << '0';
cout << std::hex << size_t(u_char(buf[a])) << std::dec; //output in hex
if(a != 37) cout << ":";
}
cout << endl << " target ip ";
for(size_t a(38); a < 42; ++a)
{
cout << size_t(u_char(buf[a])) << std::dec; //output in hex
if(a != 41) cout << '.';
}
cout << endl;
}
//****************************************************************************
//
// Function: print_icmp_packet
//
// Purpose: This will print out the ICMP request and the ICMP reply packets.
//
// Parameters: buf - the packet that was read in or created
// packet_size - size of the buffer
//
// Calls: none
//
//****************************************************************************
void print_icmp_echo(char buf[], const int& packet_size)
{
//ETHERNET HEADER
cout << " ETHERNET HEADER CONTENTS" << endl << " destination ";
for(size_t a(0); a < 6; ++a)
{
if(size_t(u_char(buf[a])) < 16) cout << '0';
cout << std::hex << size_t(u_char(buf[a])) << std::dec; //output in hex
if(a != 5) cout << ":";
}
cout << endl << " source ";
for(size_t a(6); a < 12; ++a)
{
if(size_t(u_char(buf[a])) < 16) cout << '0';
cout << std::hex << size_t(u_char(buf[a])) << std::dec; //output in hex
if(a != 11) cout << ":";
}
cout << endl << " type "
<< std::hex << u_char(buf[12]) * 256 + u_char(buf[13]) << std::dec
<< endl
//IP HEADER
<< " IP HEADER CONTENTS" << endl
<< " vers " << size_t(u_char(buf[14])) / 16 << endl
<< " len "
<< size_t(u_char(buf[14])) - (16 * (size_t(u_char(buf[14])) / 16))
<< endl << " type serv " << size_t(u_char(buf[15]))
<< endl << " total length " << size_t(u_char(buf[16]))
<< ' ' << size_t(u_char(buf[17])) << endl
<< " ident " << size_t(u_char(buf[18])) << ' '
<< size_t(u_char(buf[19])) << endl << " flags "
<< size_t(u_char(buf[20])) / 16 << endl << " fragment offset "
<< size_t(u_char(buf[20])) - (16 * (size_t(u_char(buf[20])) / 16))
<< ' ' << size_t(u_char(buf[21])) << endl
<< " time " << size_t(u_char(buf[22])) << endl
<< " proto " << size_t(u_char(buf[23])) << endl
<< " header checksum " << size_t(u_char(buf[24])) << ' '
<< size_t(u_char(buf[25])) << endl << " source ip address "
<< size_t(u_char(buf[26])) << '.' << size_t(u_char(buf[27])) << '.'
<< size_t(u_char(buf[28])) << '.' << size_t(u_char(buf[29])) << endl
<< " destination ip address " << size_t(u_char(buf[30])) << '.'
<< size_t(u_char(buf[31])) << '.' << size_t(u_char(buf[32])) << '.'
<< size_t(u_char(buf[33])) << endl
//ICMP HEADER
<< " ICMP HEADER CONTENTS" << endl
<< " type " << size_t(u_char(buf[34])) << endl
<< " code " << size_t(u_char(buf[35])) << endl
<< " checksum " << size_t(u_char(buf[36])) << ' '
<< size_t(u_char(buf[37])) << endl << " identifier "
<< size_t(u_char(buf[38])) << ' ' << size_t(u_char(buf[39])) << endl
<< " sequence number " << size_t(u_char(buf[40])) << ' '
<< size_t(u_char(buf[41])) << endl << " data ";
//ICMP DATA
for(int v(42); v < packet_size; ++v)
{ //output the data
if((v % 21) == 0) cout << "\n "; //20 bytes per line
else
{
if(size_t(u_char(buf[v])) < 16) cout << '0';
cout << std::hex << size_t(u_char(buf[v])) << std::dec << " ";
}
}
cout << endl;
}