Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

BVT1801_ping

.pdf
Скачиваний:
12
Добавлен:
18.05.2021
Размер:
165.34 Кб
Скачать

//

// ДЕКЛАРАЦИЯ БИБЛИОТЕК

//

#include <stdlib.h>

// Содержит базовые методы

#include <stdio.h>

// Содержит метод для вывода информации в консоль

#include <sys/socket.h>

// Содержит методы для работы с сокетами

#include <arpa/inet.h>

// Содержит методы необходимые для запроса информации от DNS-серверов

#include <netdb.h>

// Содержит структуру и методы для работы с ip адресами

#include <unistd.h>

// Содержит метод usleep для задержки отправки пакетов

#include <string.h>

// Содержит метод bzero для обнуления пакета

#include <netinet/ip_icmp.h> // Содержит методы необходимые для ICMP запроса

#include <time.h>

// Содержит методы для работы со временем

#include <errno.h>

// Коды ошибок

//

 

 

//

ДЕКЛАРАЦИЯ ГЛОБАЛЬНЫХ ПЕРЕМЕННЫХ

//

 

 

int currentPackage;

// Количество отправленных пакетов

int countPackage;

// Количество отправляемых пакетов

char* ip;

// IP адрес получателя

char* domain;

// Домен получателя

char* pathLog;

// Путь к файлу лога

int errorCode;

// Код ошибки

struct ping_pkt pckt;

// Пакет

struct timespec time_start; // Время отправки пакета

int sock;

// Дескриптор сокета

struct sockaddr_in sockAddr;// Настройки адреса сокета

FILE* fp;

// Log файл

char logText[100];

// Текст для записи в log файл

//

 

 

//

ДЕКЛАРАЦИЯ ПРОЦЕДУР

 

//

 

 

struct ping_pkt

// Структура пакета

{

 

 

struct icmphdr hdr;

char msg[64 - sizeof(struct icmphdr)];

};

 

 

unsigned short checksum(void* b, int len)

// Контрольная сумма

{

 

 

//ДЕКЛАРАЦИЯ ПЕРЕМЕННЫХ

 

 

unsigned short* buf;

//Буфер

 

unsigned int sum;

//Промежуточная сумма

 

unsigned short result;

//Результат

 

//ИНИЦИАЛИЗАЦИЯ ПЕРЕМЕННЫХ

 

buf = b;

 

 

sum = 0;

 

 

result = 0;

 

 

//ТЕЛО ПРОЦЕДУРЫ

 

 

//printf("Вошли в checksum\n");

//Debug

for (sum = 0; len > 1; len -= 2)

 

sum += *buf++;

 

 

if (len == 1)

 

 

sum += *(unsigned char*)buf;

 

sum = (sum >> 16) + (sum & 0xFFFF);

 

sum += (sum >> 16);

 

 

result = ~sum;

 

 

//printf("Вышли из checksum\n");

//Debug

return result;

 

 

}

 

 

int InitLog() {

 

 

//printf("Вошли в InitLog\n");

//Debug

if ((fp = fopen(pathLog, "w")) == NULL) {

 

//printf("Вышли из InitLog: 1\n");

//Debug

return 1;

 

 

}

 

 

//printf("Вышли из InitLog: 0\n");

//Debug

return 0;

}

 

int Log() {

// Запись информации в лог файл

//printf("Вошли в Log\n");

//Debug

if (fprintf(fp, "%s\n", logText)>=0)

 

{

 

//printf("Вышли из Log: 0\n");

//Debug

return 0;

 

}

 

else

 

{

 

//printf("Вышли из Log: 1\n");

//Debug

return 1;

 

}

 

}

 

void DiagLog()

// Диагностика ошибки лога

{

 

printf("Вошли в DiagLog\n");

 

switch(errno){

 

case E2BIG:

printf("Error: Input conversion stopped due to lack of space in the output buffer\n"); break;

case EILSEQ:

printf("Error: Input conversion stopped due to an input byte that does not belong to the input codeset\n"); break;

case EINVAL:

printf("Error: Input conversion stopped due to an incomplete character or shift sequence at the end of the input buffer\n"); break;

case EPERM:

printf("Error: Operation not permitted\n"); break;

case ENOENT:

printf("Error: No such file or directory\n"); break;

case EACCES:

printf("Error: Permission denied\n"); break;

case EMFILE:

printf("Error: Too many open files\n"); break;

case ENOMEM:

printf("Error: Out of memory\n"); break;

case EOVERFLOW:

printf("Error: Value too large for defined data type\n"); break;

}

 

printf("Вышли из DiagLog\n");

 

}

 

