- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <signal.h>
- #include <time.h>
- #include <unistd.h>
- #include <netdb.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <netinet/in.h>
- #include <netinet/ip.h>
- #include <netinet/ip_icmp.h>
- #define MTUSIZ 1500
- #define ICMP_DATLEN 56
- #define ICMP_REQLEN (ICMP_MINLEN + ICMP_DATLEN)
- typedef struct sockaddr sa;
- typedef struct sockaddr_in sa_in;
- typedef struct iphdr iphdr;
- typedef struct icmphdr icmphdr;
- struct pinginfo
- {
- struct addrinfo *ai;
- uint32_t reply_pkg_num;
- uint32_t request_pkg_num;
- struct timeval reply_time;
- struct timeval request_time;
- } pi;
- uint16_t ping_icmphdr_cksum(uint16_t *icmphdr_addr, size_t icmp_reqlen)
- {
- uint32_t icmphdr_cksum;
- for (icmphdr_cksum = 0; icmp_reqlen > 1; icmp_reqlen -= 2)
- icmphdr_cksum += *icmphdr_addr++;
- if (icmp_reqlen == 1)
- icmphdr_cksum += *(uint8_t *)icmphdr_addr;
- icmphdr_cksum = (icmphdr_cksum >> 16) + (icmphdr_cksum & 0xffff);
- icmphdr_cksum += icmphdr_cksum >> 16;
- return ((uint16_t)~icmphdr_cksum);
- }
- void ping_icmphdr_init(icmphdr *icmp_hdr)
- {
- static uint16_t sequence = 1;
- icmp_hdr->type = ICMP_ECHO;
- icmp_hdr->code = 0;
- icmp_hdr->checksum = 0;
- icmp_hdr->un.echo.id = getpid();
- icmp_hdr->un.echo.sequence = sequence++;
- icmp_hdr->checksum = ping_icmphdr_cksum((uint16_t *)icmp_hdr,
- ICMP_REQLEN);
- }
- void ping_send_icmp_request(int sockfd, icmphdr *icmp_pkg)
- {
- ping_icmphdr_init(icmp_pkg);
- gettimeofday(&pi.request_time, NULL);
- if (sendto(sockfd, icmp_pkg, ICMP_REQLEN, 0,
- pi.ai->ai_addr, pi.ai->ai_addrlen) != -1)
- pi.request_pkg_num++;
- }
- void ping_recv_icmp_reply(int sockfd, iphdr *ip_pkg)
- {
- double tv;
- uint16_t icmp_len;
- icmphdr *icmp_hdr;
- if (recvfrom(sockfd, ip_pkg, MTUSIZ, 0,
- pi.ai->ai_addr, &pi.ai->ai_addrlen) == -1)
- return;
- pi.reply_pkg_num++;
- gettimeofday(&pi.reply_time, NULL);
- if (ip_pkg->protocol != IPPROTO_ICMP)
- return;
- icmp_hdr = (icmphdr *)((uint8_t *)ip_pkg + (ip_pkg->ihl << 2));
- if (icmp_hdr->type != ICMP_ECHOREPLY)
- return;
- if ((icmp_len = (ICMP_REQLEN + 20) - (ip_pkg->ihl << 2)) < 8)
- return;
- if (icmp_hdr->un.echo.id != getpid())
- return;
- if (icmp_len < 16)
- return;
- tv = (double)(pi.reply_time.tv_usec - pi.request_time.tv_usec);
- fprintf(stdout, "%d bytes from %s: "
- "icmp_seq=%u ttl=%u time=%.1lf ms\\n",
- icmp_len,
- inet_ntoa(((sa_in *)pi.ai->ai_addr)->sin_addr),
- icmp_hdr->un.echo.sequence, ip_pkg->ttl,
- (tv / 1000));
- }
- void ping(int sockfd)
- {
- uint8_t ip_pkg[MTUSIZ], icmp_pkg[ICMP_REQLEN];
- while (1)
- {
- ping_send_icmp_request(sockfd, (icmphdr *)icmp_pkg);
- ping_recv_icmp_reply(sockfd, (iphdr *)ip_pkg);
- sleep(1);
- }
- }
- void ping_interrupt(int signo)
- {
- double loss;
- loss = 1 - (double)pi.reply_pkg_num / (double)pi.request_pkg_num;
- fprintf(stdout, "\\n--- %s ping statistics ---\\n"
- "%u packets transmitted, "
- "%u received, "
- "%.0lf%% packet loss\\n",
- pi.ai->ai_canonname,
- pi.request_pkg_num,
- pi.reply_pkg_num,
- (loss * 100));
- freeaddrinfo(pi.ai);
- exit(EXIT_SUCCESS);
- }
- int main(int argc, char *argv[])
- {
- int sockfd;
- struct timeval tv = {.tv_sec=5, .tv_usec=0};
- struct addrinfo hint = {.ai_flags=AI_CANONNAME, .ai_family=AF_INET};
- if (argc < 2)
- {
- fprintf(stderr, "Usage: program-name destination\\n");
- return EXIT_FAILURE;
- }
- if (getaddrinfo(argv[argc - 1], "echo", &hint, &pi.ai) != 0)
- return EXIT_FAILURE;
- if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1)
- return EXIT_FAILURE;
- setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
- signal(SIGINT, ping_interrupt);
- fprintf(stdout, "PING %s (%s) %d(%d) bytes of data.\\n",
- pi.ai->ai_canonname,
- inet_ntoa(((sa_in *)pi.ai->ai_addr)->sin_addr),
- ICMP_DATLEN, ICMP_REQLEN + 20);
- ping(sockfd);
- return 0;
- }
- //该片段来自于http://www.codesnippet.cn/detail/2303201511959.html
来源: http://www.codesnippet.cn/detail/2303201511959.html