📄 nettest.c
字号:
#ifndef lintstatic char sccsid[] = "@(#)nettest.c 1.1 7/30/92 Copyright 1985 Sun Micro";#endif/* * Copyright (c) 1987 by Sun Microsystems, Inc. *//****************************************************************************** program : nettest.c Original Author : Frank Jones 1st Revision : SCHEUFELE, SUSAN susans@freedonia Complete clean up and rewrite of original code including 4.0 bug fixes. 2nd Revision : MASSOUDI, ROBERT A. bobm@thesius 2-10-88, Structural change into more readable blocks, Complete documentation and comments, bug fix, enhancements, and mods to accommodate other network devices as well (i.e. FDDI) 3rd Revision : Anantha N. Srirama anantha@ravi Total rewrite, I ripped the guts out of this program. The present version bears very little resemblance to the previous version, tons of useless stuff has been thrown away with vengeance. enet.c bug fix and enhancements made in this Version : ------------------------------------------------------ The code now supports FDDI and with minor alteration it should be able to support any other network interface device that adheres to the IPC and the established inet standards. BUG: The nettest software could not handle multiple network interfaces configured with different IP addresses (due to the "gethostname" and "gethostbyname" scheme), so if you were to configure a system with ie0 having one IP address and ie1 having a different IP address and so forth, the test would pass ie1 even if you unplugged the cable from ie1 (due to host local loopback). The test would fetch the wrong IP address (ie0) as its own and compare it against the received packet and would mark that as a valid packet (not as the host local loopback), and consequently pass the diagnostics. FIX : use a structure that allows storing of the name,the IP address and the broadcast address of each interface. Thus when you are testing a network the correct IP address is used to check for host local loopback condition. The storing of name allows the test to directly specify which network interface it is testing by its "if" name rather than net0 net1..and so on. This enhancement allows the user' to see the actual "if" name "ie0", "fddi0", etc. What is this code supposed to do ? well, I'm glad you asked ------------------------------------------------------------- The net test uses a raw socket with the ICMP protocol (Internet Control Protocol), specifically with the message types ICMP_ECHO and ICMP_ECHOREPLY. The net test broadcasts an ICMP_ECHO message on a valid network interface, and expects to hear a reply from some other host besides itself (localhost loopback). Due to the low level nature of ICMP protocol (access through sockets, no routing), only ONE net test can run on a system at one time. Running more than one net test at a time has unpredictable results. The test uses the SICGIFCONF, SIOCGIFFLAGS, and SIOCGIFBRDADDR ioctls to obtain the network interface configuration, receive the "interface flags" to see if the net is up or down, and obtain the broadcast address. The test assumes a broadcast network, not a point to point network. The net_diag test ignores "me0" network, if it exists for one or more IPC boards. The nettest test formats with specific data and then sends out an ICMP_ECHO message to INADDR_ANY (any valid address) on a specified network interface, and then waits for replies for a given time period. The replies are counted and checked to make sure they have the same data. Since we want to test the network hardware, a reply from the localhost is not counted. It is considered to be an error if there are no replies from any other hosts. Enhancements : -------------- The test now spits out the actual network interface device names used in the configuration rather than "enet0", "enet1", ..etc, in all of its messages. In the debug mode it also prints out the names of all of the network devices found in addition to the number of devices found. ADDITIONS: ---------- 1) The test can now do a single test on a single (specified) network interface or conduct a test on all available and valid network interfaces. Supports onboard ie, le, second ie or le, fddi, and token ring (can also support multiple network interfaces). 2) Initially, the internal driver error counts are checked. After running the broadcastnets test, the spray test, the udp transmit test, and the fddi test (if applicable), the internal driver error counts are checked again. If the difference between the initial and final error counts is greater than zero, a warning message is issued. 3) If the interface is fddi, then the fddi interface is tested before it goes through the broadcasting, the spray test, and the udp transmit test. In a ring topology, receive timeouts are often seen (from broadcasting or perhaps the test machines are tied up with other tests). (Reason for running the fddi_test before the broadcasting, spray, and udp test: if it passes and the broadcasting fails due to time out, we can at least assume that the nit/sif level is functional.) Fddi_test tests the interface through the nit/sif (fddi) level; therefore, it does not need to go through the host. communication through the hosts ____________________________ | | -------- -------- | host | | host | -------- -------- | | | | -------- -------- | fddi | <-------------> | fddi | -------- -------- 4) To stress test the standard transmit and receive paths, the nettest_spray and nettest_udp functions have been added. Upon completion, these two functions print statistical information (ie.transmit rates). Using RPC, nettest_spray sends a one-way stream of packets to the first valid host that replies from the net test broadcasts (an ICMP_ECHO message on a valid network interface). A warning is issued if the percentage of packets dropped returned by nettest_spray exceeds 80%. In the UDP test, no connection to the remote host/port, is made, UDP "datagrams" are sent directly. 5) This test records the following statistical information: The accumulated number of packets transferred The accumulated number of bits transferred The accumulated number of bytes/bits in error The accumulated number of packets in error The accumulated byte/bit error rate Usage: nettest [net_if_name{0-n}|allnets] [D] [W] [S] [C] [v] [s] [u] [p] [r] [q] [d] [t] Routine specific arguments [defaults]: [net_<IF_NAME><#> | allnets] = net interface board to test [net_ie0] or all available net interface board [D=] = time delay for the spray test, default is 0 [W] = flag to print warning messages, default is FALSE [S] = flag to enable/disable the spray test, default is enabled [C=] = number of packets for the spray test, default is 10000******************************************************************************* INCLUDE FILES******************************************************************************/#include <sys/types.h>#include <stdio.h>#include <errno.h>#include <ctype.h>#include <signal.h>#include <rpc/rpc.h>#include <sys/socket.h>#include <netdb.h>#include <sys/time.h>#include <sys/wait.h>#include <sys/file.h>#include <sys/ioctl.h>#include <sys/param.h>/****************************************************************************** GLOBAL CONSTANTS INCLUDE FILES******************************************************************************/#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/ip.h>#include <netinet/ip_icmp.h>#include <arpa/inet.h>#include <net/if.h>#include "sdrtns.h"#include "../../../lib/include/libonline.h"#include "nettest.h"/****************************************************************************** Global Variable Definitions******************************************************************************/struct avail_inet_if_struct valid_if[MAXDEVNUM];struct timeval sel_time = {1, 0};struct timeval current_time[4]; /* Total of 4 loops per nettest */char device_netname[30];char *device = device_netname;int id_pid;int seqno = 0;int packetsize = PACKETSIZE;int test_flag = NO_IF;int spray_delay = 0; /* default=0 for delay option in spray test */int spray_cnt = 10000; /* default=10000 for count option in spray test */int print_warning = FALSE; /* default=FALSE for print warning messages option */int spray_test = TRUE; /* default=TRUE for spray test option */int tr_driver_error = TRUE; char *test_usage_msg = "[net_<IF_NAME>|allnets] [D=<delay for spray test>] [W] [S] \n [C=<number of packets to spray>]\n";char *pr_type ();u_short in_cksum ();/****************************************************************************** External Variable Definitions******************************************************************************/extern float nettest_spray();extern int udp_test();extern void fddi_test();extern char *inet_ntoa ();/*************************************************************************** Process nettest specific command line arguments.****************************************************************************/intprocess_net_args(argv, arrcount)char *argv[];int arrcount;{ if (strcmp (argv[arrcount], "allnets") == 0) { test_flag = ALL_IF; } else if (strncmp (argv[arrcount], "net_", 4) == 0) { test_flag = SPECIFIC_IF; (void) strcpy (device, (argv[arrcount] + 4)); device_name = device; } else if (strncmp (argv[arrcount], "D=", 2) == 0) { spray_delay = atoi(&argv[arrcount][2]); } else if (strncmp (argv[arrcount], "W", 1) == 0) { print_warning = TRUE; } else if (strncmp (argv[arrcount], "C=", 2) == 0) { spray_cnt = atoi(&argv[arrcount][2]); } else if (strncmp (argv[arrcount], "S", 1) == 0) { spray_test = FALSE; } else { return (FALSE); } return (TRUE);}introutine_usage(){ send_message(0, CONSOLE, "\n\Routine specific arguments [defaults]:\n\n\\tnet_<IF_NAME><#> = net interface board to test, e.g. net_ie0\n\\tallnets = all available net interface board\n\\tD = time delay for the spray test, default is 0\n\\tW = flag to allow printing of warning messages,\n\\t\t default is FALSE\n\\tS = flag to disable the spray test of nettest\n\\tC = number of packets to send in spray test,\n\ \t default is 10000\n");}/****************************************************************************** select_nets_to_test Initialize test flags to DONT_TEST for all available boards. Then check to see if no device is specified and set default to test the first IF board in the list. Otherwise, if ALL_IF was specified then we set them all to test, and if the SPECIFIC_IF was specified and if we get a match then we will set the test flag for that specific flag. If none of the above conditions are met this module returns a FAIL code.******************************************************************************/int select_nets_to_test (valid_if_p, device, net_boards)struct avail_inet_if_struct *valid_if_p;char *device;int net_boards;{ int not_found; int i; func_name = "select_nets_to_test"; TRACE_IN not_found = net_boards; for (i = 0; i < net_boards; i++) { valid_if[i].test_flag = DONT_TEST; } for (i = 0; ((i < net_boards) && not_found); i++) { switch (test_flag) { case SPECIFIC_IF: if (strcmp (valid_if_p[i].dev_name, device) == 0) { valid_if_p[i].test_flag = TEST; not_found = 0; } break; case ALL_IF: valid_if_p[i].test_flag = TEST; not_found--; break; case NO_IF: default: valid_if_p[i].test_flag = TEST; not_found = 0; break; } } TRACE_OUT return (not_found);}/****************************************************************************** get_nets This function calls the function 'getbroadcastnets' to figure out what are the available nets in the system. If no broadcast nets are found, then the program is exited with an error message/status.******************************************************************************/int get_nets (device)char *device;{ int net_boards, i, state; char inbuf[UDPMSGSIZE]; func_name = "get_nets"; TRACE_IN net_boards = getbroadcastnets (valid_if, inbuf); if (net_boards < 1) { send_message (-NO_NETWORKS, FATAL, "%s no networks", test_name); } if (select_nets_to_test (valid_if, device, net_boards)) { send_message (-NO_SELECTED_NETWORK, ERROR, "%s network to test (%s) not found", test_name, device); } TRACE_OUT return (net_boards);}/****************************************************************************** make_sock This function opens a socket and binds it to the network address used. It returns the socket that is opened to the calling routine. The program is exited with an error code if it cannot open or bind the socket.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -