📄 nettest.c
字号:
TRACE_IN if ((replying_host = gethostbyaddr (&from.sin_addr.s_addr, sizeof (struct in_addr),AF_INET)) == NULL) { send_message(-NO_HOST_NAME, ERROR,"%s: Invalid broadcast reply address.", func_name ); } if (strcmp(replying_host->h_name, old_host_that_failed) == 0) { TRACE_OUT return(0); } if (spray_test) { if ((exec_by_sundiag) && (spray_delay >= 1)) { sundiag_and_delay = TRUE; } /* Large spray */ if ((packets_dropped = nettest_spray(from, (sundiag_and_delay ? spray_cnt_large : spray_cnt), 1502, spray_delay)) < 0) { send_message(0, DEBUG, "%s: Large spray failed.", func_name); strcpy(old_host_that_failed, replying_host->h_name); TRACE_OUT return(0); } if ((print_warning) && (packets_dropped > 80)) { send_message(0, WARNING, "SPRAY WARNING: more than 80 percent of packets dropped"); } /* Small spray */ if (!quick_test) { if ((packets_dropped = nettest_spray(from, (sundiag_and_delay ? spray_cnt_small : spray_cnt), 86, spray_delay)) < 0) { send_message(0, DEBUG, "%s: Small spray failed.", func_name); strcpy(old_host_that_failed, replying_host->h_name); TRACE_OUT return(0); } if ((print_warning) && (packets_dropped > 80)) { send_message(0, WARNING, "SPRAY WARNING: more than 80 percent of packets dropped"); } } } /* * Test UDP. If UDP fails for reasons other than transmitting packets, * the whole program will exit. udp_test return 0 if it fails. */ if ( (udp_test(test_net, from)) == 0) { test_succeeded = 0; } else { test_succeeded = 1; } TRACE_OUT return(test_succeeded);} /* test_reply *//****************************************************************************** ping_receive This function receives a packet from the socket/network when the select call returns a ready. Otherwise a timeout is indicated and it returns with the number of packets it received. Each received packet is checked by the function 'check_reply' which stops checking in case of errors/mismatches. If the received packet is valid and it's not a reply from our own machine, then spray 10,000 packets of 86 bytes and 1502 bytes each to the first host that replies from the net test broadcasts. A warning is issued if the percentage of packets dropped exceeds 80%. Then the function udp transmit test is performed. Like nettest_spray, nettest_udp shall only be called once for each interface. Should the number of broadcast replies = 0 or no "valid" host (broadcast reply) is found to test spray and udp, the program exits with the appropriate error message. ******************************************************************************/void ping_receive (sock, my_addr, device, test_net)int sock;struct in_addr *my_addr;char *device;int test_net;{ struct sockaddr_in from; /* address of the responding node */ u_char pack[MAXPACKLEN]; /* IP packet received */ int broadcast_replies = 0; /* number of replies from broadcast */ int valid_reply = 0; int cc; /* length of received packet */ int from_len; static int tested = 0; static int broadcast_retry=0; static int succeeded_broadcast_retry = 0; char command[80]; /* netstat command */ FILE *fp_init, *fp_error; static struct hostent* hp; /* reply packet's machine name for spray */ func_name = "ping_receive"; TRACE_IN while (do_select(sock, READ_SELECT, (broadcast_replies ? WAIT_TIME:(15 * WAIT_TIME))) != 0) { /* * if the socket is not ready for a read (i.e. the socket is * empty) and time out has occurred, no data written to socket * (no new packets) we return the number of broadcast_replies. */ bzero ((char *) &from, sizeof (from)); from_len = sizeof (from); if ((cc = recvfrom (sock, (char *) pack, sizeof (pack), 0, (struct sockaddr *) &from, (int *) &from_len)) < 0) { send_message (0, ERROR, "recvfrm %s", errmsg (errno)); continue; } if (! (valid_reply = check_reply ((char *) pack, cc, &from, device))) continue; /* if reply not from our own machine */ if (from.sin_addr.s_addr != my_addr->s_addr) { /* must pass two sprays and one udp test */ if (!tested) { if ((hp = gethostbyaddr (&from.sin_addr.s_addr, sizeof (struct in_addr),AF_INET)) != NULL) { send_message (0, DEBUG, "%s: 'from' REPLY (addr: %s) (host: %s)", "ping_receive", inet_ntoa(from.sin_addr), hp->h_name); tested = test_reply(from, test_net); } } broadcast_replies++; send_message (0, DEBUG, "%s: reply from (addr: %x) self (addr: %x)", "ping_receive", from.sin_addr.s_addr, my_addr->s_addr); } else { send_message (0, DEBUG, "%s: received reply from self : %x", "ping_receive", from.sin_addr.s_addr); } } /* while */ send_message(0, DEBUG, "%s: rcv timeout, %d replies to broadcast", "ping_receive", broadcast_replies); /* * have gone through all hosts that replied but have not * sprayed any host */ if (tested == 0) { if (strncmp (device, "le", 2) == 0) { if ((!succeeded_broadcast_retry) && (broadcast_retry < 3)) { broadcast_retry++; send_message(0, DEBUG, "Retrying broadcast (%d).", broadcast_retry); run_tests(test_net, device); if (tested) succeeded_broadcast_retry = TRUE; } else if (!succeeded_broadcast_retry) { /* after 3 retries, and still have error * print out netstat status to /tmp/sundiag_netstat_info * upon error and verbose mode */ if (verbose) { if ((fp_init=fopen("/tmp/sundiag_init_netstat","r"))!=NULL) { sprintf (command, "/bin/mv /tmp/sundiag_init_netstat /tmp/sundiag_netstat_info"); system (command); if (fp_init != NULL) fclose (fp_init); } else { send_message (-FILE_OPEN_ERROR, ERROR, "Cannot open /tmp/sundiag_init_netstat"); } if ((fp_error = fopen ("/tmp/sundiag_netstat_info", "a")) != NULL) { fprintf(fp_error,"\nNetstat after running nettest.\n"); fseek (fp_error, 0, 2); /* get to the end of file */ sprintf(command,"netstat>> /tmp/sundiag_netstat_info"); system (command); if (fp_error != NULL) fclose (fp_error); } else { send_message (-FILE_OPEN_ERROR, ERROR, "Cannot open /tmp/sundiag_netstat_info"); } } /* if verbose */ } } if (!succeeded_broadcast_retry) { if (broadcast_replies == 0) { if (strncmp(device, "tr", 2) == 0) { send_message (0, VERBOSE, "%s RCV timeout on %s, no replies to broadcast.", test_name, device); check_status(device, 1, print_warning, &tr_driver_error); if (!tr_driver_error) send_message (-RECEIVE_BC_TIMEOUT, ERROR, "%s RCV timeout on %s, no replies to broadcast. No error flags set by driver.", test_name, device); } else send_message (-RECEIVE_BC_TIMEOUT, ERROR, "%s RCV timeout on %s, no replies to broadcast", test_name, device); } else { if (strncmp(device, "tr", 2) == 0) { send_message(0, VERBOSE, "Tried %d replies from broadcast. No valid host found to test spray and udp.", broadcast_replies); check_status(device, 1, print_warning, &tr_driver_error); if (!tr_driver_error) send_message(-RECEIVE_BC_TIMEOUT, ERROR, "Tried %d replies from broadcast. No valid host found to test spray and udp for %s. No error flags set by driver.", broadcast_replies, device); } else send_message(-RECEIVE_BC_TIMEOUT, ERROR, "Tried %d replies from broadcast. No valid host found to test spray and udp for %s.", broadcast_replies, device); } } } TRACE_OUT} /* ping_receive *//****************************************************************************** start_test Open a socket to the 'test_net', send and receive ICMP packets. For a successful run we must receive more than 0 packets back.******************************************************************************/void start_test (test_net, my_addr, device)int test_net;struct in_addr *my_addr;char *device;{ static struct sockaddr_in to; int sock; /* * construct an internet address using the specified nth net valid INTERNET * broadcast addresses stored in the addrs table previously */ func_name = "start_test"; TRACE_IN /* if device == fddi, run fddi_test *//************* (NOTE: this is commented out for Sundiag2.1/2.2 release) if ((strncmp (device, "fddi", 4)) == 0) { fddi_test(); send_message (0, INFO, "Passed fddi (ent) test."); }**************/ bzero ((char *) &to, sizeof (to)); to.sin_family = AF_INET; to.sin_port = 0; to.sin_addr = valid_if[test_net].broad_addrs; sock = make_sock (test_net, SOCK_RAW); id_pid = getpid () & 0xFFFF; send_message (0, DEBUG, "%s: 'To' socket info used for ICMP communication", func_name); send_message (0, DEBUG, "Family Type=0x%x, port=0x%x, Broadcast INET addr=%s", to.sin_family, to.sin_port, inet_ntoa (to.sin_addr)); ping_send (sock, &to, device); ping_receive (sock, my_addr, device, test_net); (void) close (sock); TRACE_OUT}/****************************************************************************** run_tests This function tests the network 'test_net'.******************************************************************************/run_tests (test_net, device)int test_net;char *device;{ struct in_addr my_addr, *dummy; func_name = "run_tests"; TRACE_IN dummy = (struct in_addr *) &valid_if[test_net].my_addr; my_addr = *dummy; start_test (test_net, &my_addr, device); TRACE_OUT}/****************************************************************************** main This program sets up and runs nettest on different nets. It calls the function 'test_init' to extract the interface name. Then it gets all the boards in the system which can be tested and runs the the test on each interface.******************************************************************************/int main (argc, argv)int argc;char *argv[];{ struct net_stat ifdev_net_stat; /* net stats for current IF under test */ int i; int total_boards; extern int process_net_args(); extern int routine_usage(); versionid = "1.1"; /* SCCS version id */ test_init(argc, argv, process_net_args, routine_usage, test_usage_msg); total_boards = get_nets (device); stat_start_up (); for (i = 0; i < total_boards; i++) { if (valid_if[i].test_flag == DONT_TEST) { continue; } (void) strcpy (device, valid_if[i].dev_name); device_name = device; send_message (0, VERBOSE,"Starting nettest on network = %s", device); init_net_stat (device); check_status(device, 0, print_warning, &tr_driver_error); run_tests (i, device); check_point_status (device, &ifdev_net_stat); print_net_stats (&ifdev_net_stat); check_status(device, 1, print_warning, &tr_driver_error); } test_end();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -