// add by zhangyan 2008-08-25 //发送ICMP包进行路由跟踪 int TraceReader::TraceRouteICMP(const char * cHost, int ttl) { //用在发送和接受的ICMP包头中 int seq_no = 0; ICMPHeader* send_buf = 0; IPHeader* recv_buf = 0; int rtn; int iCount = 0; int packet_size = DEFAULT_PACKET_SIZE; //packet_size = max(sizeof(ICMPHeader), min(MAX_PING_DATA_SIZE, (unsigned int)packet_size)); // 启动 Winsocket WSAData wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { //winsocket版本错误 //cout<<"winsocket版本错误\n"); return SYSERROR; } SOCKET sd; // RAW Socket句柄 sockaddr_in dest, source; // 三个任务(创建sd, 设置ttl, 初试dest的值) rtn = setup_for_ping( cHost, ttl, sd, dest, timeout); if ( rtn < 0) { //cout<<"创建 ping 错误\n"); goto cleanup; //释放资源并退出 } destMachine = dest; // 为send_buf和recv_buf分配内存 rtn = allocate_buffers(send_buf, recv_buf, packet_size); if ( rtn < 0) { //cout<<"分配发送和接收缓冲错误\n"); goto cleanup; } // 初始化IMCP数据包(type=8,code=0) init_ping_packet(send_buf, packet_size, seq_no); // 发送ICMP数据包 rtn = send_ping(sd, dest, send_buf, packet_size); //cout<<"rtn: "<<rtn<<endl; if ( rtn >= 0) { while(1) { // 接受回应包 rtn = recv_ping(sd, source, recv_buf, MAX_PING_PACKET_SIZE); if ( rtn <= 0) { if( ++iCount < retrys) { // (在重试次数内)发送ICMP数据包 send_ping(sd, dest, send_buf, packet_size); continue; } else { //cout<<"超过重试次数\n"); oneRoutePath.push_back("*"); goto cleanup; } } char szSourceIP[16]; strncpy(szSourceIP, inet_ntoa(source.sin_addr), 16); //cout<<szSourceIP<<endl; //{ // mutex::scoped_lock lock(m_tracert_mutex); // oneRoutePath.push_back(szSourceIP); //} oneRoutePath.push_back(szSourceIP); if (strcmp(szSourceIP, cHost) == 0) { //路由跟踪完成 rtn = 11; } //if( GetTickCount() - send_buf->timestamp >= iTimeOut ) // rtn = OVERTIME; goto cleanup; } } cleanup: delete[]send_buf; //释放分配的内存 delete[]recv_buf; WSACleanup(); // 清理winsock return rtn; }
int main(int argc, char **argv) { SOCKET PingSocket; ICMP_HDR *SendBuf = NULL; IPV4_HDR *RecvBuf = NULL; // ICMP + IP buffer // 입력 값 확인 if (argc < 2) { printf("usage:\n"); printf("%s <host> [data_size]", argv[0]); printf("\tdata_size can be up to %d bytes. Default is %d\n", MAX_PING_DATA_SIZE, DEFAULT_PACKET_SIZE); return 1; } // Initialize Winsock WSADATA wsaData; int result; result = WSAStartup(MAKEWORD(2, 2), &wsaData); if (result != 0) { printf("WSAStartup failed with error: %d\n", WSAGetLastError()); return -1; } // SOCKADDR_IN srcAddr, destAddr; int packet_size = DEFAULT_PACKET_SIZE; setup_for_ping(argv[1], PingSocket, destAddr); packet_size = max(sizeof(ICMP_HDR), min(MAX_PING_DATA_SIZE, (unsigned int)packet_size)); // SendBuf / RecvBuf Memory allocation allocate_buffers(SendBuf, RecvBuf, packet_size); // set up ping packet init_ping_packet(SendBuf, packet_size); // Send the ping request and Receive the reply send_ping(PingSocket, destAddr, SendBuf, packet_size); while (1) { if (recv_ping(PingSocket, srcAddr, RecvBuf, MAX_PING_PACKET_SIZE) < 0) { unsigned short header_len = RecvBuf->ip_header_length * 4; ICMP_HDR* icmphdr = (ICMP_HDR *)((char *)RecvBuf + header_len); } else { break; } } // Cleanup WSACleanup(); free(SendBuf); free(RecvBuf); return 0; }