Sunteți pe pagina 1din 17

T

Universidad Carlos III de Madrid


Dpto. de Ingeniera Telemtica

LABORATORIO DE TELEMATICA Manual de Referencia e Instalacion de LINPAL

Prof. Dr. Jos Ignacio Moreno Novella

Ingeniera de Telecomunicacin. 3er Curso

Laboratorio de Telemtica

Indice:
1. 2. 2.1. 2.2. 2.3. 2.4. 2.5. 2.6. AGRADECIMIENTOS .................................................................................................................... 3 MANUAL DE LA LIBRERA LINPAL ......................................................................................... 4 INTRODUCCIN: ...................................................................................................................... 4 DEPENDENCIAS: ....................................................................................................................... 4 INSTALACIN Y COMPILACIN: ........................................................................................ 4 MAN-PAGE: ................................................................................................................................ 5 RESUMEN DE TIPOS DE DATOS: .......................................................................................... 5 RESUMEN DE CONSTANTES: ................................................................................................ 7

CONSTANTES GLOBALES .......................................................................................................................... 7 CONSTANTES DE ESTADSTICAS ............................................................................................................... 7 CONSTANTES DE FILTROS ......................................................................................................................... 8 2.7. RESUMEN DE FUNCIONES: ................................................................................................... 8 APERTURA Y CIERRE DEL ADAPTADOR: .................................................................................................... 8 ENVO DE TRAMAS: .................................................................................................................................. 9 RECEPCIN DE TRAMAS: ........................................................................................................................... 9 CONTROL Y SOLICITUD DE INFORMACIN AL CONTROLADOR Y AL ADAPTADOR: ................................. 10 SELECCIN DE ADAPTADORES: .............................................................................................................. 12 IMPRESIN DE RESULTADOS ................................................................................................................... 13 2.8. 3. 4. 5. LIBRERAS YA INCLUIDAS EN EL PAQUETE: ............................................................... 15 EJEMPLO DE ENVO DE TRAMA ............................................................................................ 16 EJEMPLO DE RECEPCIN DE TRAMAS ............................................................................... 17 REFERENCIAS .............................................................................................................................. 17

-2-

Laboratorio de Telemtica

Laboratorio de Telemtica
1. Agradecimientos
La asignatura de Laboratorio de Telemtica agradece a D. Francisco Antonio Gomz Marcos, el trabajo realizado en su proyecto fin de carrera, que ha permitido adaptar las libreras del antiguo laboratorio basado en interfaz de packet driver a un entorno basado en plataforma Windows NT sobre interfaz NDIS, conformando el API NEPAL utilizado en el desarrollo de las prcticas del laboratorio y precursor de la actual version disponible en LINUX. Del mismo modo la asignatura agradece el trabajo desarrollado por los alumnos Da. M Jess Quevedo Muoz, D. Antonio de la Oliva Delgado para la migracin de dicha librara a entorno LINUX consituyendo el entorno LINPAL: Linux-Integrated Network Packet Adapter Library.

-3-

Laboratorio de Telemtica

2. Manual de la Librera LINPAL 2.1. Introduccin:

Este proyecto tiene como objetivo el paso de la librera Nepal, creada por D. Francico Antonio Gmez Marcos, a un entorno Linux. Al igual que Nepal se basaba en dispositivos NDIS en su versin para Windows, la librera Linpal se basar en dispositivos reconocibles mediante la libpcap para Linux.

2.2.

Dependencias:

Para el funcionamiento de Linpal se necesita la librera libpcap-dev (>=0.7.2-1) . Se puede bajar de la pgina www.tcpdump.org . Se puede descargar el paquete libpcap-dev versin 0.7.2, actualmente en fase instable.

2.3.

Instalacin y compilacin:

La instalacin se realiza a travs del paquete debian liblinpal_0.0.1-3_i386.deb. Este paquete tiene como dependencias la librera libpcap (que se instala con el paquete libpcap-dev (>=0.7.2-1)). Los comandos exactos a utilizar para instalar seran: (se supone que el usuario tiene permisos de root) apt-get install libpcap-dev dpkg i liblinpal_0.0.1-3_i386.deb Estos paquetes instalarn los siguientes ficheros en el sistema: /usr/lib/liblinpal.a /usr/include/linpal.h /usr/share/man/man3/linpal.3 Para desinstalar el paquete se debe seguir el proceso inverso: dpkg r liblinpal_0.0.1-3_i386.deb Para compilar un programa realizado con linpal, se debe utilizar el siguiente comando: gcc Wall mi_programa.c llinpal -lpcap El programa compilado es el fichero a.out

