128 lines
2.9 KiB
C
128 lines
2.9 KiB
C
#include "help.h"
|
|
#include <opt_parse.h>
|
|
#include <ping.h>
|
|
#include <signal.h>
|
|
#include <utils.h>
|
|
|
|
#include <arpa/inet.h>
|
|
#include <errno.h>
|
|
#include <netdb.h>
|
|
#include <netinet/in.h>
|
|
#include <netinet/ip.h>
|
|
#include <netinet/ip_icmp.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/time.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
|
|
char *address = NULL;
|
|
int sock = -1;
|
|
|
|
void sigint(int sig) {
|
|
(void)sig;
|
|
|
|
close(sock);
|
|
print_stats();
|
|
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
|
|
options_t init_opt(args_t *args) {
|
|
options_t opt;
|
|
verbose = args->opts[VERBOSE] != false ? true : DEFAULT_VERBOSE;
|
|
opt.count = args->arg[COUNT] != -1 ? args->arg[COUNT] : DEFAULT_COUNT;
|
|
opt.size = args->arg[SIZE] != -1 ? args->arg[SIZE] : DEFAULT_SIZE;
|
|
opt.timeout =
|
|
args->arg[TIMEOUT] != -1 ? args->arg[TIMEOUT] : DEFAULT_TIMEOUT;
|
|
opt.interval =
|
|
args->arg[INTERVAL] != -1 ? args->arg[INTERVAL] : DEFAULT_INTERVAL;
|
|
opt.linger = args->arg[LINGER] != -1 ? args->arg[LINGER] : DEFAULT_LINGER;
|
|
return opt;
|
|
}
|
|
|
|
int send_ping(int socket, struct sockaddr_in *dest, options_t opt) {
|
|
struct timeval loop_start, loop_end;
|
|
struct timeval pkt_start, pkt_end;
|
|
struct sockaddr_in addr = *dest;
|
|
int bytes;
|
|
|
|
char sendbuf[opt.size];
|
|
char recvbuf[opt.size + sizeof(struct ip)];
|
|
|
|
gettimeofday(&loop_start, 0);
|
|
while (727) {
|
|
int seq = tx_count;
|
|
|
|
init_packet(sendbuf, seq, opt.size);
|
|
|
|
gettimeofday(&pkt_start, NULL);
|
|
bytes = send_icmp(socket, sendbuf, &addr, opt.size);
|
|
tx_count++;
|
|
|
|
bytes = receive_icmp(socket, recvbuf, sizeof(recvbuf), &addr);
|
|
gettimeofday(&pkt_end, NULL);
|
|
|
|
if (bytes <= 0) {
|
|
if (verbose) {
|
|
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
|
printf("Request timeout for icmp_seq=%d\n", seq);
|
|
} else {
|
|
fprintf(stderr, "recv failed: %s\n", strerror(errno));
|
|
}
|
|
}
|
|
} else
|
|
process_icmp(recvbuf, bytes, &addr, seq, &pkt_start, &pkt_end);
|
|
if (check_for_count(opt)) {
|
|
print_stats();
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
sleep(opt.interval);
|
|
if (check_for_timeout(loop_start, opt)) {
|
|
print_stats();
|
|
return EXIT_SUCCESS;
|
|
}
|
|
}
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
int ping(args_t *args) {
|
|
int ret;
|
|
options_t opt = init_opt(args);
|
|
signal(SIGINT, &sigint);
|
|
for (int i = 0; args->hosts[i] != NULL; i++) {
|
|
address = args->hosts[i];
|
|
struct sockaddr_in addr;
|
|
struct addrinfo hints, *res;
|
|
|
|
memset(&hints, 0, sizeof(hints));
|
|
hints.ai_family = AF_INET;
|
|
hints.ai_socktype = SOCK_RAW;
|
|
hints.ai_protocol = IPPROTO_ICMP;
|
|
|
|
int status = getaddrinfo(address, NULL, &hints, &res);
|
|
if (status != 0) {
|
|
fprintf(stderr, "Bad address: %s\n", address);
|
|
ret = EXIT_FAILURE;
|
|
continue;
|
|
}
|
|
|
|
memcpy(&addr, res->ai_addr, res->ai_addrlen);
|
|
freeaddrinfo(res);
|
|
|
|
sock = init_socket(opt);
|
|
if (sock < 0) {
|
|
break;
|
|
}
|
|
|
|
printf("PING %s (%s): %d data bytes\n", address, address, opt.size);
|
|
|
|
ret = send_ping(sock, &addr, opt);
|
|
}
|
|
return ret;
|
|
}
|