Новичок
Профиль
Группа: Участник
Сообщений: 8
Регистрация: 7.2.2009
Репутация: нет Всего: нет
|
Есть такой код программы Пинг файл rawping.h Цитата |
Код | /*********************************************************************** rawping.h - Declares the types, constants and prototypes required to use the rawping.cpp module. ***********************************************************************/
#define WIN32_LEAN_AND_MEAN #include <winsock2.h>
// ICMP packet types #define ICMP_ECHO_REPLY 0 #define ICMP_DEST_UNREACH 3 #define ICMP_TTL_EXPIRE 11 #define ICMP_ECHO_REQUEST 8
// Minimum ICMP packet size, in bytes #define ICMP_MIN 8
#ifdef _MSC_VER // The following two structures need to be packed tightly, but unlike // Borland C++, Microsoft C++ does not do this by default. #pragma pack(1) #endif
// The IP header struct IPHeader { BYTE h_len:4; // Length of the header in dwords BYTE version:4; // Version of IP BYTE tos; // Type of service USHORT total_len; // Length of the packet in dwords USHORT ident; // unique identifier USHORT flags; // Flags BYTE ttl; // Time to live BYTE proto; // Protocol number (TCP, UDP etc) USHORT checksum; // IP checksum ULONG source_ip; ULONG dest_ip; };
// ICMP header struct ICMPHeader { BYTE type; // ICMP packet type BYTE code; // Type sub code USHORT checksum; USHORT id; USHORT seq; ULONG timestamp; // not part of ICMP, but we need it };
#ifdef _MSC_VER #pragma pack() #endif
extern int setup_for_ping(char* host, int ttl, SOCKET& sd, sockaddr_in& dest); extern int send_ping(SOCKET sd, const sockaddr_in& dest, ICMPHeader* send_buf, int packet_size); extern int recv_ping(SOCKET sd, sockaddr_in& source, IPHeader* recv_buf, int packet_size); extern int decode_reply(IPHeader* reply, int bytes, sockaddr_in* from); extern void init_ping_packet(ICMPHeader* icmp_hdr, int packet_size, int seq_no);
[/QUOTE]
файл ip_checksum.h [QUOTE] extern USHORT ip_checksum(USHORT* buffer, int size); [/QUOTE]
файл rawping.cpp [QUOTE] #include <winsock2.h> #include <ws2tcpip.h> #include <iostream.h>
#include "rawping.h" #include "ip_checksum.h"
//////////////////////////// setup_for_ping //////////////////////////// // Creates the Winsock structures necessary for sending and recieving // ping packets. host can be either a dotted-quad IP address, or a // host name. ttl is the time to live (a.k.a. number of hops) for the // packet. The other two parameters are outputs from the function. // Returns < 0 for failure.
int setup_for_ping(char* host, int ttl, SOCKET& sd, sockaddr_in& dest) { // Create the socket sd = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, 0, 0, 0); if (sd == INVALID_SOCKET) { cerr << "Failed to create raw socket: " << WSAGetLastError() << endl; return -1; }
if (setsockopt(sd, IPPROTO_IP, IP_TTL, (const char*)&ttl, sizeof(ttl)) == SOCKET_ERROR) { cerr << "TTL setsockopt failed: " << WSAGetLastError() << endl; return -1; }
// Initialize the destination host info block memset(&dest, 0, sizeof(dest));
// Turn first passed parameter into an IP address to ping unsigned int addr = inet_addr(host); if (addr != INADDR_NONE) { // It was a dotted quad number, so save result dest.sin_addr.s_addr = addr; dest.sin_family = AF_INET; } else { // Not in dotted quad form, so try and look it up hostent* hp = gethostbyname(host); if (hp != 0) { // Found an address for that host, so save it memcpy(&(dest.sin_addr), hp->h_name, hp->h_length); dest.sin_family = hp->h_addrtype; } else { // Not a recognized hostname either! cerr << "Failed to resolve " << host << endl; return -1; } }
return 0; }
/////////////////////////// init_ping_packet /////////////////////////// // Fill in the fields and data area of an ICMP packet, making it // packet_size bytes by padding it with a byte pattern, and giving it // the given sequence number. That completes the packet, so we also // calculate the checksum for the packet and place it in the appropriate // field.
void init_ping_packet(ICMPHeader* icmp_hdr, int packet_size, int seq_no) { // Set up the packet's fields icmp_hdr->type = ICMP_ECHO_REQUEST; icmp_hdr->code = 0; icmp_hdr->checksum = 0; icmp_hdr->id = (USHORT)GetCurrentProcessId(); icmp_hdr->seq = seq_no; icmp_hdr->timestamp = GetTickCount();
// "You're dead meat now, packet!" const unsigned long int deadmeat = 0xDEADBEEF; char* datapart = (char*)icmp_hdr + sizeof(ICMPHeader); int bytes_left = packet_size - sizeof(ICMPHeader); while (bytes_left > 0) { memcpy(datapart, &deadmeat, min(int(sizeof(deadmeat)), bytes_left)); bytes_left -= sizeof(deadmeat); datapart += sizeof(deadmeat); }
// Calculate a checksum on the result icmp_hdr->checksum = ip_checksum((USHORT*)icmp_hdr, packet_size); }
/////////////////////////////// send_ping ////////////////////////////// // Send an ICMP echo ("ping") packet to host dest by way of sd with // packet_size bytes. packet_size is the total size of the ping packet // to send, including the ICMP header and the payload area; it is not // checked for sanity, so make sure that it's at least // sizeof(ICMPHeader) bytes, and that send_buf points to at least // packet_size bytes. Returns < 0 for failure.
int send_ping(SOCKET sd, const sockaddr_in& dest, ICMPHeader* send_buf, int packet_size) { // Send the ping packet in send_buf as-is cout << "Sending " << packet_size << " bytes to " << inet_ntoa(dest.sin_addr) << "..." << flush; int bwrote = sendto(sd, (char*)send_buf, packet_size, 0, (sockaddr*)&dest, sizeof(dest)); if (bwrote == SOCKET_ERROR) { cerr << "send failed: " << WSAGetLastError() << endl; return -1; } else if (bwrote < packet_size) { cout << "sent " << bwrote << " bytes..." << flush; }
return 0; }
/////////////////////////////// recv_ping ////////////////////////////// // Receive a ping reply on sd into recv_buf, and stores address info // for sender in source. On failure, returns < 0, 0 otherwise. // // Note that recv_buf must be larger than send_buf (passed to send_ping) // because the incoming packet has the IP header attached. It can also // have IP options set, so it is not sufficient to make it // sizeof(send_buf) + sizeof(IPHeader). We suggest just making it // fairly large and not worrying about wasting space.
int recv_ping(SOCKET sd, sockaddr_in& source, IPHeader* recv_buf, int packet_size) { // Wait for the ping reply int fromlen = sizeof(source); int bread=0; bread = recvfrom(sd, (char*)recv_buf, packet_size + sizeof(IPHeader),2, (sockaddr*)&source, &fromlen); if (bread == SOCKET_ERROR) { cerr << "read failed: "; if (WSAGetLastError() == WSAEMSGSIZE) { cerr << "buffer too small" << endl; } else { cerr << "error #" << WSAGetLastError() << endl; } return -1; } return 0; }
///////////////////////////// decode_reply ///////////////////////////// // Decode and output details about an ICMP reply packet. Returns -1 // on failure, -2 on "try again" and 0 on success.
int decode_reply(IPHeader* reply, int bytes, sockaddr_in* from) { // Skip ahead to the ICMP header within the IP packet unsigned short header_len = reply->h_len * 4; ICMPHeader* icmphdr = (ICMPHeader*)((char*)reply + header_len);
// Make sure the reply is sane if (bytes < header_len + ICMP_MIN) { cerr << "too few bytes from " << inet_ntoa(from->sin_addr) << endl; return -1; } else if (icmphdr->type != ICMP_ECHO_REPLY) { if (icmphdr->type != ICMP_TTL_EXPIRE) { if (icmphdr->type == ICMP_DEST_UNREACH) { cerr << "Destination unreachable" << endl; } else { cerr << "Unknown ICMP packet type " << int(icmphdr->type) << " received" << endl; } return -1; } // If "TTL expired", fall through. Next test will fail if we // try it, so we need a way past it. } else if (icmphdr->id != (USHORT)GetCurrentProcessId()) { // Must be a reply for another pinger running locally, so just // ignore it. return -2; }
// Figure out how far the packet travelled int nHops = int(256 - reply->ttl); if (nHops == 192) { // TTL came back 64, so ping was probably to a host on the // LAN -- call it a single hop. nHops = 1; } else if (nHops == 128) { // Probably localhost nHops = 0; }
// Okay, we ran the gamut, so the packet must be legal -- dump it cout << endl << bytes << " bytes from " << inet_ntoa(from->sin_addr) << ", icmp_seq " << icmphdr->seq << ", "; if (icmphdr->type == ICMP_TTL_EXPIRE) { cout << "TTL expired." << endl; } else { cout << nHops << " hop" << (nHops == 1 ? "" : "s"); cout << ", time: " << (GetTickCount() - icmphdr->timestamp) << " ms." << endl; }
return 0; } [/QUOTE]
файл ip_checksum.cpp [QUOTE] #define WIN32_LEAN_AND_MEAN #include <windows.h>
USHORT ip_checksum(USHORT* buffer, int size) { unsigned long cksum = 0; // Sum all the words together, adding the final byte if size is odd while (size > 1) { cksum += *buffer++; size -= sizeof(USHORT); } if (size) { cksum += *(UCHAR*)buffer; }
// Do a little shuffling cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >> 16); // Return the bitwise complement of the resulting mishmash return (USHORT)(~cksum); } [/QUOTE]
драйвер ping.cpp [QUOTE] #include <winsock2.h> #include <iostream.h>
#include "rawping.h"
#define DEFAULT_PACKET_SIZE 32 #define DEFAULT_TTL 30 #define MAX_PING_DATA_SIZE 1024 #define MAX_PING_PACKET_SIZE (MAX_PING_DATA_SIZE + sizeof(IPHeader))
int allocate_buffers(ICMPHeader*& send_buf, IPHeader*& recv_buf, int packet_size);
/////////////////////////////////////////////////////////////////////// // Program entry point
int main(int argc, char* argv[]) { char buf[128]; // Init some variables at top, so they aren't skipped by the // cleanup routines. int seq_no = 0; ICMPHeader* send_buf = 0; IPHeader* recv_buf = 0;
int packet_size = DEFAULT_PACKET_SIZE; int ttl = DEFAULT_TTL; packet_size = max( sizeof(ICMPHeader), min(MAX_PING_DATA_SIZE, (unsigned int)packet_size));
cin>>buf;
while(1) { for(int i=0;i<3;i++) { // Start Winsock up WSAData wsaData; if (WSAStartup(MAKEWORD(2, 1), &wsaData) != 0) { cerr << "Failed to find Winsock 2.1 or better." << endl; return 1; }
// Set up for pinging SOCKET sd; sockaddr_in dest, source; if (setup_for_ping(buf, ttl, sd, dest) < 0) { goto cleanup; } if (allocate_buffers(send_buf, recv_buf, packet_size) < 0) { goto cleanup; } init_ping_packet(send_buf, packet_size, seq_no);
// Send the ping and receive the reply if (send_ping(sd, dest, send_buf, packet_size) >= 0) { while (1) { // Receive replies until we either get a successful read, // or a fatal error occurs. if (recv_ping(sd, source, recv_buf, MAX_PING_PACKET_SIZE) < 0) { // Pull the sequence number out of the ICMP header. If // it's bad, we just complain, but otherwise we take // off, because the read failed for some reason. unsigned short header_len = recv_buf->h_len * 4; ICMPHeader* icmphdr = (ICMPHeader*) ((char*)recv_buf + header_len); if (icmphdr->seq != seq_no) { cerr << "bad sequence number!" << endl; continue; } else { break; } } if (decode_reply(recv_buf, packet_size, &source) != -2) { // Success or fatal error (as opposed to a minor error) // so take off. break; } } }//for Sleep(1000); }//while cin>>buf; }
cleanup: delete[]send_buf; delete[]recv_buf; WSACleanup(); return 0; }
/////////////////////////// allocate_buffers /////////////////////////// // Allocates send and receive buffers. Returns < 0 for failure.
int allocate_buffers(ICMPHeader*& send_buf, IPHeader*& recv_buf, int packet_size) { // First the send buffer send_buf = (ICMPHeader*)new char[packet_size]; if (send_buf == 0) { cerr << "Failed to allocate output buffer." << endl; return -1; }
// And then the receive buffer recv_buf = (IPHeader*)new char[MAX_PING_PACKET_SIZE]; if (recv_buf == 0) { cerr << "Failed to allocate output buffer." << endl; return -1; } return 0; } [/QUOTE]
она пингует норм только вот как изменить [QUOTE] int recv_ping(SOCKET sd, sockaddr_in& source, IPHeader* recv_buf, int packet_size) { // Wait for the ping reply int fromlen = sizeof(source); int bread=0; bread = recvfrom(sd, (char*)recv_buf, packet_size + sizeof(IPHeader),2, (sockaddr*)&source, &fromlen); if (bread == SOCKET_ERROR) { cerr << "read failed: "; if (WSAGetLastError() == WSAEMSGSIZE) { cerr << "buffer too small" << endl; } else { cerr << "error #" << WSAGetLastError() << endl; } return -1; } return 0;
|
}
|
штобы если нету указанного адресса(который пингуем) программа сообщала об этом и заканчивалась , а не тупила на этой функции: recvfrom(sd, (char*)recv_buf,packet_size + sizeof(IPHeader),2(sockaddr*)&source,&fromlen); Это сообщение отредактировал(а) Олег2005 - 21.6.2009, 00:05
|