-4-

Laboratorio de Telemtica

2.4.

Man-page:

La pgina man del proyecto es accesible a travs de "man linpal".

2.5.

Resumen de Tipos de Datos:

Estos tipos de datos estn definidos en el fichero linpal.h Boolean: Define dos tipos, True y False, tipificados como 1 y 0 respectivamente. ETHERNET_ADDRESS: Define una direccin MAC Ethernet, de tamao ETHERNET_ADDRESS_LENGTH. IP_ADDRESS: Define una direccin IP, de tamao IP_ADDRESS_LENGTH. ADAPTER: Define la estructura del adaptador. Los campos que lo componen vienen a continuacin. struct ADAPTER{ unsigned char name[MAX_NAME_ADAPTER] int fd pcap_t* descriptor Byte CurrentAddress [ETHERNET_ADDRESS_LENGTH] } La estructura est formada por los campos name (nombre del adaptador en formato eth0), fd (descriptor del socket utilizado en el envo de paquetes), descriptor (descriptor de la estructura para la recepcin de paquetes) y CurrentAddress que es la direccin MAC asociada al adaptador. Todos estos campos los rellena la propia librera a travs de la funcin NepalOpenAdapter. Los campos de la estructura NO deben ser modificados por el usuario. LPADAPTER: Define un puntero a una estructura ADAPTER. Debe reservarse memoria antes de utilizarlo. ETHERNET_FRAME: Estructura que representa una trama Ethernet. Los campos de la misma se detallan a continuacin. struct ETHERNET_FRAME{ Byte DestinationAddress[ ETHERNET_ADDRESS_LENGTH ] Byte SourceAddress[ ETHERNET_ADDRESS_LENGTH ] Byte Protocol [2] Byte Data[ ETHERNET_PACKET_LENGTH ETHERNET_HEADER_LENGTH ] }
-5-

Laboratorio de Telemtica

Todos los campos de la trama son los normales en el formato de trama Ethernet. Las constantes de tamao vienen comentadas ms adelante en el manual. LPETHERNET_FRAME: Puntero a una estructura ETHERNET_FRAME. Debe reservarse memoria para la trama antes de utilizarse. ADAPTER_INFO: Estructura que contiene las diferentes estadsticas del adaptador. struct ADAPTER_INFO{ unsigned char name[14] unsigned long RxBytes unsigned long RxPackets unsigned long RxErrors unsigned long RxDrop unsigned long RxFifo unsigned long RxFrame unsigned long RxCompressed unsigned long RxMulticast unsigned long TxBytes unsigned long TxPackets unsigned long TxErrors unsigned long TxDrop unsigned long TxFifo unsigned long TxColls unsigned long TxCarrier unsigned long TxCompressed }

-6-

Laboratorio de Telemtica

Estadstica Bytes Packets Errors Drop Fifo Frame Compressed Colls Carrier Multicast

Descripcin The total number of bytes of data transmitted or received by the interface. The total number of packets of data transmitted or received by the interface. The total number of transmit or receive errors detected by the device driver. The total number of packets dropped by the device driver. The number of FIFO buffer errors. The number of packet framing errors. The number of compressed packets transmitted or received by the device driver. (This appears to be unused in the 2.2.15 kernel.) The number of collisions detected on the interface. The number of carrier losses detected by the device driver. The number of multicast frames transmitted or received by the device driver.

LPADAPTER_INFO: Puntero a una estructura de estadsticas de adaptador.

2.6.

Resumen de Constantes:
Constantes Globales

ETHERNET_ADDRESS_LENGTH 6 ETHERNET_PACKET_LENGTH 1514 ETHERNET_HEADER_LENGTH 14 MAX_NAME_LENGTH 255 IP_ADDRESS_LENGTH 4 ESTADISTICAS_SIZE 80 MAX_NAME_ADAPTER 14 Constantes de Estadsticas RXBYTES 1 RXPACKETS 2 RXERRORS 3 RXDROP 4 RXFIFO 5 RXFRAME 6 RXCOMPRESSED 7 RXMULTICAST 8 TXBYTES 9 TXPACKETS 10 TXERRROS 11 TXDROP 12
-7-

