Una de les tasques que tenia pendents al meu TODO des del començament del projecte era la d'implementar les operacions de la interfície iioctl i les d'altres interfícies si era necessari. La interfície iioctl s'encarrega d'atendre les peticions ioctl que reben com a paràmetre un socket. A més, pfinet també implementa una interfície anomenada "pfinet" que respon a les peticions SIOCGIFCONF
. Amb aquestes interfícies, podem configurar el translator programàticament des d'una aplicació d'usuari si aquesta té permisos suficients, a més, tots els usuaris poden obtindre informació sobre la configuració de la pila.
La darrera setmana he començat a escriure algunes de les operacions i a dia d'avui ja es tramiten les peticions SIOCGIFADDR
, SIOCGIFDSTADDR
, SIOCGIFBRDADDR
, SIOCGIFNETMASK
, SIOCSIFADDR
, SIOCSIFDSTADDR
, SIOCSIFBRDADDR
, SIOCSIFNETMASK
, SIOCGIFFLAGS
i SIOCSIFFLAGS
. A continuació comentaré alguns dels problemes que m'he trobat.
En primer lloc, em va estranyar comprovar que les operacions SIOCS*, és a dir, les de configuració, s'executaven sense problemes des d'un programa d'usuari normal quan només haurien d'estar permeses per a l'usuari root. Si intentava el mateix amb pfinet, aquest retornava un error EPERM
. Al final vaig descobrir que el secret estava en l'operació socket_create(). En aquesta operació s'estableix que l'usuari s'ha de considerar root si és el propietari del fitxer on està instal·lat el translator. Per tant, si funcionava en pfinet era perquè aquest estava instal·lat en /server/sockets/2
, on el meu usuari no n'era el propietari, mentre que el translator lwip estava instal·lat en un fitxer de la meua home.
Un altre problema el vaig tindre amb l'operació SIOCSIFBRDADDR
, per a canviar l'adreça de difusió d'una xarxa. Al principi no sabia com fer-ho, i prompte vaig descobrir que simplement aquesta operació no està suportada per LwIP. Tanmateix, em vaig quedar amb el dubte: Per a què necessita algú canviar l'adreça de difusió d'una xarxa? en quina situació pot ser útil això? Ho he preguntat a SuperUser i de moment ningú m'ha contestat...
Finalment m'he trobat amb un problema amb els indicadors del dispositius. El problema és el següent: si establim els indicadors amb l'operació SIOCSIFFLAGS
tot funciona bé i de seguida es noten els efectes, però quan després cridem a l'operació SIOCGIFFLAGS
no obtenim els indicadors establerts en la crida anterior, obtenim 0x00000041. De fet, no importa quins siguen els indicadors establerts al dispositiu, l'operació device_get_status() amb el paràmetre NET_STATUS
sempre retorna 0x00000041 al camp d'indicadors. Això es pot arreglar emprant el paràmetre NET_FLAGS
, amb aquest sí que he pogut comprovar que sempre retorna el valor correcte, però aquest no funciona quan s'està treballant sobre un dispositiu multiplexat amb el servidor eth-multiplexer. Al final he deixat la primera opció amb el paràmetre NET_STATUS
, però caldrà investigar si és la millor opció.
A banda de la interfície iioctl, també he dedicat una part dels darrers dies a solucionar errors. En una ocasió, em vaig trobar que la pila em retornava un error on deia que no hi havien més sockets disponibles. Això em va sorprendre, és que hi ha límit de sockets? Doncs sí, LwIP estableix un límit. A LwIP, els sockets es desen en un array global, per tant, tota la memòria necessària està ocupada des del començament i la quantitat d'elements està limitada per la quantitat de memòria disponible en el sistema. Com que LwIP està adreçat a sistemes encastats on la memòria és escassa, la quantitat màxima de sockets per defecte és... quatre. He augmentat la quantitat màxima fins arribar a la increïble xifra de 32, espere que el Hurd aguante :P. Però això m'ha fet preguntar-me si hi ha una quantitat màxima de sockets en altres sistemes. Com era d'esperar, el que he trobat per Internet és que no hi ha un límit fixat i que depèn de la configuració i la memòria disponible. Però probablement en altres sistemes els sockets es desen en memòria dinàmica que creix sota demanda. El problema amb LwIP és que es tracta de memòria estàtica i siga quina siga la xifra tirada, serà memòria malgastada en la majoria dels casos i insuficient per a casos especials. A més, aquest no és l'únic cas, el mateix problema es repeteix amb la quantitat de connexions TCP, "connexions" UDP, adreces IPv6 per interfície, etc. Lamentablement, no sembla que aquest problema tinga solució.