A hores d'ara, l'única funcionalitat present a pfinet que encara no he implementat al servidor LwIP és la de l'opció --peer, pel que fa a la resta, ja està tot. A partir d'ara la major part del treball consistirà en polir i arreglar errors, per tant, probablement parlaré diversos temes en en cada entrada.
El primer tema amb què vaig començar aquesta setmana era un error que em sorgia quan cridava apt-get update
sobre LwIP:
../sysdeps/posix/getaddrinfo.c:1722: rfc3484_sort: Assertion `a1->source_addr.sin6_family == PF_INET6' failed.
A diferència dels errors que m'havien sorgit fins ara, aquest ocorria a la Glibc i avortava el programa d'usuari, no el servidor. Evidentment, era algun comportament inesperat de la pila el que portava a la Glibc fins aquest error, ara tocava descobrir què passava. Fent una ullada al registre generat per rpctrace, podia observar que l'operació que es cridava just abans de produir-se l'error era la socket_whatis_address()
. Explicaré una mica el sentit d'aquesta operació.
La Glibc necessita emprar dues operacions que són complementàries: socket_create_address()
i socket_whatis_address()
. La primera crea un objecte de libports que conté una estructura sockaddr
creada a partir dels paràmetres rebuts: família, contingut i grandària. La segona és la inversa, a partir del port retorna les dades d'una estructura sockaddr. Quan la Glibc rep una estructura sockaddr per part de l'usuari, li envia el seu contingut a create_address()
per poder obtindre el port amb què després cridarà a una altra operació, per exemple, a bind(). De la mateixa manera, quan alguna de les operacions de la interfície socket retorna una adreça, el que rebrà la Glibc serà un port, i haurà de cridar a whatis_address per obtindre les dades amb què poder crear una còpia de l'estructura sockaddr per retornar-li-la a l'usuari. Ho podem veure a la funció getpeername().
Doncs bé, fent una ullada a la sortida d'rpctrace, es podia observar que la primera crida a create_address()
rebia com a paràmetre la família 26
(IPv6), però després en cridar a whatis_address()
sobre el mateix port, retornava el contingut d'una estructura sockaddr de la família 2
(IPv4). Al final el problema era un bug de LwIP, que quan treballava en mode dual-stack i li preguntaves per l'adreça d'un socket IPv6 te'n retornava un d'IPv4. L'error ha resultat estar ja solucionat al repositori d'LwIP i formarà part de la propera versió.
Passat aquest problema, vaig voler provar a interrogar el servidor amb inetutils-ifconfig
, i em vaig trobar que no funcionava perquè fa una crida ioctl amb la comanda SIOCGIFCONF
de la interfície pfinet que encara no havia implementat. La vaig escriure, però abans, vaig trobar que totes les operacions tant d'aquesta interfície com les d'iioctl funcionaven només amb dispositius Ethernet, això provocava dos problemes, el primer, que intentar una ioctl sobre la interfície loopback directament feia fallar el translator; i el segon, que això era un problema per a la meua previsió de crear un nou mòdul PPP i emprar-lo en lloc del mòdul Ethernet quan implemente aquesta funcionalitat. Per tot això, he decidit crear una interfície comuna per a la comunicació amb els mòduls que serveixen de pont amb els dispositius. A més, he creat un mòdul loopback que modifica la interfície loopback d'LwIP per adaptar-la a les necessitats del Hurd i que implementa les funcions necessàries per poder integrar-se amb les peticions ioctl.