Static testing is used to test the bouncer, that is, a separate set of test cases and sample outputs are provided. And the bouncer is given the test cases and its outputs are compared with sample outputs.
A verifier is used to accomplish the above function, and another bash script is written to automate the process.
The bash script is as follows:
#!/bin/sh USAGE="Usage: $0 [-v] bouncer" CMD="./verifier " TESTDIR="cases" while getopts "v" optname do case "$optname" in "v") CMD="./verifier -v " ;; *) echo $USAGE exit 1 ;; esac done shift $(($OPTIND-1)) BCER=$* if [ -f "$BCER" ] then find "$TESTDIR" -iname "*pcap" | while read i do if [ -f "$i" ] && [ -f "$i"-ref ] then echo "======================================================================" echo "Verifying file: $i" $BCER -t -l 1.1.1.1 -s 3.3.3.3 <"$i" >"$i"-out BCRT=$? echo "----------------------------------------------------------------------" if [ $BCRT != 0 ] then echo "$BCER returned with $?" echo "Exiting $0" exit 1 fi $CMD -i "$i"-out -r "$i"-ref CMDRT=$? echo "----------------------------------------------------------------------" echo "Result for $i:" echo "$CMDRT packets has passed validation" echo "======================================================================" echo "n" fi done else echo $USAGE fi exit 0
The verifier is as follows:
#include "verifier.h" typedef unsigned short u16; typedef unsigned long u32; /* CRC * Adopted from http://www.netfor2.com/ipsum.htm */ u16 ip_sum_calc(u16 len_ip_header, u16 buff[]) { u16 word16; u32 sum = 0; u16 i; // make 16 bit words out of every two adjacent 8 bit words in the packet // and add them up for (i = 0; i < len_ip_header; i = i + 2) { word16 = ((buff[i] << 8)&0xFF00)+(buff[i + 1]&0xFF); sum = sum + (u32) word16; } // take only 16 bits out of the 32 bit sum and add up the carries while (sum >> 16) sum = (sum & 0xFFFF)+(sum >> 16); // one's complement the result sum = ~sum; return ((u16) sum); } int usage() { fprintf(stderr, "Usage: verifier [-v] -i input_file -r reference_filen"); exit(1); } int main(int argc, char **argv) { int verbose = 0; opterr = 0; char c; char *ifilename, *rfilename; struct stat st; while ((c = getopt(argc, argv, "vi:r:")) != -1) { if (c == 'i') { ifilename = optarg; if (stat(ifilename, &st) != 0) { fprintf(stderr, "File does not exist!n"); exit(1); } } else if (c == 'r') { rfilename = optarg; if (stat(rfilename, &st) != 0) { fprintf(stderr, "File does not exist!n"); exit(1); } } else if (c == 'v') { verbose = 1; } else { usage(); } } pcap_t *ihandle = NULL, *rhandle = NULL; char errbufi[PCAP_ERRBUF_SIZE], errbufr[PCAP_ERRBUF_SIZE]; ihandle = pcap_open_offline(ifilename, errbufi); rhandle = pcap_open_offline(rfilename, errbufr); struct pcap_pkthdr ihdr, rhdr; const u_char *ipkt, *rpkt; ipkt = malloc(MAX_PACKET_SIZE); rpkt = malloc(MAX_PACKET_SIZE); if (ipkt == NULL || rpkt == NULL) { perror("malloc"); exit(1); } int pc = -1; /* Packet counter */ char flags[MAX_PACKETS_NO]; /* Broken or Not */ memset(flags, PKT_OK, MAX_PACKETS_NO); while ((ipkt = pcap_next(ihandle, &ihdr)) && (rpkt = pcap_next(rhandle, &rhdr))) { pc++; /* Typecasting input packet*/ const struct sniff_ethernet *iethernet; /* The ethernet header */ const struct sniff_ip *iip; /* The IP header */ const struct sniff_icmp *iicmp; /* The ICMP header */ const char *ipayload; /* Packet payload */ u_int isize_ip; iethernet = (struct sniff_ethernet*) (ipkt); iip = (struct sniff_ip*) (ipkt + SIZE_ETHERNET); isize_ip = IP_HL(iip)*4; if (isize_ip < 20) { fprintf(stderr, " * Invalid IP header length: %u bytesn", isize_ip); continue; } iicmp = (struct sniff_icmp*) (ipkt + SIZE_ETHERNET + isize_ip); ipayload = (char *) (ipkt + SIZE_ETHERNET + isize_ip + SIZE_ICMP); /* Typecasting reference packet*/ const struct sniff_ethernet *rethernet; /* The ethernet header */ const struct sniff_ip *rip; /* The IP header */ const struct sniff_icmp *ricmp; /* The ICMP header */ const char *rpayload; /* Packet payload */ u_int rsize_ip; rethernet = (struct sniff_ethernet*) (rpkt); rip = (struct sniff_ip*) (rpkt + SIZE_ETHERNET); rsize_ip = IP_HL(rip)*4; if (rsize_ip < 20) { fprintf(stderr, " * Invalid IP header length: %u bytesn", rsize_ip); continue; } ricmp = (struct sniff_icmp*) (rpkt + SIZE_ETHERNET + rsize_ip); rpayload = (char *) (rpkt + SIZE_ETHERNET + rsize_ip + SIZE_ICMP); /* Here comes the validation process */ /* Check IP checksum */ u16 ipbuf[isize_ip]; u16 ipsum = ntohs(iip->ip_sum); int i; for (i = 0; i < isize_ip; i++) { if (i == 10 || i == 11) ipbuf[i] = 0x00; else ipbuf[i] = *((u_char *) (ipkt + SIZE_ETHERNET + i)); } if (ipsum != ip_sum_calc(isize_ip, ipbuf)) { flags[pc] = ERR_IP_SUM; continue; } /* Check ICMP checksum */ int plen = ihdr.len - SIZE_ETHERNET - isize_ip - 8; u16 icmpbuf[8 + plen]; u16 icmpsum = ntohs(iicmp->icmp_sum); for (i = 0; i < 8; i++) { if (i == 2 || i == 3) icmpbuf[i] = 0x00; else icmpbuf[i] = *((u_char *) (ipkt + SIZE_ETHERNET + isize_ip + i)); } for (i = 0; i < plen; i++) { icmpbuf[i + 8] = *((u_char *) (ipayload + i)); } if (icmpsum != ip_sum_calc(8 + plen, icmpbuf)) { flags[pc] = ERR_ICMP_SUM; continue; } /* Check IP TTL */ if (iip->ip_ttl <= 0) { flags[pc] = ERR_IP_TTL; continue; } /* Check IP source address */ if (iip->ip_src.s_addr != rip->ip_src.s_addr) { flags[pc] = ERR_IP_SADDR; continue; } /* Check IP destinataion address */ if (iip->ip_dst.s_addr != rip->ip_dst.s_addr) { flags[pc] = ERR_IP_DADDR; continue; } /* Check ICMP type */ if (iicmp->icmp_type != ricmp->icmp_type) { flags[pc] = ERR_ICMP_TYPE; continue; } /* Check ICMP ID */ if (iicmp->icmp_id != ricmp->icmp_id) { flags[pc] = ERR_ICMP_ID; continue; } /* Check ICMP sequence number */ if (iicmp->icmp_sequence != ricmp->icmp_sequence) { flags[pc] = ERR_ICMP_SEQ; continue; } } pc++; int bc = 0; /* Broken packet counter */ int i; for (i = 1; i <= pc; i++) { if (flags[i-1]) bc++; if (verbose) { switch (flags[i-1]) { case PKT_OK: fprintf(stdout, "Validation passed: %d/%dn", i, pc); break; case ERR_IP_SUM: fprintf(stdout, "IP checksum failed: %d/%dn", i, pc); break; case ERR_IP_TTL: fprintf(stdout, "IP TTL check failed: %d/%dn", i, pc); break; case ERR_IP_SADDR: fprintf(stdout, "IP source address check failed: %d/%dn", i, pc); break; case ERR_IP_DADDR: fprintf(stdout, "IP destination address check failed: %d/%dn", i, pc); break; case ERR_ICMP_SUM: fprintf(stdout, "ICMP checksum failed: %d/%dn", i, pc); break; case ERR_ICMP_TYPE: fprintf(stdout, "ICMP type check failed: %d/%dn", i, pc); break; case ERR_ICMP_ID: fprintf(stdout, "IP ID check failed: %d/%dn", i, pc); break; case ERR_ICMP_SEQ: fprintf(stdout, "IP sequence check failed: %d/%dn", i, pc); break; default: fprintf(stderr, "ERROR: Unknwon error type.n"); break; } } } if (bc == 0) fprintf(stdout, "%d packets passed validationn", pc); else fprintf(stdout, "%d out of %d packets failed validationn", bc, pc); /* Return number of packets passed validation */ return (pc - bc); }Leave a Comment