1 ===============================
2 Sistemas Distribuidos I (75.74)
3 ===============================
5 ------------------------------------------------------------------
6 TP 2: Sistema de resolución de nombres sobre IP adaptado a sockets
7 ------------------------------------------------------------------
9 :Author: Leandro Lucarella (77891)
15 En el directorio `src` se encuentra el código fuente del trabajo, con su
16 correspondiente `Makefile` para compilarlo tan solo ejecutando `make`.
18 En el directorio `rutas_ejemplo` contiene algunos archivos con descripciones de
19 rutas de ejemplo para correr los programas. En el directorio `zonas_ejemplo` se
20 encuentran archivos de configuración de zonas de dominios de nombre para
27 El trabajo consta de dos programas, uno llamado `ip` y otro `dns` (más algunas
28 otras pruebas que no tienen relevancia).
33 El programa `ip` corre 3 procesos (fork(2)eados), uno que recibe paquetes IP
34 otro que recibe entrada del usuario y envía paquetes IP y otro que redirecciona
35 (forward) paquetes IP en caso de ser pertinente.
39 ./ip ip [router [forward [route_file [queue_id [proto]]]]]
42 IP que utiliza este proceso
45 0 si es router, 1 si no lo es (default 0)
48 0 si puede hacer forwarding, 1 si no (default 0)
51 Archivo con las rutas. El formato del archivo es una ruta por línea, cada
52 línea se compone de red (por ahora sólo soporta IPs puntuales), gateway (si es
53 cero es que están en la misma red), MTU y métrica (todavía no se usa),
54 separados por uno o más espacios o tabs (default `route.txt`)
57 Identificador de la cola a usar como medio físico, también establece el
58 identificador de la cola a usar para comunicarse con el otro proceso
59 (`test_ipout`) para hacer forwarding, que será queue_id + 1 (default
60 `DEV_DEFAULT_KEY` obtenido de `dev.h`)
63 Protocolo que transporta (default 0)
66 El programa se queda esperando la entrada del usuario, y sale cuando esta se
67 termina (Ctrl-D). El formato de entrada es::
72 Es decir, en una línea se pone la IP de destino y en la línea siguiente el
73 mensaje. Para enviar otro mensaje, nuevamente se pone IP de destino en una línea
74 y el mensaje en la siguiente.
79 El programa `dns` corre también 3 procesos (fork(2)eados), uno que recibe
80 peticiones de nombres, otro que recibe entrada del usuario y envía peticiones
81 (o mejor dicho encola peticiones para ser enviadas) y otro que realiza el envío
82 de las peticiones realmente.
86 ./dns ip [route_file [zone_file [port]]]
89 IP que utiliza este proceso (ídem programa `ip`)
92 Archivo con las rutas (ídem programa `ip`)
95 Archivo con la descripción de las zonas. El formato es muy simple. Cada zona
96 está separada por un renglón en blanco y empieza con una línea con 3 campos
97 separados por espacios o tab: nombre de la zona, TTL y nodo padre. Luego le
98 sigue la lista de registros de esa zona, también con 3 campos por renglón:
99 nombre, tipo de registro (A para indicar una IP, NS para indicar donde buscar
100 registros de una zona con ese nombre) e IP (ya sea la IP definitiva si es A o
101 la IP del nameserver al cual recurrir si es NS). Se pueden ver ejemplos de
102 estos archivos en el disco entregado.
105 Puerto en el cual escuchará la abstracción de capa física sobre TCP.
108 El programa es muy similar a `ip`, se queda esperando la entrada del usuario,
109 y sale cuando esta se termina (Ctrl-D). El formato de entrada es::
113 Es decir, se escribe en una línea el nombre del host del cual se quiera obtener
114 la IP y se presiona ENTER.
120 El trabajo fue desarrollado en C++, orientado a objetos. Se compone de las
124 Encapsula la capa física y el dispositivo de red. Es una interfaz abstracta.
127 Implementación de Dev utilizando una cola como medio físico y el id
128 representaría el cable (si 2 dispositivos tienen cola con id distinto serían
129 como si no compartieran el mismo cable). Por simplicidad a la cola siempre
130 se envía el tamaño del MTU completo pero se agrega una cabecera con el
131 tamaño real del frame.
134 Implementación de Dev utilizando conexiones TCP. Por cada frame saliente a un
135 destino en particular se crea una conexión TCP (a menos que ya esté creada, en
136 cuyo caso se reutiliza) y se escucha por conexiones entrantes para recibir
137 frames (también guardándolas para reutilizarlas). A diferencia del DevQue se
138 envía el tamaño del frame exacto (en realidad se agrega una pequeña cabecera).
141 Clase auxiliar que encapsula una dirección IP.
144 Encapsula una cabecera IP. El cálculo de checksum se simplificó (haciendo una
145 suma byte a byte de toda la cabecera) porque cumple con el objetivo didactico
149 Encapsula una tabla de ruteo. Por falta de tiempo y simplicidad por ahora sólo
150 soporta rutas a un sólo host (no a una red) pero es muy fácilmente extensible
151 y transparente para el resto de las clases que la usan. Las rutas se componen
152 de red (en realidad por ahora host), geteway, MTU, metrica y dispositivo de
153 red por el cual salir (Dev).
156 Es la clase encargada de recibir paquetes IP. Hace chequeos varios y descarta
157 paquetes según los siguientes criterios:
159 * Cabecera incompleta o no es IP
160 * Versión IP incorrecta
163 * No es para nosotros y no hacemos forward
164 * Es para nosotros pero somos un router
166 Si hace forwarding le pasa a IPOut el paquete por una cola y reensabla de ser
170 Es la clase encargada de enviar paquetes IP. Tiene una RouteTable para hacer
171 el ruteo y verifica si hay paquetes a forwardear antes de enviar lo que le
172 piden. También fragmenta y puede "descartar" paquetes según estos criterios:
174 * No existe una ruta para el destino
175 * Tamaño de paquete más grande que MTU y DF=1
178 Es el único componente del TP que no es orientado a objetos ya que se
179 reutilizó de trabajos anteriores. Es una pequeña abstracción sobre la API de
180 sockets de BSD para mayor simplicidad.
183 Clase que encapsula una petición de resolución de nombre a enviar via IP.
186 Clase que encapsula una respuesta de resolución de nombre a enviar via IP.
189 Clase encargada de resolver los nombres. Escucha por peticiones y puede
190 resolverlas recursiva o directamente (según venga de otro NameServer o de un
191 Resolver la petición). Esta clase se compone de varias otras clases auxiliares
192 para almacenar las zonas y el cache.
198 Archivo de configuración de zonas de 10.10.10.2::
200 homero.casa 600 10.10.10.1
210 todos NS 10.10.10.141
214 ./dns 10.10.10.2 ../rutas_ejemplo/mi_lan.txt ../zonas_ejemplo/10.10.10.2.txt
216 Resolución de un nombre local con una sola IP
217 ---------------------------------------------
221 ./dns 10.10.10.2 ../rutas_ejemplo/mi_lan.txt ../zonas_ejemplo/10.10.10.2.txt
226 Resolviendo tito.homero.casa...
227 resolv_direct -> tratando de resolver: tito.homero.casa
228 resolv_direct found (local/hijo): ResolvProtoResponse(ret=2, ttl=600, 10.10.100.1)
229 resolv_recursive -> gotcha! ResolvProtoResponse(ret=2, ttl=600, 10.10.100.1)
230 Resultado: ResolvProtoResponse(ret=2, ttl=600, 10.10.100.1)
232 Resolución de un nombre local con múltiples IP
233 ----------------------------------------------
238 Resolviendo juan.homero.casa...
239 resolv_direct -> tratando de resolver: juan.homero.casa
240 resolv_direct found (local/hijo): ResolvProtoResponse(ret=2, ttl=600, 10.10.100.2, 10.10.100.3, 10.10.100.5)
241 resolv_recursive -> gotcha! ResolvProtoResponse(ret=2, ttl=600, 10.10.100.2, 10.10.100.3, 10.10.100.5)
242 Resultado: ResolvProtoResponse(ret=2, ttl=600, 10.10.100.2, 10.10.100.3, 10.10.100.5)
244 Resolución de un nombre local no existente
245 ------------------------------------------
250 Resolviendo none.homero.casa...
251 resolv_direct -> tratando de resolver: none.homero.casa
252 resolv_direct NOT FOUND (es local pero no existe)
253 Resultado: ResolvProtoResponse(ret=4, ttl=0)
255 Resolución de un nombre remoto con múltiples IP y 2 niveles de indirección
256 --------------------------------------------------------------------------
258 Archivo de configuración de zonas de 10.10.10.1::
269 manuk NS 10.10.10.141
271 burns.casa 600 0.0.0.0
279 todos.homero.casa 9500 0.0.0.0
287 Archivo de configuración de zonas de 10.10.10.3::
289 marge.casa 600 10.10.10.1
296 manuk NS 10.10.10.141
299 todos NS 10.10.10.141
301 todos.homero.casa 9500 10.10.10.2
309 marge.homero.casa 9500 10.10.10.2
318 La petición se realiza desde 10.10.10.2, quien debe recurir a su nodo padre
319 (10.10.10.1) que indica que el encargado de resolver esa zona es 10.10.10.3.
321 Salida de 10.10.10.2::
324 Resolviendo pepe.marge.casa...
325 resolv_direct -> tratando de resolver: pepe.marge.casa
326 resolv_direct -> evaluando padre 10.10.10.1
327 resolv_direct found (al padre): 10.10.10.1
328 resolv_recursive -> redirect a ResolvProtoResponse(ret=3, ttl=600, 10.10.10.1)
329 query -> pidiendo ResolvProtoRequest(query_type=0, name=pepe.marge.casa) a 10.10.10.1
330 query -> recibido ResolvProtoResponse(ret=3, ttl=600, 10.10.10.3) de 10.10.10.1
331 resolv_recursive_r -> redirect a ResolvProtoResponse(ret=3, ttl=600, 10.10.10.3)
332 query -> pidiendo ResolvProtoRequest(query_type=0, name=pepe.marge.casa) a 10.10.10.3
333 query -> recibido ResolvProtoResponse(ret=2, ttl=600, 30.10.100.4, 30.10.100.6) de 10.10.10.3
334 resolv_recursive_r -> gotcha! ResolvProtoResponse(ret=2, ttl=600, 30.10.100.4, 30.10.100.6)
335 Resultado: ResolvProtoResponse(ret=2, ttl=600, 30.10.100.4, 30.10.100.6)
337 Salida de 10.10.10.1::
339 NameServer::send_loop() -> recibido ResolvProtoRequest(query_type=0, name=pepe.marge.casa)
340 resolv_direct -> tratando de resolver: pepe.marge.casa
341 resolv_direct found (local/hijo): ResolvProtoResponse(ret=3, ttl=600, 10.10.10.3)
342 NameServer::send_loop() -> respondo ResolvProtoResponse(ret=3, ttl=600, 10.10.10.3)
344 Salida de 10.10.10.3::
346 NameServer::send_loop() -> recibido ResolvProtoRequest(query_type=0, name=pepe.marge.casa)
347 resolv_direct -> tratando de resolver: pepe.marge.casa
348 resolv_direct found (local/hijo): ResolvProtoResponse(ret=2, ttl=600, 30.10.100.4, 30.10.100.6)
349 NameServer::send_loop() -> respondo ResolvProtoResponse(ret=2, ttl=600, 30.10.100.4, 30.10.100.6)
351 .. vim: filetype=rst sw=2 sts=2 et :