📄 pinglib.c
字号:
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; /* receive echo reply packets from remote host */ while (!pPS->numPacket || (pPS->numRx != pPS->numPacket)) { *pPS->pBufTime = tickGet (); /* load current tick count */ pPS->pBufIcmp->icmp_seq = pPS->numTx++; /* increment seq number */ pPS->pBufIcmp->icmp_cksum = 0; pPS->pBufIcmp->icmp_cksum = checksum ((u_short *) pPS->pBufIcmp, _pingTxLen); /* transmit ICMP packet */ if ((ix = sendto (pPS->pingFd, (char *) pPS->pBufIcmp, _pingTxLen, 0, (struct sockaddr *)&to, sizeof (struct sockaddr))) != _pingTxLen) if (pPS->flags & PING_OPT_DEBUG) printf ("ping: wrote %s %d chars, ret=%d\n", pPS->toHostName, _pingTxLen, ix); /* Update ICMP statistics for ECHO messages - this is not the best * place to put it since this shifts responsibility of updating ECHO * statistics to anyone writing an application that sends out ECHO * messages. However, this seems to be the only place to put it. */ #ifdef VIRTUAL_STACK _icmpstat.icps_outhist [ICMP_ECHO]++;#else icmpstat.icps_outhist [ICMP_ECHO]++;#endif /* VIRTUAL_STACK */check_fd_again: /* Wait for ICMP reply */ FD_ZERO(&readFd); FD_SET(pPS->pingFd, &readFd); sel = select (pPS->pingFd+1, &readFd, NULL, NULL, &pingTmo); if (sel == ERROR) { errno = errnoGet(); if (!(options & PING_OPT_SILENT)) printf ("ping: ERROR\n"); break; /* goto release */ } else if (sel == 0) { if (!(options & PING_OPT_SILENT)) printf ("ping: timeout\n"); errno = S_pingLib_TIMEOUT; /* timeout error */ break; /* goto release */ } if (!FD_ISSET(pPS->pingFd, &readFd)) goto check_fd_again; /* the fd is ready - FD_ISSET isn't needed */ if ((ix = recvfrom (pPS->pingFd, (char *) pPS->bufRx, PING_MAXPACKET, 0, (struct sockaddr *) &from, &fromlen)) == ERROR) { if (errno == EINTR) goto check_fd_again; break; /* goto release */ } now = tickGet(); if (pingRxPrint (pPS, ix, &from, now) == ERROR) goto check_fd_again; taskDelay (txInterval); } if (pPS->numRx > 0) status = OK; /* host is reachable */release: pingFinish (taskTcb (pPS->idRx)); return (status); }/********************************************************************************* pingRxPrint - print out information about a received packet** This routine prints out information about a received ICMP echo reply* packet. First, the packet is checked for minimum length and* correct message type and destination.** RETURNS:* N/A.*/LOCAL STATUS pingRxPrint ( PING_STAT * pPS, /* ping stats structure */ int len, /* Rx message length */ struct sockaddr_in *from, /* Rx message address */ ulong_t now ) { struct ip * ip = (struct ip *) pPS->bufRx; long * lp = (long *) pPS->bufRx; struct icmp * icp; int ix; int hlen; int triptime; char fromHostName [MAXHOSTNAMELEN + 1]; char fromInetName [INET_ADDR_LEN]; /* convert address notation */ inet_ntoa_b (from->sin_addr, fromInetName); /* Do we lookup hosts or not? */ if (pPS->flags & PING_OPT_NOHOST) *fromHostName = EOS; else { if ((hostGetByAddr (from->sin_addr.s_addr, fromHostName)) == ERROR) *fromHostName = EOS; /* hostname not found */ } hlen = ip->ip_hl << 2; if (len < hlen + ICMP_MINLEN) /* at least min length ? */ { if (pPS->flags & PING_OPT_DEBUG) printf ("packet too short (%d bytes) from %s\n", len, fromInetName); return (ERROR); } len -= hlen; /* strip IP header */ icp = (struct icmp *) (pPS->bufRx + hlen); if (icp->icmp_type != ICMP_ECHOREPLY) /* right message ? */ { if (pPS->flags & PING_OPT_DEBUG) /* debug odd message */ { if (*fromHostName != (char)NULL) printf ("%d bytes from %s (%s): ", len, fromHostName, fromInetName); else printf ("%d bytes from %s: ", len, fromInetName); icp->icmp_type = min (icp->icmp_type, ICMP_TYPENUM); printf ("icmp_type=%d\n", icp->icmp_type); for(ix = 0; ix < 12; ix++) printf ("x%2.2lx: x%8.8lx\n", (ULONG)(ix * sizeof (long)), (ULONG)*lp++); printf ("icmp_code=%d\n", icp->icmp_code); } return (ERROR); } /* check if the received reply is ours. */ if (icp->icmp_id != (pPS->idRx & 0xffff)) { return (ERROR); /* wasn't our ECHO */ } /* print out Rx packet stats */ if (!(pPS->flags & PING_OPT_SILENT) && pPS->numPacket != 1) { if (*fromHostName != (char)NULL) printf ("%d bytes from %s (%s): ", len, fromHostName, fromInetName); else printf ("%d bytes from %s: ", len, fromInetName); printf ("icmp_seq=%d. ", icp->icmp_seq); triptime = (now - *((ulong_t *) icp->icmp_data)) * (1000 / pPS->clkTick); printf ("time=%d. ms\n", triptime); pPS->tSum += triptime; pPS->tMin = min (pPS->tMin, triptime); pPS->tMax = max (pPS->tMax, triptime); } pPS->numRx++; return (OK); }/********************************************************************************* pingFinish - return all allocated resources and print out final statistics** This routine returns all resources allocated for the ping session, and* prints out a stats summary.** The ping session is located in the session list (pingHead) by searching* the ping stats structure for the receiver task ID. This is necessary* because this routine is passed a pointer to the task control block, and does* not have ready access to the ping stats structure itself. This accomodates* the use of task delete hooks as a means of calling this routine.** RETURNS:* N/A.*/LOCAL void pingFinish ( WIND_TCB * pTcb /* pointer to task control block */ ) { PING_STAT * pPS; /* ping stats structure */ PING_STAT ** ppPrev; /* pointer to prev statNext */ semTake (pingSem, WAIT_FOREVER); /* get list access */ ppPrev = &pingHead; for (pPS = pingHead; (pPS != NULL) && (taskTcb (pPS->idRx) != pTcb); pPS = pPS->statNext) /* find session in list */ ppPrev = &pPS->statNext; if (pPS == NULL) /* session found ? */ { semGive (pingSem); /* give up list access */ return; } *ppPrev = pPS->statNext; /* pop session off list */ if (pingHead == NULL) (void) taskDeleteHookDelete ((FUNCPTR) pingFinish); semGive (pingSem); /* give up list access */ /* return all allocated/created resources */#ifdef VIRTUAL_STACK if (!(pPS->flags & PING_OPT_SILENT) && virtualStackNumTaskIdSet(pPS->vsid) == ERROR) { printf("pingFinish: invalid virtual stack id\n"); return; }#endif /* VIRTUAL_STACK */ if (pPS->pingFd) (void) close (pPS->pingFd); if (!(pPS->flags & PING_OPT_SILENT)) /* print final report ? */ { if (pPS->numRx) /* received at least one ? */ { if (pPS->numPacket != 1) /* full report */ { printf ("----%s PING Statistics----\n", pPS->toHostName); printf ("%d packets transmitted, ", pPS->numTx); printf ("%d packets received, ", pPS->numRx); if (pPS->numTx) printf ("%d%% packet loss", ((pPS->numTx - pPS->numRx) * 100) / pPS->numTx); printf ("\n"); if (pPS->numRx) printf ("round-trip (ms) min/avg/max = %d/%d/%d\n", pPS->tMin, pPS->tSum / pPS->numRx, pPS->tMax); } else /* short report */ printf ("%s is alive\n", pPS->toHostName); } else printf ("no answer from %s\n", pPS->toHostName); } free ((char *)pPS); /* free stats memory space */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -