From 7ce0ea07402f8399dded0a990ef23b905b80ed63 Mon Sep 17 00:00:00 2001
From: danredo <daniel.redcal06@gmail.com>
Date: Thu, 12 Dec 2024 20:57:45 +0000
Subject: [PATCH] Upload New File

---
 P8/icmp3.c | 283 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 283 insertions(+)
 create mode 100644 P8/icmp3.c

diff --git a/P8/icmp3.c b/P8/icmp3.c
new file mode 100644
index 0000000..9735c2d
--- /dev/null
+++ b/P8/icmp3.c
@@ -0,0 +1,283 @@
+/**
+ * Practica Tema 8: ICMP-TIMESTAMP
+ *
+ * Mata, David
+ *
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/ip.h> // Define sockaddr_in
+#include <errno.h>      // Para usar errno y perror()
+#include <unistd.h>
+#include <sys/time.h>
+#include "ip-icmp.h"
+
+#define tiempo_max 5
+
+// Funcion para calcular el checksum
+unsigned short checksum(TimeStamp *ts)
+{
+    unsigned int acumulador = 0;
+    unsigned short *puntero = (unsigned short *)ts;
+    int i;
+    int len = sizeof(TimeStamp) / 2;
+
+    // Inicializamos el checksum a 0
+    ts->icmpHdr.checksum = 0;
+
+    // Calculamos el checksum
+    for (i = 0; i < len; i++)
+    {
+        acumulador += (unsigned int)*puntero;
+        puntero++;
+    }
+    // Realizamos dos veces la operacion por el acarreo
+    acumulador = (acumulador >> 16) + (acumulador & 0x0000ffff);
+    acumulador = (acumulador >> 16) + (acumulador & 0x0000ffff);
+
+    return (unsigned short)~acumulador;
+}
+// Función para manejar los errores de ICMP
+void errores_ICMP(char type, char code)
+{
+    switch (type)
+    {
+    case 3: // Destination Unreachable
+        switch (code)
+        {
+        case 0:
+            printf("Destination Unreachable: Net Unreachable\n");
+            break;
+        case 1:
+            printf("Destination Unreachable: Host Unreachable\n");
+            break;
+        case 2:
+            printf("Destination Unreachable: Protocol Unreachable\n");
+            break;
+        case 3:
+            printf("Destination Unreachable: Port Unreachable\n");
+            break;
+        case 4:
+            printf("Destination Unreachable: Fragmentation Needed\n");
+            break;
+        case 5:
+            printf("Destination Unreachable: Source Route Failed\n");
+            break;
+        case 6:
+            printf("Destination Unreachable: Destination Network Unknown\n");
+            break;
+        case 7:
+            printf("Destination Unreachable: Destination Host Unknown\n");
+            break;
+        case 8:
+            printf("Destination Unreachable: Source Host Isolated\n");
+            break;
+        case 11:
+            printf("Destination Unreachable: Destination Network Unreachable for Type of Service\n");
+            break;
+        case 12:
+            printf("Destination Unreachable: Destination Host Unreachable for Type of Service\n");
+            break;
+        case 13:
+            printf("Destination Unreachable: Communication Administratively Prohibited\n");
+            break;
+        case 14:
+            printf("Destination Unreachable: Host Precedence Violation\n");
+            break;
+        case 15:
+            printf("Destination Unreachable: Precedence Cutoff in Effect\n");
+            break;
+        }
+    case 5: // Redirect
+        switch (code)
+        {
+        case 1:
+            printf("Redirect: Redirect for Destination Host\n");
+            break;
+        case 3:
+            printf("Redirect: Redirect for Destination Host Based on Type-of-Service\n");
+            break;
+        }
+    case 11: // Time Exceeded
+        switch (code)
+        {
+        case 0:
+            printf("Time Exceeded: Time-to-Live Exceeded in Transit\n");
+            break;
+        case 1:
+            printf("Time Exceeded: Fragment Reassembly Time Exceeded\n");
+            break;
+        }
+    case 12: // Parameter Problem
+        switch (code)
+        {
+        case 0:
+            printf("Parameter Problem: Pointer indicates the error\n");
+            break;
+        case 1:
+            printf("Parameter Problem: Missing a Required Option\n");
+            break;
+        case 2:
+            printf("Parameter Problem: Bad Length\n");
+            break;
+        }
+    default:
+        printf("ICMP Error: Type %d, Code %d\n", type, code);
+    }
+}
+int main(int argc, char *argv[])
+{
+
+    struct sockaddr_in direccion; // Estructura para guardar la ip del servidor
+    int numero_socket;            // numero del sockect
+    int v = 0;                    // Modo verbose(-v)
+    socklen_t tam;                // Variable para la funcion rcvfrom
+    struct sockaddr_in myaddr;
+
+    // Comprobamos que el numero de argumentos sea correcto
+    if (argc < 2 || argc > 3)
+    {
+        fprintf(stderr, "Error en el numero de argumentos");
+        exit(EXIT_FAILURE);
+    }
+
+    // Convertimos la dirección IP
+    if (inet_aton(argv[1], &direccion.sin_addr) == 0)
+    {
+        fprintf(stderr, "Error al transformar la direccion IP\n");
+        exit(EXIT_FAILURE);
+    }
+
+    // Creamos el socket UDP
+    numero_socket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
+    if (numero_socket < 0)
+    {
+        perror("Error al crear el socket");
+        exit(EXIT_FAILURE);
+    }
+    // Asignamos la familia a la direccion
+    direccion.sin_family = AF_INET;
+
+    // Comprobamos si el tercer argumento es modo verbose y inicializamos el flag
+    if (argc == 3 && strcmp(argv[2], "-v") == 0)
+    {
+        v = 1;
+    }
+
+    printf("-> Enviando Datagrama ICMP a Destino con IP: %s\n", argv[1]);
+
+    // Creamos el mensaje Timestamp
+    TimeStamp mensaje;
+    memset(&mensaje, 0, sizeof(mensaje));
+
+    // Inicializamos la cabecera ICMP
+    mensaje.icmpHdr.type = 13;
+    mensaje.icmpHdr.code = 0;
+    mensaje.pid = getpid();
+    mensaje.sequence = 0;
+
+    // Calculamos el tiempo de origen para el mensaje enviado
+    struct timeval tiempo_ori;
+    gettimeofday(&tiempo_ori, NULL);
+    mensaje.originate = tiempo_ori.tv_sec * 1000 + tiempo_ori.tv_usec / 1000;
+
+    // Calculamos checksum y se lo asignamos al mensaje
+    mensaje.icmpHdr.checksum = 0;
+    mensaje.icmpHdr.checksum = checksum(&mensaje);
+
+    // Informacion para el modo verbose
+    if (v)
+    {
+        printf("-> Type: %d\n", mensaje.icmpHdr.type);
+        printf("-> Code: %d\n", mensaje.icmpHdr.code);
+        printf("-> PID : %d\n", mensaje.pid);
+        printf("-> Seq Numbr: %d\n", mensaje.sequence);
+        printf("-> Originate: %u\n", mensaje.originate);
+        printf("-> Receive: %d\n", mensaje.receive);
+        printf("-> Transmit: %d\n", mensaje.transmit);
+        printf("-> Tamanyo del Datagrama: %lu bytes\n", sizeof(mensaje));
+        printf("\n");
+    }
+
+    // Enviamos el mensaje
+    int bytes_enviados = sendto(numero_socket, &mensaje, sizeof(mensaje), 0, (struct sockaddr *)&direccion, sizeof(direccion));
+    if (bytes_enviados < 0)
+    {
+        perror("Error al enviar mensaje");
+        exit(EXIT_FAILURE);
+    }
+
+    printf("-> Timestamp Request enviado correctamente...\n");
+
+    // Preparar select para tiempo_espera
+    fd_set sock_lec;
+    struct timeval tiempo_espera;
+
+    FD_ZERO(&sock_lec);
+    FD_SET(numero_socket, &sock_lec);
+    tiempo_espera.tv_sec = tiempo_max;
+
+    // Esperar respuesta con tiempo_espera
+    int ready = select(numero_socket + 1, &sock_lec, NULL, NULL, &tiempo_espera);
+    if (ready < 0)
+    {
+        perror("Error en select");
+        exit(EXIT_FAILURE);
+    }
+
+    // Recibimos la respuesta
+    TimeStampReply respuesta;
+    tam = sizeof(myaddr);
+    int bytes_recibidos = recvfrom(numero_socket, &respuesta, sizeof(respuesta), 0, (struct sockaddr *)&myaddr, &tam);
+    if (bytes_recibidos < 0)
+    {
+        perror("Error en los bytes recibidos");
+        exit(EXIT_FAILURE);
+    }
+
+    // Calculamos el tiempo de recibir para el mensaje recibido
+    struct timeval tiempo_rec;
+    gettimeofday(&tiempo_rec, NULL);
+    int tiempo_rec_ms = tiempo_rec.tv_sec * 1000 + tiempo_rec.tv_usec / 1000;
+
+    printf("-> Timestamp Reply recibido desde %s\n", inet_ntoa(myaddr.sin_addr));
+    // Procesamos la respuesta ICMP
+    if (respuesta.icmpMsg.icmpHdr.type == 14 && respuesta.icmpMsg.icmpHdr.code == 0)
+    {
+        // modo verbose
+        if (v)
+        {
+            printf("-> Originate: %d\n", respuesta.icmpMsg.originate);
+            printf("-> Receive: %u\n", respuesta.icmpMsg.receive);
+            printf("-> Transmit: %u\n", respuesta.icmpMsg.transmit);
+
+            // Calcular RTT (RTT = (T2 − T1) + (T4 − T3))
+            int rtt = (respuesta.icmpMsg.receive - mensaje.originate) + (tiempo_rec_ms - respuesta.icmpMsg.transmit);
+            printf("-> RTT: %d miliseconds\n", rtt);
+
+            printf("-> TTL: %d\n", respuesta.ipHdr.TTL);
+            printf("-> Tamanyo del Datagrama: %lu bytes\n", sizeof(respuesta));
+        }
+
+        printf("-> Respuesta Correcta (Type 14, Code 0)\n");
+    }
+    // Si hay errores en la respuesta del mensaje
+    else if (respuesta.icmpMsg.icmpHdr.type == 3 || respuesta.icmpMsg.icmpHdr.type == 5 || respuesta.icmpMsg.icmpHdr.type == 11 || respuesta.icmpMsg.icmpHdr.type == 12)
+                      
+    {
+        errores_ICMP(respuesta.icmpMsg.icmpHdr.type, respuesta.icmpMsg.icmpHdr.code);
+    }
+    else
+    {
+        printf("-> ICMP Datagram Not Processed...\n");
+    }
+
+    return 0;
+}
\ No newline at end of file
-- 
GitLab