\red0\green0\blue0;
\red255\green255\blue255;}
{\stylesheet
-{\s1\fi-431\li720\sbasedon28\snext28Contents 1;}
-{\s2\fi-431\li1440\sbasedon28\snext28Contents 2;}
-{\s3\fi-431\li2160\sbasedon28\snext28Contents 3;}
-{\s8\fi-431\li720\sbasedon28Lower Roman List;}
-{\s5\tx431\sbasedon24\snext28Numbered Heading 1;}
-{\s6\tx431\sbasedon25\snext28Numbered Heading 2;}
-{\s7\fi-431\li720Square List;}
-{\*\cs11\sbasedon28Endnote Text;}
-{\s4\fi-431\li2880\sbasedon28\snext28Contents 4;}
-{\s9\fi-431\li720Diamond List;}
-{\s10\fi-431\li720Numbered List;}
+{\s1\fi-429\li720\sbasedon29\snext29Contents 1;}
+{\s2\fi-429\li1440\sbasedon29\snext29Contents 2;}
+{\s3\fi-429\li2160\sbasedon29\snext29Contents 3;}
+{\s8\fi-429\li720\sbasedon29Lower Roman List;}
+{\s5\tx431\sbasedon25\snext29Numbered Heading 1;}
+{\s6\tx431\sbasedon26\snext29Numbered Heading 2;}
+{\s7\fi-429\li720Square List;}
+{\*\cs11\sbasedon29Endnote Text;}
+{\s4\fi-429\li2880\sbasedon29\snext29Contents 4;}
+{\s9\fi-429\li720Diamond List;}
+{\s10\fi-429\li720Numbered List;}
{\*\cs12\fs20\superEndnote Reference;}
-{\s13\fi-431\li720Triangle List;}
-{\s14\tx431\sbasedon26\snext28Numbered Heading 3;}
-{\s15\fi-431\li720Dashed List;}
-{\s16\fi-431\li720\sbasedon10Upper Roman List;}
-{\s17\sb440\sa60\f0\fs24\b\sbasedon28\snext28Heading 4;}
-{\s18\fi-431\li720Heart List;}
-{\s34\fi-431\li720Box List;}
-{\s20\fi-431\li720\sbasedon10Upper Case List;}
-{\s21\fi-431\li720Bullet List;}
-{\s22\fi-431\li720Hand List;}
-{\*\cs23\fs20\sbasedon28Footnote Text;}
-{\s24\sb440\sa60\f0\fs34\b\sbasedon28\snext28Heading 1;}
-{\s25\sb440\sa60\f0\fs28\b\sbasedon28\snext28Heading 2;}
-{\s19\qc\sb240\sa120\f0\fs32\b\sbasedon28\snext28Contents Header;}
-{\s27\fi-431\li720Tick List;}
-{\s26\sb440\sa60\f0\fs24\b\sbasedon28\snext28Heading 3;}
-{\s29\fi-431\li720\sbasedon10Lower Case List;}
-{\s30\li1440\ri1440\sa120\sbasedon28Block Text;}
-{\s36\f2\sbasedon28Plain Text;}
-{\s32\tx1584\sbasedon5\snext28Section Heading;}
-{\s33\fi-431\li720Implies List;}
-{\s28\f1\fs24\lang1034Normal;}
-{\s35\fi-431\li720Star List;}
-{\*\cs31\fs20\superFootnote Reference;}
-{\s37\tx1584\sbasedon5\snext28Chapter Heading;}}
-\kerning0\cf0\ftnbj\fet2\ftnstart1\ftnnar\aftnnar\ftnstart1\aftnstart1\aenddoc\revprop3{\info\uc1}\deftab720\viewkind1\paperw11905\paperh16837\margl1440\margr1440\widowctl
+{\s13\fi-429\li720Triangle List;}
+{\s14\tx431\sbasedon27\snext29Numbered Heading 3;}
+{\s15\fi-429\li720Dashed List;}
+{\s16\fi-429\li720\sbasedon10Upper Roman List;}
+{\s17\sb440\sa60\f0\fs24\b\sbasedon29\snext29Heading 4;}
+{\s18\fi-429\li720Heart List;}
+{\s35\fi-429\li720Box List;}
+{\*\cs20\fs20Reference;}
+{\s21\fi-429\li720\sbasedon10Upper Case List;}
+{\s22\fi-429\li720Bullet List;}
+{\s23\fi-429\li720Hand List;}
+{\*\cs24\fs20\sbasedon29Footnote Text;}
+{\s25\sb440\sa60\f0\fs34\b\sbasedon29\snext29Heading 1;}
+{\s26\sb440\sa60\f0\fs28\b\sbasedon29\snext29Heading 2;}
+{\s19\qc\sb240\sa118\f0\fs32\b\sbasedon29\snext29Contents Header;}
+{\s28\fi-429\li720Tick List;}
+{\s27\sb440\sa60\f0\fs24\b\sbasedon29\snext29Heading 3;}
+{\s30\fi-429\li720\sbasedon10Lower Case List;}
+{\s31\li1440\ri1440\sa118\sbasedon29Block Text;}
+{\s37\f2\sbasedon29Plain Text;}
+{\s33\tx1584\sbasedon5\snext29Section Heading;}
+{\s34\fi-429\li720Implies List;}
+{\s29\f1\fs24\lang1034Normal;}
+{\s36\fi-429\li720Star List;}
+{\*\cs32\fs20\superFootnote Reference;}
+{\s38\tx1584\sbasedon5\snext29Chapter Heading;}}
+\kerning0\cf0\ftnbj\fet2\ftnstart1\ftnnar\aftnnar\ftnstart1\aftnstart1\aenddoc\revprop3{\info\uc1}\deftab720\viewkind1\paperw11905\paperh16837\margl1440\margr1440\widowctrl
\sectd\sbknone\colsx360\pgncont\ltrsect
-\pard\plain\ltrpar\qc\s28\itap0{\s28\f0\fs52\b\lang1034{\*\listtag0}\abinodiroverride\ltrch Sistemas Distribuidos I (75.74)}{\s28\f1\fs24\lang1034{\*\listtag1003}\par}
-\pard\plain\ltrpar\qc\s28\itap0{\s28\f0\fs28\lang1034{\*\listtag0}\abinodiroverride\ltrch TP 2: Sistema de resoluci\'f3n de nombres sobre IP adaptado a sockets}{\s28\f0\fs28\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\qc\s28\itap0{\field\fdledit{\*\fldinst {\ TOC }}}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f1\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\sb440\sa60\s24\itap0{\s24\f0\fs34\b\lang1034{\*\listtag0}\abinodiroverride\ltrch DNS}{\s24\f0\fs34\b\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\sb440\sa60\s25\itap0{\s25\f0\fs28\b\lang1034{\*\listtag0}\abinodiroverride\ltrch Diagrama de secuencia}{\s25\f0\fs28\b\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch \page }{\s28\f1\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\sb440\sa60\s25\itap0{\s25\f0\fs28\b\lang1034{\*\listtag0}\abinodiroverride\ltrch Dise\'f1o de mensajes de intercambio de DNS.}{\s25\f0\fs28\b\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch Petici\'f3n de un nameserver}{\s28\f1\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs22\lang1034{\*\listtag0}\abinodiroverride\ltrch +------------+------------+------------+}{\s28\f2\fs22\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs22\lang1034{\*\listtag0}\abinodiroverride\ltrch | QUERY_TYPE | SIZE | NAME |}{\s28\f2\fs22\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs22\lang1034{\*\listtag0}\abinodiroverride\ltrch +------------+------------+------------+}{\s28\f2\fs22\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs22\lang1034{\*\listtag0}\abinodiroverride\ltrch /-- 1 byte --/- 2 bytes --/- variable -/}{\s28\f2\fs22\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f1\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch QUERY_TYPE en realidad es una cabecera com\'fan a las peticiones y respuestas, cuyos c\'f3digos pueden ser los siguientes:}{\s28\f1\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs22\b\lang1034{\*\listtag0}\abinodiroverride\ltrch Requests}{\s28\f2\fs22\b\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs22\lang1034{\*\listtag0}\abinodiroverride\ltrch RP_REQ_DIRECT -> B\'fasqueda directa (inter nameservers)}{\s28\f2\fs22\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs22\lang1034{\*\listtag0}\abinodiroverride\ltrch RP_REQ_RECURSIVE-> B\'fasqueda recursiva (para resolvers)}{\s28\f2\fs22\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs22\b\lang1034{\*\listtag0}\abinodiroverride\ltrch Responses}{\s28\f2\fs22\b\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs22\lang1034{\*\listtag0}\abinodiroverride\ltrch RP_RES_A -> OK, se devolvi\'f3 un registro A}{\s28\f2\fs22\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs22\lang1034{\*\listtag0}\abinodiroverride\ltrch RP_RES_NS -> OK, se devolvi\'f3 un registro NS (s\'f3lo en directo)}{\s28\f2\fs22\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs22\lang1034{\*\listtag0}\abinodiroverride\ltrch RP_RES_NOTFOUND -> No se encontr\'f3}{\s28\f2\fs22\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs22\lang1034{\*\listtag0}\abinodiroverride\ltrch RP_RES_TIMEOUT -> Tard\'f3 demasiado la consulta}{\s28\f2\fs22\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f1\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch SIZE es el tama\'f1o del string con el nombre a buscar, NAME es el string (de longitud variable). Faltar\'eda agregar un campo con un ID para evitar que se confundan unas respuestas o peticiones con otras.}{\s28\f1\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f1\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch Respuesta de un nameserver}{\s28\f1\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs20\lang1034{\*\listtag0}\abinodiroverride\ltrch +-----------+-----------+-----------+-----------+-----------+-----------+}{\s28\f2\fs20\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs20\lang1034{\*\listtag0}\abinodiroverride\ltrch | RET | TTL | COUNT | IP 1 | ... | IP N |}{\s28\f2\fs20\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs20\lang1034{\*\listtag0}\abinodiroverride\ltrch +-----------+-----------+-----------+-----------+-----------+-----------+}{\s28\f2\fs20\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs20\lang1034{\*\listtag0}\abinodiroverride\ltrch /-- 1 byte -/- 4 bytes -/-- 1 byte -/- 4 bytes -/- 4 bytes -/- 4 bytes -/}{\s28\f2\fs20\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f1\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch RET es del mismo tipo que QUERY_TYPE y se hizo as\'ed para poder reconocer si un paquete es un request o un response con s\'f3lo leer el 1er byte. TTL es el tiempo que puede vivir en el cache (en segundos), COUNT es la cantidad de IPs encontradas para ese registro e IP1 a IPN son las IP en s\'ed (cantidad variable).}{\s28\f1\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\sb440\sa60\s25\itap0{\s25\f0\fs28\b\lang1034{\*\listtag0}\abinodiroverride\ltrch Par\'e1metros y resultados de la funci\'f3n gethostbyname()}{\s25\f0\fs28\b\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs20\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs20\lang1034{\*\listtag0}\abinodiroverride\ltrch std::vector< IPAddr > gethostbyname(std::string name, int& result);}{\s28\f2\fs20\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs20\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch Esta funci\'f3n toma como par\'e1metro un string con el nombre de dominio a buscar (por ejemplo "mi.dominio.casa") y retorna un vector de IPs. Si hay un error o no encuentra ninguna el vector se devuelve vac\'edo y se pone el c\'f3digo de error en la variable result. El trabajo de la funci\'f3n es conectarse a todos los nameservers que conozca y env\'ede un pedido de resoluci\'f3n de nombre RECURSIVO, hasta que tenga \'e9xito o se acabe la lista de nameservers disponibles. Por falta de tiempo esta funci\'f3n no est\'e1 implementada del lado del resolver pero s\'ed del nameserver, y es muy muy similar (hace exactamente lo mismo).}{\s28\f1\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\sb440\sa60\s24\itap0{\s24\f0\fs34\b\lang1034{\*\listtag0}\abinodiroverride\ltrch IP}{\s24\f0\fs34\b\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\sb440\sa60\s25\itap0{\s25\f0\fs28\b\lang1034{\*\listtag0}\abinodiroverride\ltrch Dise\'f1o del paquete IP}{\s25\f0\fs28\b\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch \page }{\s28\f1\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch // Campos}{\s28\f2\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch uint8_t version;}{\s28\f2\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch uint16_t total_len;}{\s28\f2\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch uint16_t id;}{\s28\f2\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch uint16_t reserved_flag: 1;}{\s28\f2\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch uint16_t df: 1;}{\s28\f2\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch uint16_t mf: 1;}{\s28\f2\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch uint16_t offset: 13;}{\s28\f2\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch uint8_t ttl;}{\s28\f2\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch uint8_t proto;}{\s28\f2\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch uint16_t checksum;}{\s28\f2\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch uint32_t src;}{\s28\f2\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f2\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch uint32_t dst;}{\s28\f2\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch \page }{\s28\f1\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\sb440\sa60\s25\itap0{\s25\f0\fs28\b\lang1034{\*\listtag0}\abinodiroverride\ltrch Diagrama de secuencia}{\s25\f0\fs28\b\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch \page }{\s28\f1\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\sb440\sa60\s25\itap0{\s25\f0\fs28\b\lang1034{\*\listtag0}\abinodiroverride\ltrch Cambios}{\s25\f0\fs28\b\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch Se agreg\'f3 principalmente la clase DevTCP que implementa la capa f\'edsica a trav\'e9s de TCP. Por cada frame saliente a un destino en particular se crea una conexi\'f3n TCP (a menos que ya est\'e9 creada, en cuyo caso se reutiliza) y se escucha por conexiones entrantes para recibir frames (tambi\'e9n guard\'e1ndolas para reutilizarlas). A diferencia del DevQue se env\'eda el tama\'f1o del frame exacto (en realidad se agrega una peque\'f1a cabecera).}{\s28\f1\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\sb440\sa60\s24\itap0{\s24\f0\fs34\b\lang1034{\*\listtag0}\abinodiroverride\ltrch Lista de fuentes de informaci\'f3n}{\s24\f0\fs34\b\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch RFC 1034 - Domain names - concepts and facilities:}{\s28\f1\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch \tab http://www.faqs.org/rfcs/rfc1034.html}{\s28\f1\fs24\lang1034{\*\listtag0}\par}
-\pard\plain\ltrpar\ql\s28\itap0{\s28\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch \tab Conceptos y desiciones de dise\'f1o del DNS.}{\s28\f1\fs24\lang1034{\*\listtag0}\par}}
\ No newline at end of file
+\pard\plain\ltrpar\qc\s29\sl240\slmult1\itap0{\s29\f0\fs52\b\lang1034{\*\listtag0}\abinodiroverride\ltrch Sistemas Distribuidos I (75.74)}{\s29\f0\fs52\b\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\qc\s29\sl240\slmult1\itap0{\s29\f0\fs28\lang1034{\*\listtag0}\abinodiroverride\ltrch TP 2: Sistema de resoluci\'f3n de nombres sobre IP adaptado a sockets}{\s29\f0\fs28\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f0\fs28\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\sb440\sa60\s25\sl240\slmult1\itap0{\s25\f0\fs34\b\lang1034{\*\listtag0}\abinodiroverride\ltrch DNS}{\s25\f0\fs34\b\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\sb440\sa60\s26\sl240\slmult1\itap0{\s26\f0\fs28\b\lang1034{\*\listtag0}\abinodiroverride\ltrch Diagrama de secuencia}{\s26\f0\fs28\b\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch \page }{\s29\f1\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\sb440\sa60\s26\sl240\slmult1\itap0{\s26\f0\fs28\b\lang1034{\*\listtag0}\abinodiroverride\ltrch Dise\'f1o de mensajes de intercambio de DNS.}{\s26\f0\fs28\b\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch Petici\'f3n de un nameserver}{\s29\f1\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs22\lang1034{\*\listtag0}\abinodiroverride\ltrch +------------+------------+------------+}{\s29\f2\fs22\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs22\lang1034{\*\listtag0}\abinodiroverride\ltrch | QUERY_TYPE | SIZE | NAME |}{\s29\f2\fs22\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs22\lang1034{\*\listtag0}\abinodiroverride\ltrch +------------+------------+------------+}{\s29\f2\fs22\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs22\lang1034{\*\listtag0}\abinodiroverride\ltrch /-- 1 byte --/- 2 bytes --/- variable -/}{\s29\f2\fs22\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs22\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch QUERY_TYPE en realidad es una cabecera com\'fan a las peticiones y respuestas, cuyos c\'f3digos pueden ser los siguientes:}{\s29\f1\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs22\b\lang1034{\*\listtag0}\abinodiroverride\ltrch Requests}{\s29\f2\fs22\b\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs22\lang1034{\*\listtag0}\abinodiroverride\ltrch RP_REQ_DIRECT -> B\'fasqueda directa (inter nameservers)}{\s29\f2\fs22\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs22\lang1034{\*\listtag0}\abinodiroverride\ltrch RP_REQ_RECURSIVE-> B\'fasqueda recursiva (para resolvers)}{\s29\f2\fs22\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs22\b\lang1034{\*\listtag0}\abinodiroverride\ltrch Responses}{\s29\f2\fs22\b\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs22\lang1034{\*\listtag0}\abinodiroverride\ltrch RP_RES_A -> OK, se devolvi\'f3 un registro A}{\s29\f2\fs22\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs22\lang1034{\*\listtag0}\abinodiroverride\ltrch RP_RES_NS -> OK, se devolvi\'f3 un registro NS (s\'f3lo en directo)}{\s29\f2\fs22\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs22\lang1034{\*\listtag0}\abinodiroverride\ltrch RP_RES_NOTFOUND -> No se encontr\'f3}{\s29\f2\fs22\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs22\lang1034{\*\listtag0}\abinodiroverride\ltrch RP_RES_TIMEOUT -> Tard\'f3 demasiado la consulta}{\s29\f2\fs22\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs22\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch SIZE es el tama\'f1o del string con el nombre a buscar, NAME es el string (de longitud variable). Faltar\'eda agregar un campo con un ID para evitar que se confundan unas respuestas o peticiones con otras.}{\s29\f1\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f1\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch Respuesta de un nameserver}{\s29\f1\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs20\lang1034{\*\listtag0}\abinodiroverride\ltrch +-----------+-----------+-----------+-----------+-----------+-----------+}{\s29\f2\fs20\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs20\lang1034{\*\listtag0}\abinodiroverride\ltrch | RET | TTL | COUNT | IP 1 | ... | IP N |}{\s29\f2\fs20\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs20\lang1034{\*\listtag0}\abinodiroverride\ltrch +-----------+-----------+-----------+-----------+-----------+-----------+}{\s29\f2\fs20\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs20\lang1034{\*\listtag0}\abinodiroverride\ltrch /-- 1 byte -/- 4 bytes -/-- 1 byte -/- 4 bytes -/- 4 bytes -/- 4 bytes -/}{\s29\f2\fs20\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs20\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch RET es del mismo tipo que QUERY_TYPE y se hizo as\'ed para poder reconocer si un paquete es un request o un response con s\'f3lo leer el 1er byte. TTL es el tiempo que puede vivir en el cache (en segundos), COUNT es la cantidad de IPs encontradas para ese registro e IP1 a IPN son las IP en s\'ed (cantidad variable).}{\s29\f1\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\sb440\sa60\s26\sl240\slmult1\itap0{\s26\f0\fs28\b\lang1034{\*\listtag0}\abinodiroverride\ltrch Par\'e1metros y resultados de la funci\'f3n gethostbyname()}{\s26\f0\fs28\b\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f0\fs28\b\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs20\lang1034{\*\listtag0}\abinodiroverride\ltrch result_t gethostbyname(std::string name, std::vector< IPAddr >& ips);}{\s29\f2\fs20\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs20\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch Esta funci\'f3n toma como par\'e1metro un string con el nombre de dominio a buscar (por ejemplo "mi.dominio.casa") y retorna un vector de IPs. Si hay un error o no encuentra ninguna el vector se devuelve intacto y se devuelve el c\'f3digo de error, que puede ser OK (respuesta v\'e1lida), HOST_NOT_FOUND (no se encuentra dicho host), NO_RECOVERY (error irreparable, por ejemplo, no hay nameservers) o TRY_AGAIN (rrror temporal, por ejemplo, timeout). El trabajo de la funci\'f3n es conectarse a todos los nameservers que conozca y enviar un pedido de resoluci\'f3n de nombre RECURSIVO, hasta que tenga \'e9xito o se acabe la lista de nameservers disponibles. }{\s29\f1\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\sb440\sa60\s25\sl240\slmult1\itap0{\s25\f0\fs34\b\lang1034{\*\listtag0}\abinodiroverride\ltrch IP}{\s25\f0\fs34\b\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\sb440\sa60\s26\sl240\slmult1\itap0{\s26\f0\fs28\b\lang1034{\*\listtag0}\abinodiroverride\ltrch Dise\'f1o del paquete IP}{\s26\f0\fs28\b\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch \page }{\s29\f1\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch // Campos}{\s29\f2\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch uint8_t version;}{\s29\f2\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch uint16_t total_len;}{\s29\f2\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch uint16_t id;}{\s29\f2\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch uint16_t reserved_flag: 1;}{\s29\f2\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch uint16_t df: 1;}{\s29\f2\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch uint16_t mf: 1;}{\s29\f2\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch uint16_t offset: 13;}{\s29\f2\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch uint8_t ttl;}{\s29\f2\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch uint8_t proto;}{\s29\f2\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch uint16_t checksum;}{\s29\f2\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch uint32_t src;}{\s29\f2\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f2\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch uint32_t dst;}{\s29\f2\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch \page }{\s29\f1\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\sb440\sa60\s26\sl240\slmult1\itap0{\s26\f0\fs28\b\lang1034{\*\listtag0}\abinodiroverride\ltrch Diagrama de secuencia}{\s26\f0\fs28\b\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch \page }{\s29\f1\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\sb440\sa60\s26\sl240\slmult1\itap0{\s26\f0\fs28\b\lang1034{\*\listtag0}\abinodiroverride\ltrch Cambios}{\s26\f0\fs28\b\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch Se agreg\'f3 principalmente la clase DevTCP que implementa la capa f\'edsica a trav\'e9s de TCP. Por cada frame saliente a un destino en particular se crea una conexi\'f3n TCP (a menos que ya est\'e9 creada, en cuyo caso se reutiliza) y se escucha por conexiones entrantes para recibir frames (tambi\'e9n guard\'e1ndolas para reutilizarlas). A diferencia del DevQue se env\'eda el tama\'f1o del frame exacto (en realidad se agrega una peque\'f1a cabecera).}{\s29\f1\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\sb440\sa60\s25\sl240\slmult1\itap0{\s25\f0\fs34\b\lang1034{\*\listtag0}\abinodiroverride\ltrch Lista de fuentes de informaci\'f3n}{\s25\f0\fs34\b\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch RFC 1034 - Domain names - concepts and facilities:}{\s29\f1\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch \tab http://www.faqs.org/rfcs/rfc1034.html}{\s29\f1\fs24\lang1034{\*\listtag0}\par}
+\pard\plain\ltrpar\ql\s29\sl240\slmult1\itap0{\s29\f1\fs24\lang1034{\*\listtag0}\abinodiroverride\ltrch \tab Conceptos y desiciones de dise\'f1o del DNS.}{\s29\f1\fs24\lang1034{\*\listtag0}\par}}
\ No newline at end of file
--- /dev/null
+10.10.10.1
10.10.10.1 0.0.0.0 30 0
10.10.10.2 0.0.0.0 30 0
10.10.10.3 0.0.0.0 30 0
-10.10.10.141 0.0.0.0 30 0
+10.10.10.5 0.0.0.0 30 0
# Para más verbose
CFLAGS += -DDEBUG2
+CFLAGS += -DDEBUG_RESOLV
+CFLAGS += -DDEBUG_TRACE
# Opciones para el compilador C++.
CXXFLAGS = $(CFLAGS) -fno-inline
CC=g++
# Programas
-targets=ip dns
+targets=ip dns res
tests=test_send test_recv test_ipaddr test_ipin test_ipout test_devtcp \
test_poll test_resolvproto test_nameserver_file \
test_nameserver_resolvnext
ip_objs=ipout.o ipin.o ipaddr.o ipheader.o devque.o devtcp.o routetable.o \
libtcp.o
-dns_objs=nameserver.o resolvproto.o
+dns_objs=resolvproto.o
# REGLAS
#########
test_resolvproto: test_resolvproto.o resolvproto.o ipaddr.o
-test_nameserver_file: test_nameserver_file.o $(dns_objs) $(ip_objs)
+test_nameserver_file: test_nameserver_file.o nameserver.o $(dns_objs) $(ip_objs)
#FIXME no va libtcp.o, debe ir sobre mi implementación de ip.
-test_nameserver_resolvnext: test_nameserver_resolvnext.o $(dns_objs) $(ip_objs)
+test_nameserver_resolvnext: test_nameserver_resolvnext.o nameserver.o \
+ $(dns_objs) $(ip_objs)
ip: ip.o $(ip_objs)
-dns: dns.o $(ip_objs) $(dns_objs)
+dns: dns.o nameserver.o $(ip_objs) $(dns_objs)
+
+res: res.o resolver.o $(ip_objs) $(dns_objs)
depend:
@makedepend $(fuentes) > /dev/null 2>&1
nameserver.o: /usr/include/gnu/stubs.h /usr/include/bits/wchar.h
nameserver.o: /usr/include/bits/wordsize.h resolvproto.h ipin.h ipheader.h
nameserver.o: ipout.h routetable.h
+res.o: ipout.h ipaddr.h /usr/include/stdint.h /usr/include/features.h
+res.o: /usr/include/sys/cdefs.h /usr/include/gnu/stubs.h
+res.o: /usr/include/bits/wchar.h /usr/include/bits/wordsize.h ipheader.h
+res.o: routetable.h dev.h ipin.h devtcp.h /usr/include/sys/poll.h
+res.o: /usr/include/bits/poll.h devque.h resolver.h resolvproto.h
+res.o: /usr/include/unistd.h /usr/include/bits/posix_opt.h
+res.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h
+res.o: /usr/include/bits/confname.h /usr/include/getopt.h
+res.o: /usr/include/fcntl.h /usr/include/bits/fcntl.h
+res.o: /usr/include/sys/types.h /usr/include/time.h /usr/include/endian.h
+res.o: /usr/include/bits/endian.h /usr/include/sys/select.h
+res.o: /usr/include/bits/select.h /usr/include/bits/sigset.h
+res.o: /usr/include/bits/time.h /usr/include/sys/sysmacros.h
+res.o: /usr/include/bits/pthreadtypes.h /usr/include/bits/sched.h
+res.o: /usr/include/sys/wait.h /usr/include/signal.h
+res.o: /usr/include/bits/signum.h /usr/include/bits/siginfo.h
+res.o: /usr/include/bits/sigaction.h /usr/include/bits/sigcontext.h
+res.o: /usr/include/asm/sigcontext.h /usr/include/asm-i486/sigcontext.h
+res.o: /usr/include/linux/compiler.h /usr/include/bits/sigstack.h
+res.o: /usr/include/bits/sigthread.h /usr/include/sys/resource.h
+res.o: /usr/include/bits/resource.h /usr/include/bits/waitflags.h
+res.o: /usr/include/bits/waitstatus.h /usr/include/sys/ipc.h
+res.o: /usr/include/bits/ipctypes.h /usr/include/bits/ipc.h
+res.o: /usr/include/sys/msg.h /usr/include/bits/msq.h
+resolver.o: resolver.h devque.h dev.h ipaddr.h /usr/include/stdint.h
+resolver.o: /usr/include/features.h /usr/include/sys/cdefs.h
+resolver.o: /usr/include/gnu/stubs.h /usr/include/bits/wchar.h
+resolver.o: /usr/include/bits/wordsize.h resolvproto.h ipin.h ipheader.h
+resolver.o: ipout.h routetable.h
resolvproto.o: resolvproto.h ipaddr.h /usr/include/stdint.h
resolvproto.o: /usr/include/features.h /usr/include/sys/cdefs.h
resolvproto.o: /usr/include/gnu/stubs.h /usr/include/bits/wchar.h
void DevQue::transmit(const std::string& data, const mac_type& mac)
throw (std::runtime_error, std::logic_error)
{
+#ifdef DEBUG_TRACE
+ std::cout << "DevQue[" << que_id << "]::transmit()\n";
+#endif
if (data.size() > mtu)
throw std::logic_error("Tamaño de datos mayor al MTU");
Frame* f = (Frame*) malloc(sizeof(Frame) + mtu);
memcpy(f->frame, data.data(), data.size());
int res = msgsnd(que_id, f, mtu + sizeof(size_t), 0);
#ifdef DEBUG2
- std::cout << "DevQue::transmit(msgtype/mac = " << f->mac << ", size = "
- << f->size << ")\n";
+ std::cout << "DevQue[" << que_id << "]::transmit(msgtype/mac = "
+ << f->mac << ", size = " << f->size << ")\n";
#endif
free(f);
if (res == -1)
std::string DevQue::receive() throw (std::runtime_error)
{
+#ifdef DEBUG_TRACE
+ std::cout << "DevQue[" << que_id << "]::receive()\n";
+#endif
return receive(mac);
}
std::string DevQue::receive(mac_type& mac) throw (std::runtime_error)
{
+#ifdef DEBUG_TRACE
+ std::cout << "DevQue[" << que_id << "]::receive(mac)\n";
+#endif
Frame* f = (Frame*) malloc(sizeof(Frame) + mtu);
if (!f)
throw std::runtime_error("No se puede reservar memoria");
mac = f->mac;
free(f);
#ifdef DEBUG2
- std::cout << "DevQue::receive(msgtype/mac = " << mac << ", size = "
- << s.size() << ")\n";
+ std::cout << "DevQue[" << que_id << "]::receive(msgtype/mac = "
+ << mac << ", size = " << s.size() << ")\n";
#endif
return s;
}
perror("fork() send");
return 2;
}
- if (pid_send) // IPOut
+ if (pid_send) // Padre
{
- pid_t pid_fw = fork();
- if (pid_fw == -1)
+ pid_t pid_recv = fork();
+ if (pid_recv == -1)
{
- perror("fork() forward");
+ perror("fork() recv");
return 3;
}
- if (pid_fw) // Padre (Entrada por teclado)
+ if (pid_recv) // Padre
{
- int ret;
- send_loop(ns);
- kill(pid_send, SIGTERM);
- waitpid(pid_send, &ret, 0);
- kill(pid_fw, SIGTERM);
- waitpid(pid_fw, &ret, 0);
- return 0;
+ pid_t pid_req = fork();
+ if (pid_req == -1)
+ {
+ perror("fork() req");
+ return 3;
+ }
+ if (pid_req) // Padre (Entrada por teclado)
+ {
+ int ret;
+ send_loop(ns);
+ kill(pid_send, SIGTERM);
+ waitpid(pid_send, &ret, 0);
+ kill(pid_recv, SIGTERM);
+ waitpid(pid_recv, &ret, 0);
+ kill(pid_req, SIGTERM);
+ waitpid(pid_req, &ret, 0);
+ return 0;
+ }
+ else // Hijo 1 (Proceso de request DNS)
+ {
+ ns.req_loop();
+ return 0;
+ }
}
- else // Hijo 1 (envío del DNS)
+ else // Hijo 2 (envío del DNS)
{
ns.send_loop();
return 0;
}
}
- else // Hijo 2 (recepción del DNS)
+ else // Hijo 3 (recepción del DNS)
{
ns.recv_loop();
return 0;
#include <iostream>
#endif
-#define DEBUG_RESOLV
-
NameServer::Name::Name(const std::string& s)
{
std::istringstream iss(s);
std::cerr << "NameServer: " << z << "\n\n";
#endif
}
+
+#ifdef DEBUG2
+ std::cout << "NameServer: req_que_id = " << req_que.que_id
+ << ", res_que_id = " << res_que.que_id
+ << ", snd_que_id = " << snd_que.que_id << "\n";
+#endif
}
/// Devuelve la parte izquierda de n, si la parte derecha coincide exactamente
/// Resuelve un nombre de forma directa (no recursiva)
ResolvProtoResponse NameServer::resolv_direct(const Name& n)
{
+#ifdef DEBUG_TRACE
+ std::cout << "NameServer::resolv_direct()\n";
+#endif
#ifdef DEBUG_RESOLV
std::cerr << "resolv_direct -> tratando de resolver: " << n << "\n";
#endif
/// Resuelve un nombre de forma recursiva
ResolvProtoResponse NameServer::resolv_recursive(const Name& n)
{
+#ifdef DEBUG_TRACE
+ std::cout << "NameServer::resolv_recursive()\n";
+#endif
ResolvProtoResponse rpr = resolv_direct(n);
switch (rpr.ret)
{
ResolvProtoResponse NameServer::resolv_recursive_r(const Name& n,
ResolvProtoResponse rpr)
{
+#ifdef DEBUG_TRACE
+ std::cout << "NameServer::resolv_recursive_r()\n";
+#endif
ResolvProtoResponse r;
for (ResolvProtoResponse::ipvec_t::const_iterator ip = rpr.ips.begin();
ip != rpr.ips.end(); ++ip)
/// Consulta a otro name server sobre un nombre
ResolvProtoResponse NameServer::query(const Name& n, const IPAddr& ip)
{
+#ifdef DEBUG_TRACE
+ std::cout << "NameServer::query()\n";
+#endif
ResolvProtoRequest r(std::string(n), RP_REQ_DIRECT);
#ifdef DEBUG_RESOLV
std::cerr << "query -> pidiendo " << r << " a " << ip << "\n";
void NameServer::recv_loop()
{
+#ifdef DEBUG_TRACE
+ std::cout << "NameServer::recv_loop()\n";
+#endif
while (true)
{
IPAddr src, dst;
void NameServer::send_loop()
{
+#ifdef DEBUG_TRACE
+ std::cout << "NameServer::send_loop()\n";
+#endif
while (true)
{
- if (!req_que.empty())
- {
- Dev::mac_type mac = 0;
- ResolvProtoRequest req(req_que.receive(mac));
+ Dev::mac_type mac = 0;
+ std::string buf = snd_que.receive(mac);
#ifdef DEBUG_RESOLV
- std::cout << "NameServer::send_loop() -> recibido " << req << "\n";
+ std::cout << "NameServer::send_loop() -> envío request "
+ << ResolvProtoRequest(buf) << "\n";
+#endif
+ ipout.send(buf, RESOLV_PROTO, IPAddr(mac));
+ }
+}
+
+void NameServer::req_loop()
+{
+#ifdef DEBUG_TRACE
+ std::cout << "NameServer::req_loop()\n";
#endif
- ResolvProtoResponse res
- = (req.query_type == RP_REQ_DIRECT)
- ? resolv_direct(req.name)
- : resolv_recursive(req.name);
+ while (true)
+ {
+ Dev::mac_type mac = 0;
+ ResolvProtoRequest req(req_que.receive(mac));
#ifdef DEBUG_RESOLV
- std::cout << "NameServer::send_loop() -> respondo " << res << "\n";
+ std::cout << "NameServer::req_loop() -> recibido " << req << "\n";
#endif
- ipout.send(res, RESOLV_PROTO, IPAddr(mac));
- }
- else if (!snd_que.empty()) // Hay un request para enviar
- {
- Dev::mac_type mac = 0;
- std::string buf = snd_que.receive(mac);
+ ResolvProtoResponse res
+ = (req.query_type == RP_REQ_DIRECT)
+ ? resolv_direct(req.name)
+ : resolv_recursive(req.name);
#ifdef DEBUG_RESOLV
- std::cout << "NameServer::send_loop() -> envío request "
- << ResolvProtoRequest(buf) << "\n";
+ std::cout << "NameServer::req_loop() -> respondo " << res << "\n";
#endif
- ipout.send(buf, RESOLV_PROTO, IPAddr(mac));
- }
- else // No hay nada, esperamos un rato
- {
- usleep(10000);
- }
+ snd_que.transmit(std::string(res), IPAddr(mac));
}
}
/// Loop que envía los paquetes de la cola de envío
void send_loop();
+ /// Loop que procesa los requests
+ void req_loop();
+
private:
/// Resuelve un nombre de forma recursiva entrando a otros ns
ResolvProtoResponse resolv_recursive_r(const Name& n,
--- /dev/null
+
+#include "ipout.h"
+#include "ipin.h"
+#include "ipaddr.h"
+#include "routetable.h"
+#include "devtcp.h"
+#include "devque.h"
+#include "resolver.h"
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <string>
+#include <cassert>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <signal.h>
+
+// Uso: ./ip ip [routes_file servers_file forward port]
+
+void send_loop(Resolver& res);
+
+int main(int argc, char* argv[])
+{
+ bool forward = false;
+ uint16_t port = DEVTCP_DEFAULT_PORT;
+ std::string rfile = "route.txt";
+ std::string sfile = "resolver.txt";
+ if (argc < 2)
+ {
+ std::cerr << "Uso: " << argv[0] << " ip [routes_file servers_file "
+ "forward port]\n";
+ return 1;
+ }
+ IPAddr addr(argv[1]);
+ if (argc > 2)
+ rfile = argv[2];
+ if (argc > 3)
+ sfile = argv[3];
+ if (argc > 4)
+ forward = atoi(argv[4]);
+ if (argc > 5)
+ port = atoi(argv[5]);
+ // Abro archivos
+ std::ifstream rifs(rfile.c_str()); assert(rifs);
+ std::ifstream sifs(sfile.c_str()); assert(sifs);
+ // Creo medio físico y cola para forwarding
+ DevTCP dev(addr, port);
+ DevQue fwque(addr, DEVQUE_DEFAULT_KEY-1);
+ DevQue resresque(addr, DEVQUE_DEFAULT_KEY-5);
+ // Creo tabla de ruteo e IP
+ RouteTable table(dev);
+ add_routes(table, rifs, dev);
+ IPOut ipout(addr, table, fwque, std::cerr);
+ IPIn ipin(addr, dev, fwque, false, forward, std::cerr);
+ Resolver res(sifs, ipin, ipout, resresque);
+ // Creo procesos
+ pid_t pid_send = fork();
+ if (pid_send == -1)
+ {
+ perror("fork() send");
+ return 2;
+ }
+ if (pid_send) // IPOut
+ {
+ pid_t pid_fw = fork();
+ if (pid_fw == -1)
+ {
+ perror("fork() forward");
+ return 3;
+ }
+ if (pid_fw) // Padre (IPOut send)
+ {
+ int ret;
+ send_loop(res);
+ kill(pid_send, SIGTERM);
+ waitpid(pid_send, &ret, 0);
+ kill(pid_fw, SIGTERM);
+ waitpid(pid_fw, &ret, 0);
+ return 0;
+ }
+ else // Hijo 1 (IPOut forward)
+ {
+ ipout.forward_loop();
+ return 0;
+ }
+ }
+ else // Hijo 2 (IPIn)
+ {
+ res.recv_loop();
+ return 0;
+ }
+ return 0;
+}
+
+void send_loop(Resolver& res)
+{
+ std::string name;
+ while (std::getline(std::cin, name))
+ {
+ std::cout << "Resolviendo " << name << "...\n";
+ Resolver::ipvec_t ips;
+ Resolver::result_t r = res.gethostbyname(name, ips);
+ switch (r)
+ {
+ case Resolver::OK:
+ std::cout << "Encontrado: " << ips << "\n";
+ break;
+ case Resolver::HOST_NOT_FOUND:
+ std::cout << "No encontrado!\n";
+ break;
+ case Resolver::NO_RECOVERY:
+ std::cout << "Error irrecuperable!\n";
+ break;
+ case Resolver::TRY_AGAIN:
+ std::cout << "Error temporal, pruebe más tarde...\n";
+ break;
+ }
+ }
+}
+
+// vim: set et sw=4 sts=4 :
--- /dev/null
+#include "resolver.h"
+#include <sstream>
+#include <algorithm>
+#include <iterator>
+#include <sstream>
+#include <functional>
+#ifdef DEBUG
+#include <iostream>
+#endif
+
+/// Parsea un archivo de nameservers
+static std::istream& parseservers(std::istream& is, Resolver::ipvec_t& nss)
+ throw (std::runtime_error)
+{
+ std::string ns;
+ // [nameserver ip]
+ while (std::getline(is, ns))
+ {
+ if (ns == "") continue; // Salteo líneas en blanco
+ nss.push_back(IPAddr(ns));
+#ifdef DEBUG_PARSER
+ std::cout << "parseservers: IP = " << IPAddr(ns) << "\n";
+#endif
+ }
+ return is;
+}
+
+/// Constructor
+Resolver::Resolver(std::istream& is, IPIn& ipin, IPOut& ipout, DevQue& res_que)
+ throw (std::runtime_error):
+ ipin(ipin), ipout(ipout), res_que(res_que)
+{
+ parseservers(is, nameservers);
+}
+
+/// Obtiene la(s) IP de un host a través de su nombre de dominio
+Resolver::result_t Resolver::gethostbyname(const std::string& name,
+ ipvec_t& ips)
+{
+ result_t result = NO_RECOVERY;
+ for (ipvec_t::const_iterator ip = nameservers.begin();
+ ip != nameservers.end(); ++ip)
+ {
+ ResolvProtoResponse r = query(name, *ip);
+ switch (r.ret)
+ {
+ case RP_RES_A:
+ ips = r.ips;
+ return OK;
+ case RP_RES_NOTFOUND:
+ result = HOST_NOT_FOUND;
+ continue;
+ default:
+#ifdef DEBUG_RESOLV
+ std::cout << "Resolver::gethostbyname ERROR!!! respuesta "
+ "inesperada: " << r << "\n";
+#endif
+ return TRY_AGAIN;
+ }
+ }
+ return result;
+}
+
+/// Consulta a otro name server sobre un nombre
+ResolvProtoResponse Resolver::query(const std::string& name, const IPAddr& ip)
+{
+ ResolvProtoRequest r(name, RP_REQ_RECURSIVE);
+#ifdef DEBUG_RESOLV
+ std::cout << "query -> pidiendo " << r << " a " << ip << "\n";
+#endif
+ ipout.send(std::string(r), RESOLV_PROTO, ip);
+ Dev::mac_type mac = ip;
+ std::string buf = res_que.receive(mac);
+ ResolvProtoResponse resp(buf);
+#ifdef DEBUG_RESOLV
+ std::cerr << "query -> recibido " << resp << " de " << ip << "\n";
+#endif
+ return resp;
+}
+
+void Resolver::recv_loop()
+{
+ while (true)
+ {
+ IPAddr src, dst;
+ uint8_t proto;
+ std::string s = ipin.recv(proto, src, dst);
+#ifdef DEBUG_RESOLV
+ std::cout << "NameServer::recv_loop() -> recibido len=" << s.size()
+ << " de " << src << " para " << dst << " (proto = "
+ << unsigned(proto) << ")\n";
+#endif
+ if (proto == RESOLV_PROTO) // Si es para nosotros
+ {
+ rp_pkt_type_t type;
+ memcpy(&type, s.data(), sizeof(uint8_t));
+ switch (type)
+ {
+ // Request
+ case RP_REQ_DIRECT:
+ case RP_REQ_RECURSIVE:
+#ifdef DEBUG_RESOLV
+ std::cout << "---> Recibido un REQUEST!!! Algo esta roto! "
+ << ResolvProtoRequest(s) << "\n";
+#endif
+ break;
+ // Response
+ default:
+#ifdef DEBUG_RESOLV
+ std::cout << "---> " << ResolvProtoResponse(s) << "\n";
+#endif
+ res_que.transmit(s, src); // Encolo
+ }
+ }
+#ifdef DEBUG_RESOLV
+ else
+ {
+ std::cout << "---> Recibido paquete IP desconocido (proto="
+ << unsigned(proto) << "): " << s << "\n";
+ }
+#endif
+ }
+}
+
+std::ostream& operator<< (std::ostream& os, const Resolver& res)
+{
+ return os << "Resolver(nameservers=" << res.nameservers << ")";
+}
+
+std::ostream& operator<< (std::ostream& os, const Resolver::ipvec_t& v)
+{
+ os << "[";
+ if (v.empty())
+ return os << "]";
+ std::copy(v.begin(), v.end() - 1,
+ std::ostream_iterator< IPAddr >(os, ", "));
+ return os << v.back() << "]";
+}
+
+// vim: set et sw=4 sts=4 :
--- /dev/null
+#ifndef _RESOLVER_H_
+#define _RESOLVER_H_
+
+#include "devque.h"
+#include "ipaddr.h"
+#include "resolvproto.h"
+#include <string>
+#include <vector>
+#include <map>
+#include <istream>
+#include <ostream>
+#include <stdexcept>
+
+/// Resolver de nombres
+struct Resolver
+{
+
+ /// Zonas para las que este servidor de nombres es autoridad
+ typedef ResolvProtoResponse::ipvec_t ipvec_t;
+ ipvec_t nameservers;
+
+ /// IP
+ IPIn& ipin;
+ IPOut& ipout;
+
+ /// Colas de recepción
+ DevQue& res_que;
+
+ /// Constructor
+ Resolver(std::istream& is, IPIn& ipin, IPOut& ipout, DevQue& res_que)
+ throw (std::runtime_error);
+
+ /// Resultado de la petición
+ enum result_t
+ {
+ OK, ///> Respuesta válida
+ HOST_NOT_FOUND, ///> No se encuentra dicho host
+ NO_RECOVERY, ///> Error irreparable (por ejemplo, no hay nameservers)
+ TRY_AGAIN ///> Error temporal (por ejemplo, timeout)
+ };
+
+ /// Obtiene la(s) IP de un host a través de su nombre de dominio
+ result_t gethostbyname(const std::string& name, ipvec_t& ips);
+
+ /// Consulta a otro name server sobre un nombre
+ ResolvProtoResponse query(const std::string& name, const IPAddr& ip);
+
+ /// Loop que recibe y carga los paquetes en las colas para ser procesados
+ void recv_loop();
+
+};
+
+/// Impresión (para debug)
+std::ostream& operator<< (std::ostream& os, const Resolver& res);
+std::ostream& operator<< (std::ostream& os, const Resolver::ipvec_t& ips);
+
+#endif // _RESOLVER_H_
+
+// vim: set et sw=4 sts=4 :
// responses
RP_RES_A, ///> OK, se devolvió un registro A
RP_RES_NS, ///> OK, se devolvió un registro NS (sólo en directo)
- RP_RES_NOTFOUND, ///> No se encontró
- RP_RES_TIMEOUT ///> Tardó demasiado la consulta
+ RP_RES_NOTFOUND ///> No se encontró
};
/// Petición de un nameserver
burns A 10.10.10.1
homero A 10.10.10.2
marge A 10.10.10.3
-manuk A 10.10.10.141
+manuk A 10.10.10.5
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
+manuk NS 10.10.10.5
burns.casa 600 0.0.0.0
tito A 100.10.100.1
marge NS 10.10.10.3
todos NS 10.10.10.1
todos NS 10.10.10.3
-todos NS 10.10.10.141
+todos NS 10.10.10.5
pepe A 30.10.100.4
juan A 30.10.100.5
pepe A 30.10.100.6
-manuk NS 10.10.10.141
+manuk NS 10.10.10.5
todos NS 10.10.10.1
todos NS 10.10.10.3
-todos NS 10.10.10.141
+todos NS 10.10.10.5
todos.homero.casa 9500 10.10.10.2
tito A 10.1.100.1