# Clases - Sniffer Simple

##Objetivos

1. Practicar la declaración e implementación de clases en C++.


## Pre-Lab:

Antes de llegar al laboratorio debes:

1. Haber repasado la declaración e implementación de clases en C++.
2. Haber estudiado los conceptos e instrucciones para la sesión de laboratorio.
3. Haber tomado el quiz Pre-Lab que se encuentra en Moodle.

## Sniffer Simple

Las computadoras se comunican con otras a través del protocolo de Internet (IP).  Cuando una computadora envia información a otra computadora es via paquetes de Internet que contienen la dirección de Internet de la computadora que envia (computadora fuente), el puerto fuente de la aplicación que está enviando el mensaje, la dirección de Internet de la computadora que recibe (computadora destino), y el puerto de la aplicación que va a recibir el mensaje.

Podemos comparar las direcciones de Internet a las direcciones de una casa, y las aplicaciones a los miembros de una casa.  Cuando se envia una carta de una casa a otra, la dirección en la carta identifica la casa destino, y el nombre en la carta identifica al miembro de la casa al que se le envía.

Por ejemplo cuando tu computadora de laboratorio esta contactactando al servidor de web del departamento, los paquetes que cargan la informacion de tu computadora al servidor de web contienen la dirección fuente de la computadora del laboratorio y la dirección destino del servidor de web; y el puerto fuente del tu buscador de web (browser) y el puerto destino del servidor de web.

Las direcciones de Internet son representados usando 4 bytes (32 bits), y comunmente son presentadas a los usuarios como cadenas de caracteres de 4 valores decimales.  Cada valor decimal es la representacion decimal de uno de los 4 bytes: "(0-255).(0-255).(0-255).(0-255)". Por ejemplo, las siguientes son tres direcciones IP  10.0.1.10, 192.168.10.11, 136.145.54.10.

Los números de los puertos son enteros sin signo en el rango de [0-65535]. Se representan usando 2 bytes (16 bits). Hay números de puertos que son asignados a servicios de aplicaciones comúnes tales como el número 22 para ssh, 23 para telnet, 25 smtp, y el 80 para http.

Para complicar las cosas un poco, cada tarjeta de red de computadoras tiene un identificador único que es usado para la comunicación entre tu computadora y el dispositivo de la red que enruta el tráfico de red de Internet y la red local a tu computadora y vice-versa (protocolo Ethernet). Este identificador único es conocido como la dirección de Hardware (también conocido como dirección MAC), es representado usando 6 bytes (48 bits), y es presentado a los usarios como una cadena de caracteres de 6 pares de dígitos hexadecimales (cada par de dígitos hexadecimal corresponde a 1 byte). Por ejemplo, los siguientes son direcciones MAC:  `e0:f8:47:01:e9:90` y  `70:ad:60:ff:fe:dd:79:d8`.

Un sniffer de paquetes (también conocido como analizador de paquetes, analizador de protocolos, o analizador de red) es un programa de computadora que puede interceptar y registrar tráfico pasando a través de una red digital, o dispositivo de red.  Mientras los datos fluyen a través de la red, el sniffer captura cada paquet, y si es necesario decodifica los datos crudos del paquete[1].

Cada paquete capturado por este programa tiene la siguiente estructura:

1. un encabezado de Ethernet que contiene las direcciones MAC fuente y destino
2. un encabezado de IP que contiene las direcciones IP fuente y destino
3. un encabezado que contiene los números de puerto fuente y destino

En esta experiencia de laboratorio completaremos un sniffer de paquetes sencillo que captura todos los paquetes de IP que fluyen a través de tu computadora de laboratorio, y alguna información adicional de los paquetes.  Adicionalmente detecta las solicitudes no encriptadas de imagenes en la web, y despliega las imágenes en el GUI.




----

![](images/ss.png)

**Figura 1** - La aplicación corriendo.

----

La Figura 1 muestra una foto de la aplicación. Cada fila en la tabla es la información de un paquete capturado, la caja de texto bajo la tabla presenta un resumen en ASCII del paquete seleccionado en la tabla, y la lista en el lado derecho presenta las imagenes que han sido solicitadas y se han visto en la tarjeta de red.

La aplicación que tu estas a punto de completar le da a los usuarios la habilidad de analizar el tráfico de red y monitorear imagenes que estan siendo vistas en tu red.


## Sesión de laboratorio

Para crear un sniffer de paquetes puedes usar la librería de *pcap* que provee una interface para accesar la data que está pasando a través de tu tarjeta de red.  Esta librería contiene una función que devuelve un torrente crudo de los bytes de cada paquete capturado.