Laboratorio de Telemtica

TXFIFO 13 TXCOLLS 14 TXCARRIER 15 TXCOMPRESSED 16 Constantes de Filtros PACKET_TYPE_BROADCAST 0x01 PACKET_TYPE_DIRECTED 0x02 PACKET_TYPE_PROMISCUOUS 0x03 OR_DIRECTED_BROADCAST 0x00

2.7.

Resumen de funciones:
Apertura y cierre del adaptador:

NepalOpenAdapter: int NepalOpenAdapter(char *name, LPADAPTER lpAdapter) Descripcin: Esta funcin sirve para abrir un adaptador especfico. Recibe un nombre de adaptador ("eth0", "eth1"...) y devuelve un LPADAPTER (puntero a una estructura adaptador).Para liberar los recursos hay que usar NepalCloseAdapter. La estructura LPADAPTER debe estar reservada en memoria previamente a la llamada a la rutina. El campo de la direccin MAC del adaptador se rellena de manera automtica y se puede acceder a l cuando se necesite la direccin MAC del adaptador. Ante errores devuelve -1. Parmetros de Entrada: Char *: name es un puntero a Byte, en l se guarda el nombre del adaptador que se desea abrir. LPADAPTER: lpAdapter es la estructura que se rellena. La memoria que ocupa debe estar reservada previamente a la llamada a la funcin. Salida: Si la funcin termina correctamente devuelve 0, si se produce un error se devuelve -1 y se rellena la variable neperror a la que se puede acceder con la funcin
printNep2Error.

-8-

Laboratorio de Telemtica

NepalCloseAdapter: void NepalCloseAdapter(LPADAPTER lpAdapter) Descripcin: Esta funcin sirve para cerrar el adaptador que hemos abierto con NepalOpenAdapter. Libera los recursos reservados en los campos del adaptador que se pasa como parmetro, NO libera la memoria asociada a la estructura del adaptador. Parmetros de Entrada: LPADAPTER: lpAdapter es el adaptador a cerrar. Salida: La funcin no devuelve nada pero si se ha producido un error se rellena la variable neperror a la que se puede acceder a travs de la funcin printNep2Error. Envo de tramas: NepalSendPacket: int NepalSendPacket( LPADAPTER lpAdapter, LPETHERNET_FRAME lpEthFrame, int lpEthFrame_size ) Descripcin: Esta funcin permite el envo por el adaptador lpAdapter de la trama lpEthFrame de tamao lpEthFrame_size. Parmetros de Entrada: LPADAPTER: lpAdapter es el adaptador por el que se enva la entrada. LPETHERNET_FRAME: lpEthFrame es la trama a enviar. lpEthFrame_size: Es el tamao de la trama a enviar. Salida: Devuelve un int, 1 si se ha podido enviar sin problemas, -1 si se ha producido algn error en la funcin. Si se ha producido un error se puede acceder a l a travs de la funcin printNep2Error. Recepcin de tramas: NepalReadPacket: int NepalReadPacket( LPADAPTER lpAdapter, LPETHERNET_FRAME lpEthFrame, Boolean is_block ) Descripcin: Esta funcin realiza la lectura de una trama. La trama es leda del adaptador lpAdapter, la trama recibida se guarda junto con su tamao en la estructura packet. La lectura puede ser bloqueante (la funcin no retorna hasta no haber completado la lectura) o no bloqueante, segn se especifique en la variable bSync.
-9-

Laboratorio de Telemtica

