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)
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
===
-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::
- ./test_ipin [ip] [mtu] [router] [forward] [proto] [queue_id]
+ ./ip ip [router [forward [route_file [queue_id [proto]]]]]
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)
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
(`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::
- ./test_ipout [ip] [dst] [mtu] [routes_file] [proto] [queue_id]
+ ./dns ip [route_file [zone_file [port]]]
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
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.
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
* 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 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
==================
-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 :