Skip to content
Snippets Groups Projects
Commit a894633b authored by danredo's avatar danredo
Browse files

Upload New File

parent 9b2f481b
No related branches found
No related tags found
No related merge requests found
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/time.h>
#include "ip-icmp.h"
#define ICMP_TIMESTAMP 13
#define ICMP_TIMESTAMP_REPLY 14
#define TIMEOUT 5
void crearICMPRequest(TimeStamp *icmp_msg);
unsigned short checksum(void *b, int len);
void imprimeError(unsigned char type, unsigned char code);
int main(int argc, char *argv[]) {
if (argc < 2 || argc > 3) {
fprintf(stderr, "Uso: %s ip [-v]\n", argv[0]);
exit(EXIT_FAILURE);
}
int verbose = (argc == 3 && strcmp(argv[2], "-v") == 0);
const char *ip = argv[1];
int sockfd;
struct sockaddr_in dest_addr, local_addr;
// Crear socket RAW para ICMP
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (sockfd < 0) {
perror("Error al crear el socket");
exit(EXIT_FAILURE);
}
// Configurar dirección local y hacer bind()
memset(&local_addr, 0, sizeof(local_addr));
local_addr.sin_family = AF_INET;
local_addr.sin_addr.s_addr = INADDR_ANY;
local_addr.sin_port = 0;
if (bind(sockfd, (struct sockaddr *)&local_addr, sizeof(local_addr)) < 0) {
perror("Error al hacer bind del socket");
close(sockfd);
exit(EXIT_FAILURE);
}
// Configurar dirección de destino
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = 0;
if (inet_pton(AF_INET, ip, &dest_addr.sin_addr) <= 0) {
perror("Error al convertir la dirección IP");
close(sockfd);
exit(EXIT_FAILURE);
}
// Construir el mensaje ICMP
TimeStamp icmp_msg;
crearICMPRequest(&icmp_msg);
if (verbose) {
printf("-> Type: %d\n", icmp_msg.icmpHdr.type);
printf("-> Code: %d\n", icmp_msg.icmpHdr.code);
printf("-> PID : %d\n", icmp_msg.pid);
printf("-> Seq Numbr: %d\n", ntohs(icmp_msg.sequence));
printf("-> Originate: %u ms\n", icmp_msg.originate);
printf("-> Receive: 0 ms\n");
printf("-> Transmit: 0 ms\n");
printf("-> Tamanyo del Datagrama: %ld bytes\n", sizeof(TimeStamp));
}
printf("-> Enviando Datagrama ICMP a Destino con IP: %s\n", ip);
if (sendto(sockfd, &icmp_msg, sizeof(icmp_msg), 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr)) < 0) {
perror("Error al enviar el datagrama");
close(sockfd);
exit(EXIT_FAILURE);
}
printf("-> Timestamp Request enviado correctamente...\n");
// Configurar timeout
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);
struct timeval timeout = {TIMEOUT, 0};
if (select(sockfd + 1, &readfds, NULL, NULL, &timeout) < 0) {
perror("Error en select");
close(sockfd);
exit(EXIT_FAILURE);
}
if (!FD_ISSET(sockfd, &readfds)) {
printf("-> Tiempo de espera agotado para %s\n", ip);
close(sockfd);
exit(EXIT_FAILURE);
}
// Recibir respuesta
TimeStampReply recv_reply;
socklen_t addr_len = sizeof(dest_addr);
if (recvfrom(sockfd, &recv_reply, sizeof(recv_reply), 0, (struct sockaddr *)&dest_addr, &addr_len) < 0) {
perror("Error al recibir el datagrama");
close(sockfd);
exit(EXIT_FAILURE);
}
printf("\n-> Timestamp Reply recibido desde %s\n", ip);
if (recv_reply.icmpMsg.icmpHdr.type == ICMP_TIMESTAMP_REPLY && recv_reply.icmpMsg.icmpHdr.code == 0) {
int originate = recv_reply.icmpMsg.originate;
int receive = recv_reply.icmpMsg.receive;
int transmit = recv_reply.icmpMsg.transmit;
struct timeval end_time;
gettimeofday(&end_time, NULL);
int t4 = (end_time.tv_sec * 1000) + (end_time.tv_usec / 1000);
int rtt = (receive - originate) + (t4 - transmit);
if (verbose) {
printf("-> Originate: %u ms\n", originate);
printf("-> Receive: %u ms\n", receive);
printf("-> Transmit: %u ms\n", transmit);
printf("-> RTT: %u ms\n", rtt);
printf("-> TTL: %d\n", recv_reply.ipHdr.TTL);
printf("-> Tamanyo del Datagrama: %ld bytes\n", sizeof(TimeStampReply));
}
printf("-> Respuesta Correcta (Type %d, Code %d)\n", recv_reply.icmpMsg.icmpHdr.type, recv_reply.icmpMsg.icmpHdr.code);
} else {
imprimeError(recv_reply.icmpMsg.icmpHdr.type, recv_reply.icmpMsg.icmpHdr.code);
}
close(sockfd);
return EXIT_SUCCESS;
}
void crearICMPRequest(TimeStamp *icmp_msg) {
memset(icmp_msg, 0, sizeof(TimeStamp));
icmp_msg->icmpHdr.type = ICMP_TIMESTAMP;
icmp_msg->icmpHdr.code = 0;
icmp_msg->pid = getpid();
icmp_msg->sequence = htons(0);
struct timeval start_time;
gettimeofday(&start_time, NULL);
icmp_msg->originate = (start_time.tv_sec * 1000) + (start_time.tv_usec / 1000);
icmp_msg->icmpHdr.checksum = 0; // Inicializar el campo checksum a 0.
icmp_msg->icmpHdr.checksum = checksum(icmp_msg, sizeof(TimeStamp));
}
// Función para calcular el checksum
unsigned short checksum(void *b, int len) {
unsigned short *buf = b;
unsigned int sum = 0; // Paso 4: Acumulador inicializado a 0.
// Paso 2: Calcular el número de palabras de 16 bits.
int half_words = len / 2;
// Paso 5: Recorrer el datagrama sumando palabras de 16 bits.
while (half_words > 0) {
sum += *buf++; // Sumar la palabra actual al acumulador.
half_words--; // Reducir el contador de palabras.
}
// Si queda un byte adicional (longitud impar), procesarlo.
if (len % 2 == 1) {
sum += *(unsigned char *)buf; // Sumar el último byte como un short.
}
// Sumar las partes alta y baja del acumulador (1ª vez).
sum = (sum >> 16) + (sum & 0xFFFF);
// Sumar nuevamente las partes alta y baja del acumulador (2ª vez).
sum += (sum >> 16);
// Complemento a uno.
return (unsigned short)(~sum);
}
void imprimeError(unsigned char type, unsigned char code) {
switch (type) {
case 3: // Destination Unreachable
printf("-> Destination Unreachable: ");
switch (code) {
case 0: printf("Net Unreachable\n"); break;
case 1: printf("Host Unreachable\n"); break;
case 2: printf("Protocol Unreachable\n"); break;
case 3: printf("Port Unreachable\n"); break;
default: printf("Unknown Code\n"); break;
}
break;
case 11:
printf("-> Time Exceeded\n");
break;
default:
printf("-> ICMP Error: Type %d, Code %d\n", type, code);
break;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment