]> git.llucax.com Git - z.facultad/75.74/practicos.git/blobdiff - practicas/pipi/README
Se verifica si expiró el cache y se lo elimina si así fuere.
[z.facultad/75.74/practicos.git] / practicas / pipi / README
index 2243ff319cf277e5b7d3c258d4e24f8e0f84f170..5e57b5bb44e12e9c5dc2466b3e15fb7bd46b306e 100644 (file)
@@ -2,12 +2,13 @@
 Sistemas Distribuidos I (75.74)
 ===============================
 
 Sistemas Distribuidos I (75.74)
 ===============================
 
-----------------------------
-Trabajo práctico de stack IP
-----------------------------
+------------------------------------------------------------------
+TP 2: Sistema de resolución de nombres sobre IP adaptado a sockets
+------------------------------------------------------------------
 
 :Author: Leandro Lucarella (77891)
 
 
 :Author: Leandro Lucarella (77891)
 
+.. contents::
 
 Organización
 ============
 
 Organización
 ============
@@ -16,29 +17,30 @@ En el directorio `src` se encuentra el código fuente del trabajo, con su
 correspondiente `Makefile` para compilarlo tan solo ejecutando `make`.
 
 En el directorio `rutas_ejemplo` contiene algunos archivos con descripciones de
 correspondiente `Makefile` para compilarlo tan solo ejecutando `make`.
 
 En el directorio `rutas_ejemplo` contiene algunos archivos con descripciones de
-rutas de ejemplo para correr los programas.
+rutas de ejemplo para correr los programas. En el directorio `zonas_ejemplo` se
+encuentran archivos de configuración de zonas de dominios de nombre para
+realizar pruebas.
 
 
 Uso
 ===
 
 
 
 Uso
 ===
 
-El trabajo tiene 2 programas de prueba principales: `test_ipin` y `test_ipout`,
-ambos generados en el directorio `src` luego de compilar el código.
+El trabajo consta de dos programas, uno llamado `ip` y otro `dns` (más algunas
+otras pruebas que no tienen relevancia).
 
 
-test_ipin
----------
+ip
+--
 
 
-Este programa es el proceso que recibe paquetes IP y los procesa.
+El programa `ip` corre 3 procesos (fork(2)eados), uno que recibe paquetes IP
+otro que recibe entrada del usuario y envía paquetes IP y otro que redirecciona
+(forward) paquetes IP en caso de ser pertinente.
 
 Uso::
 
 
 Uso::
 
-  ./test_ipin [ip] [mtu] [router] [forward] [proto] [queue_id]
+  ./ip ip [router [forward [route_file [queue_id [proto]]]]]
 
 ip
 
 ip
-  IP que utiliza este proceso (default 10.10.10.1)
-
-mtu
-  MTU de la capa física de este proceso (default 25)
+  IP que utiliza este proceso
 
 router
   0 si es router, 1 si no lo es (default 0)
 
 router
   0 si es router, 1 si no lo es (default 0)
@@ -46,8 +48,11 @@ router
 forward
   0 si puede hacer forwarding, 1 si no (default 0)
 
 forward
   0 si puede hacer forwarding, 1 si no (default 0)
 
-proto
-  Protocolo que transporta (default 0)
+route_file
+  Archivo con las rutas. El formato del archivo es una ruta por línea, cada
+  línea se compone de red (por ahora sólo soporta IPs puntuales), gateway (si es
+  cero es que están en la misma red), MTU y métrica (todavía no se usa),
+  separados por uno o más espacios o tabs (default `route.txt`)
 
 queue_id
   Identificador de la cola a usar como medio físico, también establece el
 
 queue_id
   Identificador de la cola a usar como medio físico, también establece el
@@ -55,39 +60,59 @@ queue_id
   (`test_ipout`) para hacer forwarding, que será queue_id + 1 (default
   `DEV_DEFAULT_KEY` obtenido de `dev.h`)
 
   (`test_ipout`) para hacer forwarding, que será queue_id + 1 (default
   `DEV_DEFAULT_KEY` obtenido de `dev.h`)
 