Parmetros de Entrada: LPADAPTER: lpAdapter es el adaptador en donde se escucha la trama. LPETHERNET_FRAME: lpEthFrame es la estructura en donde se guarda la trama recibida. is_block: Variable Boolean que indica cuando la lectura es bloqueante (True) o no bloqueante (False). Salida: Devuelve un entero que indica si se ha ledo correctamente. Si se ha producido cualquier error se devuelve -1. En este caso se puede acceder al error a travs de la funcin printNep2Error. Si la funcin no ha recibido ningn paquete devuelve 0, y si devuelve algn paquete devuelve la longitud del mismo. IMP: La memoria para el paquete se ha de reservar y liberar por el usuario fuera de la funcin. El tamao de memoria a reservar es ETHERNET_PACKET_LENGTH. Control y Solicitud de Informacin al Controlador y al Adaptador: NepalGetInfo: int NepalGetInfo(LPADAPTER lpAdapter, PADAPTER_INFO AdapterInfo) Descripcin: Esta funcin solicita informacin al controlador sobre el adaptador de red, devolviendo una estructura de datos con el mximo de informacin disponible sobre el controlador de red. La estructura que se pasa para rellenar con la informacin del adaptador debe ser reservada anteriormente. Parmetros de Entrada: LPADAPTER: lpAdapter es el adaptador del que se extrae la informacin. PADAPTER_INFO: AdapterInfo es la estructura a rellenar con la informacin. Salida: La funcin devuelve un int, 1 si la funcin se ha completado con xito, -1 si se ha producido algn error. En este caso se puede acceder a la informacin del error a travs de la funcin printNep2Error NepalGetStat: unsigned long NepalGetStat(LPADAPTER lpAdapter, int stat) Descripcin: Esta funcin permite consultar de forma individual informacin del adaptador de red. Parmetros de Entrada: LPADAPTER: lpAdapter es el adaptador del que se extrae la informacin.
- 10 -

Laboratorio de Telemtica

stat: Es el cdigo de la estadstica que se quiere obtener. Las estadsticas existentes son: RXBYTES RXPACKETS RXERRORS RXDROP RXFIFO RXFRAME RXCOMPRESSED RXMULTICAST TXBYTES TXPACKETS TXERRROS TXDROP TXFIFO TXCOLLS TXCARRIER TXCOMPRESSED La explicacin de las estadsticas anteriores es la misma que la de los campos de la estructura ADAPTER_INFO. Salida: Devuelve el valor de la estadstica pedida y -1 ante los errores. El mensaje de error puede obtenerse a travs de la funcin printNep2Error. NepalSetFilter: int NepalSetFilter(LPADAPTER lpAdapter, char *filtroProto, int filtroDirec) Descripcin: Esta funcin permite establecer un filtro de direccin y protocolo para el adaptador especificado. Parmetros de Entrada: LPADAPTER: lpAdapter es el adaptador al que se le quiere poner el filtro. filtroProto: Cadena que especifica el valor numrico del filtro de protocolo. Un ejemplo de filtro de protocolo sera "0x0806" que especifica ARP. filtroDirec: Cadena que especifica el filtro de direccin. Puede ser uno de los siguientes: o PACKET_TYPE_BROADCAST: Selecciona los paquetes con direccin destino de broadcast. o PACKET_TYPE_DIRECTED: Selecciona los paquetes con direccin destino la propia del adaptador (direccin MAC). o PACKET_TYPE_PROMISCUOUS: Pone el adaptador en modo promiscuo.
- 11 -

Laboratorio de Telemtica

o OR_DIRECTED_BROADCAST: Selecciona todas las tramas con direccin destino de broadcast y la propia del adaptador. Salida: int que indica si se ha podido realizar la operacin. Ante errores devuelve -1. printNep2Error: void printNep2Error(char * ErrString) Descripcin: Esta funcin permite obtener informacin acerca de los errores que se producen dentro de la librera linpal. Parmetros de Entrada: ErrString: Cadena que se imprime antes del mensaje de error. Salida: "ErrString: Error especfico." Seleccin de Adaptadores: NepalGetAvailAdapterNames: int NepalGetAvailAdapterNames (char *names, char *desc, int iDesc ) Descripcin: Esta funcin sirve para consultar el sistema y obtener informacin sobre los adaptadores disponibles. Parmetros de Entrada: names: puntero a una zona de memoria que ha sido reservada fuera de la funcin, donde se almacenaran los nombres de los adaptadores de red disponibles en el sistema. Los nombres se devuelven separados por caracteres nulos genricos y al final termina con dos nulos seguidos. desc: puntero a una zona de memoria para que la funcin almacene una descripcin de los adaptadores de red disponibles en el sistema. Las descripciones se devuelven en el mismo orden que los nombres separadas por un carcter nulo genrico ('\0') y termina con dos nulos seguidos. iDesc: valor entero de entrada que indica el nmero mximo de bytes reservados en el parmetro desc para almacenar descripciones. Salida: nmero de adaptadores de red, -1 si se ha producido un error 0 si no hay ninguno. Todas las variables que se pasan a esta funcin deben haber sido reservadas con anterioridad a la llamada. Los nombres de los adaptadores que devuelve esta funcin son del tipo "eth0". NepalSelectAdapter: int NepalSelectAdapter( char *names,
- 12 -

Laboratorio de Telemtica

char *selectedName, char *desc) Descripcin: Esta funcin permite, en modo consola, mostrar un men con los distintos adaptadores existentes en el sistema y solicita al usuario que seleccione uno de ellos. Parmetros de Entrada: names: En esta variable se almacenan los nombres de todos los adaptadores del sistema. Se almacenan con el mismo formato que en NepalGetAvailAdapters. selectedName: Puntero a una zona de memoria previamente almacenada por el usuario donde se almacena el nombre del adaptador seleccionado. desc: Mismo valor que en NepalGetAvailAdapters. Salida: Devuelve un nmero comprendido entre 1 y el nmero de adaptadores en el sistema, que corresponde con el adaptador seleccionado por el usuario. Si se produce algn error devuelve -1. El men que aparece en pantalla es tal que:

Available Adapters: -----------------------1.- eth0 (null) 2.- any Pseudo-device that captures on all interfaces 3.- lo (null) Select Adapter:_

Impresin de Resultados NepalIP2Byte int NepalIP2Byte(char *dir,IP_ADDRESS dirIP); Descripcin: Esta funcin tiene como objetivo la conversin de una direccin IP en formato "192.168.0.10" a una representacin binaria de la misma. Parmetros de Entrada: dir: Direccin IP en formato "192.168.0.10". IP_ADDRESS: dirIP es la variable en la que se almacena la representacin binaria de la direccin. Salida: La funcin retorna la direccin que pasamos en dir convertida a binario en dirIP. Ante los errores devuelve False, y se puede comprobar el error a travs de la funcin printNep2Error.
- 13 -

Laboratorio de Telemtica

NepalEther2Byte int NepalEther2Byte(char *dir,ETHERNET_ADDRESS dirEth); Descripcin: Esta funcin tiene como objetivo la conversin de una direccin MAC en formato "FF:FF:FF:FF:FF:FF" a una representacin binaria de la misma. Parmetros de Entrada: dir: Direccin MAC en formato "FF:FF:FF:FF:FF:FF". ETHERNET_ADDRESS: dirEth es la variable en la que se almacena la representacin binaria de la direccin. Salida: La funcin retorna la direccin que pasamos en dir convertida a binario en dirEth. Ante los errores devuelve False, y se puede comprobar el error a travs de la funcin printNep2Error. NepalWriteEtherAddress void NepalWriteEtherAddress(ETHERNET_ADDRESS dir); Descripcin: Esta funcin permite mostrar en la consola una direccin MAC en formato binario. La representacin de la misma en la consola tiene el formato "FF:FF:FF:FF:FF:FF". Parmetros de Entrada: ETHERNET_ADDRESS: dir es la direccin que deseamos imprimir por pantalla. Tiene un formato binario Salida: Esta funcin no devuelve nada ante errores, pero rellena la variable neperror con lo que la causa del error puede conocerse con la funcin printNep2Error. NepalWriteIPAddress void NepalWriteIPAddress(IP_ADDRESS dir); Descripcin: Esta funcin permite mostrar en la consola una direccin IP en formato binario. La representacin de la misma en la consola tiene el formato "192.168.0.10". Parmetros de Entrada: IP_ADDRESS: dir es la direccin que deseamos imprimir por pantalla. Tiene un formato binario Salida: Esta funcin no devuelve nada ante errores, pero rellena la variable neperror con lo que la causa del error puede conocerse con la funcin printNep2Error. NepalWriteEtherFrame void NepalWriteEtherFrame( LPETHERNET_FRAME lpEthFrame, int ulEthFrameTotalSize);
- 14 -

Laboratorio de Telemtica

