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

Delete icmp-timestamp.c

parent 49136983
No related branches found
No related tags found
No related merge requests found
/**
* Practica Tema 8: ICMP-TIMESTAMP
*
* Apellido, Nombre
* Apellido, Nombre
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <errno.h>
#include "ip-icmp.h" // Usa las estructuras definidas en este archivo
#define ICMP_TIMESTAMP 13
#define ICMP_TIMESTAMP_REPLY 14
#define TIMEOUT 5 // Tiempo de espera en segundos
unsigned short checksum(void *b, int len) {
unsigned short *buf = b;
unsigned int sum = 0;
unsigned short result;
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;
return result;
}
void print_icmp_error(int type, int code) {
switch (type) {
case 3:
printf("-> Destination Unreachable: ");
switch (code) {
case 0: printf("Net Unreachable\n"); break;
case 1: printf("Host Unreachable\n"); break;
default: printf("Unknown Code\n"); break;
}
break;
default:
printf("-> ICMP Error: Type %d, Code %d\n", type, 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 = 0;
const char *ip = argv[1];
if (argc == 3 && strcmp(argv[2], "-v") == 0) {
verbose = 1;
}
int sockfd;
struct sockaddr_in dest_addr;
struct timeval start_time, end_time;
unsigned char buffer[1024];
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (sockfd < 0) {
perror("Error al crear el socket");
return EXIT_FAILURE;
}
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.sin_family = AF_INET;
if (inet_pton(AF_INET, ip, &dest_addr.sin_addr) <= 0) {
perror("Error al convertir la direccion IP");
return EXIT_FAILURE;
}
// Construccion del mensaje ICMP
TimeStamp icmp_msg;
memset(&icmp_msg, 0, sizeof(icmp_msg));
icmp_msg.icmpHdr.type = ICMP_TIMESTAMP;
icmp_msg.icmpHdr.code = 0;
icmp_msg.pid = htons(getpid());
icmp_msg.sequence = htons(0);
gettimeofday(&start_time, NULL);
icmp_msg.originate = htonl((start_time.tv_sec * 1000) + (start_time.tv_usec / 1000));
icmp_msg.receive = 0; // Inicializar campo Receive a 0
icmp_msg.transmit = 0; // Inicializar campo Transmit a 0
int icmp_length = sizeof(icmp_msg); // Tamaño dinámico en caso de relleno
icmp_msg.icmpHdr.checksum = checksum(&icmp_msg, icmp_length); // Calculo y asignacion del checksum
// Enviar el mensaje
if (sendto(sockfd, &icmp_msg, sizeof(icmp_msg), 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr)) < 0) {
perror("Error al enviar el datagrama");
return EXIT_FAILURE;
}
if (verbose) {
printf("-> Enviando Datagrama ICMP a Destino con IP: %s\n", ip);
}
// Configuracion del tiempo de espera
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);
struct timeval timeout;
timeout.tv_sec = TIMEOUT;
timeout.tv_usec = 0;
int sel = select(sockfd + 1, &readfds, NULL, NULL, &timeout);
if (sel == -1) {
perror("Error en select");
return EXIT_FAILURE;
} else if (sel == 0) {
printf("-> Tiempo de espera agotado para el destino %s.\n", ip);
return EXIT_FAILURE;
}
// Recibir la respuesta
socklen_t addr_len = sizeof(dest_addr);
if (recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&dest_addr, &addr_len) < 0) {
perror("Error al recibir el datagrama");
return EXIT_FAILURE;
}
gettimeofday(&end_time, NULL);
// Excluir cabecera IP
struct iphdr *ip_hdr = (struct iphdr *)buffer;
int ip_header_length = ip_hdr->ihl * 4;
TimeStamp *recv_reply = (TimeStamp *)(buffer + ip_header_length);
// Verificar el checksum del datagrama recibido
unsigned short recv_checksum = recv_reply->icmpHdr.checksum;
recv_reply->icmpHdr.checksum = 0; // Temporalmente establece a 0 para recalcular
int icmp_length = sizeof(buffer) - ip_header_length; // Tamanno real del ICMP
if (checksum(recv_reply, icmp_length) != 0) {
fprintf(stderr, "Error: Checksum invalido en el datagrama recibido.\n");
return EXIT_FAILURE;
}
recv_reply->icmpHdr.checksum = recv_checksum; // Restaurar el valor original
if (recv_reply->icmpHdr.type == ICMP_TIMESTAMP_REPLY) {
unsigned long originate = ntohl(recv_reply->originate);
unsigned long receive = ntohl(recv_reply->receive);
unsigned long transmit = ntohl(recv_reply->transmit);
unsigned long t4 = (end_time.tv_sec * 1000) + (end_time.tv_usec / 1000);
unsigned long rtt = (receive - originate) + (t4 - transmit);
// Mensajes que se imprimen siempre
printf("-> Timestamp Reply recibido desde %s\n", ip);
printf("-> Respuesta Correcta (Type %d, Code %d)\n", recv_reply->icmpHdr.type, recv_reply->icmpHdr.code);
// Mensajes que solo se imprimen con -v
if (verbose) {
printf("-> Originate (recibido): %lu\n", originate);
printf("-> Receive (recibido): %lu\n", receive);
printf("-> Transmit (recibido): %lu\n", transmit);
printf("-> T4 (local): %lu\n", t4);
printf("-> RTT: %lu ms\n", rtt);
printf("-> TTL: %d\n", ip_hdr->ttl);
printf("-> Tamanyo del Datagrama: %zu bytes\n", sizeof(buffer));
}
// Si algun tiempo es 0, el destino no ha procesado los campos
if (receive == 0 || transmit == 0) {
fprintf(stderr, "Error: El destino no procesa correctamente los campos Receive (%lu) o Transmit (%lu).\n", receive, transmit);
return EXIT_FAILURE;
}
// Error si: el tiempo en que se recibio el mensaje es menor al tiempo en que se envio,
// el tiempo en que se transmitio la respuesta es menor que el tiempo en que se recibio,
// o el tiempo en que se recibio la respuesta del origen (t4) es menor al tiempo de transmision de la respuesta
if (receive < originate || transmit < receive || t4 < transmit) {
fprintf(stderr, "Error: Valores de marcas de tiempo inconsistentes.\n");
return EXIT_FAILURE;
}
} else {
print_icmp_error(recv_reply->icmpHdr.type, recv_reply->icmpHdr.code);
}
close(sockfd);
return EXIT_SUCCESS;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment