ÏT Universidad Carlos III de Madrid Dpto. de Ingeniería Telemática LABORATORIO DE TELEMATICA Manual de Referencia e Instalacion de LINPAL Prof. Dr. José Ignacio Moreno Novella Ingeniería de Telecomunicación. 3er Curso Laboratorio de Telemática Indice: 1. AGRADECIMIENTOS .................................................................................................................... 3 2. MANUAL DE LA LIBRERÍA LINPAL ......................................................................................... 4 2.1. INTRODUCCIÓN: ...................................................................................................................... 4 2.2. DEPENDENCIAS: ....................................................................................................................... 4 2.3. INSTALACIÓN Y COMPILACIÓN: ........................................................................................ 4 2.4. MAN-PAGE: ................................................................................................................................ 5 2.5. RESUMEN DE TIPOS DE DATOS: .......................................................................................... 5 2.6. RESUMEN DE CONSTANTES: ................................................................................................ 7 CONSTANTES GLOBALES .......................................................................................................................... 7 CONSTANTES DE ESTADÍSTICAS ............................................................................................................... 7 CONSTANTES DE FILTROS ......................................................................................................................... 8 2.7. RESUMEN DE FUNCIONES: ................................................................................................... 8 APERTURA Y CIERRE DEL ADAPTADOR: .................................................................................................... 8 ENVÍO DE TRAMAS: .................................................................................................................................. 9 RECEPCIÓN DE TRAMAS: ........................................................................................................................... 9 CONTROL Y SOLICITUD DE INFORMACIÓN AL CONTROLADOR Y AL ADAPTADOR: ................................. 10 SELECCIÓN DE ADAPTADORES: .............................................................................................................. 12 IMPRESIÓN DE RESULTADOS ................................................................................................................... 13 2.8. LIBRERÍAS YA INCLUIDAS EN EL PAQUETE: ............................................................... 15 3. EJEMPLO DE ENVÍO DE TRAMA ............................................................................................ 16 4. EJEMPLO DE RECEPCIÓN DE TRAMAS ............................................................................... 17 5. REFERENCIAS .............................................................................................................................. 17 -2- Laboratorio de Telemática Laboratorio de Telemática 1. Agradecimientos La asignatura de Laboratorio de Telemática agradece a D. Francisco Antonio Goméz Marcos, el trabajo realizado en su proyecto fin de carrera, que ha permitido adaptar las librerías 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 prácticas del laboratorio y precursor de la actual version disponible en LINUX. Del mismo modo la asignatura agradece el trabajo desarrollado por los alumnos Dña. Mª Jesús Quevedo Muñoz, D. Antonio de la Oliva Delgado para la migración de dicha libraría a entorno LINUX consituyendo el entorno LINPAL: Linux-Integrated Network Packet Adapter Library. -3- Laboratorio de Telemática 2. Manual de la Librería LINPAL 2.1. Introducción: Este proyecto tiene como objetivo el paso de la librería Nepal, creada por D. Francico Antonio Gómez Marcos, a un entorno Linux. Al igual que Nepal se basaba en dispositivos NDIS en su versión para Windows, la librería Linpal se basará en dispositivos reconocibles mediante la libpcap para Linux. 2.2. Dependencias: Para el funcionamiento de Linpal se necesita la librería libpcap-dev (>=0.7.2-1) . Se puede bajar de la página www.tcpdump.org . Se puede descargar el paquete libpcap-dev versión 0.7.2, actualmente en fase instable. 2.3. Instalación y compilación: La instalación se realiza a través del paquete debian liblinpal_0.0.1-3_i386.deb. Este paquete tiene como dependencias la librería libpcap (que se instala con el paquete libpcap-dev (>=0.7.2-1)). Los comandos exactos a utilizar para instalar serían: (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 instalarán 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 Telemática 2.4. Man-page: La página man del proyecto es accesible a través de "man linpal". 2.5. Resumen de Tipos de Datos: Estos tipos de datos están definidos en el fichero linpal.h Boolean: Define dos tipos, True y False, tipificados como 1 y 0 respectivamente. ETHERNET_ADDRESS: Define una dirección MAC Ethernet, de tamaño ETHERNET_ADDRESS_LENGTH. IP_ADDRESS: Define una dirección IP, de tamaño IP_ADDRESS_LENGTH. ADAPTER: Define la estructura del adaptador. Los campos que lo componen vienen a continuación. 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 envío de paquetes), descriptor (descriptor de la estructura para la recepción de paquetes) y CurrentAddress que es la dirección MAC asociada al adaptador. Todos estos campos los rellena la propia librería a través de la función 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 continuación. 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 Telemática Todos los campos de la trama son los normales en el formato de trama Ethernet. Las constantes de tamaño vienen comentadas más 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 estadísticas 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 Telemática Estadística Bytes Packets Errors Drop Fifo Frame Compressed Colls Carrier Multicast Descripción 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 estadísticas 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 Estadísticas 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 Telemática 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) Descripción: Esta función sirve para abrir un adaptador específico. 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 dirección MAC del adaptador se rellena de manera automática y se puede acceder a él cuando se necesite la dirección MAC del adaptador. Ante errores devuelve -1. Parámetros 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 función. Salida: Si la función 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 función printNep2Error. -8- Laboratorio de Telemática NepalCloseAdapter: void NepalCloseAdapter(LPADAPTER lpAdapter) Descripción: Esta función sirve para cerrar el adaptador que hemos abierto con NepalOpenAdapter. Libera los recursos reservados en los campos del adaptador que se pasa como parámetro, NO libera la memoria asociada a la estructura del adaptador. Parámetros de Entrada: ¾ LPADAPTER: lpAdapter es el adaptador a cerrar. Salida: La función no devuelve nada pero si se ha producido un error se rellena la variable neperror a la que se puede acceder a través de la función printNep2Error. Envío de tramas: NepalSendPacket: int NepalSendPacket( LPADAPTER lpAdapter, LPETHERNET_FRAME lpEthFrame, int lpEthFrame_size ) Descripción: Esta función permite el envío por el adaptador lpAdapter de la trama lpEthFrame de tamaño lpEthFrame_size. Parámetros de Entrada: ¾ LPADAPTER: lpAdapter es el adaptador por el que se envía la entrada. ¾ LPETHERNET_FRAME: lpEthFrame es la trama a enviar. ¾ lpEthFrame_size: Es el tamaño de la trama a enviar. Salida: Devuelve un int, 1 si se ha podido enviar sin problemas, -1 si se ha producido algún error en la función. Si se ha producido un error se puede acceder a él a través de la función printNep2Error. Recepción de tramas: NepalReadPacket: int NepalReadPacket( LPADAPTER lpAdapter, LPETHERNET_FRAME lpEthFrame, Boolean is_block ) Descripción: Esta función realiza la lectura de una trama. La trama es leída del adaptador lpAdapter, la trama recibida se guarda junto con su tamaño en la estructura packet. La lectura puede ser bloqueante (la función no retorna hasta no haber completado la lectura) o no bloqueante, según se especifique en la variable bSync. -9- Laboratorio de Telemática Parámetros 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 leído correctamente. Si se ha producido cualquier error se devuelve -1. En este caso se puede acceder al error a través de la función printNep2Error. Si la función no ha recibido ningún paquete devuelve 0, y si devuelve algún paquete devuelve la longitud del mismo. IMP: La memoria para el paquete se ha de reservar y liberar por el usuario fuera de la función. El tamaño de memoria a reservar es ETHERNET_PACKET_LENGTH. Control y Solicitud de Información al Controlador y al Adaptador: NepalGetInfo: int NepalGetInfo(LPADAPTER lpAdapter, PADAPTER_INFO AdapterInfo) Descripción: Esta función solicita información al controlador sobre el adaptador de red, devolviendo una estructura de datos con el máximo de información disponible sobre el controlador de red. La estructura que se pasa para rellenar con la información del adaptador debe ser reservada anteriormente. Parámetros de Entrada: ¾ LPADAPTER: lpAdapter es el adaptador del que se extrae la información. ¾ PADAPTER_INFO: AdapterInfo es la estructura a rellenar con la información. Salida: La función devuelve un int, 1 si la función se ha completado con éxito, -1 si se ha producido algún error. En este caso se puede acceder a la información del error a través de la función printNep2Error NepalGetStat: unsigned long NepalGetStat(LPADAPTER lpAdapter, int stat) Descripción: Esta función permite consultar de forma individual información del adaptador de red. Parámetros de Entrada: ¾ LPADAPTER: lpAdapter es el adaptador del que se extrae la información. - 10 - Laboratorio de Telemática ¾ stat: Es el código de la estadística que se quiere obtener. Las estadísticas existentes son: RXBYTES RXPACKETS RXERRORS RXDROP RXFIFO RXFRAME RXCOMPRESSED RXMULTICAST TXBYTES TXPACKETS TXERRROS TXDROP TXFIFO TXCOLLS TXCARRIER TXCOMPRESSED La explicación de las estadísticas anteriores es la misma que la de los campos de la estructura ADAPTER_INFO. Salida: Devuelve el valor de la estadística pedida y -1 ante los errores. El mensaje de error puede obtenerse a través de la función printNep2Error. NepalSetFilter: int NepalSetFilter(LPADAPTER lpAdapter, char *filtroProto, int filtroDirec) Descripción: Esta función permite establecer un filtro de dirección y protocolo para el adaptador especificado. Parámetros de Entrada: ¾ LPADAPTER: lpAdapter es el adaptador al que se le quiere poner el filtro. ¾ filtroProto: Cadena que especifica el valor numérico del filtro de protocolo. Un ejemplo de filtro de protocolo sería "0x0806" que especifica ARP. ¾ filtroDirec: Cadena que especifica el filtro de dirección. Puede ser uno de los siguientes: o PACKET_TYPE_BROADCAST: Selecciona los paquetes con dirección destino de broadcast. o PACKET_TYPE_DIRECTED: Selecciona los paquetes con dirección destino la propia del adaptador (dirección MAC). o PACKET_TYPE_PROMISCUOUS: Pone el adaptador en modo promiscuo. - 11 - Laboratorio de Telemática o OR_DIRECTED_BROADCAST: Selecciona todas las tramas con dirección destino de broadcast y la propia del adaptador. Salida: int que indica si se ha podido realizar la operación. Ante errores devuelve -1. printNep2Error: void printNep2Error(char * ErrString) Descripción: Esta función permite obtener información acerca de los errores que se producen dentro de la librería linpal. Parámetros de Entrada: ¾ ErrString: Cadena que se imprime antes del mensaje de error. Salida: "ErrString: Error específico." Selección de Adaptadores: NepalGetAvailAdapterNames: int NepalGetAvailAdapterNames (char *names, char *desc, int iDesc ) Descripción: Esta función sirve para consultar el sistema y obtener información sobre los adaptadores disponibles. Parámetros de Entrada: ¾ names: puntero a una zona de memoria que ha sido reservada fuera de la función, donde se almacenaran los nombres de los adaptadores de red disponibles en el sistema. Los nombres se devuelven separados por caracteres nulos genéricos y al final termina con dos nulos seguidos. ¾ desc: puntero a una zona de memoria para que la función almacene una descripción de los adaptadores de red disponibles en el sistema. Las descripciones se devuelven en el mismo orden que los nombres separadas por un carácter nulo genérico ('\0') y termina con dos nulos seguidos. ¾ iDesc: valor entero de entrada que indica el número máximo de bytes reservados en el parámetro desc para almacenar descripciones. Salida: número de adaptadores de red, -1 si se ha producido un error ó 0 si no hay ninguno. Todas las variables que se pasan a esta función deben haber sido reservadas con anterioridad a la llamada. Los nombres de los adaptadores que devuelve esta función son del tipo "eth0". NepalSelectAdapter: int NepalSelectAdapter( char *names, - 12 - Laboratorio de Telemática char *selectedName, char *desc) Descripción: Esta función permite, en modo consola, mostrar un menú con los distintos adaptadores existentes en el sistema y solicita al usuario que seleccione uno de ellos. Parámetros 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 número comprendido entre 1 y el número de adaptadores en el sistema, que corresponde con el adaptador seleccionado por el usuario. Si se produce algún 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:_ Impresión de Resultados NepalIP2Byte int NepalIP2Byte(char *dir,IP_ADDRESS dirIP); Descripción: Esta función tiene como objetivo la conversión de una dirección IP en formato "192.168.0.10" a una representación binaria de la misma. Parámetros de Entrada: ¾ dir: Dirección IP en formato "192.168.0.10". ¾ IP_ADDRESS: dirIP es la variable en la que se almacena la representación binaria de la dirección. Salida: La función retorna la dirección que pasamos en dir convertida a binario en dirIP. Ante los errores devuelve False, y se puede comprobar el error a través de la función printNep2Error. - 13 - Laboratorio de Telemática NepalEther2Byte int NepalEther2Byte(char *dir,ETHERNET_ADDRESS dirEth); Descripción: Esta función tiene como objetivo la conversión de una dirección MAC en formato "FF:FF:FF:FF:FF:FF" a una representación binaria de la misma. Parámetros de Entrada: ¾ dir: Dirección MAC en formato "FF:FF:FF:FF:FF:FF". ¾ ETHERNET_ADDRESS: dirEth es la variable en la que se almacena la representación binaria de la dirección. Salida: La función retorna la dirección que pasamos en dir convertida a binario en dirEth. Ante los errores devuelve False, y se puede comprobar el error a través de la función printNep2Error. NepalWriteEtherAddress void NepalWriteEtherAddress(ETHERNET_ADDRESS dir); Descripción: Esta función permite mostrar en la consola una dirección MAC en formato binario. La representación de la misma en la consola tiene el formato "FF:FF:FF:FF:FF:FF". Parámetros de Entrada: ¾ ETHERNET_ADDRESS: dir es la dirección que deseamos imprimir por pantalla. Tiene un formato binario Salida: Esta función no devuelve nada ante errores, pero rellena la variable neperror con lo que la causa del error puede conocerse con la función printNep2Error. NepalWriteIPAddress void NepalWriteIPAddress(IP_ADDRESS dir); Descripción: Esta función permite mostrar en la consola una dirección IP en formato binario. La representación de la misma en la consola tiene el formato "192.168.0.10". Parámetros de Entrada: ¾ IP_ADDRESS: dir es la dirección que deseamos imprimir por pantalla. Tiene un formato binario Salida: Esta función no devuelve nada ante errores, pero rellena la variable neperror con lo que la causa del error puede conocerse con la función printNep2Error. NepalWriteEtherFrame void NepalWriteEtherFrame( LPETHERNET_FRAME lpEthFrame, int ulEthFrameTotalSize); - 14 - Laboratorio de Telemática Descripción: Esta función permite la impresión en la consola de una trama completa Ethernet. Parámetros de Entrada: ¾ LPETHERNET_FRAME: lpEthFrame es la trama que queremos mostrar. ¾ ulEthFrameTotalSize: Es el tamaño de la trama lpEthFrame. Salida: Esta función no devuelve nada ante errores, pero rellena la variable neperror con lo que el error es accesible a través de la función printNep2Error. Un ejemplo de la representación de una trama sería: 0000: 0001: 0002: 0003: 0004: 2.8. 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 Librerías ya incluidas en el paquete: Las librerías que a continuación 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 Telemática 3. Ejemplo de Envío 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 Telemática 4. Ejemplo de Recepción 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 -