📄 pinglib.c
字号:
/* pingLib.c - Packet InterNet Groper (PING) library *//* Copyright 1994 - 2002 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01r,22apr02,rae Note that PING_OPT_DONTROUTE affects pinging localhost (SPR #72917), other minor changes01q,11mar02,rae Print stats when task killed (SPR #73570)01p,08jan02,rae Don't print error messages when PING_OPT_SILENT (SPR #69537)01o,15oct01,rae merge from truestack ver 01q, base 01k (SPRs 67440, 30151, 66062, etc.)01n,30oct00,gnn Added PING_OPT_NOHOST flag to deal with SPR 2276601m,08nov99,pul T2 cumulative patch 201l,22sep99,cno corrected ping error for pingRxPrint() (SPR22571)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 whenINCLUDE_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 "hostLib.h"#include "ioLib.h"#include "tickLib.h"#include "taskHookLib.h"#include "sysLib.h"#include "vxLib.h"#include "netinet/in_systm.h"#include "netinet/ip.h"#include "netinet/ip_icmp.h"#include "netinet/icmp_var.h"#include "pingLib.h"#include "errnoLib.h"#include "kernelLib.h"#ifdef VIRTUAL_STACK#include "netinet/vsLib.h"#endif /* VIRTUAL_STACK *//* 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 *//* static forward declarations */LOCAL STATUS pingRxPrint (PING_STAT *pPS, int len, struct sockaddr_in *from, ulong_t now);LOCAL void pingFinish (WIND_TCB *);/********************************************************************************* pingLibInit - initialize the ping() utility** This routine allocates resources used by the ping() utility.* It is called automatically when INCLUDE_PING is defined.** RETURNS:* OK*/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. This also prevents pinging* local addresses (i.e. the IP address of the host itself). The 127.x.x.x * addresses will still work however.* .iP PING_OPT_NOHOST* Suppress host lookup. This is useful when you have the DNS resolver* but the DNS server is down and not returning host names.* .iP PING_OPT_DEBUG* Enables debug output.* .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 txInterval; /* packet interval in ticks */ STATUS status = ERROR; /* return status */ struct fd_set readFd; struct timeval pingTmo; ulong_t now; int sel;#ifndef ALT_PING_PAR_SEMANTIC if (numPackets < 0) /* numPackets positive ? */ { errno = EINVAL; return (ERROR); }#else /* alternative parameter semantic for numPackets */ if (numPackets < -1) /* numPackets positive or -1 ? */ { errno = EINVAL; return (ERROR); } if (numPackets == 0) numPackets = 3; /* don't do infinite by default */ if (numPackets == -1) numPackets = 0; /* infinite */#endif /* ALT_PING_PAR_SEMANTIC */ /* allocate size for ping statistics/info structure */ if ((pPS = (PING_STAT *) calloc (1, sizeof (PING_STAT))) == NULL) return (ERROR);#ifdef VIRTUAL_STACK virtualStackIdCheck(); pPS->vsid = myStackNum;#endif /* VIRTUAL_STACK */ semTake (pingSem, WAIT_FOREVER); /* get access to list */ pPS->statNext = pingHead; /* push session onto list */ if (pingHead == NULL && !(options & PING_OPT_SILENT)) if (taskDeleteHookAdd ((FUNCPTR) pingFinish) == ERROR) { free ((char *) pPS); semGive (pingSem); /* give up access to list */ if (options & PING_OPT_DEBUG) printf ("ping: unable to add task Delete hook\n"); 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 */ txInterval = _pingTxInterval * pPS->clkTick;/* init interval value */ pingTmo.tv_sec = _pingTxTmo; pingTmo.tv_usec = 0; 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 */ /* initialize the socket address struct */ to.sin_family = AF_INET; if ((to.sin_addr.s_addr = inet_addr (host)) == (u_long) ERROR) { if ((to.sin_addr.s_addr = hostGetByName (host)) == (u_long) 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 = max (_pingTxLen, PING_MINPACKET); /* sanity check global */ _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); if (options & PING_OPT_DONTROUTE) /* disallow packet routing ? */ if (setsockopt (pPS->pingFd, SOL_SOCKET, SO_DONTROUTE, (char *) &ix, sizeof (ix)) == ERROR)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -