Member of The Internet Defense League Últimos cambios
Últimos Cambios
Blog personal: El hilo del laberinto Geocaching

Desarrollo de una Herramienta Software para el Acceso a Redes TCP/IP a través de la Red Telefónica Conmutada

Última Actualización: 30 de Junio de 1.996 - Domingo

Capítulo 5:
El Módulo IP

El módulo IP (Internet Protocol) es el equivalente a la capa de RED (nivel 3) del modelo OSI de ISO. Gracias a este nivel se logra ofrecer una visión homogenea y coherente de la "red", independientemente de que ésta esté constituida por un sinnúmero de tecnologías hardware, topologías, protocolos de enlace, etc., diferentes. El objetivo último de este módulo consiste en hacer llegar datagramas de una capa IP de una máquina origen a la capa IP de la máquina destino, abstrayéndonos de los detalles subyacentes. Sus características más destacables son:

  • Proporciona una interfaz de red homogenea y estable independientemente de la red física subyacente, liberando a las capas superiores de los posibles cambios tecnológicos. Cada máquina conectada a la red dispone de una dirección IP de 32 bits que la identifica de forma unívoca, y que es independiente de su dirección física real.

  • Proporciona un servicio orientado a datagramas sin conexión. No garantiza ni la fiabilidad en la entrega ni el orden de llegada. Cuando ello es importante resulta necesario utilizar otro protocolo por encima, como el TCP (Transmission Control Protocol).

  • La posible fragmentación de los datagramas demasiado grandes como para poder atravesar redes con una MTU (Maximum Transfer Unit) pequeña es transparente a las capas superiores [RFC815].

  • Gestiona el enrutado de datagramas a máquinas en otras redes físicas de forma automática y transparente. De esta forma consigue crear la ilusión de estar compartiendo una red única a pesar de que las máquinas en cuestión pertenezcan a redes físicamente diferentes, tecnológicamente distintas y separadas por miles de kilómetros.

El protocolo IP [RFC791] es el resultado de diversos proyectos de investigación de DARPA (Defense Advanced Research Projects Agency), y aunque inicialmente su ámbito de actuación era, sobre todo, militar y universitario, en los últimos años se ha producido una explosión comercial y el número de empresas proveedoras de servicios y de máquinas conectadas a la red crece rápidamente. Ello está ocasionando que el protocolo IP original (conocido como "Versión 4") empiece a tener problemas de escala, seguridad, encaminamiento y congestión, lo que ha llevado a definir, recientemente, una ampliación conocida como "IP Versión 6" o, más popularmente, "IP Next Generation" [RFC1883] [RFC1884].

Dado que la estandarización del nuevo protocolo es muy reciente, apenas cinco meses en el momento de escribir estas líneas, hemos decidido implantar, en este Proyecto Fin de Carrera, el protocolo original. Se vaticina, además, un período de larga coexistencia mientras se produce la migración a la nueva arquitectura, siendo los sistemas personales -precisamente donde se enmarca este Proyecto- los que probablemente tarden más en completar la evolución.


Interfaz

La interfaz de este módulo se compone tanto de procesos como de rutinas que se ejecutan en el contexto del llamante.


PROC_IP_BC

Este proceso se encarga de inicializar y finalizar el módulo IP. Los mensajes admitidos son MSG_INIT y MSG_QUIT. Los campos de información son ignorados.

Una vez que este módulo ha sido inicializado, este proceso se "recicla" para gestionar las temporizaciones de los reensamblajes: cuando se recibe un datagrama fragmentado se inicia una temporización de 30 segundos y si ésta vence antes de que llegue el resto del datagrama, se descarta.


PROC_IP_SUP

Este proceso es invocado cuando alguna tarea quiere enviar un datagrama. Los mensajes que espera recibir son "MSG_MBUF", y la interpretación de los campos es como sigue:

campo1 contiene una cadena de MBUFs cuyo primer elemento consiste en una estructura IP interfaz definida como:


  typedef struct {
    uint32 ip_fuente;
    uint32 ip_destino;
    uint8  dummy;
    uint8  protocolo;
    uint16 longitud;
  } ip_header;

"ip_fuente" debe ser una de nuestras direcciones IP, mientras que "ip_destino" indica la dirección del destinatario. "dummy" es un campo ignorado y que debe ser cero. "protocolo" identifica el protocolo que debe gestionar el datagrama en el destino, mientras que "longitud" contiene el número de bytes del datagrama en sí, que aparece a continuación en la cadena MBUFs.

El datagrama puede estar constituido por varios MBUFs, pero es necesario que la cabecera IP interfaz y el datagrama en sí estén en MBUFs diferentes y que la primera esté contenida en un único MBUF.

Todos los valores multibyte de la cabecera IP interfaz deben estar en formato de red. Es decir, el byte de mayor peso es el que aparece primero (la dirección de memoria más baja).

campo2 contiene, en sus 16 bits de menor peso, un valor que no debe repetirse -en un tiempo de varios minutos- entre datagramas diferentes enviados al mismo destino y con el mismo protocolo. Este valor se utiliza en el reensamblaje IP para poder diferenciar los distintos fragmentos de un datagrama. Es posible, incluso recomendable, utilizar el mismo valor en las retransmisiones de un mismo datagrama.

campo3 contiene, normalmente, el valor cero. En ese caso se indica a la capa IP local, y a todas las que el datagrama tenga que atravesar hasta llegar a su destino, que se admite la fragmentación. Si este parámetro contiene el valor uno implicará que no se permite fragmentar el datagrama. En este caso el datagrama será descartado si es mayor que el MTU de alguna de las redes a lo largo del camino. Ello, normalmente, genera una respuesta ICMP.


PROC_IP_INF

Este proceso es el que recibe los datagramas de la capa física. Los mensajes que recibe son "MSG_MBUF". En campo1 se almacena el MBUF al datagrama (compuesto por un sólo MBUF), y campo2 y campo3 contienen valores indefinidos.

Si el datagrama es para nosotros, y tras un posible reensamblaje, se envía al proceso correspondiente según el campo "protocolo" original. El mensaje enviado es, también, "MSG_MBUF". campo1 consiste en una cadena de tres MBUFs:

  • El primer MBUF contiene la cabecera IP interfaz, definida exactamente igual que antes.

  • El segundo MBUF contiene los datos en sí del datagrama, independientemente de que el original estuviese compuesto por una cadena.

  • El tercer MBUF contiene la cabecera IP original del datagrama. Esta estructura no tiene ninguna utilidad para las capas superiores y su primera tarea debiera ser su liberación. Su razón de ser está relacionada con la capa ICMP y la gestión de errores IP.

En cuanto a rutinas en sí, tenemos:


estado ip_alta_canal(uint32 canal,uint16 MTU);

Esta rutina permite dar de alta un canal, que es una interfaz de entrada/salida de datagramas IP. Un canal, normalmente, corresponde a una interfaz física, si bien algunos sistemas permiten multiplexar diversos canales a través del mismo enlace hardware (por ejemplo, el protocolo PPP). "canal" contiene el nombre del canal que estamos creando.

"MTU" informa a la capa IP de cual es la MTU (Maximum Transfer Unit) del canal. El protocolo IP permite enviar datagramas, en teoría, de hasta 64Kb. En la práctica se ha definido un tamaño mínimo que cualquier capa IP debe gestionar: 576 bytes. El Proyecto desarrollado permite intercambiar datagramas de hasta 1024 bytes. Si se intenta enviar un datagrama con un tamaño mayor que la MTU del canal por el cual va a viajar, éste se fragmentará en porciones más manejables, que se enviarán por separado y que serán reensambladas en el destino.


void ip_baja_canal(uint32 canal);

Esta función da de baja un canal.


estado ip_alta_ip(uint32 ip,uint32 mask,uint32 canal);

Esta rutina permite asignar un número IP a un canal dado. "mask" contiene la máscara de red de esa dirección. Cualquier dirección IP cuya dirección de red, según esa máscara, coincida con la dirección de red de "ip" según esa misma máscara, se considera "alcanzable" directamente a través de ese canal. Todos los valores están en formato RED.

Por ejemplo:

ip=193.216.57.165
mask=255.255.255.128
canal=CHN1

Nuestra dirección IP asociada al canal "CHN1" es 193.216.57.165, y todas las direcciones entre 193.216.57.128 y 193.216.57.255 son "alcanzables" a través de él (pertenecen a nuestra red).

Un canal está capacitado para poseer varias direcciones IP asociadas, que pueden pertenecer a redes diferentes.


void ip_baja_ip(uint32 ip);

Esta rutina da de baja una dirección IP, en formato RED.


uint16 ip_mtu(uint32 ip);

Esta rutina devuelve el MTU del canal asociado a una dirección IP. "ip" es una de nuestras direcciones, en formato RED. La función retorna el MTU del canal, o cero si no existe.


estado ip_alta_gateway(uint32 ip,uint32 mask,uint32 gateway);

Esta rutina permite crear tablas de encaminamiento mediante la inclusión de pasarelas y redes asociadas. "ip" y "mask", juntos, definen la dirección de red alcanzable a través de la pasarela propuesta. Las pasarelas deben ser "alcanzables" a través de alguno de nuestros canales.


void ip_baja_gateway(uint32 gateway);

Como su nombre indica, esta rutina da de baja una pasarela.


estado ip_alta_protocolo(uint8 protocolo,proc_id id);

Todos los datagramas tienen un protocolo asociado (ver la definición de la cabecera IP interfaz definida con anterioridad). Esta rutina permite especificar qué proceso se encarga de gestionar los datagramas recibidos para un protocolo dado: ICMP, IGMP, UDP, TCP, RTP, etc.


void ip_baja_protocolo(uint8 protocolo);

Da de baja un protocolo. Los datagramas que se reciban para ese protocolo serán descartados y se generará un error ICMP.


proc_id ip_proc_protocolo(uint8 protocolo);

Esta rutina indica qué proceso es el responsable de un protocolo. Si el protocolo especificado no tiene un proceso asociado se devuelve PROC_INDEF.


uint32 ip_calcula_destino(uint32 ip_destino,puint32 ip_nuevo_dest);

Esta rutina proporciona información de encaminamiento. "ip_destino" contiene la dirección que queremos alcanzar. La rutina devuelve la dirección IP del interfaz que debemos utilizar para llegar a la máquina deseada, mientras que "ip_nuevo_dest" nos dará la nueva dirección destino. Será la misma que la inicial si la dirección indicada pertenece a una de nuestras redes locales (es "alcanzable"). En caso contrario "ip_nuevo_dest" contendrá la dirección de la pasarela que tendremos que usar para alcanzar el objetivo.

Un valor devuelto de 0.0.0.0 indica que nuestras tablas de encaminamiento no permiten llegar a esa localización.

Todos los valores están en formato RED.


estado ip_flujo(uint32 ip,uint16 tamanho);

Dado que la capa IP proporciona un servicio de datagramas sin control de flujo implícito y este Proyecto Fin de Carrera ha sido diseñado para trabajar con interfaces serie de baja velocidad, resulta necesario implementar algún mecanismo de control de flujo para evitar el desbordamiento de las colas de transmisión. Esta rutina nos da acceso a dicho mecanismo. A través de ella se pide permiso para enviar un datagrama de "tamanho" bytes a través de la dirección local "ip" (este último valor en formato RED). Si se nos deniega podemos reintentarlo de nuevo tras una espera prudencial (una décima de segundo, por ejemplo).

Este sistema es completamente diferente al implementado en el Laboratorio de Comunicación de Datos [LABCD], basado en el intercambio de testigos, debido a que ahora pueden existir diversas fuentes de datagramas y diversas vías de salida (canales).


estado ip_trace(uint32 canal,tip_trace POINTER trace);

Esta rutina devuelve una estructura "tip_trace" conteniendo diversa información sobre un canal dado. Se declara como:


  typedef struct {
    uint32 rx;
    uint32 tx;
    uint32 vers_error;
    uint32 ihl_error;
    uint32 df_error;
    uint32 tl_error;
    uint32 ttl_excedido;
    uint32 prot_error;
    uint32 hc_error;
  } tip_trace;

Los dos primeros campos indican el número de datagramas transmitidos y recibidos. Los siguientes campos informan del número de datagramas recibidos con diversos errores: versión, tamaño de la cabecera, fragmentación y longitud. "ttl_excedido" indica el número de datagramas cuyo tiempo de vida se excedió mientras los estábamos reencaminando. "prot_error" contabiliza el número de datagramas recibidos que iban destinados a un protocolo desconocido. Por último, "hc_error" cuenta el número de errores de suma de control detectados.


Implementación

Este módulo implanta una capa IP fiel al modelo definido en [RFC791]. Se han eliminado, no obstante, algunas funcionalidades por considerarlas superfluas y que no son utilizadas en Internet: opciones de seguridad, "source routing", "record route", "stream ID" e "Internet timestamp".

Adicionalmente se han fijado los siguientes valores de operación:

  • Longitud fija de la cabecera IP: 20 bytes.

  • Tipo de servicio "normal": retardo, capacidad y fiabilidad normales. Tráfico tipo "rutina".

  • Tiempo de vida máximo de los datagramas: 60 segundos

Cuando se envía un datagrama se comprueba que la dirección IP fuente especificada se corresponda con alguna de las nuestras. Lo siguiente que se hace es comprobar si el destino pertenece a alguna de nuestras redes locales. Si es así, se le envía directamente. En caso contrario se busca alguna pasarela que lo cubra, y en cuanto se encuentre una válida se le enviará a ella.

Las tablas de encaminamiento, por tanto, deben declararse de redes pequeñas a grandes. En particular, resulta útil definir una pasarela última con máscara 0.0.0.0 que se haga responsable de todos los datagramas que no sabemos enrutar. Las pasarelas en sí, como ya se ha indicado, deben ser alcanzables directamente.

Cualquier error detectado en la gestión de datagramas provoca la generación de respuestas ICMP. Ello incluye también la incapacidad de llegar a una dirección dada ("Destination Unreachable"), el vencimiento del tiempo de vida de los datagramas reencaminados y del tiempo de reensamblaje ("Time Exceded") y el desbordamiento de las colas de transmisión durante el reenrutado ("Source Quench").

Para dar de alta una nueva dirección IP es necesario haber declarado antes su canal. Igualmente, cuando se elimina un canal se borran de forma automática todas sus direcciones IP asociadas.


Bibliografía


[LABCD]     Laboratorio de Comunicación de Datos
            Curso 94-95. Vigo, 16 de Marzo de 1.995
            Alvaro Manuel Gómez Vieites
            Carlos Gabieiro Martínez
            Jose Cadavid Jáuregui
            Jesús Cea Avión

[RFC791]    RFC 791: "Internet Protocol"
            Jon Postel
            Septiembre 1.981

[RFC815]    RFC 815: "IP Datagram Reassembly Algorithms"
            David D. Clark
            Julio 1.982

[RFC966]    RFC966: "Host Groups: A Multicast Extension to the
            Internet Protocol"
            S. E. Deering
            D. R. Cheriton
            Diciembre 1.985

[RFC988]    RFC988: "Host Extensions for IP Multicasting"
            S. E. Deering
            Julio 1.986

[RFC1112]   RFC1112: "Host Extensions for IP Multicasting"
            Steve Deering
            Agosto 1.989

[RFC1122]   RFC1122: "Requirements for Internet Hosts --
            Communication Layers"
            Robert Braden
            Octubre 1.989

[RFC1349]   RFC1349: "Type of Service in the Internet Protocol
            Suite"
            Philip Almquist
            Julio 1.992

[RFC1455]   RFC1455: "Physical Link Security Type of Service"
            Donald E. Eastlake, III
            Mayo 1.993

[RFC1546]   RFC1546: "Host Anycasting Service"
            Walter Milliken
            Trevor Mendez
            Craig Partridge
            Noviembre 1.993

[RFC1812]   RFC1812: "Requirements for IP Version 4 Routers"
            Fred Baker
            Junio 1.995

[RFC1883]   RFC1883: "Internet Protocol, Version (IPv6)
            Specification"
            S. Deering
            R. Hinden
            Diciembre 1.995

[RFC1884]   RFC1884: "IP Version 6 Addressing Architecture"
            S. Deering
            R. Hinden
            Diciembre 1.995



Python Zope ©1996 jcea@jcea.es

Más información sobre los OpenBadges

Donación BitCoin: 19niBN42ac2pqDQFx6GJZxry2JQSFvwAfS