|
|
@@ -0,0 +1,205 @@
|
|
|
+//
|
|
|
+// THIS CODE IS BASED ON THE CODE FROM
|
|
|
+// THE BOOK WINSOCK 2.0 BY LEWIS NAPPER...
|
|
|
+//
|
|
|
+//
|
|
|
+
|
|
|
+#include "publicFunExport.h"
|
|
|
+#include<sys/socket.h>
|
|
|
+#include<sys/types.h>
|
|
|
+#include<netinet/in.h>
|
|
|
+#include<netinet/ip_icmp.h>
|
|
|
+#include<arpa/inet.h>
|
|
|
+#include<unistd.h>
|
|
|
+#include<sys/time.h>
|
|
|
+
|
|
|
+typedef uint32_t DWORD;
|
|
|
+typedef int SOCKET;
|
|
|
+typedef struct sockaddr_in* LPSOCKADDR_IN;
|
|
|
+typedef struct hostent* LPHOSTENT;
|
|
|
+
|
|
|
+#define SOCKET_ERROR (-1)
|
|
|
+#define FAILURE (-1)
|
|
|
+#define SIZE_LINE_NORMAL (1024)
|
|
|
+#define SUCCESS (0)
|
|
|
+
|
|
|
+#pragma pack(1)
|
|
|
+#define ICMP_ECHOREPLY 0
|
|
|
+#define ICMP_ECHOREQ 8
|
|
|
+
|
|
|
+// IP Header -- RFC 791
|
|
|
+typedef struct tagIPHDR
|
|
|
+{
|
|
|
+ u_char VIHL; // Version and IHL
|
|
|
+ u_char TOS; // Type Of Service
|
|
|
+ short TotLen; // Total Length
|
|
|
+ short ID; // Identification
|
|
|
+ short FlagOff; // Flags and Fragment Offset
|
|
|
+ u_char TTL; // Time To Live
|
|
|
+ u_char Protocol; // Protocol
|
|
|
+ u_short Checksum; // Checksum
|
|
|
+ struct in_addr iaSrc; // Internet Address - Source
|
|
|
+ struct in_addr iaDst; // Internet Address - Destination
|
|
|
+} IPHDR, * PIPHDR;
|
|
|
+
|
|
|
+
|
|
|
+// ICMP Header - RFC 792
|
|
|
+typedef struct tagICMPHDR
|
|
|
+{
|
|
|
+ u_char Type; // Type
|
|
|
+ u_char Code; // Code
|
|
|
+ u_short Checksum; // Checksum
|
|
|
+ u_short ID; // Identification
|
|
|
+ u_short Seq; // Sequence
|
|
|
+ char Data; // Data
|
|
|
+} ICMPHDR, * PICMPHDR;
|
|
|
+
|
|
|
+
|
|
|
+#define REQ_DATASIZE 32 // Echo Request Data size
|
|
|
+
|
|
|
+// ICMP Echo Request
|
|
|
+typedef struct tagECHOREQUEST
|
|
|
+{
|
|
|
+ ICMPHDR icmpHdr;
|
|
|
+ DWORD dwTime;
|
|
|
+ char cData[REQ_DATASIZE];
|
|
|
+} ECHOREQUEST, * PECHOREQUEST;
|
|
|
+
|
|
|
+
|
|
|
+// ICMP Echo Reply
|
|
|
+typedef struct tagECHOREPLY
|
|
|
+{
|
|
|
+ IPHDR ipHdr;
|
|
|
+ ECHOREQUEST echoRequest;
|
|
|
+ char cFiller[256];
|
|
|
+} ECHOREPLY, * PECHOREPLY;
|
|
|
+
|
|
|
+#pragma pack()
|
|
|
+
|
|
|
+static u_short api_checksum16(u_short *buffer, int size) ;
|
|
|
+static int gen_icmp_packet(struct icmp *icmp_packet, int type, int seq);
|
|
|
+
|
|
|
+int gen_icmp_packet(struct icmp *icmp_packet, int type, int seq)
|
|
|
+{
|
|
|
+ if ( !icmp_packet ) {
|
|
|
+ return FAILURE;
|
|
|
+ }
|
|
|
+
|
|
|
+ icmp_packet->icmp_type = type;
|
|
|
+ icmp_packet->icmp_code = 0;
|
|
|
+ icmp_packet->icmp_cksum = 0;
|
|
|
+ icmp_packet->icmp_id = htons(getpid());
|
|
|
+ icmp_packet->icmp_seq = htons(seq);
|
|
|
+
|
|
|
+ gettimeofday((struct timeval *)icmp_packet->icmp_data, NULL);
|
|
|
+ icmp_packet->icmp_cksum = api_checksum16((unsigned short *)icmp_packet, sizeof(struct icmp));
|
|
|
+
|
|
|
+ return SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+u_short api_checksum16(u_short *buffer, int size)
|
|
|
+{
|
|
|
+ u_int cksum = 0;
|
|
|
+
|
|
|
+ if ( !buffer ) {
|
|
|
+ printf("NULL\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ while ( size > 1 ) {
|
|
|
+ printf("1. Cksum: 0x%08x + 0x%04x\n", cksum, *buffer);
|
|
|
+ cksum += *buffer++;
|
|
|
+ size -= sizeof(u_short);
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( size ) {
|
|
|
+ cksum += *(u_char *)buffer;
|
|
|
+ }
|
|
|
+
|
|
|
+ printf("2. Cksum: 0x%08x\n", cksum);
|
|
|
+
|
|
|
+ /* 32 bit change to 16 bit */
|
|
|
+ while ( cksum >> 16 ) {
|
|
|
+ cksum = (cksum >> 16) + (cksum & 0xFFFF);
|
|
|
+ printf("3. Cksum: 0x%08x\n", cksum);
|
|
|
+ }
|
|
|
+
|
|
|
+ return (u_short)(~cksum);
|
|
|
+}
|
|
|
+
|
|
|
+int Ping(const std::string& dst_ip)
|
|
|
+{
|
|
|
+ int ret = FAILURE;
|
|
|
+ int sd = 0;
|
|
|
+
|
|
|
+ char buf[SIZE_LINE_NORMAL] = { 0 };
|
|
|
+
|
|
|
+ struct ip* ip = NULL;
|
|
|
+ struct sockaddr_in dst_addr = { 0 };
|
|
|
+ struct icmp icmp_packet = { 0 };
|
|
|
+
|
|
|
+ struct timeval tm = { .tv_sec = 1, .tv_usec = 0 };
|
|
|
+
|
|
|
+ fd_set rdfds;
|
|
|
+
|
|
|
+ if (dst_ip.empty()) {
|
|
|
+ goto _E1;
|
|
|
+ }
|
|
|
+
|
|
|
+ sd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
|
|
|
+ if (sd < 0) {
|
|
|
+ printf("socket fail: %d\n", errno);
|
|
|
+ goto _E1;
|
|
|
+ }
|
|
|
+
|
|
|
+ dst_addr.sin_family = AF_INET;
|
|
|
+ dst_addr.sin_addr.s_addr = inet_addr(dst_ip.c_str());
|
|
|
+
|
|
|
+ ret = gen_icmp_packet(&icmp_packet, 8, 1);
|
|
|
+ if (SUCCESS != ret) {
|
|
|
+ goto _E2;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = sendto(sd, &icmp_packet, sizeof(struct icmp), 0,
|
|
|
+ (struct sockaddr*)&dst_addr, sizeof(struct sockaddr_in));
|
|
|
+ if (ret < 0) {
|
|
|
+ goto _E2;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Timeout 1s to recv icmp */
|
|
|
+ FD_ZERO(&rdfds);
|
|
|
+ FD_SET(sd, &rdfds);
|
|
|
+
|
|
|
+ ret = select(sd + 1, &rdfds, NULL, NULL, &tm);
|
|
|
+ if (-1 == ret && EINTR != errno) {
|
|
|
+ /* if serial error */
|
|
|
+ printf("select fail\n");
|
|
|
+ goto _E2;
|
|
|
+ } else if (0 == ret) {
|
|
|
+ /* timeout */
|
|
|
+ printf("recv timeout\n");
|
|
|
+ ret = FAILURE;
|
|
|
+ goto _E2;
|
|
|
+ }
|
|
|
+ if (FD_ISSET(sd, &rdfds)) {
|
|
|
+ ret = recv(sd, buf, sizeof(buf), 0);
|
|
|
+ if (ret <= 0) {
|
|
|
+ perror("recv\n");
|
|
|
+ goto _E2;
|
|
|
+ }
|
|
|
+
|
|
|
+ ip = (struct ip*)buf;
|
|
|
+ printf("from: %s\n", inet_ntoa(ip->ip_src));
|
|
|
+ printf(" to: %s\n", inet_ntoa(ip->ip_dst));
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = SUCCESS;
|
|
|
+
|
|
|
+_E2:
|
|
|
+ close(sd);
|
|
|
+_E1:
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|