+proto
+  Protocolo que transporta (default 0)
+
+
+El programa se queda esperando la entrada del usuario, y sale cuando esta se
+termina (Ctrl-D). El formato de entrada es::
+
+  IP DESTINO
+  MENSAJE
 
 
-test_ipout
-----------
+Es decir, en una línea se pone la IP de destino y en la línea siguiente el
+mensaje. Para enviar otro mensaje, nuevamente se pone IP de destino en una línea
+y el mensaje en la siguiente.
 
 
-Este programa es el proceso que envía paquetes IP y rutea.
+dns
+---
+
+El programa `dns` corre también 3 procesos (fork(2)eados), uno que recibe
+peticiones de nombres, otro que recibe entrada del usuario y envía peticiones
+(o mejor dicho encola peticiones para ser enviadas) y otro que realiza el envío
+de las peticiones realmente.
 
 Uso::
 
 
 Uso::
 
-  ./test_ipout [ip] [dst] [mtu] [routes_file] [proto] [queue_id]
+  ./dns ip [route_file [zone_file [port]]]
 
 ip
 
 ip
-  IP que utiliza este proceso (default 10.10.10.2)
+  IP que utiliza este proceso (ídem programa `ip`)
 
 
-dst
-  IP del destino al cual mandar paquetes (default 10.10.10.1)
+route_file
+  Archivo con las rutas (ídem programa `ip`)
 
 
-mtu
-  MTU de la capa física de este proceso (default 25)
+zone_file
+  Archivo con la descripción de las zonas. El formato es muy simple. Cada zona
+  está separada por un renglón en blanco y empieza con una línea con 3 campos
+  separados por espacios o tab: nombre de la zona, TTL y nodo padre. Luego le
+  sigue la lista de registros de esa zona, también con 3 campos por renglón:
+  nombre, tipo de registro (A para indicar una IP, NS para indicar donde buscar
+  registros de una zona con ese nombre) e IP (ya sea la IP definitiva si es A o
+  la IP del nameserver al cual recurrir si es NS). Se pueden ver ejemplos de
+  estos archivos en el disco entregado.
 
 
-route_file
-  Archivo con las rutas. El formato del archivo es una ruta por línea, cada
-  línea se compone de red (por ahora sólo soporta IPs puntuales), gateway (si es
-  cero es que están en la misma red) y métrica (todavía no se usa), separados
-  por uno o más espacios o tabs (default `route.txt`)
+port
+  Puerto en el cual escuchará la abstracción de capa física sobre TCP.
 
 
-proto
-  Protocolo que transporta (default 0)
 
 
-queue_id
-  Identificador de la cola a usar como medio físico, también establece el
-  identificador de la cola a usar para comunicarse con el otro proceso
-  (`test_ipout`) para hacer forwarding, que será queue_id + 1 (default
-  `DEV_DEFAULT_KEY` obtenido de `dev.h`)
+El programa es muy similar a `ip`, se queda esperando la entrada del usuario,
+y sale cuando esta se termina (Ctrl-D). El formato de entrada es::
+
+  HOSTNAME_A_BUSCAR
+
+Es decir, se escribe en una línea el nombre del host del cual se quiera obtener
+la IP y se presiona ENTER.
 
 
 Diseño del trabajo
 
 
 Diseño del trabajo
@@ -97,11 +122,21 @@ El trabajo fue desarrollado en C++, orientado a objetos. Se compone de las
 siguientes clases:
 
 Dev
 siguientes clases:
 
 Dev
-  Encapsula la capa física y el dispositivo de red. Utiliza una cola como medio
-  físico y el id representaría el cable (si 2 dispositivos tienen cola con id
-  distinto serían como si no compartieran el mismo cable). Por simplicidad a la
-  cola siempre se envía el tamaño del MTU completo pero se agrega una cabecera
-  con el tamaño real del frame.
+  Encapsula la capa física y el dispositivo de red. Es una interfaz abstracta.
+
+DevQue
+  Implementación de Dev utilizando una cola como medio físico y el id
+  representaría el cable (si 2 dispositivos tienen cola con id distinto serían
+  como si no compartieran el mismo cable). Por simplicidad a la cola siempre
+  se envía el tamaño del MTU completo pero se agrega una cabecera con el
+  tamaño real del frame.
+
+DevTCP
+  Implementación de Dev utilizando conexiones TCP. Por cada frame saliente a un
+  destino en particular se crea una conexión TCP (a menos que ya esté creada, en
+  cuyo caso se reutiliza) y se escucha por conexiones entrantes para recibir
+  frames (también guardándolas para reutilizarlas). A diferencia del DevQue se
+  envía el tamaño del frame exacto (en realidad se agrega una pequeña cabecera).
 
 IPAddr
   Clase auxiliar que encapsula una dirección IP.
 
 IPAddr
   Clase auxiliar que encapsula una dirección IP.
