-
- (void)gettimeofday(&now,(struct timezone *)NULL);
- tvsub(&now, &p->last_ping_sent);
-
- if(now.tv_sec > p->ping_interval)
- {
- /* Time to send ping */
-
- icp = (struct icmphdr *)outpack;
- icp->icmp_type = ICMP_ECHO;
- icp->icmp_code = 0;
- icp->icmp_cksum = 0;
- icp->icmp_seq = p->socket;
- icp->icmp_id = ident;
-
- if(isVerbose)
- log(LOG_INFO,"Sending ICMP packet to %s.",p->name);
-
- (void)gettimeofday((struct timeval *)&outpack[8],
- (struct timezone *)NULL);
-
- cc = DEFDATALEN + 8; /* skips ICMP portion */
-
- /* compute ICMP checksum here */
- icp->icmp_cksum = in_cksum((u_short *)icp, cc);
-
- i = sendto(p->socket, (char *)outpack, cc, 0, (const struct sockaddr *)(&p->dest),
- sizeof(struct sockaddr));
-
- (void)gettimeofday(&p->last_ping_sent,
- (struct timezone *)NULL);
-
- if(i<0 || i!=cc)
- {
- if(i<0)
- log(LOG_WARNING,"Sending ICMP packet to %s failed.",p->name);
- }
- p->sentpackets++;
+ }
+
+ if (elapsed_time.tv_sec > host->ping_interval) {
+ if (verbose) printf("INFO: Sending ICMP packet to %s.\n", host->name);
+
+ icmp_packet = (struct icmp *) packet;
+ icmp_packet->icmp_type = ICMP_ECHO;
+ icmp_packet->icmp_code = 0;
+ icmp_packet->icmp_cksum = 0;
+ icmp_packet->icmp_seq = host->socket;
+ icmp_packet->icmp_id = getpid() & 0xFFFF;
+
+ /* Write a timestamp struct in the packet's data segment for use in calculating travel times. */
+ gettimeofday((struct timeval *) &packet[ICMP_ECHO_HEADER_BYTES], NULL);
+
+ icmp_packet->icmp_cksum = checksum((uint16_t *) packet);
+
+ size_t bytes_sent = sendto(host->socket, packet, ICMP_ECHO_PACKET_BYTES, 0,
+ (const struct sockaddr *) &host->dest,
+ sizeof(struct sockaddr));
+
+ if (bytes_sent == ICMP_ECHO_PACKET_BYTES) {
+ gettimeofday(&host->last_ping_sent, NULL);
+ } else {
+ fprintf(stderr, "WARN: Failed sending ICMP packet to %s.\n", host->name);
+ }
+ }
+ host = host->next;
+ }
+
+ signal(SIGALRM, pinger);
+ alarm(TIMER_RESOLUTION);
+}
+
+void
+read_icmp_data(struct host_entry * host)
+{
+ struct timeval now;
+ gettimeofday(&now, NULL);
+
+ struct sockaddr_in from;
+ socklen_t fromlen = sizeof(from);
+ int bytes;
+ unsigned char packet[IP_PACKET_MAX_BYTES]; /* Use char so this can be aliased later. */
+ if ((bytes = recvfrom(host->socket, packet, sizeof(packet), 0, (struct sockaddr *) &from, &fromlen)) < 0) {
+ if (errno != EINTR) fprintf(stderr, "WARN: Error reading ICMP data from %s.\n", host->name);
+ return;
+ }
+
+ struct ip * ip = (struct ip *) packet;
+ int iphdrlen = ip->ip_hl << 2;
+ struct icmp * icmp = (struct icmp *) (packet + iphdrlen);
+
+ if (bytes < iphdrlen + ICMP_MINLEN) {
+ fprintf(stderr, "WARN: Received short packet from %s.\n", host->name);
+ return;
+ }
+
+ if (icmp->icmp_type == ICMP_ECHOREPLY && icmp->icmp_id == (getpid() & 0xFFFF) && icmp->icmp_seq == host->socket) {
+ memcpy(&host->last_ping_received, &now, sizeof(now));
+ if (verbose) printf("INFO: Got ICMP reply from %s.\n", host->name);
+ if (!host->host_up) {
+ if (verbose) printf("INFO: Host %s started responding. Executing UP command.\n", host->name);
+ host->host_up = true;
+ if (!fork()) {
+ system(host->up_cmd);
+ exit(EXIT_SUCCESS);