//------------------------------------------------------------------- // echotest.cpp // // This program sends ethernet frames of varying lengths which // contain our distinctive protocol-identifier and filled with // randomly generated data; it assumes that our 'sendback.cpp' // is executing on another station on the local network. Then // statistics are shown on the count of validly echoed frames. // // programmer: ALLAN CRUSE // written on: 01 MAY 2005 //------------------------------------------------------------------- #include // for printf(), perror() #include // for open() #include // for exit() #include // for read(), write() #include // for memcpy(), memset() #include // for gethostbyname(), htons() #include // ioctl() #define MY_TYPE 0x0635 // our protocol-type identifier #define N_FRAMES 2048 // total number of frames char nicname[] = "/dev/nic"; unsigned char nicaddr[10]; int main( int argc, char **argv ) { // open device-file and get hardware-address int nic = open( nicname, O_RDWR ); if ( nic < 0 ) { perror( nicname ); exit(1); } if ( ioctl( nic, 0, &nicaddr ) < 0 ) { perror( "ioctl" ); exit(1); } // get this station's IP-address char hostname[64] = {0}; gethostname( hostname, 64 ); struct hostent *hostinfo = gethostbyname( hostname ); if ( !hostinfo ) { perror( "gethostbyname" ); exit(1); } memcpy( nicaddr+6, hostinfo->h_addr_list[0], 4 ); printf( "\n\tstation-hostname: %s ", hostname ); printf( "\n\tprotocol-address: " ); for (int i = 0; i < 4; i++) { printf( "%d", nicaddr[6+i] ); if ( i < 3 ) printf( "." ); else printf( " " ); } printf( "\n\thardware-address: " ); for (int i = 0; i < 6; i++) { printf( "%02X", nicaddr[i] ); if ( i < 5 ) printf( ":" ); else printf( " " ); } printf( "\n\n" ); // the echo testing begins here unsigned char query[ 4096 ] = {0}, *q = query; unsigned char reply[ 4096 ] = {0}, *r = reply; int frames = 0, errors = 0, oktotal = 0; for (int i = 0; i < N_FRAMES; i++) { int pktlen = rand()%1514; // random frame-size if ( pktlen < 64 ) pktlen = 64; // cannot be below 64 // create ethernet packet having our protocol-type memset( query+0, 0xFF, 6 ); // dest'n hw-address memcpy( query+6, nicaddr, 6 ); // source hw-address *(short*)(query+12) = htons( MY_TYPE ); // Type/Len // fill remainder of packet with random data-bytes for (int j = 16; j < pktlen; j++) query[j] = (unsigned char)rand(); // transmit the packet containing our random data int txbytes = write( nic, query, pktlen ); if ( txbytes < 0 ) { perror( "write" ); exit(1); } else ++frames; // count this transmission // receive packets until our protocol is recognized int rxbytes; for(;;) { rxbytes = read( nic, reply, sizeof( reply ) ); if ( rxbytes < 0 ) { perror( "read" ); exit(1); } if ( *(short*)(reply+12) == htons( MY_TYPE ) ) break; } // check whether reply-data matches query-data int match = ( txbytes == rxbytes ) ? 0 : -1; for (int j = 12; j < txbytes; j++) match |= ( query[j] ^ reply[j] )&0xFF; if ( match == 0 ) oktotal += txbytes; else ++errors; // count this error-packet // verbose reporting of individual echo-transaction printf( "#%-5d ", i+1 ); printf( "sent %d bytes ", txbytes ); printf( "read %d bytes ", rxbytes ); printf( "match=%d \n", match ); } // report the testing statistics printf( "\ncorrectly echoed %d bytes \n", oktotal ); printf( "correctly echoed %d packets \n", frames - errors ); printf( "incorrectly echoed %d packets \n\n", errors ); }