@@ -115,8 +150,8 @@ RouteTable
   Encapsula una tabla de ruteo. Por falta de tiempo y simplicidad por ahora sólo
   soporta rutas a un sólo host (no a una red) pero es muy fácilmente extensible
   y transparente para el resto de las clases que la usan. Las rutas se componen
   Encapsula una tabla de ruteo. Por falta de tiempo y simplicidad por ahora sólo
   soporta rutas a un sólo host (no a una red) pero es muy fácilmente extensible
   y transparente para el resto de las clases que la usan. Las rutas se componen
-  de red (en realidad por ahora host), geteway, metrica y dispositivo de red por
-  el cual salir (Dev).
+  de red (en realidad por ahora host), geteway, MTU, metrica y dispositivo de
+  red por el cual salir (Dev).
   
 IPIn
   Es la clase encargada de recibir paquetes IP. Hace chequeos varios y descarta
   
 IPIn
   Es la clase encargada de recibir paquetes IP. Hace chequeos varios y descarta
@@ -125,6 +160,7 @@ IPIn
   * Cabecera incompleta o no es IP
   * Versión IP incorrecta
   * Mal checksum
   * Cabecera incompleta o no es IP
   * Versión IP incorrecta
   * Mal checksum
+  * TTL=0
   * No es para nosotros y no hacemos forward
   * Es para nosotros pero somos un router
 
   * No es para nosotros y no hacemos forward
   * Es para nosotros pero somos un router
 
@@ -139,169 +175,178 @@ IPOut
   * No existe una ruta para el destino
   * Tamaño de paquete más grande que MTU y DF=1
 
   * No existe una ruta para el destino
   * Tamaño de paquete más grande que MTU y DF=1
 
+libtcp
+  Es el único componente del TP que no es orientado a objetos ya que se
+  reutilizó de trabajos anteriores. Es una pequeña abstracción sobre la API de
+  sockets de BSD para mayor simplicidad.
+
+ResolvProtoRequest
+  Clase que encapsula una petición de resolución de nombre a enviar via IP.
+
+ResolvProtoResponse
+  Clase que encapsula una respuesta de resolución de nombre a enviar via IP.
+
+NameServer
+  Clase encargada de resolver los nombres. Escucha por peticiones y puede
+  resolverlas recursiva o directamente (según venga de otro NameServer o de un
+  Resolver la petición). Esta clase se compone de varias otras clases auxiliares
+  para almacenar las zonas y el cache.
+
 
 Ejemplo de corrida
 ==================
 
 
 Ejemplo de corrida
 ==================
 
