Scavenger
For this assignment we had to write a prog in c to read in a trace file of network communications (in hex) and print out what was happening (SYN/ACK etc.). We also had to print the payload if there was any.
PA1: Scavenger assignment description
Trace File sample trace
Trace File2 sample trace
Sample Output example of expected output
pa1.c my solution
/**
* scavenger.c
*
* @author Will Mernagh
* @version PA1
* @course COMP 150-ICS
* @date Feb 08 2007
*/
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h> /* Need this for inet_ntoa to work properly */
#include <string.h> /* Need this for strchr to work */
#include <getopt.h>
/* ERROR CODES */
#define NO_FILE_SPECIFIED -1
#define NO_DATAGRAMS_FOUND -2
#define INVALID_IP_FORMATION -3
#define INVALID_TCP_FORMATION -4
#define VALID_PACKET_FORMATION 0
#define INVALID_HEX_DIGIT -5
#define VALID_HEX_DIGIT 0
#define INVALID_PAYLOAD_LENGTH -6
/* End of ERROR CODES */
/* Options */
#define RAW_OFF 0
#define RAW_ON 1
#define DEBUG_OFF 0
#define DEBUG_ON 1
#define ERRORS_OFF 0
#define ERRORS_ON 1
#define DG_BY_DG_ON 1 /*Datagram by packet*/
#define DG_BY_DG_OFF 0
/* End Options */
#define RESTRICTED_PORTS 1026
#define PACKET_LENGTH 1026
#define TRUE 1
#define FALSE 0
static int pause_flag;
static int debug_flag;
static int errors_flag;
static int raw_flag;
typedef struct collection COLLECTION;
struct collection {
int dg_index;
int valid;
unsigned short **packets;
};
/* Function declerations */
struct collection parse_file(char *, unsigned short **);
void print_info();
unsigned short ** memory_alloc(unsigned short ** packets, int d_index);
void print_dg_info(unsigned short *);
char * string_ip_flags(struct ip *);
char * string_tcp_flags(struct tcphdr *);
void print_ip_header(struct ip *);
void print_tcp_header(struct tcphdr *);
void print_payload(unsigned short *);
void print_usage();
char * read_options(int, char **);
int validate_is_hex ( char *);
int validate_packet(unsigned short *);
void debug_fun(unsigned short *);
/* End of function declerations */
/**
* Reads a file of packets (possibly ip/tcp) into an array. It
* then displays the data in a meiningfull way
*
* It can also take in a number of options including -debug
*
* @param argc the number of command line arguments including the program
* @param argv a pointer to an array of strings holding the command line
*
* @return an int defining its success, failure.
*/
int main(int argc, char *argv[]){
char *file_in;
int i = 0;
int packet_count;
unsigned short **packets;
COLLECTION dg_col;
/* reads the file name and command line options if given */
if((file_in = read_options(argc, argv))==NULL){
print_usage();
return NO_FILE_SPECIFIED;
}
dg_col = parse_file(file_in, packets);
/* Count is greater than an array index by one */
packet_count = dg_col.dg_index + 1;
if (packet_count != 0){
for(i = 0; i < packet_count; i++){
//debug_fun(dg_col.packets[i]);
if(dg_col.valid){print_info(dg_col.packets[i], i);}
/* Free memory assigned to packets */
if(dg_col.packets[i] != NULL){free(dg_col.packets[i]);}
}
/* Free memory assigned to packets */
if(dg_col.packets != NULL){free(dg_col.packets);}
return 0;
}else{
return NO_DATAGRAMS_FOUND;
}
}
/**
* Parses <filename> into an array of packets. It expects each line to be
* numbered. It then reads the line number and white space and ignores them.
* The length of the number + whitespace is determined by the offset.
*
* @param filename the file to parse
* @param packets array holding packets
*
* @return the packets from the file, their count and
* whether the packet is valid
*/
COLLECTION parse_file(char *filename, unsigned short **packets){
char b1[6], b2[6], *c; //stores chars read in
int hex_count = 0; //The number of hex value groups in a line
int d_index = -1; //The number of packets
int offset = 3, order = 10;
COLLECTION dg_col;
unsigned short part_of_packet;
c = b1;
FILE *file;
file = fopen(filename, "r");
if (file == NULL){
fprintf(stderr, "Error: fopen(%s, r)\n", filename);
}else {
/* We need to read the line number and ignore it */
while (fgets(c, offset, file)!=NULL){
/* Allocate memory for a pointer to a 2D array */
packets = memory_alloc(packets, d_index);
/* Datagram index incements for each line read */
d_index++;
/* Now we read 5 characters at a time from the file
(Until we reach either end of file or end of line.
End of line is handled by a break later)
this includes the 4 hex values and the white space */
while(fgets(c, 6, file) != NULL){
/* If there is a \n then this is last read on current packet*/
if((strchr(c, '\n')!=NULL)){
/* If less than 2 then no hex just end of line */
if(strlen(c)<2){
hex_count = 0;
break;
}else if(strlen(c)<5){/* hex and \n */
/* we need to just have hex values */
b2[0] = b1[0];
b2[1] = b1[1];
b2[2] = '0';
b2[3] = '0';
b2[4] = 0;
b2[5] = 0;
c = b2;
}else{
/* we need to just have hex values */
b2[0] = b1[0];
b2[1] = b1[1];
b2[2] = b1[2];
b2[3] = b1[3];
b2[4] = 0;
b2[5] = 0;
c = b2;
}
}
/* Check if data parsed is a hex value and return if it
is not */
if(validate_is_hex(c) == INVALID_HEX_DIGIT){
fprintf(stderr, "Error: Invalid data in file\n");
dg_col.dg_index = d_index;
dg_col.packets = packets;
dg_col.valid = FALSE;
return dg_col;
}
/* Read the hex value from the c string and
place it in the array */
sscanf(c, "%x", &part_of_packet);
/* Convert the packet into network readable format */
packets[d_index][hex_count] = htons(part_of_packet);
hex_count++;
/* Ensures we do not overwrite the buffer */
if(hex_count > PACKET_LENGTH){
fprintf(stderr, "Error: Packet length too large. ");
fprintf(stderr, "Can only read in %d hex ", PACKET_LENGTH);
fprintf(stderr, "values per packet\n");
dg_col.dg_index = d_index;
dg_col.valid = FALSE;
dg_col.packets = packets;
return dg_col;
}
/* then a \n was found and this indicates end of packet */
if(c == b2){
hex_count =0;
c = b1;
break;
}
}
/* We need to ignore the line numbers. These numbers can take up more
than one character depending on their value, hence the offset changes
every *10 */
if((d_index + 2)/order){
order = order * 10;
offset = offset + 1;
}
}
fclose(file);
dg_col.packets = packets;
}
dg_col.dg_index = d_index;
dg_col.valid = TRUE;
return dg_col;
}
/**
* Prints all the relevant information
*
* @param packets array holding packets
* @param dg_number The index number of the packets (Index starts at 1)
*
*/
void print_info(unsigned short *packet, int dg_number){
int j, size;
char a; //used for pausing after print to screen
/* Point the IP header to the start of the packet */
struct ip *ip_hdr = (struct ip *) packet;
struct tcphdr *tcp_hdr = (struct tcphdr *) (packet +(ip_hdr->ip_hl * 2));
/* Print out relevant information */
if(validate_packet(packet) == VALID_PACKET_FORMATION){
printf("Packet Number %d\n", dg_number + 1);
print_dg_info(packet);
print_ip_header(ip_hdr);
print_tcp_header(tcp_hdr);
if(debug_flag == DEBUG_ON){print_payload(packet);}
printf("\n");
/* prints packet as it is in the file if raw_flag is set */
if(raw_flag){
if(ntohs(ip_hdr->ip_len)%2){
size = ntohs(ip_hdr->ip_len)/2 + 1;
}else{
size = ntohs(ip_hdr->ip_len)/2;
}
for(j = 0; j < size ; j++){
printf("%04x ", ntohs(packet[j]));
}
}
/* this puts a pause after each displayed packet */
if(pause_flag) {scanf("%c", &a);}
}else if(errors_flag){
fprintf(stderr, "Error: In packet number %d\n", dg_number + 1);
}
}
/**
* Prints info about the packet. Its source and destination types and what type of
* packet it is.
*
* @param packet a pointer to an ip and tcp struct
*/
void print_dg_info(unsigned short *packet){
char *output, *dest, *source;
/* Point the IP header to the start of the packet */
struct ip *ip_hdr = (struct ip *) packet;
/* Point the TCP header to the start of the packet */
struct tcphdr *tcp_h = (struct tcphdr *) (packet +(ip_hdr->ip_hl * 2));
#ifdef DARWIN
if(ntohs(tcp_h->th_sport) >= RESTRICTED_PORTS){
#else
if(ntohs(tcp_h->source) >= RESTRICTED_PORTS){
#endif
source = "Client -> ";
}else{
source = "Server -> ";
}
#ifdef DARWIN
if(ntohs(tcp_h->th_dport) >= RESTRICTED_PORTS){
#else
if(ntohs(tcp_h->dest) >= RESTRICTED_PORTS){
#endif
dest = "Client";
}else{
dest = "Server";
}
output =(char *)calloc(strlen(source) + strlen(dest) + 1, sizeof(char));
output = strcat(output, source);
output = strcat(output, dest);
printf("%s\n", output);
printf("Type of TCP packet: %s\n", string_tcp_flags(tcp_h));
}
/**
* Returns a pointer to a string specifing which flag is set.
*
* @param iph a pointer to an ip struct
* @return pointer to a string [RF|DF|MF|MASK|UNSET]
*/
char * string_ip_flags(struct ip *ip_h){
char *flag = "UNSET";
if(ntohs(ip_h->ip_off) == IP_RF){flag = "RF";}
if(ntohs(ip_h->ip_off) == IP_DF){flag = "DF";}
if(ntohs(ip_h->ip_off) == IP_MF){flag = "MF";}
if(ntohs(ip_h->ip_off) == IP_OFFMASK){flag = "MASK";}
return flag;
}
/**
* Returns a pointer to a string specifing which flag is set.
*
* @param tcp_h a pointer to an tcp struct
* @return pointer to a string [FIN|SYN|RST|PUSH|ACK|URG|UNSET]
*/
char * string_tcp_flags(struct tcphdr *tcp_h){
char *flag = "UNSET";
# ifdef DARWIN /* attempt to have this working locally and in school */
if(ntohs(tcp_h->th_flags) == TH_FIN){flag = "FIN";}
if(ntohs(tcp_h->th_flags) == TH_SYN){flag = "SYN";}
if(ntohs(tcp_h->th_flags) == TH_RST){flag = "RST";}
if(ntohs(tcp_h->th_flags) == TH_PUSH){flag = "PUSH";}
if(ntohs(tcp_h->th_flags) == TH_ACK){flag = "ACK";}
if(ntohs(tcp_h->th_flags) == TH_URG){flag = "URG";}
# else /* !DARWIN */
if((tcp_h->fin)){ flag = "FIN";}
if((tcp_h->rst)){ flag = "RST";}
if((tcp_h->psh)){ flag = "PSH";}
if((tcp_h->ack)){ flag = "ACK";}
if((tcp_h->syn)){ flag = "SYN";}
if((tcp_h->urg)){ flag = "URG";}
# endif /* DARWIN */
return flag;
}
/**
* Prints the IP header information to STDOUT of a given packet
* in a human readable form.
*
* @param ip_hdr a pointer to a ip header
* which holds a packet in network form
*
* @see htons, ntohs
*/
void print_ip_header(struct ip *ip_hdr){
printf("-----------------------------------------\n");
printf("|(VER) %d |(HL) %d |(TOS) %2x |(LEN) %6d|\n",
ip_hdr->ip_v,
ip_hdr->ip_hl,
ip_hdr->ip_tos,
ntohs(ip_hdr->ip_len));
printf("-----------------------------------------\n");
printf("|(ID) %5d |(FLAGS) %5s|(OFF) %6d |\n",
ip_hdr->ip_id,
string_ip_flags(ip_hdr),
ip_hdr->ip_off);
printf("-----------------------------------------\n");
printf("|(TTL) %5d|(PROTP) %5d|(CKSUM) %5d|\n",
ip_hdr->ip_ttl,
ip_hdr->ip_p,
ip_hdr->ip_sum);
printf("-----------------------------------------\n");
printf("|(SOURCE)\t%15s\t\t|\n", inet_ntoa(ip_hdr->ip_src));
printf("|(DEST)\t\t%15s\t\t|\n", inet_ntoa(ip_hdr->ip_dst));
}
/**
* Prints the TCP header information to STDOUT of a given packet
* in a human readable form. It also attempts to work on mac OS X
* linux using the c preprocessor.
*
* @param tcp_hdr a pointer to a tcp header struct
* which holds a packet in network form
*
* @see htons, ntohs
*/
void print_tcp_header(struct tcphdr *tcp_hdr){
printf("-----------------------------------------\n");
# ifdef DARWIN
printf("(SPORT) %5d\t |(DPORT) %5d\t\t|\n", ntohs(tcp_hdr->th_sport),
ntohs(tcp_hdr->th_dport));
printf("-----------------------------------------\n");
printf("(SEQ) %10u |(ACK) %15u |\n", ntohl(tcp_hdr->th_seq),
ntohl(tcp_hdr->th_ack));
# else /* DARWIN */
printf("(SPORT) %5d\t |(DPORT) %5d\t\t|\n", ntohs(tcp_hdr->source),
ntohs(tcp_hdr->dest));
printf("-----------------------------------------\n");
printf("(SEQ) %10u |(ACK) %15u |\n", ntohl(tcp_hdr->seq),
ntohl(tcp_hdr->ack_seq));
# endif /* DARWIN */
printf("-----------------------------------------\n");
printf("(FLAGS) \t\t%10s\t|\n", string_tcp_flags(tcp_hdr));
printf("-----------------------------------------\n");
}
/**
* Prints the payload in the packet which is located after the ip and tcp
* headers.
*
* @param packet a packet of ip, tcp and data
*
*/
void print_payload(unsigned short *packet){
int i;
struct ip *ip_hdr = (struct ip *) packet;
struct tcphdr *tcp_hdr = (struct tcphdr *) (packet +(ip_hdr->ip_hl * 2));
#ifdef DARWIN
short data_length = ntohs(ip_hdr->ip_len) - tcp_hdr->th_off*4 - ip_hdr->ip_hl*4;
printf("data_len = %d = ", data_length);
printf("ntohs(ip_hdr->ip_len) - tcp_hdr->th_off*4 - ip_hdr->ip_hl*4 = \n");
printf("%d - %d - %d\n", ntohs(ip_hdr->ip_len),tcp_hdr->th_off*4,ip_hdr->ip_hl*4);
unsigned char *payload = (unsigned char *) (packet + (ip_hdr->ip_hl*2)
+ tcp_hdr->th_off*2);
#else /* DARWIN */
short data_length = ntohs(ip_hdr->ip_len) - tcp_hdr->doff*4 - ip_hdr->ip_hl*4;
unsigned char *payload = (unsigned char *) (packet + (ip_hdr->ip_hl*2)
+ tcp_hdr->doff*2);
#endif /* DARWIN */
for(i=0;i<data_length;i++){
/* check if the character is printable */
if(isprint(payload[i])){
printf("%c", payload[i]);
}else{
printf("^");
}
}
printf("\n");
}
/**
* Prints the usage statement to STDOUT
*/
void print_usage(){
printf("\nusage: scavenger [-debug | -p | -r | -e] <file>\n");
printf("\n");
printf(" -debug prints the payload of the packet\n");
printf(" -r prints out the packet in its original form\n");
printf(" -p puts a pause after displaying each packet\n");
printf(" -e prints all errors. Prints if a packet is invalid\n");
printf("\n");
printf("Info: Scavenger will print information on the packets that are written"
" to a file.\nThe file needs to be formatted correctly or no information"
" will be displayed. If\nthe file is formatted correctly and the packet is a"
" valid IP/TCP packet then the\npacket gets displayed. If there is an"
" invalid TCP/IP packet it will be skipped.");
printf("\n\n");
}
/**
* Returns the file that was read from the command line. It also sets the debug
* and display flags depending on the command line options.
*
* @param argc the number of command line arguments including the program
* @param argv a pointer to an array of strings holding the command line
* argumants.
*
* @return a pointer to a file name (string)
*
* @see getopt_long_only
*/
char * read_options(int argc, char **argv){
int c;
static struct option long_options[] = {
/* These options set a flag. */
{"p", no_argument, &pause_flag, DG_BY_DG_ON},
{"debug", no_argument, &debug_flag, DEBUG_ON},
{"e", no_argument, &errors_flag, ERRORS_ON},
{"r", no_argument, &raw_flag, RAW_ON},
};
while (1) {
/* getopt_long stores the option index here. */
/* We do not use it to access any options here though */
int option_index = 0;
//c = getopt_long (argc, argv, "", long_options, &option_index);
c = getopt_long_only (argc, argv, "", long_options, &option_index);
/* Detect the end of the options. */
if (c == -1){ break;}
}
/* Return the file name */
if (optind < argc) {
return argv[optind];
}else{
return NULL;
}
}
/**
* Checks whether each character in a string is a hex digit
*
* @param a A string pointer
*
* @return 0 if valid else INVALID_HEX_DIGIT
*
* @see isxdigit()
*/
int validate_is_hex ( char *a )
{
unsigned i;
/* We are expecting 4 hex and one space,
so we need to ignore the trailing space.
for ( i = 0; i < strlen ( a ) -1; i++ ){ */
for ( i = 0; i < strlen ( a ) -2; i++ ){
if ( !isxdigit ( a[i] ) ){
if(errors_flag){
fprintf(stderr, "Error: %c is not a hex value\n", a[i]);
}
return INVALID_HEX_DIGIT;
}
}
return VALID_HEX_DIGIT;
}
/**
* Checks whether each ip/tcp header is formed properly
*
* @param packet the packet to check
*
* @return Either VALID_PACTET_FORMATION, INVALID_IP_FORMATION or
* INVALID_TCP_FORMATION
*
*/
int validate_packet(unsigned short *packet){
/* Point the IP header to the start of the packet */
struct ip *ip_hdr = (struct ip *) packet;
struct tcphdr *tcp_hdr = (struct tcphdr *) (packet +(ip_hdr->ip_hl * 2));
unsigned short ip_v = ip_hdr->ip_v;
unsigned short ip_hl = ip_hdr->ip_hl;
char *flag = string_ip_flags(ip_hdr);
#ifdef DARWIN
short data_length = ntohs(ip_hdr->ip_len) - tcp_hdr->th_off*4 - ip_hdr->ip_hl*4;
#else /* DARWIN */
short data_length = ntohs(ip_hdr->ip_len) - tcp_hdr->doff*4 - ip_hdr->ip_hl*4;
#endif /* DARWIN */
/* Check that information in ip/tcp adds up */
if(data_length < 0){
if(errors_flag){fprintf(stderr, "Error: negative payload length\n");}
return INVALID_PAYLOAD_LENGTH;
}
/* Check that IP is formed correctly */
if(flag == "UNSET" || (ip_v != 4 && ip_v != 6) || ip_hl < 5){
if(errors_flag){fprintf(stderr, "Error: invalid ip packet\n");}
//return INVALID_IP_FORMATION;
}
/* Check if TCP is formed correctly */
flag = string_tcp_flags(tcp_hdr);
if(flag == "UNSET"){
#ifndef DARWIN
if(errors_flag){fprintf(stderr, "Error: invalid tcp packet\n");}
return INVALID_TCP_FORMATION;
#endif /* DARWIN - cannot get flags working for mac */
}
return VALID_PACKET_FORMATION;
}
/**
* Allocates memory for the packets pointer. It decides whether to malloc or realloc
* based on the d_index value.
*
* @param packets the pointer to allocate memory for
* @param d_index the index of the packets array. If 0 malloc else realloc
*
* @return pointer to allocated memory (Pointer to 2D array)
*
* @see malloc, realloc
*/
unsigned short ** memory_alloc(unsigned short ** packets, int d_index){
/* Allocate memory for a pointer to a 2D array */
if(d_index < 0){
packets = (unsigned short **)malloc(sizeof(unsigned short *));
if (packets == NULL){
fprintf(stderr, "Error: Malloc failed\n");
}
packets[0] =
(unsigned short *)malloc(PACKET_LENGTH * sizeof(unsigned short));
if (packets[0] == NULL){
fprintf(stderr, "Error: Malloc failed\n");
}
}else{
/* allocate more memory */
packets = (unsigned short **)realloc((unsigned int **)packets,
((d_index + 2)*sizeof(unsigned short *)));
if(packets == NULL){
fprintf(stderr, "Error: Realloc failed for #%d\n", d_index);
}
packets[d_index+1]=
(unsigned short*)malloc(PACKET_LENGTH*sizeof(unsigned short));
if (packets[d_index + 1] == NULL){
fprintf(stderr, "Error: Realloc failed for #%d\n", d_index);
}
}
return packets;
}
void debug_fun(unsigned short * packet){
/* Point the IP header to the start of the packet */
struct ip *ip_hdr = (struct ip *) packet;
struct tcphdr *tcp_hdr = (struct tcphdr *) (packet +(ip_hdr->ip_hl * 2));
printf("ntohs(ip_hdr->ip_len) = %d\t", ntohs(ip_hdr->ip_len));
printf("ip_hdr->ip_len = %d\n", ip_hdr->ip_len);
printf("ntohs(ip_hdr->ip_id) = %d\t", ntohs(ip_hdr->ip_id));
printf("ip_hdr->ip_id = %d\n", ip_hdr->ip_id);
printf("ntohs(ip_hdr->ip_v) = %d\t", ntohs(ip_hdr->ip_v));
printf("ip_hdr->ip_v = %d\n", ip_hdr->ip_v);
printf("ntohs(ip_hdr->ip_hl) = %d\t", ntohs(ip_hdr->ip_hl));
printf("ip_hdr->ip_hl = %d\n", ip_hdr->ip_hl);
printf("ntohs(ip_hdr->ip_tos) = %d\t", ntohs(ip_hdr->ip_tos));
printf("ip_hdr->ip_tos = %d\n", ip_hdr->ip_tos);
printf("ntohs(ip_hdr->ip_off) = %d\t", ntohs(ip_hdr->ip_off));
printf("ip_hdr->ip_off = %d\n", ip_hdr->ip_off);
printf("ntohs(ip_hdr->ip_ttl) = %d\t", ntohs(ip_hdr->ip_ttl));
printf("ip_hdr->ip_ttl = %d\n", ip_hdr->ip_ttl);
printf("ntohs(ip_hdr->ip_p) = %d\t", ntohs(ip_hdr->ip_p));
printf("ip_hdr->ip_p = %d\n", ip_hdr->ip_p);
printf("ntohs(ip_hdr->ip_sum) = %d\t", ntohs(ip_hdr->ip_sum));
printf("ip_hdr->ip_sum = %d\n", ip_hdr->ip_sum);
printf("ntohs(ip_hdr->ip_sum) = %d\t", ntohs(ip_hdr->ip_sum));
printf("ip_hdr->ip_sum = %d\n", ip_hdr->ip_sum);
printf("ntohs(ip_hdr->ip_off) = %d\t", ntohs(ip_hdr->ip_off));
printf("ip_hdr->ip_off = %d\n", ip_hdr->ip_off);
#ifdef DARWIN
printf("ntohs(tcp_hdr->th_dport) = %d\t", ntohs(tcp_hdr->th_dport));
printf("tcp_hdr->th_dport = %d\n", tcp_hdr->th_dport);
printf("ntohs(tcp_hdr->th_sport) = %d\t", ntohs(tcp_hdr->th_sport));
printf("tcp_hdr->th_sport = %d\n", tcp_hdr->th_sport);
printf("ntohl(tcp_hdr->th_seq) = %u\t", ntohl(tcp_hdr->th_seq));
printf("tcp_hdr->th_seq = %u\n", tcp_hdr->th_seq);
printf("ntohs(tcp_hdr->th_off) = %d\t", ntohs(tcp_hdr->th_off));
printf("tcp_hdr->th_off = %d\n", tcp_hdr->th_off);
printf("ntohs(tcp_hdr->th_flags) = %d\t", ntohs(tcp_hdr->th_flags));
printf("tcp_hdr->th_flags = %d\n", tcp_hdr->th_flags);
#endif
printf("*************************************\n");
/*printf("ntohl(ip_hdr->ip_len) = %d\t", ntohl(ip_hdr->ip_len));
printf("ip_hdr->ip_len = %d\n", ip_hdr->ip_len);
printf("ntohl(ip_hdr->ip_v) = %d\t", ntohl(ip_hdr->ip_v));
printf("ip_hdr->ip_v = %d\n", ip_hdr->ip_v);
printf("ntohl(ip_hdr->ip_hl) = %d\t", ntohl(ip_hdr->ip_hl));
printf("ip_hdr->ip_hl = %d\n", ip_hdr->ip_hl);
printf("ntohl(ip_hdr->ip_tos) = %d\t", ntohl(ip_hdr->ip_tos));
printf("ip_hdr->ip_tos = %d\n", ip_hdr->ip_tos);
printf("ntohl(ip_hdr->ip_off) = %d\t", ntohl(ip_hdr->ip_off));
printf("ip_hdr->ip_off = %d\n", ip_hdr->ip_off);
printf("ntohl(ip_hdr->ip_ttl) = %d\t", ntohl(ip_hdr->ip_ttl));
printf("ip_hdr->ip_ttl = %d\n", ip_hdr->ip_ttl);
printf("ntohl(ip_hdr->ip_p) = %d\t", ntohl(ip_hdr->ip_p));
printf("ip_hdr->ip_p = %d\n", ip_hdr->ip_p);
printf("ntohl(ip_hdr->ip_sum) = %d\t", ntohl(ip_hdr->ip_sum));
printf("ip_hdr->ip_sum = %d\n", ip_hdr->ip_sum);
printf("ntohl(ip_hdr->ip_sum) = %d\t", ntohl(ip_hdr->ip_sum));
printf("ip_hdr->ip_sum = %d\n", ip_hdr->ip_sum);
printf("ntohl(ip_hdr->ip_off) = %d\t", ntohl(ip_hdr->ip_off));
printf("ip_hdr->ip_off = %d\n", ip_hdr->ip_off);
printf("ntohl(tcp_hdr->th_dport) = %d\t", ntohl(tcp_hdr->th_dport));
printf("tcp_hdr->th_dport = %d\n", tcp_hdr->th_dport);
printf("ntohl(tcp_hdr->th_sport) = %d\t", ntohl(tcp_hdr->th_sport));
printf("tcp_hdr->th_sport = %d\n", tcp_hdr->th_sport);
printf("ntohl(tcp_hdr->th_seq) = %d\t", ntohl(tcp_hdr->th_seq));
printf("tcp_hdr->th_seq = %d\n", tcp_hdr->th_seq);
printf("ntohl(tcp_hdr->th_flags) = %d\t", ntohl(tcp_hdr->th_flags));
printf("tcp_hdr->th_flags = %d\n", tcp_hdr->th_flags);*/
}