void Diag()

// Диагностика ошибки в параметрах, отправке и получение пакета

{

 

printf("Вошли в Diag\n");

 

switch(errorCode){

 

case 1:

 

sprintf(logText,"Error: Wrong number of input parameters"); break;

case 2:

sprintf(logText,"Error: Domain doesn't match to any IP address"); break;

case 3:

sprintf(logText,"Error: Wrong initialization socket"); break;

case 4:

sprintf(logText,"Error: Wrong sending packet"); break;

case 5:

sprintf(logText,"Error: The number of sent parts of the package does not match the number of received"); break;

case 6:

sprintf(logText,"Error: The amount of the received packet does not match the sent");

break;

}

printf("Вышли из Diag\n");

}

 

 

int InitICMP(struct sockaddr_in* sockAddr)

// Инициализация сокета и адреса

{

 

 

//ДЕКЛАРАЦИЯ ПЕРЕМЕННЫХ

 

 

struct timeval tv_out;

//Настройки времени для сокета

int ttl_val;

//Размер пакета

 

//ИНИЦИАЛИЗАЦИЯ ПЕРЕМЕННЫХ

 

ttl_val = 64;

 

 

//ТЕЛО ПРОЦЕДУРЫ

 

 

//printf("Вошли в InitICMP\n");

//Debug

sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);

 

if (sock < 0)

 

// Успешно ли создался?

{

 

 

//printf("Вышли из InitICMP: 1\n");

//Debug

errorCode = 3;

 

 

return 1;

 

 

}

 

 

else

 

 

{

 

 

(*sockAddr).sin_family = AF_INET;

// Заполняем адрес

(*sockAddr).sin_port = htons(0); (*sockAddr).sin_addr.s_addr = inet_addr(ip);

tv_out.tv_sec = 1; // Заполняем настройки для соединения tv_out.tv_usec = 0;

setsockopt(sock, SOL_IP, IP_TTL, &ttl_val, sizeof(ttl_val));

setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv_out, sizeof tv_out);

//printf("Вышли из InitICMP: 0\n");

//Debug

return 0;

 

}

 

}

 

 

int MakeICMPRequest(struct sockaddr_in* sockAddr)

// Отправляем пакет

{

 

 

//ДЕКЛАРАЦИЯ ПЕРЕМЕННЫХ

 

int msg_count;

//Количество ожидаемых пакетов

 

int i;

//Счетчик пакетов

 

//ИНИЦИАЛИЗАЦИЯ ПЕРЕМЕННЫХ

 

msg_count = 0;

 

 

i = 0;

 

 

//ТЕЛО ПРОЦЕДУРЫ

 

 

//printf("Вошли в MakeICMPRequest\n");

//Debug

//printf("currentPackage: %d\n",currentPackage);//Debug

if (currentPackage >= countPackage)

// Все пакеты были отправлены?

{

 

 

//printf("Вышли из MakeICMPRequest: 2\n");

//Debug

return 2;

 

 

}

 

 

else

 

 

{

 

 

bzero(&pckt, sizeof(pckt));

 

pckt.hdr.type = ICMP_ECHO;

// Инициализируем пакет для отправки

pckt.hdr.un.echo.id = getpid();

 

for (i = 0; i < sizeof(pckt.msg) - 1; i++) pckt.msg[i] = i + '0';

pckt.msg[i] = 0; pckt.hdr.un.echo.sequence = msg_count++;

pckt.hdr.checksum = checksum(&pckt, sizeof(pckt));

usleep(1000000);

// Задержка отправки пакета

clock_gettime(CLOCK_MONOTONIC, &time_start);

if (sendto(sock, &pckt, sizeof(pckt), 0,

// Отправка пакета

(struct sockaddr*)sockAddr,

 

sizeof(*sockAddr)) <= 0)

 

{

 

//printf("Вышли из MakeICMPRequest: 1\n");//Debug errorCode = 4;

return 1;

}

currentPackage++;

//printf("Вышли из MakeICMPRequest: 0\n"); //Debug return 0;

}

}

 

int MakeICMPReplay()

// Дожидаемся пакета в ответ