-Host 10.10.10.1
----------------
-
-Rutas:
-
-* 10.10.10.1   0.0.0.0         0
-* 10.10.10.3   10.10.10.5      0
-* 10.10.10.5   0.0.0.0         0
-
-Envía "adios mundo cruel!!!" al host 10.10.10.3::
-
-  $ ./test_ipout 10.10.10.1 10.10.10.3 25 ../rutas_ejemplo/route_10.10.10.1.txt 
-  Se agregó tabla para 10.10.10.1: gw = 0.0.0.0, metric = 0
-  Se agregó tabla para 10.10.10.2: gw = 0.0.0.0, metric = 0
-  Se agregó tabla para 10.10.10.3: gw = 10.10.10.5, metric = 0
-  Se agregó tabla para 10.10.10.5: gw = 0.0.0.0, metric = 0
-  adios mundo cruel!!!
-  IPOut::send: Fragmento 0 => IPHeader: version= total_len=40 id=56121 DF=0 MF=1 offset=0 TTL=64 proto=0 checksum=196 src=10.10.10.1 dst=10.10.10.3
-          data (5) = adios
-  Dev::transmit(msgtype/mac = 168430085, size = 25)
-  IPOut::send: Fragmento 0 => IPHeader: version= total_len=35 id=56121 DF=0 MF=1 offset=5 TTL=64 proto=0 checksum=231 src=10.10.10.1 dst=10.10.10.3
-          data (5) =  mund
-  Dev::transmit(msgtype/mac = 168430085, size = 25)
-  IPOut::send: Fragmento 0 => IPHeader: version= total_len=30 id=56121 DF=0 MF=1 offset=10 TTL=64 proto=0 checksum=266 src=10.10.10.1 dst=10.10.10.3
-          data (5) = o cru
-  Dev::transmit(msgtype/mac = 168430085, size = 25)
-  IPOut::send: Fragmento 0 => IPHeader: version= total_len=25 id=56121 DF=0 MF=0 offset=15 TTL=64 proto=0 checksum=297 src=10.10.10.1 dst=10.10.10.3
-          data (5) = el!!!
-  Dev::transmit(msgtype/mac = 168430085, size = 25)
-  Enviado 'adios mundo cruel!!!' a 10.10.10.3
-
-El proceso test_ipin de este host no tiene relevancia.
-
-Router 10.10.10.5
------------------
-
-Rutas:
-
-* 10.10.10.1   0.0.0.0         0
-* 10.10.10.3   0.0.0.0         0
-* 10.10.10.5   0.0.0.0         0
-
-Recibe el mensaje::
-
-  $ ./test_ipin 10.10.10.5 25 1 1
-  Quedan 4 mensajes en la cola
-  Dev::receive(msgtype/mac = 168430085, size = 25)
-  IPIn::recv: IPHeader: version= total_len=40 id=56121 DF=0 MF=1 offset=0 TTL=64 proto=0 checksum=196 src=10.10.10.1 dst=10.10.10.3
-    data (5) = adios
-  Dev::transmit(msgtype/mac = 168430085, size = 25)
-  Dev::receive(msgtype/mac = 168430085, size = 25)
-  IPIn::recv: IPHeader: version= total_len=35 id=56121 DF=0 MF=1 offset=5 TTL=64 proto=0 checksum=231 src=10.10.10.1 dst=10.10.10.3
-    data (5) =  mund
-  Dev::transmit(msgtype/mac = 168430085, size = 25)
-  Dev::receive(msgtype/mac = 168430085, size = 25)
-  IPIn::recv: IPHeader: version= total_len=30 id=56121 DF=0 MF=1 offset=10 TTL=64 proto=0 checksum=266 src=10.10.10.1 dst=10.10.10.3
-    data (5) = o cru
-  Dev::transmit(msgtype/mac = 168430085, size = 25)
-  Dev::receive(msgtype/mac = 168430085, size = 25)
-  IPIn::recv: IPHeader: version= total_len=25 id=56121 DF=0 MF=0 offset=15 TTL=64 proto=0 checksum=297 src=10.10.10.1 dst=10.10.10.3
-    data (5) = el!!!
-  Dev::transmit(msgtype/mac = 168430085, size = 25)
-
-Y lo forwardea (refragmentando porque tiene un MTU más pequeño)::
-
-  $ ./test_ipout 10.10.10.5 10.10.10.1 23 ../rutas_ejemplo/route_10.10.10.5.txt
-  Se agregó tabla para 10.10.10.1: gw = 0.0.0.0, metric = 0
-  Se agregó tabla para 10.10.10.2: gw = 0.0.0.0, metric = 0
-  Se agregó tabla para 10.10.10.3: gw = 0.0.0.0, metric = 0
-  Se agregó tabla para 10.10.10.5: gw = 0.0.0.0, metric = 0
-  a
-  IPOut::send: Fragmento 0 => IPHeader: version= total_len=21 id=56140 DF=0 MF=0 offset=0 TTL=64 proto=0 checksum=194 src=10.10.10.5 dst=10.10.10.1
-    data (1) = a
-  Dev::transmit(msgtype/mac = 168430081, size = 21)
-  Enviado 'a' a 10.10.10.1
-  a
-  Dev::receive(msgtype/mac = 168430085, size = 25)
-  IPOut::send: A forwardear
-  IPOut::send: Fragmento 0 => IPHeader: version= total_len=40 id=56121 DF=0 MF=1 offset=0 TTL=64 proto=0 checksum=196 src=10.10.10.1 dst=10.10.10.3
-    data (3) = adi
-  Dev::transmit(msgtype/mac = 168430083, size = 23)
-  IPOut::send: Fragmento 0 => IPHeader: version= total_len=37 id=56121 DF=0 MF=1 offset=3 TTL=64 proto=0 checksum=217 src=10.10.10.1 dst=10.10.10.3
-    data (2) = os
-  Dev::transmit(msgtype/mac = 168430083, size = 22)
-  Dev::receive(msgtype/mac = 168430085, size = 25)
-  IPOut::send: A forwardear
-  IPOut::send: Fragmento 0 => IPHeader: version= total_len=35 id=56121 DF=0 MF=1 offset=5 TTL=64 proto=0 checksum=231 src=10.10.10.1 dst=10.10.10.3
-    data (3) =  mu
-  Dev::transmit(msgtype/mac = 168430083, size = 23)
-  IPOut::send: Fragmento 0 => IPHeader: version= total_len=32 id=56121 DF=0 MF=1 offset=8 TTL=64 proto=0 checksum=252 src=10.10.10.1 dst=10.10.10.3
-    data (2) = nd
-  Dev::transmit(msgtype/mac = 168430083, size = 22)
-  Dev::receive(msgtype/mac = 168430085, size = 25)
-  IPOut::send: A forwardear
-  IPOut::send: Fragmento 0 => IPHeader: version= total_len=30 id=56121 DF=0 MF=1 offset=10 TTL=64 proto=0 checksum=266 src=10.10.10.1 dst=10.10.10.3
-    data (3) = o c
-  Dev::transmit(msgtype/mac = 168430083, size = 23)
-  IPOut::send: Fragmento 0 => IPHeader: version= total_len=27 id=56121 DF=0 MF=1 offset=13 TTL=64 proto=0 checksum=287 src=10.10.10.1 dst=10.10.10.3
-    data (2) = ru
-  Dev::transmit(msgtype/mac = 168430083, size = 22)
-  Dev::receive(msgtype/mac = 168430085, size = 25)
-  IPOut::send: A forwardear
-  IPOut::send: Fragmento 0 => IPHeader: version= total_len=25 id=56121 DF=0 MF=1 offset=15 TTL=64 proto=0 checksum=301 src=10.10.10.1 dst=10.10.10.3
-    data (3) = el!
-  Dev::transmit(msgtype/mac = 168430083, size = 23)
-  IPOut::send: Fragmento 0 => IPHeader: version= total_len=22 id=56121 DF=0 MF=0 offset=18 TTL=64 proto=0 checksum=62 src=10.10.10.1 dst=10.10.10.3
-    data (2) = !!
-  Dev::transmit(msgtype/mac = 168430083, size = 22)
-  IPOut::send: Fragmento 0 => IPHeader: version= total_len=21 id=56147 DF=0 MF=0 offset=0 TTL=64 proto=0 checksum=201 src=10.10.10.5 dst=10.10.10.1
-    data (1) = a
-  Dev::transmit(msgtype/mac = 168430081, size = 21)
-  Enviado 'a' a 10.10.10.1
-
-(notar que para que haga el forwarding se tuvo que enviar un paquete
-*dummy* para que busque en la cola de paquetes a forwardear (es un error
-de diseño que tendré que corregir de alguna forma)
-
-Host 10.10.10.3
----------------
-
-Rutas:
-
-* 10.10.10.1   10.10.10.5      0
-* 10.10.10.3   0.0.0.0         0
-* 10.10.10.5   0.0.0.0         0
-
-Finalmente este host recibe todos los fragmentos, reensabla y pasa el
- paquete completo a la capa superior::
-
-  $ ./test_ipin 10.10.10.3 23
-  Quedan 8 mensajes en la cola
-  Dev::receive(msgtype/mac = 168430083, size = 23)
-  IPIn::recv: IPHeader: version= total_len=40 id=56121 DF=0 MF=1 offset=0 TTL=64 proto=0 checksum=196 src=10.10.10.1 dst=10.10.10.3
-    data (3) = adi
-  Dev::receive(msgtype/mac = 168430083, size = 22)
-  IPIn::recv: IPHeader: version= total_len=37 id=56121 DF=0 MF=1 offset=3 TTL=64 proto=0 checksum=217 src=10.10.10.1 dst=10.10.10.3
-    data (2) = os
-  Dev::receive(msgtype/mac = 168430083, size = 23)
-  IPIn::recv: IPHeader: version= total_len=35 id=56121 DF=0 MF=1 offset=5 TTL=64 proto=0 checksum=231 src=10.10.10.1 dst=10.10.10.3
-    data (3) =  mu
-  Dev::receive(msgtype/mac = 168430083, size = 22)
-  IPIn::recv: IPHeader: version= total_len=32 id=56121 DF=0 MF=1 offset=8 TTL=64 proto=0 checksum=252 src=10.10.10.1 dst=10.10.10.3
-    data (2) = nd
-  Dev::receive(msgtype/mac = 168430083, size = 23)
-  IPIn::recv: IPHeader: version= total_len=30 id=56121 DF=0 MF=1 offset=10 TTL=64 proto=0 checksum=266 src=10.10.10.1 dst=10.10.10.3
-    data (3) = o c
-  Dev::receive(msgtype/mac = 168430083, size = 22)
-  IPIn::recv: IPHeader: version= total_len=27 id=56121 DF=0 MF=1 offset=13 TTL=64 proto=0 checksum=287 src=10.10.10.1 dst=10.10.10.3
-    data (2) = ru
-  Dev::receive(msgtype/mac = 168430083, size = 23)
-  IPIn::recv: IPHeader: version= total_len=25 id=56121 DF=0 MF=1 offset=15 TTL=64 proto=0 checksum=301 src=10.10.10.1 dst=10.10.10.3
-    data (3) = el!
-  Dev::receive(msgtype/mac = 168430083, size = 22)
-  IPIn::recv: IPHeader: version= total_len=22 id=56121 DF=0 MF=0 offset=18 TTL=64 proto=0 checksum=62 src=10.10.10.1 dst=10.10.10.3
-    data (2) = !!
-  IPIn::recv: Paquete completo: data = 'adios mundo cruel!!!'
-  Recibido 'adios mundo cruel!!!' (len 20) de 10.10.10.1 para 10.10.10.3 (proto = 0)
-
-El proceso test_ipout de este host no tiene relevancia.
-
-
-.. vim: filetype=rst :
+Archivo de configuración de zonas de 10.10.10.2::
+
+  homero.casa  600     10.10.10.1
+  tito A       10.10.100.1
+  juan A       10.10.100.2
+  juan A       10.10.100.3
+  pepe A       10.10.100.4
+  juan A       10.10.100.5
+  pepe A       10.10.100.6
+  marge        NS      10.10.10.3
+  todos        NS      10.10.10.1
+  todos        NS      10.10.10.3
+  todos        NS      10.10.10.141
+
+Línea de comandos::
+
+  ./dns 10.10.10.2 ../rutas_ejemplo/mi_lan.txt ../zonas_ejemplo/10.10.10.2.txt
+
+Resolución de un nombre local con una sola IP
+---------------------------------------------
+
+Línea de comandos::
+
+  ./dns 10.10.10.2 ../rutas_ejemplo/mi_lan.txt ../zonas_ejemplo/10.10.10.2.txt
+
+Salida::
+
+  tito.homero.casa
+  Resolviendo tito.homero.casa...
+  resolv_direct -> tratando de resolver: tito.homero.casa
+  resolv_direct found (local/hijo): ResolvProtoResponse(ret=2, ttl=600, 10.10.100.1)
+  resolv_recursive -> gotcha! ResolvProtoResponse(ret=2, ttl=600, 10.10.100.1)
+  Resultado: ResolvProtoResponse(ret=2, ttl=600, 10.10.100.1)
+
+Resolución de un nombre local con múltiples IP
+----------------------------------------------
+
+Salida::
+
+  juan.homero.casa
+  Resolviendo juan.homero.casa...
+  resolv_direct -> tratando de resolver: juan.homero.casa
+  resolv_direct found (local/hijo): ResolvProtoResponse(ret=2, ttl=600, 10.10.100.2, 10.10.100.3, 10.10.100.5)
+  resolv_recursive -> gotcha! ResolvProtoResponse(ret=2, ttl=600, 10.10.100.2, 10.10.100.3, 10.10.100.5)
+  Resultado: ResolvProtoResponse(ret=2, ttl=600, 10.10.100.2, 10.10.100.3, 10.10.100.5)
+
+Resolución de un nombre local no existente
+------------------------------------------
+
+Salida::
+
+  none.homero.casa
+  Resolviendo none.homero.casa...
+  resolv_direct -> tratando de resolver: none.homero.casa
+  resolv_direct NOT FOUND (es local pero no existe)
+  Resultado: ResolvProtoResponse(ret=4, ttl=0)
+
+Resolución de un nombre remoto con múltiples IP y 2 niveles de indirección
+--------------------------------------------------------------------------
+
+Archivo de configuración de zonas de 10.10.10.1::
+
+  casa  600 0.0.0.0
+  burns A 10.10.10.1
+  homero  A 10.10.10.2
+  marge A 10.10.10.3
+  manuk A 10.10.10.141
+  juan  A 100.10.100.5
+  pepe  A 100.10.100.6
+  homero  NS  10.10.10.2
+  marge NS  10.10.10.3
+  manuk NS  10.10.10.141
+
+  burns.casa  600 0.0.0.0
+  tito  A 100.10.100.1
+  juan  A 100.10.100.2
+  juan  A 100.10.100.3
+  pepe  A 100.10.100.4
+  juan  A 100.10.100.5
+  pepe  A 100.10.100.6
+
+  todos.homero.casa 9500  0.0.0.0
+  tito  A 10.1.100.1
+  juan  A 10.1.100.2
+  juan  A 10.1.100.3
+  pepe  A 10.1.100.4
+  juan  A 10.1.100.5
+  pepe  A 10.1.100.6
+
+Archivo de configuración de zonas de 10.10.10.3::
+
+  marge.casa  600 10.10.10.1
+  tito  A 30.10.100.1
+  juan  A 30.10.100.2
+  juan  A 30.10.100.3
+  pepe  A 30.10.100.4
+  juan  A 30.10.100.5
+  pepe  A 30.10.100.6
+  manuk NS  10.10.10.141
+  todos NS  10.10.10.1
+  todos NS  10.10.10.3
+  todos NS  10.10.10.141
+
+  todos.homero.casa 9500  10.10.10.2
+  tito  A 10.1.100.1
+  juan  A 10.1.100.2
+  juan  A 10.1.100.3
+  pepe  A 10.1.100.4
+  juan  A 10.1.100.5
+  pepe  A 10.1.100.6
+
+  marge.homero.casa 9500  10.10.10.2
+  tito  A 10.3.100.1
+  juan  A 10.3.100.2
+  juan  A 10.3.100.3
+  pepe  A 10.3.100.4
+  juan  A 10.3.100.5
+  pepe  A 10.3.100.6
+
+
+La petición se realiza desde 10.10.10.2, quien debe recurir a su nodo padre
+(10.10.10.1) que indica que el encargado de resolver esa zona es 10.10.10.3.
+
+Salida de 10.10.10.2::
+
+  pepe.marge.casa
+  Resolviendo pepe.marge.casa...
+  resolv_direct -> tratando de resolver: pepe.marge.casa
+  resolv_direct -> evaluando padre 10.10.10.1
+  resolv_direct found (al padre): 10.10.10.1
+  resolv_recursive -> redirect a ResolvProtoResponse(ret=3, ttl=600, 10.10.10.1)
+  query -> pidiendo ResolvProtoRequest(query_type=0, name=pepe.marge.casa) a 10.10.10.1
+  query -> recibido ResolvProtoResponse(ret=3, ttl=600, 10.10.10.3) de 10.10.10.1
+  resolv_recursive_r -> redirect a ResolvProtoResponse(ret=3, ttl=600, 10.10.10.3)
+  query -> pidiendo ResolvProtoRequest(query_type=0, name=pepe.marge.casa) a 10.10.10.3
+  query -> recibido ResolvProtoResponse(ret=2, ttl=600, 30.10.100.4, 30.10.100.6) de 10.10.10.3
+  resolv_recursive_r -> gotcha! ResolvProtoResponse(ret=2, ttl=600, 30.10.100.4, 30.10.100.6)
+  Resultado: ResolvProtoResponse(ret=2, ttl=600, 30.10.100.4, 30.10.100.6)
+
+Salida de 10.10.10.1::
+
+  NameServer::send_loop() -> recibido ResolvProtoRequest(query_type=0, name=pepe.marge.casa)
+  resolv_direct -> tratando de resolver: pepe.marge.casa
+  resolv_direct found (local/hijo): ResolvProtoResponse(ret=3, ttl=600, 10.10.10.3)
+  NameServer::send_loop() -> respondo ResolvProtoResponse(ret=3, ttl=600, 10.10.10.3)
+
+Salida de 10.10.10.3::
+
+  NameServer::send_loop() -> recibido ResolvProtoRequest(query_type=0, name=pepe.marge.casa)
+  resolv_direct -> tratando de resolver: pepe.marge.casa
+  resolv_direct found (local/hijo): ResolvProtoResponse(ret=2, ttl=600, 30.10.100.4, 30.10.100.6)
+  NameServer::send_loop() -> respondo ResolvProtoResponse(ret=2, ttl=600, 30.10.100.4, 30.10.100.6)
+
+.. vim: filetype=rst sw=2 sts=2 et :