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

Upload New File

parent 29304242
Branches
No related tags found
No related merge requests found
/**
* Practica Tema 8: ICMP-TIMESTAMP
*
* Redondo Calleja, Daniel
* Jimenez Prieto, Roberto
*
*/
#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 // Tiempo de espera en segundos
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);
}
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = 0; // Inicializar sin_port
if (inet_pton(AF_INET, ip, &dest_addr.sin_addr) <= 0) {
perror("Error al convertir la dirección IP");
close(sockfd);
exit(EXIT_FAILURE);
}
// Asociar socket a la dirección local
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 asociar el socket a la dirección local");
close(sockfd);
exit(EXIT_FAILURE);
}
// Construir el mensaje ICMP
TimeStamp icmp_msg;
crearICMPRequest(&icmp_msg);
// En modo verbose, imprime los detalles del datagrama enviado
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));
}
// Enviar mensaje ICMP
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};
int sel = select(sockfd + 1, &readfds, NULL, NULL, &timeout);
if (sel < 0) {
perror("Error en select");
close(sockfd);
exit(EXIT_FAILURE);
} else if (sel == 0) {
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);
}
// Verificar tipo de respuesta
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 if (recv_reply.icmpMsg.icmpHdr.type == 3){
imprimeError(recv_reply.icmpMsg.icmpHdr.type, recv_reply.icmpMsg.icmpHdr.code);
}else {
printf("-> ICMP Datagram Not Processed...\n");
}
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;
icmp_msg->icmpHdr.checksum = checksum(icmp_msg, sizeof(TimeStamp));
}
unsigned short checksum(void *b, int len) {
unsigned short *buf = b;
unsigned int sum = 0;
for (; len > 1; len -= 2) {
sum += *buf++;
}
if (len == 1) {
sum += *(unsigned char *)buf;
}
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
return ~sum;
}
void imprimeError(unsigned char type, unsigned char code) {
const char *mensaje = "";
if (type == 3) {
switch (code) {
case 0: mensaje = "Net Unreachable"; break;
case 1: mensaje = "Host Unreachable"; break;
case 2: mensaje = "Protocol Unreachable"; break;
case 3: mensaje = "Port Unreachable"; break;
case 4: mensaje = "Fragmentation Needed"; break;
case 5: mensaje = "Source Route Failed"; break;
case 6: mensaje = "Destination Network Unknown"; break;
case 7: mensaje = "Destination Host Unknown"; break;
case 8: mensaje = "Source Host Isolated"; break;
case 11: mensaje = "Destination Network Unreachable for Type of Service"; break;
case 12: mensaje = "Destination Host Unreachable for Type of Service"; break;
case 13: mensaje = "Communication Administratively Prohibited"; break;
case 14: mensaje = "Host Precedence Violation"; break;
case 15: mensaje = "Precedence Cutoff in Effect"; break;
default: mensaje = "Unknown Code"; break;
}
} else if (type == 5) {
switch (code) {
case 1: mensaje = "Redirect for Destination Host"; break;
case 3: mensaje = "Redirect for Destination Host Based on Type-of-Service"; break;
default: mensaje = "Unknown Code"; break;
}
} else if (type == 11) {
switch (code) {
case 0: mensaje = "Time-to-Live Exceeded in Transit"; break;
case 1: mensaje = "Fragment Reassembly Time Exceeded"; break;
default: mensaje = "Unknown Code"; break;
}
} else if (type == 12) {
switch (code) {
case 0: mensaje = "Pointer indicates the error"; break;
case 1: mensaje = "Missing a Required Option"; break;
case 2: mensaje = "Bad Length"; break;
default: mensaje = "Unknown Code"; break;
}
} else {
mensaje = "ICMP Error";
}
printf("-> %s (Type %d, Code %d)\n", mensaje, type, code);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment