Cosas mías

October 31, 2006

Cómo convertir una IP en formato texto a su valor numérico

Filed under: Programación

En un boot de Windows CE, de cuyo nombre no me dejan acordarme, no ha mucho tiempo tuve que realizar un parser de una IP en formato texto a valor númerico, sin biblioteca en tiempo de ejecución, depurador y sin cualquiera otra extensión. Limitado a un espacio de 128K con todo incluído, arranque, asignación de memoria, inicio de red las más noches, carga sobre SD los sábados…

Bueno, tras este homenaje al insigne escritor español, vuelvo a empezar.

Es cosa interesante esta de los sistemas de arranque, con todas sus limitaciones, tanto a la hora de desarrollarlos como a la de depurarlos. Windows CE lleva un modelo de arranque en tres etapas. La primera la suministra el fabricante del microprocesador y la implementa el ingeniero de hardware. Normalmente va integrada dentro de la propia flash del micro y apenas tiene código para buscar el dispositivo de arranque real. Vamos, que es como una BIOS.

Luego está el fichero llamado "eboot.nb0", que se situa sobre el almacenamientos secundario (una tarjeta Secure Digital en mi caso, en otros un disco duro, un CD o una ROM). Este fichero es lanzado por la BIOS (para entendernos), y sería el equivalente al arranque de un XP. En el CE estamos limitados a 128 KB de tamaño, en el que tenemos que embutir como podamos todo lo necesario para arrancar la máquina. Luego ese fichero termina llamando a NK.BIN, que realmente es el sistema operativo, almacenado en una imagen con el nombre descrito.

En el caso que nos ocupa, el "eboot.nb0" ha de inicializar la RAM y su correspondiente MMU, los puertos serie, la tarjeta de red (puesto que existe la opción de conectar el Platform Builder en lugar de arrancar el sistema operativo desde la placa), el puerto paralelo si lo hubiera, el pcmcia y los sistemas de ficheros básicos. Y sorprendentemente, todo eso apenas ocupa 80K de código.

Este "eboot.nb0" lo suministra el fabricante del chip, aunque todos terminan tomando el modelo de Microsoft, que viene de la época del MS-DOS y apenas ha evolucionado. Y el fabricante te da unas especificaciones, y si quieres otras, pues te toca meterle mano a ese código.

Aunque existe un depurador para ello, no es habitual disponer de él, por lo que te las tienes que ingeniar. Normalmente este fichero saca un montón de información por puerto serie… una vez que has conseguido poner dicho puerto serie en marcha, por lo que si lo que vas a modificar no tiene que ver con el hardware de la máquina, pues lo mejor es hacerte un proyecto en el PC simulando lo mejor que puedas la tarea, y luego copiar el código y rezar para que no tenga demasiados bugs.

En mi caso el fabricante suministra la conexión con el Platform Builder mediante DHCP, y si tienes un dispositivo sin pantalla (como es mi caso), la cosa se puede volver muy, pero que muy interesante, pues estás poco menos que ciego. Por ello decidí cambiar el boot de DHCP a IP estática, IP que vendría indicada en un fichero de texto ASCII con el formato habitual de "aaa.bbb.ccc.ddd".

Pero eso suponía el tener que convertir dicha cadena, una vez cargada de SD mediante una serie de funciones un tanto barrocas, a un unsigned int, que es el formato que realmente entiende el ordenador. El mayor problema es que no disponemos de nada, apenas de lo que el fabricante haya incluído en ese fichero. Por suerte la función atoi sí que está implementada…

Otro problema es localizar dónde cambiarla o asignarla, aunque no vamos a entrar en él, la cosa puede convertirse en una búsqueda interesante, entretenida, forzosamente desesperante y tendente al suicidio. Pero supongamos que hemos descubierto el lugar correcto y sabemos cómo hacerlo. Sólo nos queda realizar la conversión.

En ip tendremos el valor final de la IP convertida, y en ucAsciiIP, el valor original en formato texto. El código es el siguiente:

 UCHAR ucAsciiIP,*ptemp;
 unsigned long ip=0;
 int i,j=0;

 ptemp=ucAsciiIP;
 for(i=0;i<4;i++)
 {
  ptemp=&ptemp[j];
  if(i<3)
  {
   j=0;
   while(ptemp[j]!=’.')
    j++;
   ptemp[j]=0;
  }
  ip+=atoi(ptemp)<<(i*8);
  j++;
 }

Aunque el pedazo de código pueda parecer lioso, es muy sencillo. Vamos buscando los puntos y sustituyéndolos por un cero; luego la cadana anterior contiene el número correspondiente entre 0 y 255 en formato ASCII. La llamada a atoi realiza la conversión, y volvemos a iterar. El condicional que compara si i es menor que tres está porque el último número ya tiene su terminador nulo.

De esta forma hemos realizado un parser de IPs compacto, rápido y que sólo utiliza una función de la biblioteca de tiempo de ejecución. La implementación de atoi es trivial, y la dejamos para ejercicio del lector.

Una ventaja importante de este código es que la IP en formato cadena no tiene que tener un formato fijo, sino que valores como "192.168.2.1", "133.5.4.6" o "1.3.5.5" son perfectamente válidos y parseables.

Get free blog up and running in minutes with Blogsome
Theme designed by Gary Rogers