Descripcin: Esta funcin permite la impresin en la consola de una trama completa Ethernet. Parmetros de Entrada: LPETHERNET_FRAME: lpEthFrame es la trama que queremos mostrar. ulEthFrameTotalSize: Es el tamao de la trama lpEthFrame. Salida: Esta funcin no devuelve nada ante errores, pero rellena la variable neperror con lo que el error es accesible a travs de la funcin printNep2Error. Un ejemplo de la representacin de una trama sera: 0000: 0001: 0002: 0003: 0004: 00 C0 26 A3 7F EC 08 00 45 00 00 28 8A 48 A3 75 8C B2 00 16 E3 A0 DB D9 44 70 C4 E4 00 00 00 C0 26 A0 20 32 10 B0 40 00 80 06 A3 75 8C 3A 04 38 F4 2E 8E B0 50 10 20 20 20 20 20 20

2.8.

Libreras ya incluidas en el paquete:

Las libreras que a continuacin se detallan ya se incluyen en linpal.h. NO hace falta definirlas en el programa a desarrollar. #include <sys/types.h> #include <sys/socket.h> #include <string.h> #include <errno.h> #include <stdlib.h> #include <unistd.h> #include <pcap.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netinet/ether.h> #include <sys/ioctl.h> #include <net/if.h> #include <ctype.h>

- 15 -

Laboratorio de Telemtica

3. Ejemplo de Envo de trama


/*Este programa es un ejemplo para mandar una trama broadcast */ #include <linpal.h> int main(){ char selec[MAX_NAME_LENGTH]="eth0"; int i; struct ADAPTER lpAdapter; struct ETHERNET_FRAME frame;

if ((NepalOpenAdapter(selec, &lpAdapter))==-1){ printNep2Error("Error en NepalOpenAdapter"); exit(1); } NepalEther2Byte("ff:ff:ff:ff:ff:ff",frame.DestinationAddress); memcpy(frame.SourceAddress,&(lpAdapter.CurrentAddress),ETHERNET_ADDRES S_LENGTH); frame.Protocol[0]=0x08; frame.Protocol[1]=0x00; memset(&(frame.Data),'\0',ETHERNET_PACKET_LENGTH ETHERNET_HEADER_LENGTH); i=NepalSendPacket(&lpAdapter, &frame, ETHERNET_PACKET_LENGTH); if (i==-1){ printNep2Error("Error en NepalSendPacket"); exit(1); } NepalWriteEtherFrame(&frame, ETHERNET_PACKET_LENGTH); NepalCloseAdapter(&lpAdapter); return i; }

- 16 -

Laboratorio de Telemtica

4. Ejemplo de Recepcin de tramas


/*Ejemplo de recepcion de tramas con Linpal*/ #include <linpal.h> int main(){ char selec[MAX_NAME_LENGTH]="eth0"; int i; struct ADAPTER adapter; // struct PACKET packet; struct ETHERNET_FRAME frame; // int longitud; if ((NepalOpenAdapter(selec, &adapter))==-1){ printNep2Error("Error al abrir el adaptador"); return -1; } if ((NepalSetFilter(&adapter, NULL, PACKET_TYPE_PROMISCUOUS))==-1){ printNep2Error("Error NepalSetFilter"); exit(1); } for (i=0;i<4;i++){ while (NepalReadPacket(&adapter, &frame, 0)==-1){ //True es bloqueante printf("."); } printf("_%i_\n",i); NepalWriteEtherFrame (&frame, 20); } NepalCloseAdapter(&adapter); return 0; }

5. Referencias
[Stevens94] TCP/IP Illustrated, Vol 1. W.Richard Stevens. Addison-Wesley 1994. [Perlman00] Interconnections. Bridges, Routers, Switches and Interworking Protocols.2 Edition. R.Perlman. Addison Wesley. 2000. [Comer95] Internetworking with TCP/IP. Third Edition. D.Comer. Prentice Hall. 1995. [RFC826] An Ethernet Address Resolution Protocol. Request for Comments 826, D.C.Plummer. Nov 1982. [RFC1700] Assigned Numbers. J. Reynolds,J. Postel. October 1994. [RFC1055] A Nonstandard for Transmision of IP Datagrams over Serial Lines: SLIP. J. Romkey. June 1988. [Kelley98] A Book on C", 4 ed., Al Kelley, Ira Pohl, Addison Wesley [Kernighan88] "The C Programming Languaje", 2 ed. Brian W. Kernighan, Dennis M. Ritchie, Prentice-Hall [Tanem] A.S. Tanembaum, Redes de Ordenadores 3 Ed. Prentice Hall, 1997

- 17 -

S-ar putea să vă placă și