Es la tarea del programador del sniffer decodificar el torrente en crudo a información legible por humanos.  Afortunadamente esta no va a ser tu tarea, pero tu puedes aprender a hacerlo, si quieres, leyendo el código fuente de este laboratorio.  Tu tarea es seguir los ejercicios abajo para que puedas proveerle al sniffer los objetos necesarios (Clases) para procesar los paquetes.

## Ejercicio 1: Familiriarizate con la aplicación

**Instrucciones**

1. Para cargar este proyecto necesitas correr qt creator con privilegios de administrador (root).
        ```sudo qtcreator Documents/eip/simplesniffer/SimpleSniffer.pro```

2. El proyecto `SimpleSniffer` está en el directorio `Documents/eip/simplesniffer` de tu computadora.  Alternativamente puedes crear un clon del repositorio git `http://bitbucket.org/eip-uprrp/classes-simplesniffer` para descargar el directorio `classes-simplesniffer` a tu computadora.

3. Configura el proyecto. El proyecto consiste de varios archivos.  En este laboratorio trabajarás con los archivos `ethernet_hdr.h`, `ethernet_packet.h`, `ethernet_packet.cpp`, `ip_packet.h` and `ip_packet.cpp`.

## Ejercicio 2: Completa la clase ethernet_packet

Lee el archivo `ethernet_hdr.h`, este contiene la definición de la estructura de datos que representa un encabezado de Ethernet. A continuación mostramos esa definición:

```
#define ETHER_ADDR_LEN 6

struct sniff_ethernet {
        u_char  ether_dhost[ETHER_ADDR_LEN];    /* direccion destino */
        u_char  ether_shost[ETHER_ADDR_LEN];    /* direccion fuente */
        u_short ether_type;                     /* IP? ARP? RARP? etc */
};
```

El encabezado de Ethernet arriba es usado para decodificar la parte Ethernet de los datos crudos en cada paquete.  Este se compone de la dirección MAC fuente (ether_shost, 6 bytes), la dirección MAC destino (ether_dhost, 6 bytes), y el tipo de paquete de Ethernet (ether_type, 2 bytes) que es usado para determinar si el paquete es un paquete de IP.

Como puedes ver, no es una buena idea enseñar este formato de información a un usario regular.  Tu primer tarea es definir las funciones de la clase de C++ que define las funciones para traducir la información de las direcciones MAC a cadenas de caracteres legibles por humanos.

El encabezado de la clase está en el archivo `ethernet_packet.h` y también la mostramos a continuación:

```
class ethernet_packet
{

    sniff_ethernet ethernet ;
    // Devuelve una direccion de 6 bytes MAC en una cadena de caracteres.
    string mac2string(u_char []) ;

public:
    ethernet_packet();  // Constructor por defecto

    // Ajusta la variable miembro ether_host a los valores
    // recibidos en el arreglo
    void setEtherDHost(u_char []) ;
    // Lo mismo que arriba pero al  ether_shost
    void setEtherSHost(u_char []) ;

    // Ajusta el ethernet type al valor recibido.
    void setEtherType(u_short) ;

    // Devuelve la representación en cadenas de caracteres de las direcciones
    // Ethernet
    string getEtherDHost() ;
    string getEtherSHost() ;

    // Devuelve el tipo de ethernet.
    u_short getEtherType() ;

};
```

Implementa las funciones en el archivo `ethetnet_packet.cpp`.

**[Rafa] Puedes sugerir una forma para que validen si han implementado bien la función.**

## Ejercicio 3: Construye el encabezado de ip_packet

Para el Ejercicio 3 debes estudiar las definiciones de las funciones de la clase `ip_packet` que se encuentra en el archivo `ip_packet.cpp`

Tu tarea es definir el **encabezado** de la clase siguiendo las funciones en ese archivo.  Las variables miembro son:

* dos variables  `string` para almacenar las direcciones de IP fuente y destino
* una variable de un byte (`char`) para almacenar el typo de protocolo IP
* dos variables `unsigned short` para almacenar el puerto fuente y destino
* una variable `string` para almacenar la carga del paquete.

En la declaración de la clase `ip_packet` debes especificar que es una clase derivada de la clase `ethernet_packet`.

### Entregas

Utiliza "Entrega" en Moodle para entregar los archivos `ethernet_packet.cpp` y `ip_packet.h` que definistes.

### Referencias

[1]http://en.wikipedia.org/wiki/Packet_analyzer


----
