Сделал свою реализацию traceroute. Ни один маршрутизатор не отвечает на эхо-запрос. Обычный tracert, встроенный в Windows, работает нормально. ping, часть кода которого я взял для tracert, также работает нормально. Убирал setsockopt()
- все равно нет ответа, везде превышено время ожидания. Что нужно сделать, чтобы все заработало?
main()
:
#include "winsock_error.h"
#include "io_ext.h"
#include <cstdio>
#define SOCK_NUM 3
#pragma comment(lib, "ws2_32.lib")
#pragma warning(disable : 4996)
int main()
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_INTENSITY);
WSADATA filler;
if (WSAStartup(WSA_VERSION, &filler))
{
output_error("Couldn't initialize WSA");
return EXIT_FAILURE;
}
char host_name[MAXGETHOSTSTRUCT];
enter_message("Please enter a host name: ", host_name);
std::cout << std::endl;
LPHOSTENT remote_host_info = gethostbyname(host_name);
if (remote_host_info == NULL)
{
output_error("Couldn't get a host info");
finalize();
return EXIT_FAILURE;
}
if (remote_host_info->h_addrtype == AF_INET6)
{
output_error("Sorry, but R-Scan can't perform scanning of ipv6-hosts");
finalize();
return EXIT_SUCCESS;
}
//ALIASES SHOWING
if (remote_host_info->h_aliases[0])
{
std::cout << "Server name aliases: " << std::endl;
for (int i = 0; remote_host_info->h_aliases[i]; i++)
std::cout << remote_host_info->h_aliases[i] << std::endl;
std::cout << std::endl;
}
else
std::cout << "Host has no aliases" << std::endl << std::endl;
in_addr tmp;
//ADDRESSES SHOWING
if (remote_host_info->h_addr_list[1])
{
std::cout << "Server addresses: " << std::endl;
for (int i = 0; remote_host_info->h_addr_list[i]; i++)
{
tmp.s_addr = *(LPWORD)remote_host_info->h_addr_list[i];
std::cout << inet_ntoa(tmp) << std::endl;
}
std::cout << std::endl;
}
else
{
std::cout << "Server address: ";
tmp.s_addr = *(u_long*)remote_host_info->h_addr;
std::cout << inet_ntoa(tmp) << std::endl << std::endl;
}
WORD temp;
BYTE max_hops_num;
//MAX HOPS NUM INPUT
while (true)
{
std::cout << "Please enter max number of hops: ";
(std::cin >> temp).get();
if (!std::cin || temp > TTL_MAX_VAL)
{
clear_istream(std::cin);
std::cerr << "You entered wrong value; try again" << std::endl << std::endl;
}
else
break;
}
__asm //firstly value is assigned to 16 bit temporary variable, then left octet of temporary variable is assigned to max_hops_num variable
{
mov ax, temp
mov max_hops_num, al
}
fd_set read;
SOCKET sock = ICMP_SOCKET;
sockaddr_in server_data;
ECHO_REQUEST echo_req;
ECHO_REPLY echo_rep;
timeval wait_time = { 2, 0 };
bool need_break = false;
//CONNECTION DATA FILLING
server_data.sin_family = AF_INET;
server_data.sin_port = 0;
tmp.s_addr = *(LPWORD)&remote_host_info->h_addr;
inet_pton(AF_INET, (PCSTR)inet_ntoa(tmp), &server_data.sin_addr);
//ICMP HDR AND ECHO_REQUEST STRUCT FILLING
echo_req.icmp_hdr.type = ICMP_ECHO_REQ;
echo_req.icmp_hdr.code = 0;
echo_req.icmp_hdr.id = 0;
echo_req.icmp_hdr.seq = 0;
echo_req.icmp_hdr.checksum = 0;
echo_req.dw_time = GetTickCount();
memset(echo_req.data, ECHO_FILLER, PACK_FRAME_SIZE);
echo_req.icmp_hdr.checksum = IP_checksum((LPWORD)&echo_req, sizeof(echo_req) / 2);
//TRACERT LOOP
for (BYTE TTL = 1; TTL <= max_hops_num || !max_hops_num; TTL++)
{
tmp.s_addr = 0;
printf("%3d\t", TTL);
//set TTL
if (setsockopt(sock, IPPROTO_IP, IP_TTL, (PCSTR)&TTL, sizeof(TTL)) == SOCKET_ERROR)
{
error_to_close_socket("Couldn't set IP header TTL", sock);
finalize();
return EXIT_FAILURE;
}
//send 3 ICMP echo requests
RANGE(0, SOCK_NUM)
{
echo_req.dw_time = GetTickCount();
echo_req.icmp_hdr.checksum = IP_checksum((LPWORD)&echo_req, sizeof(echo_req) / 2);
if (sendto(sock, (PCSTR)&echo_req, sizeof(echo_req), 0, (LPSOCKADDR)&server_data, sizeof(server_data)) == SOCKET_ERROR)
{
error_to_close_socket("Couldn't send ICMP packet", sock);
finalize();
return EXIT_FAILURE;
}
FD_ZERO(&read);
FD_SET(sock, &read);
int ret = select(0, &read, NULL, NULL, &wait_time);
if (ret == SOCKET_ERROR)
{
error_to_close_socket("Error while analyzing socket", sock);
finalize();
return EXIT_FAILURE;
}
else
if (ret == 0)
std::cout << " * \t";
else
{
if (recvfrom(sock, (LPSTR)&echo_rep, sizeof(echo_rep), 0, NULL, NULL) == SOCKET_ERROR)
{
error_to_close_socket("Couldn't receive data", sock);
finalize();
return EXIT_FAILURE;
}
printf("%4d ms\t", GetTickCount() - echo_rep.echo_request.dw_time);
tmp = echo_rep.ip_hdr.src_addr;
}
}
if (tmp.s_addr == 0)
{
std::cout << "Waiting time exceeded" << std::endl;
continue;
}
//RECEIVING HOST DATA BY ADDR
remote_host_info = gethostbyaddr((PCSTR)&echo_rep.ip_hdr.src_addr, AF_INET_ADDR_LEN, AF_INET);
if (remote_host_info == NULL)
std::cout << inet_ntoa(echo_rep.ip_hdr.src_addr) << std::endl;
else
printf("%s [%s]", remote_host_info->h_name, inet_ntoa(echo_rep.ip_hdr.src_addr));
if (echo_rep.echo_request.icmp_hdr.type == 0 && echo_rep.echo_request.icmp_hdr.code == 0)
break;
}
}
Заголовочный файл со структурами данных для заголовков IP и ICMP:
#pragma once
#ifndef WINSOCK_ERROR
#define WINSOCK_ERROR
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#include <cstdlib>
#include <vector>
#include <cstring>
#include <ctime>
#include <WS2tcpip.h>
#define ECHO_PORT 32768
#define WSA_VERSION 0x0202
#define LOCALHOST "127.0.0.1"
#define BUFF_SIZE 8192
#define BACKLOG 4
#define WAIT_TIME 1
#define INPUT_BUFF 16
#define PACK_FRAME_SIZE 64
#define REPLY_DATA_SIZE 0x100
#define TTL_MAX_VAL 0xFF
#define ICMP_ECHO_REQ 8
#define ECHO_FILLER 87
#define EVERLAST_HOPS_PARAM 0
#define AF_INET_ADDR_LEN 4
#define TCP_SOCKET socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)
#define UDP_SOCKET socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)
#define ICMP_SOCKET socket(AF_INET,SOCK_RAW,IPPROTO_ICMP)
namespace con_mode
{
enum mode
{
write, //socket condition for sending data
read, //socket condition for receiving data
input, //socket condition for entering data by user
timeout //socket condition for inactivity
};
}
typedef struct async_connection //structure for saving data of one asynchronous socket connection
{
SOCKET sock;
con_mode::mode c_mode;
DWORD dw_time;
} async_connection;
typedef struct port_range //port scan range specified by user
{
USHORT from;
USHORT to;
bool error_flag;
char* error_message;
} port_range;
typedef struct ICMP_hdr //ICMP header representation
{
BYTE type;
BYTE code;
WORD checksum;
WORD id;
WORD seq;
} ICMP_HDR;
typedef struct echo_request //packet that will be sent through the network
{
ICMP_HDR icmp_hdr;
DWORD dw_time;
char data[PACK_FRAME_SIZE];
} ECHO_REQUEST;
typedef struct ip_hdr
{
BYTE ver_ihl; //4 bit for version, 4 bit for internet header length (in DWORDs)
BYTE dscp_ecn; //DiffServ: 6 bit for dscp (packet priority or ToS) and 2 bit ECN (congestion flag); if congestion exists, transmission rate reduces
WORD tot_len; //length of header + data, 16 bit field
WORD id; //for packet fragments identifying (if a packet was fragmented)
WORD flag_off; //flags of fragmentation and fragment offset; 1st bit - reserved; 2nd bit - if set, packet won't be fragmented if it need and will be dropped;
//3rd bit - set for all fragmented packets; fragment offset - 13 bit field, defines a fragment offset relative to the beginnig of original IP datagram; measured in 64 bit blocks
BYTE TTL; //time-to-live, 8 bit field; measured determined bu the number of gateways and hosts packet can traverse
BYTE protocol; //8 bit field; protocol list: https://en.wikipedia.org/wiki/List_of_IP_protocol_numbers
WORD checksum; //16 bit field; if it hasn't been computed yet, it must be equal to 0
in_addr src_addr; //32 bit sender IP address
in_addr dst_addr; //32 bit receiver IP address
} IP_HDR;
typedef struct echo_reply //ICMP echo response from server
{
IP_HDR ip_hdr;
ECHO_REQUEST echo_request;
char c_filler[REPLY_DATA_SIZE];
} ECHO_REPLY;
typedef std::vector<async_connection> con_list; //list of async_connection structures
inline WORD IP_checksum(LPWORD data, size_t d_size)
{
DWORD sum = 0;
while (d_size > 0)
{
sum += *data++;
d_size--;
}
sum += (sum >> 16);
return (WORD)~sum;
}
inline void output_error(const char* message)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_INTENSITY);
std::cerr << message << std::endl;
std::cerr << "Error code: " << WSAGetLastError() << std::endl;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_INTENSITY);
}
inline void finalize()
{
WSACleanup();
system("pause");
}
inline void close_socket(SOCKET sock)
{
if (closesocket(sock) == SOCKET_ERROR)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_INTENSITY);
std::cerr << "Couldn't close socket: error " << WSAGetLastError() << std::endl;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_INTENSITY);
}
}
inline void error_to_close_socket(const char* message, SOCKET sock)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_INTENSITY);
output_error(message);
close_socket(sock);
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_INTENSITY);
}
#endif
Скриншот сниффера:
Получается, что что ответы от маршрутизаторов приходят, но не поступают на ICMP-сокет, т.к. select() возвращает 0.
Оборудование для ресторана: новинки профессиональной кухонной техники
Частный дом престарелых в Киеве: комфорт, забота и профессиональный уход
При вызове функции Add() 10 000 000 раз функция HowManySize() вернет значение которое будет равно примерно 152 мегабайтамОднако средства диагностики Visual...
Итак, задача : Реализовать шаблонные функции (массив передаётся в функцию в качестве параметра), выполняющие следующие действия:
Нужно сделать, чтобы на странице, где расположено видео с YoutubeКак сделать, чтобы кнопка появлялась в заданое время от не загрузки страницы...