{

 

//ДЕКЛАРАЦИЯ ПЕРЕМЕННЫХ

 

long double rtt_msec;

//Разница между отправкой и прибытием

int msg_count;

//Количество пакетов

int addr_len;

//Размер адреса

struct timespec time_end;

//Время прибытия

struct sockaddr_in r_addr;

//Адрес

double timeElapsed;

//Прошедшее время

struct tm *uTime;

//Структура для вывод времени

//ИНИЦИАЛИЗАЦИЯ ПЕРЕМЕННЫХ

 

rtt_msec = 0;

 

msg_count = 0;

 

addr_len = sizeof(r_addr);

 

//ТЕЛО ПРОЦЕДУРЫ

//printf("Вошли в MakeICMPReplay:\n"); //Debug if (recvfrom(sock, &pckt, sizeof(pckt), 0,

(struct sockaddr*)&r_addr, &addr_len) <= 0 && msg_count > 1)

{

//printf("Вышли из MakeICMPReplay: 1\n");

//Debug

errorCode = 5;

 

return 1;

 

}

 

else

 

{

 

clock_gettime(CLOCK_MONOTONIC, &time_end);

// Запоминаем время отправки

timeElapsed = ((double)(time_end.tv_nsec - time_start.tv_nsec)) / 1000000.0; rtt_msec = (time_end.tv_sec - time_start.tv_sec) * 1000.0 + timeElapsed;

if (!(pckt.hdr.type == 69 && pckt.hdr.code == 0)) // Пришел верный ответ?

{

//printf("Error..Packet received with ICMP type %d code %d\n", pckt.hdr.type, pckt.hdr.code); //printf("Вышли из MakeICMPReplay: 1\n"); //Debug

errorCode = 6; return 1;

}

else

{

char strTime[40] = { 0 };

const time_t timer = time(NULL); uTime = localtime(&timer);

strftime(strTime, 80, "%H:%M:%S", uTime);

sprintf(logText,"[%s] %s %s количество байт = 64, RTT = %Lf ms",strTime, ip, domain, rtt_msec); printf("%s %s количество байт = 64, RTT = %Lf ms\n", ip, domain, rtt_msec);

//printf("Вышли из MakeICMPReplay: 0\n");

//Debug

return 0;

 

}

 

}

 

}

 

int GetIP()

// Получаем IP адрес на основе домена

{

 

//ДЕКЛАРАЦИЯ ПЕРЕМЕННЫХ

 

struct hostent* ghbn; //Запрос к DNS серверу

 

//ИНИЦИАЛИЗАЦИЯ ПЕРЕМЕННЫХ

 

ghbn = gethostbyname(domain);

// создаем структуру на основе домена

//ТЕЛО ПРОЦЕДУРЫ

//printf("Вошли в GetIP\n"); //Debug //printf("DOMAIN: "); printf(domain); printf("\n"); //Debug

if (ghbn)

// Если структура была созданна, значит соответствующему домену найден ip

{

 

ip = inet_ntoa(*(struct in_addr*)ghbn->h_addr); //сохраняем полученный ip printf("IP: "); printf(ip); printf("\n");

//printf("Вышли из GetIP: 0\n"); //Debug return 0;

}

 

 

else

 

 

{

 

 

//printf("Вышли из GetIP: 1\n");

//Debug

errorCode = 2;

 

 

return 1;

 

//Для данного домена не найден ip

}

 

 

}

 

 

int ReadingParams(int argc, char* argv[])

// Проверяем указанные параметры на валидность и присваиваем значения глобаль

ным переменным

 

 

{

 

 

//ДЕКЛАРАЦИЯ ПЕРЕМЕННЫХ

 

long int a;

//Очередной байт ip адреса

 

char* endptr;

//char представление адреса

 

//ИНИЦИАЛИЗАЦИЯ ПЕРЕМЕННЫХ

 

char* IP = argv[1];

 

//ТЕЛО ПРОЦЕДУРЫ

 

 

//printf("Вошли в ReadingParams\n");

//Debug

if (argc != 4)

{

errorCode = 1; return 1;

}

countPackage = atoi(argv[2]); pathLog = argv[3];

if (a = strtol(IP, &endptr, 10)) if (a >= 0 && a <= 255)

{

int i;

for (i = 0; i < 3; i++)

{

++endptr;

if (!(a = strtol(endptr, &endptr, 10)) || !(a >= 0 && a <= 255))

{

domain = IP;

 

//printf("Вышли из ReadingParams: 2\n");

//Debug

return 2;

 

}

 

}

 

if (i < 3)

 

{

 

domain = IP;

 

//printf("Вышли из ReadingParams: 2\n");

//Debug

return 2;

 

}

 

else

 

{

 

ip = IP;

 

//printf("Вышли из ReadingParams: 0\n");

//Debug

return 0;

 

}

 

}

 

else

 

{