📄 pinglib.c
字号:
/* pingLib.c - Packet InterNet Grouper (PING) library *//* Copyright 1994-1997 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01k,14mar99,jdi doc: removed refs to config.h and/or configAll.h (SPR 25663).01j,12mar99,p_m Fixed SPR 8742 by documentating ping() configuration global variables.01i,05feb99,dgp document errno values01h,17mar98,jmb merge jmb patch of 04apr97 from HPSIM: corrected creation/deletion of task delete hook.01g,30oct97,cth changed stack size of tPingTxn from 3000 to 6000 (SPR 8222).01f,26aug97,spm removed compiler warnings (SPR #7866)01e,30sep96,spm corrected ping error for little-endian machines (SPR #4235)01d,13mar95,dzb changed to use free() instead of cfree() (SPR #4113)01c,24jan95,jdi doc tweaks01b,10nov94,rhp minor edits to man pages01a,25oct94,dzb written*//*DESCRIPTIONThis library contains the ping() utility, which tests the reachabilityof a remote host.The routine ping() is typically called from the VxWorks shell to check thenetwork connection to another VxWorks target or to a UNIX host. ping()may also be used programmatically by applications that require such a test.The remote host must be running TCP/IP networking code that responds toICMP echo request packets. The ping() routine is re-entrant, thus maybe called by many tasks concurrently.The routine pingLibInit() initializes the ping() utility and allocatesresources used by this library. It is called automatically whenthe configuration macro INCLUDE_PING is defined.*//* includes */#include "vxWorks.h"#include "string.h"#include "stdioLib.h"#include "wdLib.h"#include "netLib.h"#include "sockLib.h"#include "inetLib.h"#include "semLib.h"#include "taskLib.h"#include "taskHookLib.h"#include "hostLib.h"#include "ioLib.h"#include "tickLib.h"#include "sysLib.h"#include "vxLib.h"#include "netinet/in_systm.h"#include "netinet/ip.h"#include "netinet/ip_icmp.h"#include "pingLib.h"/* defines */#define pingError(pPS) { pPS->flags |= PING_OPT_SILENT; goto release; }/* globals */int _pingTxLen = 64; /* size of icmp echo packet */int _pingTxInterval = PING_INTERVAL; /* packet interval in seconds */int _pingTxTmo = PING_TMO; /* packet timeout in seconds */extern int errno;/* locals */LOCAL PING_STAT * pingHead = NULL; /* ping list head */LOCAL SEM_ID pingSem = NULL; /* mutex for list access */LOCAL int pingSeq = 0; /* spawned task seq counter *//* static forward declarations */LOCAL void pingTx (PING_STAT *pPS, struct sockaddr *toAddr, int delay);LOCAL void pingRxPrint (PING_STAT *pPS, int len, struct sockaddr_in *from);LOCAL void pingTimeout (PING_STAT *pPS);LOCAL void pingFinish (WIND_TCB *pTcb);/********************************************************************************* pingLibInit - initialize the ping() utility** This routine allocates resources used by the ping() utility.* It must be called before ping() is used. It is called automatically* when the configuration macro INCLUDE_PING is defined.** RETURNS:* OK, or ERROR if the ping() utility could not be initialized.*/STATUS pingLibInit (void) { if (pingSem == NULL) /* already initialized ? */ { if ((pingSem = semMCreate (SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE)) == NULL) return (ERROR); } return (OK); }/********************************************************************************* ping - test that a remote host is reachable** This routine tests that a remote host is reachable by sending ICMP* echo request packets, and waiting for replies. It may called from* the VxWorks shell as follows:* .CS* -> ping "remoteSystem", 1, 0* .CE* where <remoteSystem> is either a host name that has been previously added* to the remote host table by a call to hostAdd(), or an Internet address in* dot notation (for example, "90.0.0.2").** The second parameter, <numPackets>, specifies the number of ICMP packets* to receive from the remote host. If <numPackets> is 1, this routine waits* for a single echo reply packet, and then prints a short message* indicating whether the remote host is reachable. For all other values* of <numPackets>, timing and sequence information is printed as echoed* packets are received. If <numPackets> is 0, this routine runs continuously.* * If no replies are received within a 5-second timeout period, the* routine exits. An ERROR status is returned if no echo replies* are received from the remote host.** The following flags may be given through the <options> parameter:* .iP PING_OPT_SILENT* Suppress output. This option is useful for applications that * use ping() programmatically to examine the return status.* .iP PING_OPT_DONTROUTE* Do not route packets past the local network.** .RS 4 4* \&NOTE: The following global variables can be set from the target shell* or Windsh to configure the ping() parameters:* .iP _pingTxLen * Size of the ICMP echo packet (default 64).* .iP _pingTxInterval* Packet interval in seconds (default 1 second).* .iP _pingTxTmo* Packet timeout in seconds (default 5 seconds).*.RE** RETURNS:* OK, or ERROR if the remote host is not reachable.** ERRNO: EINVAL, S_pingLib_NOT_INITIALIZED, S_pingLib_TIMEOUT**/STATUS ping ( char * host, /* host to ping */ int numPackets, /* number of packets to receive */ ulong_t options /* option flags */ ) { PING_STAT * pPS; /* current ping stat struct */ struct sockaddr_in to; /* addr of Tx packet */ struct sockaddr_in from; /* addr of Rx packet */ int fromlen = sizeof (from);/* size of Rx addr */ int ix = 1; /* bytes read */ int txPriority; /* priority of Tx task */ int txInterval; /* packet interval in ticks */ int txTmo; /* packet timeout in ticks */ int seq = pingSeq++; /* unique sequence number */ char tName [PING_TASK_NAME_LEN]; /* spawned names */ STATUS status = ERROR; /* return status */ if (pingSem == NULL) /* already initialized ? */ { errno = S_pingLib_NOT_INITIALIZED; return (ERROR); } if (numPackets < 0) /* numPackets positive ? */ { errno = EINVAL; return (ERROR); } /* allocate size for ping statistics/info structure */ if ((pPS = (PING_STAT *) calloc (1, sizeof (PING_STAT))) == NULL) return (ERROR); semTake (pingSem, WAIT_FOREVER); /* get access to list */ pPS->statNext = pingHead; /* push session onto list */ if (pingHead == NULL) if (taskDeleteHookAdd ((FUNCPTR) pingFinish) == ERROR) { free ((char *) pPS); semGive (pingSem); /* give up access to list */ return (ERROR); } pingHead = pPS; semGive (pingSem); /* give up access to list */ pPS->tMin = 999999999; /* init min rt time */ pPS->numPacket = numPackets; /* save num to send */ pPS->flags = options; /* save flags field */ pPS->clkTick = sysClkRateGet (); /* save sys clk rate */ taskPriorityGet (0, &txPriority); txPriority = min (255, txPriority + 1); /* Tx task 1 lower priority */ txInterval = _pingTxInterval * pPS->clkTick;/* init interval value */ txTmo = _pingTxTmo * pPS->clkTick; /* init timeout value */ pPS->pBufIcmp = (struct icmp *) pPS->bufTx; /* pointer to icmp header out */ pPS->pBufTime = (ulong_t *) (pPS->bufTx + 8);/* pointer to time out */ pPS->idRx = taskIdSelf (); /* get own task Id */ /* create sem for timing out a pended socket read */ if ((pPS->semIdTimeout = semBCreate (SEM_Q_FIFO, SEM_EMPTY)) == NULL) pingError (pPS); /* initialize the socket address struct */ to.sin_family = AF_INET; if ((to.sin_addr.s_addr = inet_addr (host)) == ERROR) { if ((to.sin_addr.s_addr = hostGetByName (host)) == ERROR) { if (!(options & PING_OPT_SILENT)) printf ("ping: unknown host %s\n", host); pingError (pPS); } inet_ntoa_b (to.sin_addr, pPS->toInetName); } strcpy (pPS->toHostName, host); /* save host name */ _pingTxLen = min (_pingTxLen, PING_MAXPACKET);/* sanity check global */ pPS->dataLen = _pingTxLen - 8; /* compute size of data */ /* open raw socket for ICMP communication */ if ((pPS->pingFd = socket (AF_INET, SOCK_RAW, ICMP_PROTO)) < 0) pingError (pPS); sprintf (tName, "tPingTmo%d", seq); /* assign unique task name */ if ((pPS->idTimeout = taskSpawn (tName, 0, 0, 3000, (FUNCPTR) pingTimeout, (int) pPS, 0,0,0,0,0,0,0,0,0)) == ERROR) pingError (pPS); if (options & PING_OPT_DONTROUTE) /* disallow packet routing ? */ if (setsockopt (pPS->pingFd, SOL_SOCKET, SO_DONTROUTE, (char *) &ix, sizeof (ix)) == ERROR) pingError (pPS); if (!(options & PING_OPT_SILENT) && pPS->numPacket != 1) { printf ("PING %s", pPS->toHostName); /* print out dest info */ if (pPS->toInetName[0]) printf (" (%s)", pPS->toInetName); printf (": %d data bytes\n", pPS->dataLen); } pPS->pBufIcmp->icmp_type = ICMP_ECHO; /* set up Tx buffer */ pPS->pBufIcmp->icmp_code = 0; pPS->pBufIcmp->icmp_id = pPS->idRx & 0xffff; for (ix = 4; ix < pPS->dataLen; ix++) /* skip 4 bytes for time */ pPS->bufTx [8 + ix] = ix; if ((pPS->wdTimeout = wdCreate()) == NULL) /* create timeout watchdog */ pingError (pPS); if ((wdStart (pPS->wdTimeout, txTmo, (FUNCPTR) semGive, (int) pPS->semIdTimeout)) == ERROR) /* start timeout watchdog */ pingError (pPS);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -