865 | | #ifdef USING_MINGW |
866 | | u_short in_cksum(u_short *addr, int len) |
867 | | { |
868 | | register int nleft = len; |
869 | | register u_short *w = addr; |
870 | | register u_short answer; |
871 | | register int sum = 0; |
872 | | |
873 | | /* |
874 | | * Our algorithm is simple, using a 32 bit accumulator (sum), |
875 | | * we add sequential 16 bit words to it, and at the end, fold |
876 | | * back all the carry bits from the top 16 bits into the lower |
877 | | * 16 bits. |
878 | | */ |
879 | | while (nleft > 1) |
880 | | { |
881 | | sum += *w++; |
882 | | nleft -= 2; |
883 | | } |
884 | | |
885 | | /* mop up an odd byte, if necessary */ |
886 | | if (nleft == 1) |
887 | | { |
888 | | u_short u = 0; |
889 | | |
890 | | *(u_char *)(&u) = *(u_char *)w ; |
891 | | sum += u; |
892 | | } |
893 | | |
894 | | /* |
895 | | * add back carry outs from top 16 bits to low 16 bits |
896 | | */ |
897 | | sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ |
898 | | sum += (sum >> 16); /* add carry */ |
899 | | answer = ~sum; /* truncate to 16 bits */ |
900 | | return (answer); |
901 | | } |
902 | | #endif |
903 | | |
916 | | #define ICMP_ECHOREPLY 0 |
917 | | #define ICMP_ECHOREQ 8 |
918 | | struct IPHDR { |
919 | | u_char VIHL; // Version and IHL |
920 | | u_char TOS; // Type Of Service |
921 | | short TotLen; // Total Length |
922 | | short ID; // Identification |
923 | | short FlagOff; // Flags and Fragment Offset |
924 | | u_char TTL; // Time To Live |
925 | | u_char Protocol; // Protocol |
926 | | u_short Checksum; // Checksum |
927 | | struct in_addr iaSrc; // Internet Address - Source |
928 | | struct in_addr iaDst; // Internet Address - Destination |
929 | | }; |
930 | | struct ICMPHDR { |
931 | | u_char Type; // Type |
932 | | u_char Code; // Code |
933 | | u_short Checksum; // Checksum |
934 | | u_short ID; // Identification |
935 | | u_short Seq; // Sequence |
936 | | char Data; // Data |
937 | | }; |
938 | | |
939 | | struct Request { |
940 | | ICMPHDR icmpHdr; |
941 | | DWORD dwTime; |
942 | | char cData[32]; |
943 | | }; |
944 | | struct Reply { |
945 | | IPHDR ipHdr; |
946 | | Request echoRequest; |
947 | | char cFiller[256]; |
948 | | }; |
949 | | |
950 | | if (INVALID_SOCKET == (rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP))) |
951 | | { |
952 | | VERBOSE(VB_SOCKET, "Ping: can't create socket"); |
| 874 | if (myth_system(cmd)) |
954 | | } |
955 | | |
956 | | lpHost = gethostbyname(host.toLocal8Bit().constData()); |
957 | | if (!lpHost) |
958 | | { |
959 | | VERBOSE(VB_SOCKET, "Ping: gethostbyname failed"); |
960 | | closesocket(rawSocket); |
961 | | return false; |
962 | | } |
963 | | |
964 | | saDest.sin_addr.s_addr = *((u_long FAR *) (lpHost->h_addr)); |
965 | | saDest.sin_family = AF_INET; |
966 | | saDest.sin_port = 0; |
967 | | |
968 | | Request echoReq; |
969 | | echoReq.icmpHdr.Type = ICMP_ECHOREQ; |
970 | | echoReq.icmpHdr.Code = 0; |
971 | | echoReq.icmpHdr.ID = 123; |
972 | | echoReq.icmpHdr.Seq = 456; |
973 | | for (unsigned i = 0; i < sizeof(echoReq.cData); i++) |
974 | | echoReq.cData[i] = ' ' + i; |
975 | | echoReq.dwTime = GetTickCount(); |
976 | | echoReq.icmpHdr.Checksum = in_cksum((u_short *)&echoReq, sizeof(Request)); |
977 | | |
978 | | if (SOCKET_ERROR == sendto(rawSocket, (LPSTR)&echoReq, sizeof(Request), |
979 | | 0, (LPSOCKADDR)&saDest, sizeof(SOCKADDR_IN))) |
980 | | { |
981 | | VERBOSE(VB_SOCKET, "Ping: send failed"); |
982 | | closesocket(rawSocket); |
983 | | return false; |
984 | | } |
985 | | |
986 | | struct timeval Timeout; |
987 | | fd_set readfds; |
988 | | readfds.fd_count = 1; |
989 | | readfds.fd_array[0] = rawSocket; |
990 | | Timeout.tv_sec = timeout; |
991 | | Timeout.tv_usec = 0; |
992 | | |
993 | | if (SOCKET_ERROR == select(1, &readfds, NULL, NULL, &Timeout)) |
994 | | { |
995 | | VERBOSE(VB_SOCKET, "Ping: timeout expired or select failed"); |
996 | | closesocket(rawSocket); |
997 | | return false; |
998 | | } |
999 | | |
1000 | | closesocket(rawSocket); |
1001 | | VERBOSE(VB_SOCKET, "Ping: done"); |
1002 | | return true; |