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