J Desarrollo de una aplicación administración en el ...148.206.53.84/tesiuami/UAM5907.pdf · No...
Transcript of J Desarrollo de una aplicación administración en el ...148.206.53.84/tesiuami/UAM5907.pdf · No...
J Desarrollo de una aplicación de administración de redes basada en el protocolo SNMP.
Presentan: i Adrián Moreno Garcia
Juan Ernesto Cervantes Ojeda
Asesor:
Miguel Angel Ruiz Sánchez.
Enero de 1998
Deseamos expresar nuestra gratitud a Miguel Angel Ruiz Sánchez, quien nos apoyó siempre para la realización de nuestro trabajo, así como a los profesores Victor Manuel Ramos, Ricardo Marcelín, Mauricio Villaseñor y Fausto Casco que compartieron con nosotros su área de trabajo apoyándonos moralmente en todo momento. ,
Queremos agradecer también a todos nuestros amigos que, estuvieron con nosotros dando ánimos y consejos, en especial a El ías Sánchez, Alejandro Montejo y Alejandro Castillo, quienes han sido y serán durante mucho tiempo nuestros mejores amigos.
De manera especial participaron nuestros padres quienes nunca se alejaron y fueron inspiración para poder concluir nuestra labor.
Adrián Moreno Garcia
Juan Ernesto Cervantes Ojeda.
Microsoft, MS y MS-DOS son marcas registradas y y Windows es marca registrada de Microsoft Corporation.
Archive es una marca registrada de Archive Corporation. 3Com es una marca registrada de 3Com Corporation.
Banyan y VINES son marcas registradas de Banyan Systems. Inc. Cipher es una marca registrada de Cipher Data Products. COMPAQ es una marca registrada de Compag Computer Corporation. CompuServe es una marca registrada de CompuServe. Inc. Hewlett-Packard, LaserJet y PCL son marcas registradas de Hewlett-Packard Company. IBM, os/2, AT, y PC/AT son marcas registradas y Proprinter es una (marca de International Business Machines Corporation. NetWare y Novell son marcas registradas de Novell, Inc. SYBASE es una marca registrada, y Transact-SQL y DB-Library son marcas registradas de
Sytron. Sytos Plus y Sytos Plus File Backup Manager son Sybase, Inc.
TEAC es una marca registrada de TEAC Corporation. arcas registradas de Sytron Corp.
Tecmar es una marca registrada de Tecmar, Inc.
Apple, Laserwriter. Macintosh and TrueType son marcas registradas de Apple Computer, Inc. Corel es una marca registrada de Corel Systems Corporation.
DEC es una marca registrada de Digital Equipment Corporation. dBASE es una marca registrada de Ashton-Tate Corporation.
Epson es una marca registrada de Epson America, Inc. PostScript es una marca registrada de Adobe Systems, Inc. QMS es una marca registrada de QMS, Inc. SREAMS es una marca registrada de American Telephone and Telegraph
LJNIX es una marca registrada de UNIX Systems Laboratories. Company.
Wordperfect es una marca registrada de Wordperfect Corporation.
A mi madre, por sus oraciones; a mi hermana Elvia, por sus ganas y su ánimo; a mi hermana Alejandra, por toda su paciencia; a mis hermanos Beatriz y José, porque me fueron ejemplo, a pesar de los problemas, y a aquel que me aconsejaba, aunque ya no esté conmigo para compartir ésta meta, mi padre ...
A mis cuates, que estuvieron conmigo en las buenas y las malas y que me ayudaron de mil formas a salir adelante ...
Doy gracias a Dios por todo Su amor, Su Gracia, Su misericordia y por la vida que me ha dado para llegar hasta aquí ...
A.M.G.
A mis padres y hermanos que me apoyaron siempre a lo largo de mi carrera. En especial a mi padre que con su apoyo siempre me impulso a concluir esta meta y a mi madre quién en la distancia siempre la extrañe en mis pesares de vivir en la ciudad de México y a mis hermanos quienes formaron parte de la inspiración para dar un ejemplo y recibir uno. Gracias por esas palabras que en momentos difíciles recordé “Tu puedes”, gracias.
Doy gracias a mis amigos que compartieron mi esfuerzo y me acompañaron en las buenas y en las malas en especial Minerva Sánchez quién al final de mi tarea me apoyó moralmente para no decaer, a Adrián con quién he trabajado en este trabajo que me llena de satisfacción.
Juan Ernesto Cervantes Ojeda.
CONTENIDO
Introducción Protocolos más importantes de la familia TCP/IP
Protocolo IP (Internet Protocol) TCP UDP (User Datagram Protocol)
Protocolo SNMP ASN. 1 MIB. SNMP - BER
Descripción del proyecto Objetivos Plataforma Estructura
Conclusiones
Manual de usuario Requerimientos del Sistema ¿Cómo Iniciar? Diálogo Grupos Inserta un nodo para administrarlo Cómo cambiar el valor de comunity Archivo de inicialización SNMPADMI.IN1 Sesión típica de Instalación Sesión de Desinstalación
Apéndice A. Objetos definidos
Apéndice B. Código fuente del programa Encabezado del archivo de codificación (F3ER.H) Codificación del archivo de codificación (F3ER.CPP) Archivo de encabezado principal (snmpadmi.h) Archivo fuente principal Archivo de recursos (SnmpAdmi.rc) Archivo de definiciones (SNMPADMLDEF)
Bibliografía Índice de tablas
Índice de diagramas fndice de figuras
fndice completo
2 2
14 24
27 27 33 46 51
64 64 64 67
92 93 93 93 94 95 96 97 97
100
101 102 102 107 127 128 164 166
167 1
11
111 ...
V
Introducción
INTRODUCCI~N En los últimos días, se ha incrementado notoriamente el uso de redes que
usan protocolos de la familia TCPAP. Con el fin de suministrar una herramienta para la administración de estas redes, planteamos la creación de una aplicación de administración que utiliza el protocolo SNMP, el cual fue diseiíado para este tipo de redes.
Para explicar la forma en que funciona esta aplicación primero explicamos un poco acerca de como funcionan, de manera global, los protocolos necesarios para implementar la aplicación, la cual fue desarrollada para trabajar en WindowsTM, ya que se ha extendido su uso en este tipo de redes.
Una vez explicados los protocolos más importantes (TCPJP y UDP), entramos en materia con el protocolo SNMP, el cual forma parte fundamental del proyecto. Para poder entender con claridad la forma que funciona este protocolo, se explica el lenguaje abstracto ASN.1, y la base de datos MIB, la cual le sirve a una aplicación SNMP para conocer el tipo de variables que debe administrar. Hasta este punto, contamos con las herramientas adecuadas para poder explicar el funcionamiento del protocolo SNMP.
Como complemento y para poder implementar la aplicación SNMP, se describen las reglas de codificación BER, que fueron creadas para este fin.
En la segunda parte del documento comenzamos con la descripción global del proyecto desde el punto de vista de un programador. Es en esta sección donde debemos hablar primero de la plataforma en que se desarrolla el proyecto y su funcionamiento a nivel de aplicación, tocando los puntos de la administración de memoria, la multitarea, el ambiente integrado GUI y el uso de código compartido en Windows.
Es importante también en este sección explicar como se implementa el protocolo SNMP enfocado a una programación Orientada a objetos. Por último se explica como fue programada la aplicación final.
1
Administrador de Redes SNMP
PROTOCOLOS MAS IMPORTANTES DE LA FAMILIA TcP/IP
PROTOCOLO IP (INTERNET PROTOCOL) Propósito
El Protocolo Internet (IP) está diseñado para ser usado en sistemas interconectados mediante redes de computadoras de conmutación de paquetes. L a unidad de transmisión de la información se llama DATAGRAMA, y el envío se hace desde una fuente llamada "host" hasta un destino denominado de igual forma, utilizando una dirección de longitud fija. Además, el protocolo IP provee fragmentación y reensamble de datagramas (paquetes) muy grandes en unidades más pequeñas (paquetes pequeños) para envio de la información.
Alcance
IP únicamente se limita a una transmisión de paquetes (datagramas) a través de la red. No define ninguna forma de controlar el envío de información confiablemente, ni controla el flujo, ni la secuencia, ni otros servicios comúnmente usados en otros protocolos (protocolos host-a-host). IP no provee manejo de Confiabilidad en la comunicación. No existe reconocimiento de recepción de información punto a punto, ni control de errores de datos, lo Único que realiza es un Checksum en el encabezado, para garantizar que no llegue a un destino incorrecto. No existen retransmisiones ni control de flujo. Sólo cierto tipo de errores se reportan medante ICMP (Protocolo de Control de Mensajes de Internet). Su alcance se limita sólo a transmitir y recibir información sin ser confiable.
Interfaces
L a función de IP es ser llamado por protocolos host-a-host en un ambiente de red. IP llama a su vez, a protocolos de red local para enviar los paquetes (datagramas) al siguiente ruteador (gateway) o host destino.
Diferentes implementaciones de IP pueden tener diferentes interfaces de usuario. Sin embargo, todo IP debe tener un mínimo de servicios para garantizar el soporte en la misma jerarquía del protocolo.
El protocolo IP enlaza un protocolo de red local con otro de más alto nivel o un programa aplicación. En lo consecuente, se debe llamar "usuario" a todo aquel programa que use IP. Cada llamada a IP por el usuario provee toda l a información necesaria para ejecutar el servicio requerido.
2
Protocolos más importantes de la familia TCP/IP
Operación
IP implementa dos funciones básicas: direccionamiento y fragmentación. La selección de una ruta para el envío de la información se llama encaminamiento.
El módulo IP usa un encabezado (header) para fragmentar y reensamblar datagramas (cuando se necesita fragmentar), haciéndolos pequeños "paquetes" de información.
Un módulo IP se almacena en los ruteadores, los cuales son puntos que interconectan redes. Estos comparten reglas comunes entre sí, de forma que puedan interpretar el direccionamiento, fragmentación y reensamble de los paquetes.
Cada paquete se envía independientemente de los demás, de forma que todo un conjunto de información puede estar fragmentada y estar distribuida por toda la red (es decir, no existe un solo camino ni "circuito virtual "). 1
El protocolo IP contempla. cuatro aspectos para la provisión de un servicio:
t Tipo de servicio +& Tiempo de Vida +% Opciones FES Checksum del encabezado
El Tipo de Servicio se usa para indicar la calidad del servicio deseado y es una abstracción o generalización de parámetros que caracteriza el servicio elegido provisto en la red.
El tiempo de vida es el tiempo máximo en que un datagrama puede "vivir" dentro de la red. Este tiempo se da desde el host origen, y conforme se va viajando de ruteador en ruteador este tiempo de vida se va disminuyendo. Si un datagrama alcanza un tiempo de vida igual a cero antes de que alcance su destino, éste se destruye. El tiempo de vida se puede ver como un tiempo límite de autodestrucción'.
fue la red telefónica. De manera análoga, algunos servicios en las redcs de conmutación de I En la tecnolozía de redes, se conoce como circuito virtual a las redes por circuitos, como lo
paquetes, se requlere crear un circuito o ruta única, para transmitir por ejemplo voz. A estos circuitos, por estar emulados por paquetes se les conoce como circuito virtual
2 Esto st' debe a que el protocolo IF no garantiza una comunicación, pues no realiza mas que un checksum.
Administrador de Redes SNMP
El parámetro Opciones provee funciones de control usadas cuando se requiere más de una transmisión común. Estos tipos de funciones incluyen encaminamiento especial y seguridad.
El Checksum provee una verificación tal que la información contenida en el encabezado sea transmitida correctamente. Si el Checksum no concuerda entonces la entidad (host, ruteador, etc.) que tenga ese datagrarna lo desecha en el momento en que se detecta el error3.
Relación de IP con otros protocolos
El protocolo IP tiene la jerarquía con otros protocolos mostrada en el diagrama 1.
Telnet
... ... UDP TCP
... ... SNMP FTP
IP y ICMP
Protocolo de Red Local I 1 Diagrama 1 Relaciones entre Protocolos
El protocolo SNMP se encuentra sobre U D P que a su vez requiere de los servicios de IP y es el protocolo que nos corresponde estudiar, de ahí la necesidad de hablar de IP como de UDP.
Modelo de Operación
U n paquete de información viaja más o menos de la siguiente forma (ver diagrama 2):
La aplicación origen, toma la información que desea enviar y la pasa a IP, IP adjunta información y crea un encabezado, al que le corresponde un valor de Checksum. IP envía este paquete a su destino inmediato (normalmente un ruteador) el cual contiene una implementación de IP, la cual toma el paquete, lo interpreta y decide su destino, al hacer esto disminuye su tiempo de vida además de otros posibles valores, lo que origina un cambio en el encabezado IP, y hace necesario crear uno nuevo. EL nuevo paquete es enviado a su destino inmediato y se continua este proceso hasta llegar al destino final.
:' Es esta entre otras razones, por lo que se dice que IF no es confiable
4
Protocolos más importantes de la familia TCP/IP
Diagrama 2 Forma en que viaja un paquete IP
El propósito de IP es enviar datagramas a través de una red, haciendo uso de ruteadores, hasta llevar la información a su destino, mediante un direccionamiento.
El direccionamiento indica d6nde está el punto que buscamos así como un nombre indica qué es lo que buscamos y una ruta indica cómo llegar a ese punto.
Las direcciones son de tamaño fijo (4 octetos o 32 bits). Existen tres clases principales de direccionamiento:
E n una dirección de clase A el bit más significativo es cero; los siguientes 7 bits indican la red y los siguientes 24 bits indican la dirección local.
En una dirección de clase B ‘los dos bits más significativos son uno - cero (10); los siguientes 14 bits son la red y los restantes 16 bits indican la dirección local.
En una dirección de clase C los primeros tres bits son uno - uno - cero (110) los siguientes 21 bits son la red y los restantes 8 bits son la dirección local.
La flexibilidad para direccionar tiene un propósito: El campo Dirección se codifica para especificar un pequeño número de redes con un gran número de host o, un número intermedio de redes con un número intermedio de host o un gran número de redes con un pequeño número de host. Cada una de estas formas de direccionamiento es interpretada y da lugar a una clase de direccionamiento (una para cada caso en particular). En l a tabla 1 se define el formato para cada tipo de direccionamiento:
5
Administrador de Redes SNMP
Bits más significativos
O 10 110 111
Formato Clase
7 bits para red, 24 bits para hosts 14 bits para red, 16 bits para host 21 bits para red, 8 bits para host
Tabla 1 Clases de direccinamiento en IP
Un valor de cero en el campo red significa esta red. Esto sólo es usado para ciertos mensajes ICMP. El modo de direccionamiento extendido está indefinido. Ambos aspectos están reservados para un uso futuro.
Fragmentación de un datagrama
U n datagrama se debe fragmentar si la red por donde se debe transportar para llevarlo limita el tamaño de los paquetes, o si los datagramas son muy extensos.
U n datagrama debe poder ser fragmentado en un número de partes arbitrariamente elegido para después ser reensamblado. El receptor de fragmentos usa el campo Identificación para asegurar que los paquetes no se mezclen; el campo offset indica la posición del paquete dentro del datagrama; el offset y la longitud determinan la porción original del datagrama cubierta por este fragmento; estos campos proveen suficiente información para reensamblar datagramas. El campo Identificación se usa para distinguir si los fragmentos pertenecen a un datagrama o a otro.
Para fragmentar un datagrama, se divide el contenido esencial de la información en dos, y el encabezado que existía en el datagrama antes de ser fragmentado se copia como encabezado en los nuevos datagramas ”fragmentos”. El primer fragmento del datagrama debe ser forzosamente una trama formada por 8 octetos (64 bits).
Para ensamblar los fragmentos de un datagrama, IP combina todos los fragmentos que tienen el mismo valor para los cuatro campos: Identificación, fuente, destino y protocolo. El orden de reensamble se da mediante el fragmento que define el offset, para colocar cada fragmento de la información dentro del datagrama original.
El campo Identificación (ID) se usa junto con la dirección fuente y la dirección destino y los campos Protocolo para identificar los fragmentos del datagrama para reensamble.
El bit bandera “Más Fragmentos” (MF) se pone en uno si el datagrama no es el último fragmento. El campo Offset de Fragmento identifica la ubicación
6
Protocolos más importantes de la familia TCP/IP
del fragmento, relativo al comienzo del datagrama original sin fragmentar. Los fragmentos se cuentan en unidades de 8 octetos.
Cuando la fragmentación ocurre, algunas opciones son copiadas, pero otras permanecen con el primer fragmento Gnicamente.
Cada módulo IP debe ser capaz de enviar un datagrama de 68 octetos sin fragmentación. Esto se debe a qu'e un encabezado IP puede estar por arriba de 60 octetos, y el mínimo fragmento es de 8 octetos.
Cada destino debe ser capaz de recibir un datagrama de 576 octetos cualquiera en una pieza o en fragmentos a ser ensamblados.
Si la bandera No Fragmentar (NF) es puesta a uno, entonces la fragmentación de este datagrama está prohibida; esto se usa para evitar la fragmentación en casos en que el receptor no tenga suficientes recursos para reensamblar los fragmentos.
Ruteadores o Gateways
Los ruteadores tienen implementados protocolo IP para conducir a un datagrama a través de una red. También tiene implementado el protocolo Ruteador a Ruteador (GGP -Gateway to Gateway Protocol-) para enrutar un datagrama.
Especificación
Se muestra el contenido de un encabezado: o 1 2 3 U 1 2 3 ~ 5 6 7 8 9 0 1 2 3 4 ~ 6 7 8 9 U 1 2 ? 4 5 6 7 9 9 0 1
Tiet3;lon Longxtud Total Tipo de Senrsta I H L 1 Identlficacion I Flags I Offset de Frapnento
T~etnpo de V A Checksum da1 Header Pratocalo
D ~ r e c c d n O r p n
Dlteccdn Dcrtmo
Figura 1 Encabezado IP
Versión: 4 bits
El campo Versión indica el formato del encabezado.
IHL: 4 bits
Internet Header Length (IHL) es la longitud del encabezado Internet en palabras de 32 bits, y de esta forma apunta al inicio de los datos. El valor mínimo para un encabezado correcto es 5.
7
Administrador de Redes SNMP
Tipo de Servicio: 8 bits
El tipo de Servicio provee una indicación de parámetros abstractos de la calidad del servicio deseado.
Bits 0-2: Precedencia Bit 3: O = Retardo Normal, 1 = Poco Retardo Bit 4: O = Envío Normal, 1 = Envío rápido Bit 5: O = Confiabilidad Normal, 1 = Confiabilidad Alta Bits 6-7: Reservados para un uso futuro.
O 1 2 3 4 5 6 7 t PROCEDENCIA I RETARDO I ENVíO I CONFIAR I RESERVADA 1
Figura 2 Tipo de servicio en IP
Los usos de indicaciones retardo, puesta a envío y confiabilidad pueden incrementar el costo del tipo del servicio. en muchas redes la mejora del desempeño de uno de ellos puede empeorar el desempeño de alguno de los otros; pero por mucho (excepto en casos extremos) sólo dos de ellos deben ser puestos en marcha.
El Tipo de Servicio se usa para especificar el tratamiento del uso del datagrama a través de la red.
Precedencia
Es una medida independiente de la importancia del datagrama.
Retardo.
Indica que debe liberarse pronto.
Puesta a Envío
Indica que debe trasnmitirse en alta velocidad de datos.
Confiabilidad
Pide un alto esfuerzo para asegurar liberación.
Longitud Total: 16 bits
El campo Longitud Total es la longitud del datagrama, medido en octetos, incluyendo encabezado y datos. Este campo aloja una longitud para un datagrama de hasta 65,535 octetos.
8
Protocolos más importantes de la familia TCP/IP
Identificación: 16 bits
Es un identificador asignado cuando comienza el envío para ayudar a ensamblar los fragmentos de un datagrama.
La elección del Identificador para un datagrama se basa en la necesidad de proveer un camino que únicamente identifique los fragmentos de un datagrama en particular. El módulo del protocolo de ensamble de fragmentos decide qué fragmentos pertenecen al mismo datagrama si ellos tienen la misma fuente, destino, protocolo e Identificador. De esta forma, el que envía debe elegir un identificador Único para esta fuente, destino y protocolo para el tiempo en que un datagrama deba estar vivo dentro de la red.
Banderas (Flags): 3 bits Bit O: Reservado, debe ser cero Bit 1: (DF) O =Se puede Fragmentar, 1 =No Fragmentar Bit 2: (MF) O = Ultimo Fragmento, 1 = Más fragmentos
O 1 2
I O DF M F Figura 3 Banderas en encabezado IP
Offset: 13 bits
Este campo indica dónde se debe ubicar este fragmento en el datagrama. El Offset se mide en unidades de 8 octetos (64 bits). El primer fragmento debe tener un offset igual a cero.
Tiempo de vida: 8 bits
Este campo define el tiempo en que un datagrama "vive" dentro de la red. Cuando un datagrama se lanza a la red, lleva un valor en este campo. Este valor se decrementa por lo menos en una unidad y se lleva a cabo el decremento cuando el datagrama viaja desde un ruteador hasta otro (en el cambio de encabezado es cuando se decrementa). Cuando el valor llega a cero, entonces el datagrama es destruido por el ruteador o host en el que se encuentre.
Protocolo: 8 bits
Este campo indica el protocolo de siguiente nivel usado en la porción de datos del datagrama.
Checksum del encabezado: 16 bits
Es una suma sólo del encabezado. Ya que algunos encabezados cambian (por ejemplo, debido al tiempo de vida), ésta operación se vuelve a realizar y se
9
Administrador de Redes SNMP
verifica a cada punto en que el se procesa. El algoritmo del Checksum es el siguiente: El campo Checksum es el complemento a uno de 16 bits de la suma de los complementos a uno de todas las palabras de 16 bits en el encabezado. Para propósitos de cómputo del Checksum, su valor es cero.
Dirección Fuente: 32 bits
Indica la dirección IP en donde se origina la información, la cual ha de ser transportada a través de la red.
Opciones: Variable
El campo Opciones puede o no aparecer en datagramas. Este debe ser implementado por IP. E n algunos ambientes el campo seguridad puede ser requerido en todos los datagramas. El campo Opciones es variable en longitud. Puede haber cero o más opciones. Existen dos casos para el formato de una opción:
Caso 1.- U n simple octeto de opción - tipo
Caso 2.- U n octeto de opción - tipo, un octeto de opción - longitud y los actuales octetos opción - datos.
El octeto opción - longitud cuenta el octeto opción - tipo y el octeto opción - longitud tan bien como los octetos opción - datos.
El octeto opción - tipo se ve como tres campos:
1 bit bandera de copiado
2 bits clase opción
5 bits número opción
La bandera de copiado indica que ésta opción es copiada dentro de todos los fragmentos en la fragmentación.
O = No copiado 1 =copiado
Las clases opción son:
O = Control
1 =Reservado para uso futuro
2 =Depuración y medida
3 =Reservado para uso futuro
Las siguientes opciones se definen en la tabla 2:
10
Protocolos más importantes de la familia TCP/IP
CLASE DESCRIPCI~N LONGITUD NÚMERO
Grupo de Usuario (TCC) y Códigos de Restricción de
octeto de longitud
octeto; no tiene octeto de longitud
Manejo compatibles con los requerimientos DOD
datagrama basada en información suplida por la fuente.
datagrama basada en información suplida por la fuente.
que un datagrama toma.
O
Seguridad. Usado para llevar Seguridad, Compartición, 1 1 2 O
No operación. Esta opción usa sólo un octeto; no tiene 1 O
Fin de la lista de Opciones. Esta opción usa sólo 1 - O
O
Cadena ID. Usado para llevar el identificador cadena. 4 8 O
Ruta Registrada. Usada para trazar la ruta registrada variable. 7 O
Ruteo de Fuente Estricta. Usada para rutear a un variable. 9 O
Ruteo de Fuente Perdida. Usada para rutear a un variable. 3
2 4 variable. Timestamp Internet
Tabla 2 Opciones en el encabezado IP La presencia o ausencia de una opción es la elección de quien lo envía, pero
IP debe ser capaz de delimitar e identificar cada opción. Puede haber varias opciones presentes en el campo Opciones.
Relleno: variable
El relleno sirve para asegurar que el encabezado termine en 32 bits y tiene un valor de cero.
Ejemplos':
Este es un ejemplo del mínimo de datos que debe llevar un datagrama:
0 1 2 O 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
Vec;ión=4 [ I H L = 5 [ TIFO de S c m c m
Checksum del Header Protocolo=l Ttcmpo d e VxdaZ123
Fl@=O I Ofket de F r a p e n t o = U Ident~fwaclón=lll 9
3
D ~ r c c s t b n Destmo
Figura 4 Mínimos datos que debe llevar un datagrama
Los ejemplos aqui mostrados, se sac.won del RFC 791 correspondlente al protocolo IF.
11
Administrador de Redes SNMP
Ejemplo 2:
En este ejemplo, se muestra un datagrama de tamaño medio (452 octetos de datos), de los cuales se obtendrán dos fragmentos si el máximo tamaño de transmisión es de 280 octetos: U 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 ~ G ~ ~ 9 0 1 Verstón=4 I IHL=S 1 Ttpo de Setviclo
I d e n t l f m c d n = l l l
Longitud Total=472
D m c c h n Orlgcn
ChackSum de1 Header Protocolo=B Tlcrnpo de Vtda=123
Flg=O 1 Ofket de F r a p e n t o = D
D t r e c c ~ ó n Destino
datos
Figura 5 Datagrama de tamaño medio
Ahora se muestra el primer fragmento que resulta de la división del datagrama: (256 octetos de datos):
U 1 2 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
Verrlbn=4 I I TIPO de Scwtcm
Identlbcaemn=lll
Longltvd Totd=276
D ~ r r c e l ó n Destrna
Dtrcccnón Origen
ChcckSum dclHszder Tlcrnpo d e Vxda=119 I Protocolo=6
Fl@=l I O f h t de Ftawsnto=O
datos
datos
Figura 6 Primer fragmento de la división de un datagrama
Ahora se muestra el segundo fragmento: 0 1 2 3 U 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 Verr16n=4 I I E L = 5 1 TIPO de Servrsro I Longaud Totd=ZlG Idmttf tcachn=l l l Tmmpo de Vlda=119 I Pzotacolo=6
1 F l p = l 1 O f h t de F z a p c n t o = 3 2 1 ChcckSum da1 Heads.
Figura 7 Segundo fragmento de la división de un datagrama
12
Protocolos más importantes de la familia TCPAP
Ejemplo 3:
Se muestra un datagrama que: contiene opciones: O 1 2 3
0 1 2 3 4 5 6 7 8 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 G 7 8 9 0 1
VcmÓn=4 1 E = 8 1 Tipo de S c n r ~ ~ o
CheckSum del Header Ttcrnpo de Vtda=123 I Protocolo=6
Flp=O I Offset de Fragnento=O Idcntlfccaclón = 111
Longitud Total=5?6
Dlrecclón Dectmo
Ope Longitud = 3 Opc Longctud = 4 Valor Opcdn o p c CÓ&go = 1 o p c codlgo = y Opc Lengttud = 3 Valor Opcr6n opc C ó d t p = o datar
Figura 8 Datagrama con opciones
NOTAS IMPORTANTES:
Para realizar una transmisión se debe considerar el significado de cada bit que se recibe o que se transmite. A continuación se muestra un ejemplo de la interpretación de cada bit dentro de una trama según el orden en que se transmite (el orden en que se transmiten es el orden en que están numerados).
O 1 2 3 O 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1 2
12 11 10 9
8 7 6 5
4 3
Figura 9 Interpretación de cada bit dentro de una trama según el orden en que se transmite
Siempre que un octeto representa una cantidad numérica el bit más hacia la izquierda en el diagrama es el orden alto ó bit m6s significativo. Por ejemplo, el siguiente diagrama representa el número decimal 170
O 1 2 3 4 5 6 7
1 O 1 O 1 3 1 O
Figura 10 diagrama que representa el número decimal 170
Similarmente, siempre que un campo multiocteto represente una cantidad numérica, el bit más hacia la izquierda representa el bit más significativo.
13
Administrador de Redes SNMP
Cuando una trama multiocteto es transmitida el octeto más significativo se transmite primero.
TCP Introducción
El Protocolo de Control de Transmisión PCP) es usado como un protocolo de transmisión de información confiable de host-a-host entre redes de comunicación de conmutación de paquetes.
T C P está orientado a conexión y diseñado para accesar dentro de una jerarquía de nivel de protocolos que soportan aplicaciones multiredes. Su forma de acceso es en una arquitectura de protocolo de nivel justo sobre un protocolo de nivel más básico, tal como IP, el cual provee un camino a T C P para enviar información y recibir información de segmentos de longitud variable encapsulados en un datagrama.
En la Figura 11 se muestra un diagrama de protocolos de nivel y el lugar que ocupa TCP:
Nivel más alto
TCP
I Red de comunicación I Figura 11 Diagrama de protocolos de nivel
Alcance
El protocolo TCP intenta proveer un servicio de comunicación proceso a proceso en un ambiente multired. Se intenta que TCP sea un protocolo host-a- host de uso común en múltiples redes.
Interfaces
T C P proporciona un camino para enlazar un usuario o proceso aplicación con un protocolo de más bajo nivel tal como IP. TCP está diseñado para trabajar en un ambiente muy general de redes interconectadas. El nivel más bajo que se asume para trabajar con TCP de aquí en adelante es el protocolo P .
Áreas básicas en las que se usa TCP. O Transferencia Básica de Datos +% Confiabilidad +% Control de Flujo
14
Prorocolos más importantes de la familia TCP/IP
P Multiplexión P Conexiones t Precedencia y Seguridad
Transferencia Básica de Datos.
T C P es capaz de transferir una cadena continua de octetos en cada dirección entre sus usuarios empaquetando algún número de octetos dentro de segmentos de transmisión a través de la red. Generalmente, T C P decide cuándo hacer un bloque y cuándo enviarlo a su propia conveniencia.
Confiabilidad.
T C P debe recuperar los datos que son dañados, perdidos, duplicados o eliminados mediante la comunicación Internet. Esto se consigue asignando un número de secuencia a cada octeto transmitido y requiriendo un reconocimiento positivo (ACK) del TCP receptor. Si el ACK no es recibido dentro de un tiempo definido, 121 dato es retransmitido. En el receptor, los número de secuencia son usados para ordenar correctamente los segmentos que puedan recibirse fuera de orden y eliminar los duplicados. Los dañados son manejados añadiendo un CheckSum a cada segmento transmitido, verificándolo en el receptor y descartando los que estén dañados.
Control de Flujo.
T C P provee una forma de que el receptor reciba los datos enviados. Esto se logra enviando una "ventana" con cada ACK indicando un rango de números de secuencia aceptables más allá del último segmento satisfactoriamente recibido. La ventana indica un número de octetos que el transmisor puede enviar antes de recibir nuevo permiso.
Multiplexión.
Para poder alojar múltiples procesos en un Host usando los servicios de comunicación T C P , se provee un. direccionamiento a puertos dentro de cada host, concatenados con las direcciones de host y de red desde el nivel IP de comunicación, a esto se le conoce como SOCKET'. Un par de sockets únicamente identifican una conexión. Un socket puede ser usado simultáneamente en múltiples conexiones. Conexiones.
L a confiabilidad y mecanismos de control de flujo descritos antes requieren que T C P inicialice y mantenga cierta información del estatus para
Los sockets en la plataforma Wir.dows los proporciona la biblioteca de enlace dinlmica Winsock que se instala cuando se requiere un servicio de TCF/IF
15
Administrador de Redes SNMP
cada flujo de datos. La combinación de esta información, incluyendo sockets, números de secuencia y tamaños de ventanas se llama Conexión. Cada conexión es completamente especificada por un par de sockets identificando sus dos lados. Precedencia y Seguridad.
Los usuarios de TCP pueden indicar la seguridad y precedencia de sus comunicaciones. Se proveen valores por omisión cuando estos aspectos no son necesitados.
Elementos del Sistema InterRedes.
El sistema interedes consiste en hosts conectados a redes que a su vez están conectadas internamente a través de ruteadores. Las redes pueden ser redes locales o redes amplias, pero en cualquier caso están basadas en tecnología de conmutación de paquetes. Los agentes activos que producen y consumen mensajes son procesos. Varios niveles de protocolos, los ruteadores y los hosts soportan un sistema de comunicación de interproceso que permite un flujo de datos two-way (dos caminos) en conexiones lógicas entre puertos de procesos.
Modelo de operación.
Los procesos transmiten datos haciendo llamadas a TCP y pasando buffers de datos como parámetros. TCP empaqueta los datos de esos buffers en segmentos y llama a su vez a IP para transmitir cada segmento al TCP destino. El receptor coloca los datos de los segmentos en un buffer de recepción de usuario y se lo notifica. TCP incluye información de control en los segmentos que se usa para asegurar una transmisión de datos ordenada y confiable.
Interfaces
L a interfaz de usuario TCP provee llamadas hechas por el usuario para abrir (OPEN) y cerrar (CLOSE) una conexión. Esas llamadas son como en un ambiente PC, en el que se abre y se cierra un archivo.
Relación con otros protocolos.
El la Figura 12 se ilustra el lugar que ocupa TCP.
Telnet I FTP Nivel Aplicación SNMP ... Voz
TCP Nivel Host UDP ... RTP
IP & ICMP Nivel Gateway Protocolo de Red Local Nivel Red
Figura 12 Lugar que ocupa TCP en la jerarquía de protocolos
16
Prctocolos más importantes de la familia TCP/IP
Comunicación confiable.
La Transmisión se hace confiable a través del uso de números de secuencia y reconocimientos. El número de secuencia del primer octeto de datos en un segmento es transmitido con ese segmento y es llamado número de secuencia de segmento. Los segmentos además llevan un número de reconocimiento que es el número de secuencia del siguiente octeto de datos esperado de transmisión en dirección contraria. Cuando TCP transmite un segmento que contiene datos, &te pone una copia en una cola de retransmisión e inicia un temporizador. Cuando el reconocimiento para ese dato es recibido, la copia del segmento se borra de la cola. Si el reconocimiento no es recibido antes de que el temporizador transcurra un tiempo límite, el segmento es retransmitido.
Establecimiento y Liberación de la Conexión
Para identificar los flujos de datos separados que TCP puede manejar, se provee un identificador de puerto. E n el momento en que los identificadores de puerto son seleccionados independientemente por cada implementación de TCP, &tos no tienen por qué ser únicos. Para distinguir a cada elemento se puede crear un socket que será Único a través de toda la red.
Una conexión es especificada por un par de sockets en los extremos. Un socket local puede participar en muchas conexiones hacia diferentes sockets foráneos. Una conexión puede ser usada para llevar datos en ambas direcciones, esto es, "full-duplex'".
Una conexión se especifica en la llamada OPEN por el puerto local y el socket foráneo, pasando éstos como parámetros. T C P devuelve un nombre de conexión local al cual el usuario se refiere a la conexión en llamadas subsecuentes.
Los procedimientos para establecer comunicación utilizan la bandera de control de sincronía (SYN) y contempla un intercambio de tres mensajes. Este intercambio ha sido llamado "three-way hand shake"
Una conexión se inicia cuando se dan cita un segmento que llega conteniendo un SYN y TCB creado por un comando de usuario OPEN. La compatibilidad entre sockets locales y foráneos determina cuando una conexión se ha iniciado. La conexión llega a ser establecida (ESTABLISHED) cuando los números de secuencia hayan sido sincronizados en ambas direcciones.
Full Duplex es un termino usado para indicar que la transmisión cs en ambos sentidos en forma slmultinea.
17
Administrador de Redes SNMP
La liberación de una conexión además envuelve el intercambio de segmentos, en este caso, llevando la bandera de control FIN.
Comunicación de Datos.
Los datos que fluyen en una conexión pueden ser pensados como un flujo de octetos. El usuario transmisor indica en cada llamada SEND si los datos en esa llamada (y cualquier llamada precedente) pueden ser inmediatamente enviados al receptor usando la bandera PUSH. Cuando un receptor T C P ve habilitada la bandera P U S H no debe esperar más datos del transmisor y pasa los datos al proceso receptor.
Precedencia y Seguridad.
TCP hace uso del campo Tipo de Servicio y Seguridad de IP para proveer precedencia y seguridad en cada conexión básica para cada usuario. No todos los TCP necesariamente funcionarán en un ambiente de seguridad multinivel. Algunos pueden estar limitados a un uso no clasificado únicamente, y otros pueden operar en únicamente un nivel de seguridad. Consecuentemente, algunas implementaciones y servicios a usuarios pueden estar limitados a un subconjunto de casos de seguridad multinivel.
Principio de Robustez.
Las implementaciones TCP seguirán un principio general de robustez: ser conservativo en lo que se hace, liberal en lo que se acepta de otros.
Especificación funcional Formato del encabezado
Los segmentos TCP se envían como datagramas. El encabezado IP lleva varios campos de información incluyendo las direcciones host fuente y destino. Un encabezado T C P sigue a un encabezado IP supliendo información especifica del protocolo TCP. Esta división permite la existencia de otros protocolos a nivel host que no sean TCP.
Protocolos más importantes de la familia TCP/IP
Formato del encabezado TCP n 1 3 0 1 ? 3 4 5 6 7 8 ~ 0 1 2 3 4 5 6 7 8 9 0 1 2 ) 4 5 6 ; 6 1 0 1
Datos
Datw
Figura 13 Formato del encabezado TCP
A continuación se describen cada uno de esos campos.
Puerto Origen: 16 bits
Numero del puerto origen
Puerto destino: 16 bits
Numero del puerto destino.
Numero de secuencia: 32 bits
Es el numero de secuencia de1 primer octeto de datos en este segmento (excepto cuando la bandera S Y N este presente). Si S Y N esta presente el numero de secuencia es el numero de secuencia inicial (ISN) y el primer octeto de datos es ISN+ 1
Numero de Reconocimiento: 32 bits
SI el bit de control ACK esta habilitado este campo contiene el valor del siguiente numero de secuencia que el transmisor de segmento espera recibir. Una vez que una conexión se establece, este numero siempre se envía.
Offset de datos: 4 bits
Es el numero de palabras de 32 bits en el encabezado TCP. Indica donde comienzan los datos.
Reservado: 6 bits
Reservado para un uso futuro. Su valor siempre es cero.
Bits de control: 6 bits (de izquierda a derecha)
URG.- Campo de significado apuntador urgente.
ACK.- Campo de significado 13econocimiento
19
Administrador de Redes SNMP
PSH.- Función Push
RST.- Reset de la conexión
SYN.- Números de secuencia sincronizada
FIN.- No mas datos del transmisor
Ventana: 16 bits
EL numero de octetos de datos comenzando con aquel indicado en el campo reconocimiento al cual el transmisor de este segmento esta dispuesto a aceptar.
Checksum: 16 bits
El campo Checksum es el complemento a 1 de 16 bits de las sumas de complementos a 1 de todas las palabras de 16 bits en el encabezado y texto. Si un segmento contiene un numero impar del encabezado y de los octetos de texto se hace un Checksum, el ultimo octeto es rellenado hacia la derecha con ceros para formar una palabra de 16 bits para propósitos del Checksum. El relleno no se transmite como parte del segmento. Mientras se calcula el Checksum, el campo Checksum se reemplaza a si mismo con ceros.
Apuntador Urgente: 16 bits
Este campo comunica el valor actud del siguiente apuntador urgente como un offset positivo del número de secuencia en este segmento. El apuntador urgente apunta al numero de secuencia del octeto siguiendo los datos urgentes. Este campo se interpreta solo en segmentos con el bit URG puesto.
Opciones: variable
Las Opciones pueden ocupar espacio al final del encabezado TCP y son múltiplos de 8 bits en longitud. Una opción puede comenzar en la frontera de cualquier octeto. Existen dos casos para el formato de una opción:
caso 1: Un octeto simple de opción - tipo
caso 2: Un octeto de opción - tipo, un octeto de opción longitud, y los octetos actuales de opción - datos
La opción - longitud cuenta los dos octetos de opción - tipo y opción - longitud tan bien como los octetos de opción - datos.
20
Protocolos más importantes de la familia TCPAP
Relleno: variable
El relleno del encabezado TCP se usa para asegurar que el encabezado TCP termine y los datos comiencen en un limite de 32 bits. El relleno se compone de ceros. Terminología
El mantenimiento de una coaexión TCP requiere recordar varias variables. Estas variables se alojan en un registro de conexión llamado Transmisión Control Block (Bloque de Control de Transmisión) o TCB. Asimismo, existen variables de envío y recepción de la información en un TCB.
Variables de secuencia de envío
SND.UNA - enviar no reconocido
SND.NXT - enviar siguiente
SND.WND - enviar ventana
SND.UP - enviar apuntador urgente
SND.WL1 - numero de secuencia de segmento usado para la ultima actualización de ventana
SND.WL2 - numero de reconocimiento de segmento usado para la ultima actualización ventana
ISS - numero de secuencia de envío inicial.
Variables de secuencia de Recepción
RCV.NXT - recibir el siguiente
RCV.WND - recibir ventana
RCV.UP - recibir apuntador urgente
IRS - numero de secuencia de recepción inicial
El Diagrama 3 puede ayudar a relacionar algunas de esas variables al espacio de secuencia
1 2 3 4
SND.UNA SND.NXT SND.UNA I ” I I
+SND.WND
Diagrama 3 Variables relacionadas al espacio de secuencia
21
Administrador de Redes SNMP
1 - números de secuencia anteriores que han sido reconocidos
2 - números de secuencia de datos no reconocidos
3 - números de secuencia alojados para transmisión de nuevos datos
4 - números de secuencia futuros que no se alojan todavía.
La ventana enviada es la porción del espacio de secuencia etiquetado con un 3 en el Diagrama 4.
1 2 3 I I
RCV-NXT RCVINKT +RCV.WND
Diagrama 4 Espacio de secuencia etiquetado
1 - Números de secuencia anteriores que han sido reconocidos
2 - números de secuencia permitidos para nueva recepción
3 - números de secuencia futuros que no se han alojado todavía
Existen además varias variables usadas frecuentemente que toman sus valores del segmento actual
Variables de Segmento actual
SEG.SEQ - numero de secuencia de segmento
SEG.ACK - numero de reconocimiento de segmento
SEG.LEN - longitud de segmento
SEG.WND - ventana de segmento
SEG.UP - apuntador urgente de segmento
SEG.PRC - valor de precedencia de segmento
Una conexión se lleva a cabo a través de una serie de estados durante su tiempo de vida. Los estados son: LISTEN, SYN-SENT, SYN-RECEIVED,
LAST-ACK, TIME-WAIT y el estado ficticio CLOSED. CLOSED es ficticio porque representa el estado donde no existe TCB, y de esta forma, ninguna conexión. Los significados de los estados son:
ESTABLISHED, FIN-WAIT-1, FIN-WAIT-2, CLOSE-WAIT, CLOSING,
LISTEN.- Representa la espera de un requerimiento de conexión de cualquier TCP y puerto remotos.
22
Protocolos más importantes de la familia TCP/IP
SYN-SENT.- Representa la espera de un empate de requerimiento de conexión después de haber enviado un requerimiento de conexión
SYN-RECEIVED.- Representa la espera de la confirmación del reconocimiento del requerimiento de una conexión después de haber enviado y recibido un requerimiento de conexión
ESTABLISHED.- Representa una conexión abierta, los datos recibidos pueden darse al usuario. Es el estado normal para la fase de transmisión de datos de la conexión
FIN-WAIT-1 .- Representa la espera de un requerimiento de terminación de conexión de un TCP remoto o un reconocimiento del requerimiento de terminación de conexión previamente enviado
FIN-WAIT-2 .- Representa la espera de un requerimiento de terminación de conexión del TCP remoto
CLOSE-WAIT .- Representa la espera de un requerimiento de terminación de conexión del usuario local
CLOSING .- Representa la espera de un reconocimiento de un requerimiento de terminación de conexión del TCP remoto.
LAST-ACK .- Representa la espera de un reconocimiento de un requerimiento de terminación cle conexión previamente enviado al TCP remoto (la cual) incluye un reconocimiento de su requerimiento de terminación de conexión).
TIME-WAIT.- Representa la espera por tiempo suficiente para asegurarse que el TCP remoto recibió el reconocimiento de su requerimiento de terminación de conexión.
CLOSED .- Representa un estado de no conexión.
Una conexión TCP cambia de un estado a otro en respuesta a eventos. Los eventos son las llamadas de usuario: OPEN, SEND, RECEIVE, CLOSE, ABORT y ESTATUS, los segmentos próximos a llegar, particularmente 10s que contienen las banderas SYN, ACK, RST y FIN, y los timeouts (tiempos fuera).
El diagrama de estados (Diagrama 5) ilustra sólo cambios de estado, junto con los eventos y acciones de resultado.
23
Administrador de Redes SNMP
Diagrama 5 Estados de TCP
Diagrama de Estados de una conexión TCP
UDP (USER DATAGRAM PROTOCOL) Este protocolo se define para llevar a cabo una comunicación de
conmutación de paquetes en un ambiente de redes. Este protocolo asume que el IP (Internet Protocol) es usado como el protocolo de nivel de abajo.
Este protocolo provee un procedimiento para aplicaciones para enviar mensajes a otros programas con un mínimo de pasos. El protocolo es orientado a transacción, y la protección de liberación y duplicidad no están garantizadas. Las aplicaciones que requieran flujos de datos ordenados y confiables deberían usar e1 protocolo TCP.
Formato:
O 7 8 15 16 23 24 3 1
Puerto Fuente
Datos
Checksum Longitud
Puerto Destino
Figura 14 Formato del encabezado de un datagrama UDP
24
Protocolos más importantes de la familia TCPAP
Campos de UDP
Puerto Origen
El puerto origen es un campo opcional. Indica que es el puerto de proceso de envío y puede ser interpretado como el puerto al cual una réplica pueda ser direccionada en ausencia de cualquier otra información. Si no se usa, el valor de cero es insertado.
Puerto destino
El puerto destino significa dentro del contexto como una dirección destino.
Longitud
El campo Longitud indica la longitud en octetos del datagrama UDP incluyendo su encabezado y datos.
El valor mínimo de la longitud es ocho.
Checksum
El Checksum es el complemento a uno de 16 bits de la suma de complementos a uno de un pseudo-encabezado de información del encabezado IP, el encabezado UDP y datos, rellenando con octetos ceros al final, para hacer un múltiplo de dos octetos.
El encabezado contiene la dirección origen, la dirección destino, el protocolo y la longitud UDP.
El procedimiento Checksum es el mismo que el usado en TCP. O 8 16 24
Dirección Origen Dirección Destino Cero I Protocolo I longitud UDP
Figura 15 Encabezado de UDP
Si el Checksum vale cero, todos se transmite como unos (el equivalente a complemento a uno aritmético). <:uando se transmiten ceros para el Checksum significa que el transmisor no generó Checksum.
Interfaz de Usuario.
Una interfaz de usuario puede permitir la creación de nuevos puertos de recepclon, recibir operaciones en los puertos de recepción que devuelven octetos de datos y una indicación del puerto origen y el puerto destino, y una
.,
25
Administrador de Redes SNMP
operación que aloja un datagrama para ser enviado, especificando los datos puertos fuente y destino y la dirección para ser enviados.
Interfaz IP
El módulo U D P debe ser capaz de determinar las direcciones IP de origen y destino y además el campo de protocolo en el encabezado IP. Una posible interfaz UDP/IP podría proporcionar un datagrama IP incluyendo todo el encabezado como respuesta de una operación de recepción. De esta forma esta interfaz libera de trabajo al UDP para que este envíe a IP un datagrama completo con encabezado, al cual IP podría verificar ciertos campos y el Checksum del encabezado IP para enviarlo a su destino final.
Protocolo SNMP
PROTOCOLO SNMP ASN. 1
A nivel aplicación, las estruct.uras de datos intercambiadas entre entidades de protocolos son muy complejas. Por esto, es necesario introducir un nuevo formalismo para describir esas estructuras.
Este nuevo formalismo se llama sintaxis abstracta, la cual es usada para definir datos sin considerar estructuras y restricciones orientadas a la arquitectura de una máquina. En el Ambiente de Administración de Redes del estándar Internet (Internet-standard Network Management Framework), un lenguaje de OSI, llamado Abstract Syntax Notation One (ASN.l) se usa para este propósito.
Se debe enfatizar que ASN.l se usa para dos diferentes propósitos en este ambiente:
+t+ Definir los formatos de los PDUs intercambiados por el protocolo de
+&+ Sirve como el medio de definición de los objetos que son administración.
administrados. Esto es: la sintaxis abstracta es usada para describir estructuras de datos
intercambiadas a nivel protocolo que llevan información de administración.
ASN.l es usado como lenguaje independiente de l a máquina para estructuras de datos, y las Reglas Eiásicas de Codificación (Basic Encoding Rules- BER) se usan como reglas para codificación.
ASN. 1 es un lenguaje formal! que está definido en términos de gramática.
MÓDULOS
Una colección de descripciones de ASN.l se llama módulo. La sintaxis de alto nivel de un módulo es simple:
<<module>> DEFINITIONS:=BEGIN <<linkage>> <<declarations>> END
La cláusula <<module>> nomhra al módulo. Varios módulos puestos en una librería que se vayan a de necesitar se declaran dentro de la cláusula <</inkage>>. Así, los módulos pueden export.ar definiciones para uso de otros módulos.
27
Administrador de Redes SNMP
Finalmente, la cláusula <<declarations>> contiene las definiciones reales ASN. 1, de las que existen tres tipos de objetos definidos.
O Tipos, el cual define nuevas estructuras de datos +% Valores, que son variables de un tipo O macros, que son usadas para cambiar la gramática actual del lenguaje
ASN. 1 Cada uno de esos objetos es nombrado usando una palabra reservada
ASN.1; sin embargo, ASN.l usa una convención alfabética de casos para indicar el tipo de objeto al cual la palabra se refiere:
O Para un tipo, la palabra comienza con mayúscula (ejemplo: Tiempo) O Para un valor, la palabra comienza con minúscula (ejemplo: internet) O para una macro, la palabra consiste úricamente de mayúsculas
(ejemplo: OBJECT-TYPE)
Las palabras reservadas del ASN. 1 aparecen con puras mayúsculas.
Tipos y Valores
U n tipo ASN. 1 es definido usando la sintaxis:
NombreDeTipo :: =
TIPO
Similarmente, un valor (del tipo de dato) se define como:
nombreDeValor NombreDeTipo :: =
V A L O R
Esto es, primero la variable es nombrada (nombreDeValor), entonces se da el tipo (NombreDeTipo), y entonces el valor es asignado.
El ambiente de administración de redes usa cuatro clases de tipos ASN.1.
Tipos Simples
INTEGER: Tipo de dato tomando un número cardinal como su valor.
Nótese que ya que ASN.l describe un objeto conceptual, no existe limitación de precisión a nivel bit que puede ser requerido para representar al número.
28
Protocolo SNMP
Por ejemplo:
Estado:: =
INTEGER { Arriba(l), Abajo(2), Prueba(3)) miEstado Estado:: = Arriba //Vale 1
Si los valores simbólicos para un tipo de datos entero son enumerados (como en el ejemplo anterior), entonces sólo esos valores son válidos para variables de ese tipo de dato.
OCTET STRING: Cadena de octetos o bytes que toman valores entre O y 255 y usualmente representan datos en un código tal como ASCII
OBJECT IDENTIFIER: Tipo de dato que hace referencia a un objeto definido por una autoridad.
NULL: Tipo de dato que sirve para delimitar conjuntos, el cual corresponde a la abstracción del conjunto vacío.
Tipos Construidos
SEQUENCE: Tipo de dato que denota una lista ordenada de cero o más elementos, los cuales son datos con tipos ASN.1. Es similar a una estructura en muchos lenguajes de programación.
SEQUENCE OF: Tipo de dato que denota una lista ordenada de cero o más elementos que corresponden a un tipo ASN.l. Es similar a un arreglo dinámico en muchos lenguajes de programación: el número de elementos no es usualmente conocido hasta que el arreglo es creado, pero cada elemento tiene una sintaxis idéntica.
Tipos Etiquetados
ASN.l provee opciones para definir nuevos tipos de datos "etiquetando" un tipo previamente definido. El nuevo tipo y el viejo son distinguibles usando diferentes etiquetas, pero se refieren al mismo concepto.
ASN.l define cuatro clases de etiquetas, basadas en los requerimientos de identificación de programación de aplicaciones:
29
Administrador de Redes SNMP
*ks': C
Etiqueta Universal
1 2 3 4 5 6 7 8 9 10
12-15 16 17 1s 19 20 21 22 23 24 25 26 27 28
29- ...
pos universales. Estos tipos ya están definidos y los hemos jcrito. Sus etiquetas se resumen a continuación
Tipo ASN. 1
BOOLEAN INTEGER BIT STRING OCTET STRING NULL OBJECT IDENTIFIER Object Descriptor EXTERNAL REAL ENUMERATED Reservado para anexos o uso futuro SEQUENCE, SEQUENCE OF SET, SET OF Numericstring Printablestring TeletexString VideoTextSrring IA5String UTCTime GeneralizedType GraphicsString VisibleString Generalstring Characterstring Reservado para anexos o uso futuro
Tabla 3 Títulos universales en ASN.l
+% De aplicación (aplicación-amplia). Estos tipos son definidos localmente para una aplicación particular, y se etiqueta debe ser única en los módulos con variables de este tipo.
+t+ Etiquetas de contexto específico, sirven para identificar en orden de satisfacción a un tipo de constructor tal como un SEQUENCE o un CHOICE. * Etiqueta de uso privado. Es usada y única dentro de una empresa tal como lo provee un acuerdo bilateral dentro de los estándares.
Todas las etiquetas consisten de una clase (una para las cuatro introducidas) y un entero no negativo. D e esta forma varias etiquetas aplicación amplia deben estar definidas en un módulo, cada una con un número diferente. La sintaxis ASN.l usada para llevar la información etiquetada (excepto en etiquetas de contexto específico) es sencilla: cuando se define un tipo de datos, después de haber tecleando el nombre y el símbolo :: = , la etiqueta es dada entre corchetes [...I, es decir:
30
Protocolo SNMP
Opaque :: =
[APPLICATION 41 IMPLICIT OCTET STRING
Desde un nivel conceptual, etiquetando un tipo de datos resulta en un "encapsulamiento" del tipo de datos existente, dentro de un nuevo tipo de dato. Es necesario decir qué tipo de datos están realmente siendo usados. Si este conocimiento puede ser derivado por otros medios, entonces este encapsulamiento es innecesario. ],a palabra reservada IMPLICIT se usa para denotar esto, como se ve en el ejemplo anterior.
Subtipos
Una extensión usual definida para ASN.l es aquella de realizar subtipos, la cual habilita al programador para hacer refinamientos. Las reglas de ASN. 1 para realizar subtipos son largas y complejas. Afortunadamente, el ambiente de administración sólo hace uso de dos, tal como se muestran en estos ejemplos:
IpAddress ::= // en el orden red-byte [APPLICATION O]
IMPLICIT OCTET STRING (SIZE (4)) Counter ::=
[APPLICATION I ] IMPLICIT INTEGER (0..4294967295)
E n el primer ejemplo, un nuevo tipo de dato IpAddress que contiene una cadena de octetos es definida. Aunque no se requieren valores en cada octeto, la longitud de la cadena es estrictamente de 4. El comentario en la primera línea indica cómo una dirección IP es representada dentro de la cadena de octetos. E n el segundo ejemplo, un nuevo tipo de dato entero con valor es definido. Las instancias de este tipo de datos pueden tomar cualquier valor no negativo menor que 2". Identificador de Objetos (OBJECT IDENTIFIER)
U n identificador de objeto es una secuencia de valores enteros no negativos que atraviesan un árbol. El árbol consiste de una raiz conectada a un número de nodos etiquetados a través de enlaces. Cada etiqueta consiste de un valor entero no negativo y posiblemente una descripción breve. Cada nodo puede tener hijos propios, llamados subordinados, los cuales también son etiquetados. Este proceso puede continuar hasta un cualquier nivel de profundidad.
Cuando se describe un Identificador de Objeto existen varios formatos que pueden ser usados. El formato t e X d más conciso para enlistar los valores se da
31
Administrador de Redes SNMP
atravesando el árbol, comenzando en la raíz y procediendo al objeto en cuestión. Los valores enteros son separados por un punto. De esta forma: 1.0.8571.5.1 identifica al objeto encontrado comenzando desde la raíz, moviéndose al nodo con etiqueta 1, después al nodo con etiqueta O , y así sucesivamente.
El nodo raíz tiene tres subordinados:
+% ccitt(0) el cual es administrado por el Comité Consultivo
+% ¡so( 1 ), el cual es administrado por la Organización Internacional para
+% joint-¡so-ccitt(2) el cual es administrado juntamente por ISO/IEC y
Internacional de Telégrafos y Teléfonos
Estándares y el Comité Electrotécnico Internacional.
CCITT.
De esta forma, el primer corte del árbol aparece así:
ccitt[O] iso[l] joint-iso-ccitt[Z]
Figura 16 Primer nivel del corte del árbol para normalizar variables
y la autoridad administrativa para cada nodo es libre de asignar nodos subordinados adicionales y opcionalmente delegar autoridad a otros para nombrar objetos bajo esos nodos.
En el contexto de administración de redes, sólo el árbol ISO(1) es de interés. ISO/IEC ha definido cuatro subordinados:
iso[l]
standard(0) registration-authority[l) member-body(21 identified-organization[3)
Figura 17 Primer nivel del subárbol I S 0
32
Protocolo SNMP
Ellos son:
+$+ Standard(O), la cual tiene un subordinado asignado a cada Estándar
t%r registration-authority( 1 ), la cual es reservada para uso por autoridades de registro OSI.
I rnember-body(2), la cual tiene asignada un subordinado a cada miembro de OSI/IEC. € 1 valor de la etiqueta asignada a cada nodo es un código decimal de pais (DCC).
I identified-organization(3), la cual tiene un subordinado asignado a cualquier organización que ISO/IEC desee a favor. Este da una forma para cualquier 0rg;anización de nombrar objetos.
Internacional.
Finalmente, la junta de comités ISO/IEC y CCITT delegan nombrando autoridad bajo el árbol joint-iso-ccitt..
La sintaxis del Identificador de Objeto es simple:
Document-Type-Name :: =
OBJECT IDENTIFIER fTAM-1 Document-Type-Name :: =
(1 O 8571 5 l} E n este ejemplo, la declaracihn del valor muestra únicamente los valores
numéricos de los nodos. El valor textual puede ser también usado, previendo que aquellas cadenas sean inambiguas:
fTAM-1 Document-Type-Name :: =
{iso standard 8571 5 1) Para reafirmar el poder de lectura (y no el riesgo de ambigüedad) esas dos
formas se pueden combinar en:
fTAM-1 Document-Type-Name ::= (iso(1) standard@) 8571 5 l}
0:
internet OBJECT IDENTIFIER :: = (is0 or&) dod(6) 1) directory OBJECT IDENTIFIER :: = {internet 1)
MIB. La Estructura de Información de Administración (SMI) define ciertas reglas
de administración.
33
Administrador de Redes SNMP
Los objetos administrados residen en un almacén virtual, tal como una base de datos; el SMI define el esquema para esa base de datos. L a base de datos se llama Base de Información de Administración (MIB - Management Information Base). ÉSta define aquellos objetos que esperan ser implementados por nodos de administración corriendo la serie de protocolos Internet.
MIB ha tenido un par de versiones (MIB-I y MIB-11). L a primer MIB estándar, referida como MIB-I fue diseñada para incluir el mínimo número de objetos administrados pensados para ser útiles para la administración Internet. Pero, a medida que las necesidades crecieron, se amplió la robustez de la MIB, convirtiéndose en la MIB-11.
MIB-I divide a los objetos en ocho grupos.
Grupo system interfaces at iP lcmp tCP
egP UdP
total
no. 3
22 3
33 26 17 4 6
114
objetos para el mismo nodo administrado entradas a la red traslación dirección IP el protocolo Internet el protocolo de Contro de Mensajes Internet El protocolo de Control de Trasnsmisión el protocolo de Datagrama de Usuarios El protocolo de Gateway Exterior
Tabla 4 Grupos de la MIB-I
L a nueva versión de MIB (MIB-11).
grupo system interfaces at iP icmp t CP
egP transmission snmp
UdP
total
no. 7
23 3
38 26 19 7
18 O
30 171
objetos para era 3 era 22 será O era 33 sin cambio era 17 nueva tabla tabla expandida nuevo nuevo 50% más largo
Tabla 5 Grupos de la MIB-I1
Formato de las Entradas
34
Protocolo SNMP
Tanto en la MIB-I como en la MIB-11, cada objeto es definido con la macro OBJECT-TYPE.
Por convención, ningún objeto se define en la MIB Internet Estándar con un nombre que termine con un sub-identificador de cero. Este valor está reservado para uso futuro. D e esta forma, la primera variable dentro del grupo system se define:
system OBJECT IDENTIFIER :: = { mib 1 } Tiene el nombre { system 1 } o 1.3.6.1.2.1.1.1
Una segunda convención es que el descriptor simbólico de objetos, por ejemplo, sysDescr en
sysDescr OBJECT-TYPE
SYNTAX OCTET STRING
ACCESS read-only
ESTATUS mandatory
::= { system 1 }
sea corto. De esta forma debe ser Único dentro del módulo MIB.
La MIB Estándar - Internet
Grupo System
El grupo System debe ser implementado por todos los nodos administrados, y contiene información de configuración genérica:
system OBJECT IDENTIFIER :: = { mib 1 } sysDescr: Descripcibn del dispositivo sysObjectID: identidad del software agente sysUpTirne: hace cuánto comenzó el agente syscontact: nombre de la persona a contactar sysName: nombre del dispositivo syslocation: ubicación física del dispositivo sysservices: servicios ofrecidos por el dispositivo
Un valor ejemplo de la variable - objeto para el grupo system dentro de la MIB puede aparecer como se muestra:
35
Administrador de Redes SNMP
sysDescr sysObjectID sysUpTime
sysContact sysName sysLocation
"VIGIA SNMP" 1.3.6.1.4.1.4.1.2.1 45366736 (5 días, 6 horas, 1 minuto, 7.36 segundos) "Miguel Angel Ruíz < [email protected] > " vigia.uam.mx "Rectoría UAM" 0x48 (transport, application)
Tabla 6 Valor ejemplo de una variable - objeto para el grupo system
Grupo Inteqaces
El grupo System debe ser implementado por todos los nodos y contiene información genérica en las entidades a nivel interfaz. Este grupo contiene dos objetos de alto nivel: el número de intentos de enlace de interfaz en el nodo, y una simple tabla conteniendo información de esas interfaces:
interfaces OBJECT IDENTIFIER :: = { mib } ifNumber OBJECT-TYPE
SYNTAX INTEGER ACCES read-only ESTATUS mandatory
::= { interfaces 1 } i f f able OBJECT IDENTIFIER :: = { interfaces 2 } ifEntry OBJECT DENTIFIER :: = {iffable 1 1
Cada renglón de la tabla contiene varias columnas:
ifIndex: número de interface
ifDescr: descripción de la interface
ifType: tipo de interface
ifMtu: tamaño del MTU
ifspeed: Velocidad de transmisión en bits/segundo
ifPhysAddress: dirección específica del medio
ifAdminEstatus: estatus de interfaz deseado
ifOperEstatus: estatus actual de la interfaz
iflastchange: hace cuánto cambió el estatus de la interfaz
ifInOctets: total de octetos recibidos del medio
36
Protocolo SNMP
ifInUcastPkts: paquetes de difusión única liberados arriba
ifInNUcastPkts: paquetes de difusión múltiple/distribuida liberados arriba
ifInDiscards: paquetes descartados por limitación en los recursos
ifInErrors: paquetes descartados por errores
iflJnknownProtos: paquetes destinados para protocolos desconocidos
ifOutOctets: total de octetos enviados en el medio
ifOutUcastPkts: difusión única de paquetes desde arriba
ifOutNUcastPkts: pa.quetes de difusión múltiple/distribuida desde arriba
ifOutDiscards: paquetes descartados debido a límite de recursos
ifOutErrors: paquete:; descartados debido a errores
ifOutQlen: tamaño del paquete en la cola de salida
ifspecific: apuntador .MIB-específico
nivel superior
iflnUcastPkts* iflnNUcostPkts
iflnDiscords
iflnUnknownProtor
iflnErrors
"
nivel inferior
Diagrama 6 Casos para el grupo Interfaces
Todos esos objetos son genéricos en aquello que se aplica a todas las interfaces según s u tipo.
37
Administrador de Redes SNMP
U n valor ejemplo de la variable - objeto para el renglón correspondiente a la primera interfaz en el nodo administrado puede aparecer como sigue:
iflndex ifDescr i f f ype ifMtu ifspeed ifPhysAddress ifAdminEstatus ifOperEstatus ifInUcastPkts ifInErrors ifOutUcastPkts ifOutDiscards ifOutErrors ifOutQLen ifspecific
1 “leO“ 6 (ethernet-csmacd) 1500 10000000 08:00:20:00:38:ba 1 (UP) 1 (UP> 986357 94 887098 O O O 0.0
Tabla 7 U n valor ejemplo de la variable - objeto para el renglón correspondiente a la primera interfaz
Grupo Address Translation
El grupo address translation debe ser implementado por todos los nodos administrados y contiene información de resolución de dirección. De hecho, el grupo contiene una sencilla tabla usada para el mapeo de direcciones IP dentro un direccionamiento del medio:
at OBJECT IDENTIFIER ::= { mib 3 } atTable OBJECT IDENTIFIER :: = { at 1 } atEntry OBJECT IDENTIFIER :: = { atTable 1 }
Cada renglón de la tabla contiene tres columnas:
atIfIndex: número de interface atPhysAddress: diección del medio de mapeo atNetAddress: dirección IP de mapeo
U n valor ejemplo de la variable - objeto en la tabla address translation puede aparecer como sigue:
38
Protocolo SNMP
atIfIndex
192.33.4.4 00:00:22:08:2a:c3 1 192.33.4.3 00:00:22:08:2a:c3 1 192.33.4.20 08:00:20:00:38:ba 1 atNet Address atPhysAddress
Tabla 8 Un valor ejemplo de la variable - objeto en la tabla address translation
Grupo IP
El grupo IP debe ser implementado por todos los nodos administrados. El grupo contiene varios escalares y cuatro tablas.
ip OBJECT IDENTIFIER :: = { mib 4 } Los escalares son:
ipForwarding: actúa como gateway o host
ipDefaultTTL: TTL default para paquetes IP ipInReceives: datagramas totales de abajo
ipInHdrErrors: datagramas descartados debido a errores de formato
ipInAddrErrors: datagramas descartados debido a falta de liberación en el medio
ipForwDatagrams: datagramas adelantados
ipInUnknownProtos: datagramas destinados para protocolos desconocidos
ipInDiscards: datagramas descartados debido a límite de recursos
ipInDelivers: datagramas liberados arriba
ipOutRequests: datagramas de arriba
ipOutNoRoutes: datagramas descartados debido a que no hay ruta
ipReasmTimeout: tiempo agotado para cola de reensamble
ipReasmReqds: fragmentos recibidos que necesitan reensamble
ipReasmOks: datagramas satisfactoriamente reensamblados
ipReasmFails: fallas de reensamble
ipFragOKs: datagramas satisfactoriamente fragmentados
39
Administrador de Redes SNMP
ipFragFails: datagramas que necesitan ser fragmentados pero que los campos flags IP dicen que no
ipFragCreates: fragmentos creados
Cada renglón de la tabla contiene varias columnas:
ipAdEntAddr: la dirección IP de esta entrada
ipAdEntIfIndex: numero de interface
ipAdEntNetMask: máscara subred para la dirección IP ipAdEntBcastAddr: dirección de difusión IP o LSB
ipAdEntReasmMaxSize: el datagrama IP más largo capaz de ser reensamblado
Un valor ejemplo de la variable - objeto en un renglón de esta tabla puede aparecer como sigue:
ipAdEntAddr ip AdEntIfIndex ipAdEntNetMask ipAdEntBcastAddr inAdEntReasmMaxSixe
255.255.255.0
t í 5535
Tabla 9 Ejemplo de la tabla ip address I ~ C I abwc
""""""""
A iblnDrlw~rs -- ib0utpulRtqucrts --
iplnUnknownPmtor f
I&Drcwdr t
tpRearmOKr
ipRcarrnFilr +- ipRcssnRwdr e
ipForwDatwromr
IplnAddrEltbrr f
iplnReccivrr - + ipFrrgFnil. iplnHdrEllorr f
+ ipFrwOKs
- ipFrasCrcater
_""""" ""
laver b e l w
Diagrama 7 Casos para el grupo IP
40
Protocolo SNMP
L a tabla de ruteo IP guarda el camino de las rutas IP asociadas con el nodo administrado:
ipRoutingTable OBJECT IDENTIFIER ::= { ip 21 }
ipRouteEntry OBJE,CT IDENTIFIER ::= { ipRoutingTable 1 }
Cada renglón de la tabla contiene varias columnas:
ipRouteDest: direccion IP destino
ipRouteIfIndex: número de interface
ipRouteMetric1: mktrica de ruteo #1
ipRouteMetric2: mktrica de ruteo #2
ipRouteMetric3: mktrica de ruteo #3
ipRouteMetric4: mktrica de ruteo #4
ipRouteNextHop: siguiente salto (dirección gateway IP para ruteo indirecto)
ipRouteType: tipo (directa, remota, válida, inválida)
ipRouteProto: mecanismo usado para determinar la ruta
ipRouteAge: tiempo de ruta en segundos
ipRouteMask: máscara subred para ruteo
U n valor ejemplo de la variable - objeto en esta tabla puede aparecer como sigue:
Dest
255.255.255.0 3 (directo) 192.44.33.200 1 192.44.33.0
Mask Type NextHop IfIndex 0.0.0.0 0.0.0.0 4 (remoto) 192.44.33.3 1
Tabla 10 Ejemplo de la tabla de ruteo IP La tabla de interpretación de direcciones IP, añadida en la MIB-11, guarda
el camino de mapeo entre IP y el direccionamiento específico en el medio:
ipNetToMediaTable OBJECT IDENTIFIER :: = { ip 22 }
ipNetToMediaEntry OBJECT IDENTIFIER :: = { ipNetToMediaTable 1 }
Cada renglón de la tabla contiene cuatro columnas:
ipNetToMediaIfIndex: número de interface
ipNetToMediaPhysAddress: direccióndel medio de mapeo
41
Administrador de Redes SNMP
ipNetToMediaNetAddress: dirección IP de mapeo
ipNetToMediaType: cómo se determinó el mapeo
Si el valor de ipNetToMediaType es inválido, entonces el correspondiente renglón es inválido.
Un valor ejemplo de la variable - objeto en esta tabla puede aparecer como sigue:
IfIndex Type NetAddress PhysAddress 1
3 (directo) 192.33.4.4 00:00:22:08:2a:c3 1 3 (directo) 192.33.4.3 00:00:22:08:2a:c3 1 3(dinámico) 192.33.4.20 08:00:20:00:38:ba
Tabla 11 Ejemplo de la tabla de interpretación de direcciones IP
Grupo ICMP
El grupo ICMP debe ser implementado por todos los nodos administrados. El grupo consiste de 26 contadores. Se puede abreviar:
para cada tipo de mensaje ICMP existen 2 contadores, uno contando el número de veces que este tipo de mensaje fue generado por la entidad local IP, y el otro contando el número de veces que este tipo de mensaje fue recibido por la entidad local IP. Existen cuatro contadores adicionales los cuales guardan el camino del número total de mensajes ICMP recibidos, enviados, recibidos con error o no enviados debido a error.
icmp OBJECT IDENTIFIER ::= { mib 5 }
La siguiente figura muestra el diagrama de casos describiendo esos objetos:
42
Protocolo SNMP
ZERO
icmplnDcstUnrcochr i-
icmplnTimcExcds + icmplnParmProbs + icmplnSrcQucnchs +
icmplmRcdirccts i-
icmplnEchos + icmplnEchoRcps i-
icmplnTimestamps +
icmplnTimestompsRcps
icmplnAddrMasks i-
icmplnAddrMoskRcps i-
icmplnErrors i-
icmplnMsgs -- - ""_
L o w Bclow
Diagrama 8, Casos para el grupo ICMP
Grupo TCP
El grupo IP debe ser implementado por todos los nodos administrados que implementan TCP. El grupo contiene varios escalares y una tabla.
tcp OBJECT IDENTIFIER ::= { mib 6 }
Los escalares son:
tcpRtoAlgorithm: identifica el algoritmo de retransmisión
tcpRtoMin: Tiempo agotado mínimo de retransmisión en milisegundos
tcpRtoMax: Tiempo agotado máximo de retransmisión en milisegundos
tcpMaxConn: número máximo de conexiones simultáneas TCP alojadas
tcpActiveOpens: número de aperturas activas
tcpPassiveOpens: número de: aperturas pasivas
tcpAttemptFails: número de intentos de conexión fallados
tcpEstabResets: número de conexiones reedtablecidas
43
Administrador de Redes SNMP
tcpCurrEstab: número de conexiones actuales
tcpInSegs: número de segmentos recibidos
tcpOutSegs: número de segmentos enviados
tcpRetransSeg: número de segmentos retransmitidos
tcpInErrs: número de segmentos descartados debido a error de formato
tcpOutRsts: número de reestablecimientos generados
La tabla es usada para guardar el camino de las entidades de aplicación que estén usando TCP:
tcpconnTable OBJECT IDENTIFIER ::= { tcp 13 }
tcpConnEntry OBJECT IDENTIFIER ::= { tcpConnTable 1 }
Cada renglón de la tabla contiene cinco columnas:
tcpConnState: estatus de la conexión
tcpConnLocalAddress: dirección local IP
tcpConnLocalPort: puerto local T C P
tcpConnRemAddress: dirección IP remota
tcpConnRemPort: puerto remoto TCP
1 1 Dtm fuentes
tcplnErrs tcpOutRrts
tcpRctrmrScqs
tcplnScgs tcpOutScys
"~"""""""~~""
N k l inferior
Diagrama 9 Entidades de aplicación que usen TCP/IP
El valor 0.0.0.0 es usado para direcciones IP cuando la información no ha sido todavía enlazada para la conexión.
44
Protocolo SNMP
Un valor ejemplo de la variable - objeto en esta tabla puede aparecer como sigue:
tc ConnLocal tcpConnState Address Port Address
11 (timewait) 127.0.0.1 4459 127.0.0.1 21 0.0.0.0
192.33.4.20 23 192.33.4.4
Tabla 12 Ejemplo de la tabla TCP
Remote Port
C 1
1803
Grupo UDP El grupo UDP debe ser implementado por todos los nodos administrados
que implementan UDP. El grupo contiene cuatro contadores y una tabla
udp OBJECT IDENTIFIER ::= { udp 7 }
Los escalares son:
udpInDatagrams: datagramas liberados hacia arriba
udpNoPorts: datagramas destinados para puertos desconocidos
udpInErrors: datagramas descartados debido a errores de formato
udpOutDatagrams: datagrarnas enviados desde arriba
La tabla: añadida en la MIB-I1 es usada para guardar el camino de las entidades de aplicación que estén usando UDP:
udpTable OBJECT IDENTIFIER ::= { udp 5 }
udpEntry OBJECT IDENTIFIER ::= { udpTable 1 }
Cada renglón de la tabla contiene dos columnas:
udpLocalAddress: dirección local IP
udpLocalPort: puerto local lJDP
El valor 0.0.0.0 se usa para direcciones IP cuando su información no ha sido todavía enlazada.
U n valor ejemplo de la valor - objeto en esta tabla puede aparecer como sigue:
45
Administrador de Redes SNMP
~~~~~~ ~ ~
udpLocalAddress
111 0.0.0.0 53 0.0.0.0 42 0.0.0.0 udpLocalPort
127.0.0.1 53 192.33.4.20 53 192.33.4.20 1024
. . . . .
Tabla 13 Ejemplo de la tabla UDP
Grupo EGP
El grupo E G P es obligatorio para aquellos nodos administrados que implementan el Protocolo de ruteador Exterior (EGP).
El grupo transmisión está definido e la MIB-11, así como el grupo SNMP
SNMP
Introducción
El protocolo que se ha definido para la administración de nodos de Internet, se llama precisamente SNMP (Simple Network Management Protocol). Este protocolo está definido para ser compatible con la base de datos de información de administración (MIB Management Information Base) definida bajo la estructura de información de administración (SMI Structure Management Information), descritas como estándares bajo TCP/IP
La IAB (Internet Activities Board) recomienda que los agentes de administración definan con la SMI una MIB para el trabajo con el protocolo SNMP. Con esto se logra que en el entorno de administración de redes basadas en el protocolo TCP/IP consista en identificar y estructurar la información de administración tal como se describe en la SMI, la cual esta en un archivo MIB y corresponde en nuestro caso a la MIB-I1 descrita en el capítulo anterior.
La estructura de la MIB organiza en grupos los objetos de administración, de tal manera que basta solo adicionar nuevos objetos en nuevos grupos sin modificar sus agentes y administradores.
Arquitectura de la administración SNMP.
El modelo de la administración SNMP consiste en un grupo de estaciones de administración de redes y elementos de redes. Las estaciones ejecutan procesos de administración para controlar y monitorear a los elementos de la red. Los elementos de red son los rutedores, servidores, clientes y demás. El
46
Protocolo SNMP
protocolo sirve para intercambiar i.nformación entre los agentes y las estaciones administradoras de estos recursos.
Características del protocolo SNMP
1. El protocolo minimiza en número y en complejidad las funciones que por si mismo debería usar el agente de administración. Esta ventaja es atractiva en por lo menos cuatro puntos:
El desarrollo de un programa agente de administración con este protocolo es más barato que otros.
La administración puede ser remota y completa en el uso de Internet y proporciona una tarea más a través de esta red.
El grado de las funciones de administración remota, impone pocas restricciones en las herramientas que se utilizan para la administración.
Simplifica en grupos de administración al conjunto de funciones de un administrador de redes.
2. El protocolo SNMP hace adaptable la administración y control de elementos de la red y previene la posibilidad de aspectos inanticipados propios de la administración de redes.
3. La arquitectura de la administración SNMP es independiente del Hardware que se utilice.
Elementos de la arquitectura
La arquitectura de la administ ración SNMP permite solucionar problemas de administración de redes en términos de:
El alcance de la información.
El alcance de la información de administración con el protocolo SNMP, es precisamente el marcado en el convenio para el uso de la MIB o la de cualquier base de datos basada en la SMI.
Una aplicación con el protocolo SNMP usualmente hace una consulta a un archivo que contiene la MIB o una base de datos con la SMI, con lo que basta con modificar esta base de datos para que el programa administre nuevas variables.
La representación de la información.
La información de admini.stración para el protocolo SNMP, esta basada en un subconjunto de las reglas de ASN.l , el cual esta bien especificado
47
Administrador de Redes SNMP
en la estructura SMI. D e hecho estas especificaciones son dicho subconjunto.
El SGMP (Simple Gateway Management Protocol) adoptó un subconjunto de ASN.l para representar su información, al ser SNMP heredero de este protocolo, continua y extiende el uso de tipos definidos en ASN.l para el uso de la administración de redes. Esto se decide a partir de las experiencias obtenidas en el uso del protocolo SGMP.
3. Las operaciones soportadas para la administración.
En la administración con el protocolo SNMP, un agente tiene como función principal inspeccionar y modificar el valor de las variables de administración. Una estación de administración, interactúa a través de la red, tal ves en forma remota, con el agente, para que este obtenga o asigne un valor a una variable.
Una tercera función del agente es enviar un mensaje al administrador cuando se requiere la atención del mismo, basando las ideas en la interrupción de un proceso (trap), en cuyo caso el administrador tomará decisiones y enviari los mensajes pertinentes.
4. La forma y significado de la información intercambiada por distintas entidades.
La forma y significado de la información que se intercambia, esta basada en los mensajes, los cuales determinan estos dos factores. Mas adelante se describe la estructura y significado de estos mensajes.
La ventaja que se apunta por si sola al hablar de mensajes en una red TCP/IP es que estos se pueden trasmitir en datagramas y por lo tanto se monta sobre el protocolo UDP de la familia TCP/IP.
5. Relaciones entre entidades dentro de la administración.
Una aplicación SNMP es un programa que reside en una estación de administración o un programa en alguna terminal de la red que se comunica con otros usando el protocolo SNMP. El proceso de administración requiere pues aplicaciones SNMP para su desarrollo.
Un agente SNMP es una aplicación SNMP que obtiene o modifica los valores de una variable.
Un administrador SNMP es una aplicación SNMP que se comunica con un agente para que este obtenga o modifique los valores de las variables.
48
Protocolo SNMP
La comunidad SNMP es el conjunto formado por un agente SNMP con un conjunto arbitrario de aplicaciones SNMP, las cuales tienen un nombre en común definido en una cadena de octetos que en inglés se conoce como comunity.
Un mensaje SNMP es un mensaje originado por una aplicación SNMP con un nombre de comunidad válido para un elemento de dicha comunidad. Al conjunto de reglas que sirven para determinar si un mensaje es SNMP para una particular comunidad, se le conoce como esquema de autenticidad. Una función que determina la autenticidad de un mensaje SNMP con vario esquemas de autenticidad, se le llama Servicio de Autenticidad.
Cuando un elemento de la red solicita el valor de un subconjunto de objetos definidos en la MIB se dice que hace una consulta SNMP de la MIB .
El modo de acceso SNMP es la forma en que se consultan objetos, los cuales pueden ser de Solo Lectura o Solo escritura.
Al par de un modo de acceso SNMP con una consulta SNMP a la MIB, se le conoce como Pe@ S.NMP de comunidad.
Al par de un Modo de Acceso SNMP con un Perfil SNMP de Comunidad, se le conoce como una política de acceso SNMP.
6. La forma y significado de las referencias a información.
La SMI contiene en s u definición de sus elementos las siguientes características.
I. La referencia a variables no es ambigua
Dado que la definición de objetos de administración es solo conceptual, es importante saber que podrían aparecer nombres de objetos iguales. pero en contextos diferente, para evitar esto, se crea un identificador Único, (en una estructura de árbol) y de esta manera se resuelve la ambigüedad’.
II. Las referencias a través de diferentes versiones es distinguible.
En la MIB se encuentran los objetos administrados, cada objeto con un identificador Único, el cual se encuentra en una
Ver Identificador de Objetos (OBJECT IDENTIFIER) en la página 31 para mayor información.
49
Administrador de Redes SNMP
estructura de árbol. D e alguna manera en esta estructura está implícita la versión de SNMP que se maneja.
111. Se identifican los valores de variables pertenecientes a un objeto definido en la MIB.
U n objeto definido con SMI, tiene un nombre que forma parte de un árbol Único, de esta forma se puede hacer referencia señalando su ruta desde la raíz separando cada nodo con un punto. Cada subnodo es numerado a partir de 1 y el O se reserva para indicar que se trata de una variable de este objeto. E n el caso de que se llega a una hoja y continúa un número diferente de O , indica que corresponde a uno de varios valores que contiene este objeto.
Por ejemplo la variable sysDescr contiene la ruta siguiente
iso.org.dod.internet.mgmt.mib.sytem.sysDescr
La cual, puede representarse con números que resultan de una consulta de profundidad por la izquierda al árbol. Esto es:
1.3.6.1.2.1.1.1
Esta ruta identifica a la variable, la cual en el momento de devolver un valor debe aumentarse un cero, por lo que la cadena 1.3.6.1.2.1.1.1.0 identifica un valor de esta variable.
El protocolo SNMP
El protocolo consiste precisamente en enviar un paquete U D P a través de la red, el que contiene un mensaje SNMP que contiene la siguiente información.
U n identificador secuencia1 para uso interno del administrador.
La versión del protocolo.
La comunidad SNMP a la que se refiere la pregunta.
Un control de errores.
El tipo de mensaje que puede ser la solicitud de variables explícitas, o bien la solicitud de las variables siguientes en el árbol a los nodos que se indican.
La lista de nodos que sirve para indicar la solicitud en el mensaje SNMP. Al recibirlo el agente SNMP, obtiene los valores que corresponden a la
solicitud y los guarda en un mensaje SNMP de respuesta, el cual contiene:
50
Protocolo SNMP
U n identificador secuencia1 para uso interno del administrador.
O L a versión del protocolo. I L a comunidad SNMP a la que se refiere la pregunta. O Un control de errores. +% El tipo de mensaje que en este caso indica que es una respuesta. I L a lista de nodos que sirve para indicar los objetos seguidos de los
valores que se han solicitado en el mensaje SNMP anterior.
De manera opcional, en la versión 1 del protocolo SNMP, se contempla la posibilidad de manejar mensajes (de TRAP para obtener avisos en momentos críticos los cuales no los describimos aquí por no estar contempladas en el proyecto.
- BER
CODIFICACION DE DATOS
Ahora es tiempo de describir cómo las variables de tipos de datos definidos usando ASN.l se concatenan en cadenas de octetos. Así como ASN.l define una notación de sintaxis abstracta, existe una correspondiente notación de sintaxis de transferencia llamada RegZas Bdsicas de Codificación (Basic Encoded Rules- o BER). Estas reglas son simplemente un algoritmo recursivo que puede producir un octeto compacto codificado para cualquier valor ASN. 1
A un nivel alto, BER describe cómo codificar un tipo simple ASN.l. Este puede ser un tipo simple tal como un INTEGER, o un tipo de complejidad arbitraria. Conceptualmente, la clave para aplicar el BER es entender que el tipo ASN.l más complejo no es más que un número de tipos pequeños menos complejos ASN.l . Si esta descom.posición continúa, entonces un tipo simple ASN.l tal como un INTEGER es codificado.
Usando el BER, cada tipo AS.N.1 es codificado como tres campos:
O Un campo tug (etiqueta), que indica el tipo ASN.l +!+ Un campo longitud, el cual indica el tamaño del valor ASN.l
codificado U n campo valor, el cual es el valor ASN.l codificado
Figura 18 Etiqueta TLV Llamaremos a este tipo de etiquetas TLV (tag long value).
51
Administrador de Redes SNMP
Cada uno de esos campos tiene una longitud variable. Debido a que ASN. 1 puede ser usado para definir tipos arbitrariamente complejos, el BER debe ser capaz de soportar codificaciones arbitrariamente complejas.
Orden de los Bits
En BER, el bit de orden más alto (o más significativo) es llamado bit 8, mientras que el menos significativo es el bit 1. Es importante aplicar esto consistentemente, ya que diferentes arquitecturas de máquinas utilizan diferentes reglas de orden. Aplicando esto, quedaría:
a la red < "_"""" octeto 1 8 7 6 5 4 3 2 1
Figura 19 Un octeto que viaja por la red
Campo Etiqueta
El campo etiqueta es codificado como uno o más octetos identificadores. Esta codificación debe de alguna forma capturar la definición del correspondiente tipo ASN.l . El BER hace esto codificando la etiqueta ASN.l del tipos.
Existen cuatro clases de etiquetas en ASN.1:
O Etiquetas universales, para los tipos de datos ya conocidos. t8t Etiquetas dentro de la aplicación, las cuales están definidas dentro de
O Etiquetas uso-privado usadas por partes ímicas y autorizadas O Etiquetas de contexto específico.
un módulo ASN. 1 sencillo.
Realizar la codificación del campo etiqueta como una secuencia de octetos es muy simple. El campo etiqueta consiste de uno o más octetos. Los dos primeros bits indican la clase de la etiqueta. El tercer bit es una bandera denominada f, y los siguientes cinco bits determinan el número de la etiqueta (no negativo).
8 7 6 5 1
Figura 20 Campo tag de una TLV
Recuérdese que un tipo de datos tiene asignado una etiqueta como se puede ver en Tipos Etiquetados en la página 29.
52
Protocolo SNMP
La tabla para codificar los dos primeros bits (que definen la clase) son:
Universal Ancho-Aplicación Contexto-Específico Privada 1
Figura 21 Clases de tipos en BER
D e esta forma, existen cinco bits para codificar un número de etiqueta no negativo. Los valores posibles para este número están entre O y 63, pero pueden existir más de 64 tipos de etiquetas posible. Entonces, para implementar un número de etiqueta mayor a 63 (y por consecuencia, que se necesiten más de cinco bits), BER usa la siguiente regla:
Si el número de etiqueta es menor a 31, entonces se codifica ese número dentro de estos cinco bits, usando la representación sin signo. En otro caso, los cinco bits son puestos todos a uno, que indica que el octeto que sigue contiene el número de etiqueta.
En muchos casos, sólo un octeto basta para codificar el campo etiqueta. En los otros casos, uno o más octetos siguen al primero. Para los octetos subsecuentes, cuando el bit más significativo de cada octeto es puesto a cero, indica que éste es el último octeto del campo etiqueta:
Figura 22 Codificación del campo tag de una TLV
De esta forma, en el caso en que el número de etiqueta sea mayor o igual a 31, el valor es codificado usando la representación entera sin signo concatenando los valores de 7 bits de los octetos que siguen al octeto identificador inicial.
Campo Longitud
El campo longitud se codifica en uno o más octetos. Esta codificación indica cuántos de los octetos que siguen realizan el valor del tipo ASN.l que está siendo codificado.
Si la longitud del código es conocida, éste se llama forma definida.
53
Administrador de Redes SNMP
Si el número de octetos de código es menor a 128, un sólo octeto puede usarse para codificar la longitud:
3 7 6 5 4 3 2 1
Si la longitud es mayor, entonces se usa más de un octeto. El primer octeto contiene el bit más significativo (bit 8) puesto a uno. Los siguientes siete bits comprenden un número que representa cuántos octetos siguen dentro del campo longitud (cualquier valor entre 1 y 126 octetos). La longitud es codificada usando la representación numérica sin signo, concatenando los octetos que siguen al octeto inicial de longitud. Como todos los ocho bits son usados, se pueden usar arriba de 126"-8 o 1008 bits.
Como 2'Oo8.' es mayor que un espacio de memoria de cualquier computadora a ser construida en cualquier época, éste es suficiente un número de bits. Así, BER provee una futura extensibilidad.
p i G q ~ ] = = = ~
1 2 3 4 5 6 7 8
Existe asimismo la forma indefinida de codificación de la longitud. En esta, el campo longitud consiste de un simple octeto que tiene el bit más significativo puesto a uno, y los siguientes bits a cero. Después de este octeto, el valor del campo es codificado, consistiendo de cero o más códigos ASN.1. Para marcar el fin del código se envía fin-de-contenido. Esto se hace enviando dos octetos con todos sus bits puestos a cero:
El uso de la forma de longitud indefinida se prohibe y no es usado, ya que la forma de longitud definida se necesita para códigos primitivos.
Campo Valor
El campo valor es codificado como cero o más octetos de contenido.
Tipos Simples
Los tipos simples proveen codificación fundamental que son usados por el BER:
54
Protocolo SNMP
INTEGER
U n valor INTEGER es codificado como uno o más octetos de contenido, siempre en forma primitiva. El valor es codificado usando código de complemento a dos en el cual debe prohibirse tener todos los bits puestos a cero o a uno para evitar redundancia.
Por ejemplo, el valor 100 decimal se codifica como:
I O 0 1 0 1 2 I ~ c ~ 1 ~ 1 ) 0 ~ 0 ) 1 ~ 0 ) 0 ~
clase f número longitud contenido
Figura 23 Codificación del valor 100
el cual, ignorando los bits con valor cero, tenemos:
26 + 2' + 22 = 64 + 32 + 4 = 100 OCTET STRING
Un valor OCTET STRING es codificado como cero o más octetos de contenido, en su forma primitiva o construida.
Aquí se presenta el código en forma primitiva del valor "snmp":
10 0101 4 ] 141 clxe f numem iongihrd
10 1 1 I O 0 í 11 l o 1 1 o 1 1 o í I Io 1 1 í o o o o ~ I, I, I , I , "m" "P"
Figura 24 Codificación de una cadena
Una forma construida de un valor OCTET STRING es simplemente una colección de OCTET STRING más pequeños. Cada substring que tenga su campo etiqueta toma el valor para OCTET STRING.
NULL
U n valor NULL es codificado como cero octetos de contenido. Es sintácticamente similar al fin-de-octetos (dos octetos con valor cero), pero tiene una etiqueta diferente:
l o ola[ 5 I I o I
Figura 25 Código ver de NULL
55
Administrador de Redes SNMP
OBJECT IDENTIFIER
U n valor OBJECT IDENTIFIER es codificado como uno o más octetos de contenido, siempre en forma primitiva.
Para propósitos de codificación usando el BER: t8t los primeros dos elementos en la secuencia forman un sub-
ident2ficador con el valor X V O + Y , donde X es el valor del primer elemento, y Y es el valor del segundo elemento, y
I cada elemento que sigue en la secuencia además forma un sub- identzficudor con un valor igual al valor de ese elemento
Por ejemplo:
1.0.8571.5.1
consiste de cuatro sub-identificadores: (40:'l +O), 8571 y 3
Al codificar éste número da como resultado los números 40, 8571 y 1
La representación es como sigue:
close f numero longitud primer sub-id : 40
11 1 0 0 0 0 1 01 l o 1 1 1 1 0 l O l ~ 0 0 0 0 0 1 0 1 ~ ~ 0 0 0 0 0 0 0 1 ~ scgundo sub-id = 8571 tercer sub-id 5 cuarto sub-id = 1
Figura 26 Código BER de un objeto identificador Tipos Constructores
Así como lenguaje ASN.l definió tipos complejos en términos de la combinación de tipos simples con constructores, el BER codifica tipos complejos codificando un constructor cuyo valor consiste en código de tipos simples.
SEQUENCE
Un valor SEQUENCE es codificado como cero o más octetos de contenido, siempre en forma construida. Básicamente, los campos etiqueta y longitud son generados. Entonces, para cada elemento presente en el SEQUENCE el BER es recursivamente aplicado.
El orden de codificación debe empatar el orden en que los elementos fueron definidos en el módulo ASN.l para este tipo.
56
Protocolo SNMP
Considérese una codificación de:
VarBind :: =
SEQUENCE{ nombre NombreObjeto, valor SintaxisObjeto
l. Sin conocer los tipos de NombreObjeto y SintaxisObjeto, el código para
VarBind debe parecerse a algo como ésto:
close f numero longitud
Contenido NombreObicto NombrcObicto t4ombrcObieto
VdorObicto VolorObieto VdorObicto
Figura 27 Código BER del tipo VarBind en forma definida
si se usa la longitud definida, o:
10 0111 16 I v m close f numero longitud indcfinda
NombreObicto NombreObieto NombrcObicto I I
Figura 28 Código BER del tipo VarBind en forma indefinida
si se usa la longitud indefinida.
57
Administrador de Redes SNMP
SEQUENCE OF
U n valor SEQUENCE OF se codifica igual que un SEQUENCE ; las etiquetas son las mismas. Nótese que las etiquetas de los elementos son efectivamente redundantes aquí. Sin embargo, deben codificarse para mantener el formato TLV'.
Tipos etiquetados
U n tipo etiquetado de la forma:
AlgunTipo:: =
[Etiqueta] IMPLICIT OtroTipo
es codificado usando las reglas de OtroTipo, siendo la diferencia que un nuevo valor fue usado en el campo etiqueta.
Podemos considerar cómo una definición de la forma
AlgunTipo:: =
[Etiqueta]
OtroTipo
debe ser codificada (aquí no está la palabra reservada IMPLICIT ). La respuesta es que una definición etiquetada de esta forma es tratada como un constructor análogo a:
AlgunTipo:: =
[Etiqueta] IMPLICIT SEQUENCE {
OtroTipo 1
La idea es que etiquetando la información de OtroTipo se mantiene intacta, siendo contenida dentro de otro tipo que tiene una nueva etiqueta. Además B E R no establece reglas de codificación para tipos etiquetados en este aspecto.
Entonces, en una codificación de: AlgunTipo:: =
[APLICACION O] OtroTipo
siempre se muestra algo como esto:
I' Ver significado en página 51
58
Protocolo SNMP
OtroTipa OtroTipo ...
OtraTipo
I n octctos I
Figura 29 Código BER de un SECUENCE OF Un ejemplo
Ahora se muestra un ejemplo que ilustra cómo el BER puede ser aplicado a los tipos de datos del ASN.l usados en el ambiente de administración de redes.
Considérese el valor ASN. 1: ejemplo Message::=
{ version version-1, community "public", data
{ get-response
{ request-id 17, error-estatus noError, error-index O variable-bindings
{ name 1.3.6.1.2.1.1.1.1.0, value
{ simple
string "unix"
3
3 3
59
Administrador de Redes SNMP
3 En la generación del código usando el BER para este valor, el primer paso
(conceptual) es ver el valor como si fuera compuesto por tipos simples y constructor ASN.l:
1.3.6.1.2.1.1.1.1.0, "unix"
1 3
3 } Esto ilustra la forma de cómo los valores de los datos quedarán
codificados.
El siguiente paso es construir el código.
Un Mensaje consiste de tres partes. El campo etiqueta es fácil de generar.
Rastreando los componentes del mensaje, y calculando sus longitudes se determina que 43 octetos son necesarios para la parte que corresponde al campo valor. De esta forma, los primeros dos octetos del código serían:
clnsc f numero longitud
Después, el número de versión, un INTEGER,
clwc f numero longitud
se codifica como:
contenido
El nombre community, un OCTET STRING se codifica como:
60
Protocolo SNMP
Loolol 4 I I 6 I clwc f numero longitud
[ o 1 1 1 o o o o l piTmi3-q l o 1 1 O 0 0 1 o ] Io1 1 o 1 o 1 11
1 0 1 1 o 1 0 0 1 1 ViEiml O'V"
I, I,
"b" "11'
"jll "C"
Figura 30 Código de una cadena
Ahora se codifica una instancia de los tipos de dato PDU. Como éste es un CHOICE, cualquier dato que sea especificado por el campo valor es codificado en su lugar: en este caso, una instancia del GetResponse-PDU. Este es un tipo etiquetado implícitamente, y un valor PDU es codificado, pero con una etiqueta diferente. U n tipo de dato PDU es un SEQUENCE, debe usarse la forma de codificación construida. Comen:zamos generando los campos etiqueta y longitud:
clast f numero longitud
Después, los campos identificador de requerimientos, índice de error son codificados. Todos ellos son enteros:
clast f numcro
clast f
Finalmente, codifica. Una vez
numtro
estatus de error e
longitud contenido
longitud conttnidu
Figura 31 código del cuerpo de un choice
el dato variable-bindings, un valor SEQUENCE OF, se más, se generan 1'0s campos etiqueta y longitud:
-1 I 19 I clase f numcro longitud
Cada elemento del valor SEQUENCE OF es un valor VarBind, el cual es un SEQUENCE. Como existe sólo un elemento en el SEQUENCE OF, sólo
61
Administrador de Redes SNMP
un valor necesita ser codificado. Como es usual, los campos etiqueta y longitud son codificados:
clorc f numero longitud
Finalmente, los componentes del valor VarBind son generados comenzado con un valor ObjectName (nombre del objeto). Este es un OBJECT IDENTIFIER con valor 1.3.6.1.2.1.1.1.1.0, teniendo 9 subidentificadores:
[ O O l O l 6 I I 9 I l o 0 1 o 1 o 1 11 c lwe f numero longitud primer sub-id 43
sequndo sub-id: 6 terccr sub-id 1 cuarto sub-id: 2 quinto rub-id 1
scxto sub-id 1 scptimo subid 1 octaV0 sub-id 1 novcno sub-id: O
Figura 32 Código BER de un identificador de objetos
Este es seguido por un valor Objectvalue el cual es un OCTET STRING:
l o o l o l 4 I 1 4 1 CIMC f numero longitud
Figura 33 Código BER de una cadena
Poniéndolos todos juntos, aquí hay 45 octetos que son generados (en hexadecimal):
30 2b 02 o1 O0 04 06 70 75 62 6c 69 63 a2 l e
O201 11 02 o1 O0 02 o1 O0 30 13
30 11 06 O9 2b 06 O1 02 O1 O1 O1 O1 O0
62
Protocolo SNMP
04 04 75 6e 69 78
63
Administrador de Redes SNMP
DESCRIPCI~N DEL PROYECTO El administrador de redes propuesto, está pensado para ejecutarse bajo
ambiente Windows, por lo que para desarrollarlo, es necesario tener una introducción clara al ambiente Windows, como maneja su memoria y como funcionan los mensajes a las ventanas.
Otro de los puntos importantes es la forma en que se puede compartir código ejecutable en tiempo de ejecución, mecanismo por el cual usamos los servicios de IP y UDP, para poder implementar el protocolo SNMP.
OBJETIVOS Al ser un requisito el desarrollo de un proyecto terminal para obtener el
grado, creemos que es necesario desarrollar un trabajo completo y amplio en algún tema de actualidad. En este caso encontramos el desarrollo de un administrador de redes con el protocolo SNMP como un buen proyecto, el cual requiere de un conocimiento completo en el ámbito de las comunicaciones de redes y en la programación; Los objetivos que nos planteamos para este proyecto, que son también las razones por las que aceptamos este trabajo son los siguientes:
1.Desarrollar una aplicación en el ámbito de las redes
2.0btener el conocimiento detallado de por lo menos uno de los protocolos de la familia TCPAP
3.Conocer de manera amplia el funcionamiento del sistema operativo Windows a nivel del programador.
4.Crear una aplicación Windows en el lenguaje de programación C+ +. 5.Conocer el uso y funcionamiento de los recursos dinámicos de
información que proporciona Windows.
6.Implementar un protocolo de comunicación.
7.Proporcionar una herramienta útil y de actualidad a todo aquel que se interese en el tema de las redes.
PLATAFORMA Aprovechando que el sistema operativo Windows, se ha generalizado en el
mundo de las PC, y que proporciona acceso a Internet, la creación de un
64
Descripción del proyecto
administrador SNMP para este sistema es viable. Hay que tomar en cuenta para ello que dicho administrador será una aplicación Windows, la cual debe reunir las características propias de estas aplicaciones. Por ello en esta sección se habla acerca de como opera una aplicacitjn típica para Windows 3.1 o compatible.
Como administra Windows la memoria.
Windows 3.1 es un sistema operativo para procesadores Intel 80286 o superiores, que se ejecuta a partir de MSDOS y conmuta al modo protegido del procesador. En este modo se pueden accesar hasta 16 Mb de memoria RAM física. Windows 3.1 cuenta con una extensión para procesadores Intel 80386 o superiores, con la cual entre otras cosas se puede acceder hasta 4 GB de memoria RAM física, esto sin tomar en cuenta la gestión de memoria virtual, con la cual se puede gestionar más: memoria aún. Pero no todo es fácil, ya que un programa normal para Windows 3.1 no puede ver bloques más grandes que 64 KB, al menos que este diseñado para trabajar a 32 bits. El compilador de Borland C+ + nos permite crear programas a 16 bits para Windows 3.1 y proporciona todos los recursos, rxzón por la cual centraremos nuestra atención en este tipo de aplicaciones.
Estructura de un programa para Windows.
Windows nos proporciona en el modo protegido una multitarea siempre y cuando, todas las aplicaciones cooperen para esto, con lo cual determinan una manera de proceder que se describe a continuación.
1. El programa ejecuta un modulo principal con los siguientes pasos.
Definir la clase de programa que se desea ejecutar, en la cual se especifica su icono, su cursor de ratón, su menú entre otras.
Registrar la clase de programa definida.
Crear la ventana principal.
Mostrar y actualizar la ventana principal.
Generar un ciclo que consi:;te en:
I. Pedir un mensaje a Windows.
11. Trasladarlo a la cola de mensajes del programa.
111. Despachar el mensaje.
2. El programa contiene una función que administra los mensajes, la cual se define cuando se registra la clase de programa. Esta función, es básicamente
65
Administrador de Redes SNMP
una serie de casos que determina que función llamar dependiendo del mensaje que recibe.
La multitarea de Windows
La forma en que Windows realiza su multitarea es exigiendo a un programa que este le regrese el control cada vez que sea posible, 10 cual se logra al pedir un mensaje, trasladarlo y despacharlo. En cada uno de estos puntos, Windows recibe el control, además de tomarlo cada vez que se presenta una interrupción en el sistema.
Para que esto funcione de manera adecuada, Windows nos proporciona una serie de mensajes, los cuales se acompañan de parámetros con valores que nos permitan determinar que ha sucedido. De manera adicional nos proporciona recursos gráficos (GUI, Interfaz Gráfica de Usuario) para desarrollar aplicaciones de manera rápida y sencilla, sin que nos preocupemos del código que se necesita para tal efecto.
Hasta este momento solo queda un problema por resolver, ¿Cómo hace Windows para ejecutar programas basados en MSDOS sin que le afecte SU
multitarea? Esto no es sencillo, pero para ello proporciona maquinas virtudes, las cuales funcionan de manera diferente según si se esta ejecutando en el modo extendido del 80386 o en el modo normal. De cualquier forma una maquina virtual, puede gestionar el modo protegido y ayudar a realizar la multitarea de Windows dándole el control cada vez que pueda.
Los archivos DLL de Windows.
Dado que las ventanas, los menús los mapas de bits, lo iconos, las barras de desplazamiento y en general, todos los controles propios de Windows, son finalmente código maquina y son utilizados por cualquier aplicación Windows, no tiene caso que cada programa cree su propio código, ni que en tiempo de ejecución este forme parte del mismo. De la misma manera existe otro código no tan obvio que tiene las mismas características y que por tanto, puede formar parte de bibliotecas de funciones que puedan cargarse y descargarse según se necesite, que además no formen parte del código del programa y que varios programas puedan accesarlas sin que entren en conflicto.
Windows proporciona este tipo de bibliotecas de funciones a las que llama bibliotecas de enlace dinámico, precisamente por poder cargarlas y descargarlas, así como por dar acceso a cualquier aplicación a las mismas mediante un protocolo. Las bibliotecas de enlace dinámico (DLL), son programas como aplicaciones finalmente, las cuales tienen una estructura similar a las aplicaciones normales de Windows, solo que no contienen una ventana.
66
Descripción del proyecto
Las bibliotecas más comunes de este tipo son las encargadas de los cuadros de diálogo que gestionan Archivos, las de impresión y las de recursos como la red. Cabe destacar, en este proyecto, el uso de la biblioteca dinámica Winsock la cual se dedica gestionar el protocolo de comunicación TCPAP.
Los dispositivos de contexto
Para poder tener control de las ventanas y su contenido, Windows proporciona un recurso al que se le llama dispositivo de contexto, el cual se encarga de identificar cada objeto o región que forma parte de la ventana. Estos dispositivos sirven para escribir en ellos, dibujar figuras y mapas de bits entre otras cosas.
Cuando es necesario dibujar una ventana, se genera un mensaje, y uno debe crear estos dispositivos y tener mucho cuidado de destruirlos una vez que han sido utilizados.
ESTRUCTURA El proyecto se ha dividido en cuatro bloques, y proponemos usar en la
medida de lo posible la programación orientada a objetos (POO), usando el compilador de Borland C + + versión 3.1. A esta programación se le conoce como híbrida.
Los bloques en que hemos dividido el programa son: +?+ Comunicación TCP/II’. O Codificación en BER para uso del protocolo SNMP. +?+ Proceso de Administracitjn en SNMP. 9 Ambiente gráfico.
Comunicación TCP/IP
Para la implementación de la comunicación en la red se utiliza la biblioteca de enlace dinámico (DLL) Winsok.dl1, la cual nos proporciona el acceso a los protocolos TCPAP. Esta biblioteca es proporcionada por varias aplicaciones comerciales como es Pathway.
Toda la colección de archivos necesarios para programar usando Winsock.dl1 se encuentra en la versión de Borland C+ + 4.5 y esta compuesta por:
Winsock.dll Biblioteca de enlace dinámico utilizada en tiempo de ejecución. Wins0ck.h Encabezado en ANSI 12 para producir aplicaciones Windows que
utilicen la biblioteca Winsock.dl1 versión 1.1. Winsock.lib Biblioteca de funciones para que el compilador de Borland
67
Administrador de Redes SNMP
proporcione manejadores automáticos de Winsock.dl1. Winsock.hlp Ayuda para el programador del Winsock.dl1 en C
Esta colección puede ser utilizada con el compilador Borland C+ + 3.1 realizando solo una modificación que consiste en ejecutar el programa Implib.exe proporcionado por la versión 3.1 de Borland, para generar un nuevo archivo Winsock.lib a partir de Winsock.dl1 el cual será compatible con el compilador.
La desventaja inmediata de el uso de ésta colección, es que rompe por completo con la programación orientada a objetos (POO), sin embargo éste problema no es representativo en el desarrollo del código, ya que el lenguaje de programación C + + no es un lenguaje cien por ciento orientado a objetos y uno de los problemas más típicos es el manejo de las bibliotecas dinámicas en Windows, el cual no está orientado a objetos. Esto origina que el manejo de Bibliotecas Dinámicas en nuestra aplicación, sea no orientado a objetos; sin embargo, si encapsulamos (encriptamos en términos de POO) este problema queda oculto en nuestro código y tenemos sintaxis de C + +.
Codificación en BER para uso del protocolo SNMP.
Al estar basado en el protocolo SNMP versión 1, se requiere una biblioteca que implemente este protocolo, la cual se programó en un conjunto de dos archivos BER.h y BER.cpp, los cuales se analizarán más tarde. El nombre se deriva a partir de la idea de implementar una biblioteca de funciones que codifica en BER estructuras basadas en módulos ASN.l sin tomar como fuente un módulo ASN.l que realice esta codificación, ya que ASN.l no permite el manejo de estructuras de control (si ... entonces, repite .. hasta, haz mientras ... etc..) ni permite sentencias imperativas, sino más bien solo define en forma abstracta tipos de datos. BER en cambio, es en forma concreta un dato definido en ASN.l el cual toma valores y solo valores, y es esta la utilidad de dicha biblioteca, solo proporcionar las estructuras como objetos de datos definidos en ASN. 1 y aplicarlos al protocolo SNMP.
Proceso de administración en SNMP.
Este proceso consiste precisamente en estar enviando y recibiendo los mensajes SNMP a cada Servidor (agente) que se desee, resolviendo los problemas de como pedir una tabla completa. Este proceso debe realizarse considerando la forma en que opera Windows como sistema operativo, ya que este administra procesos en forma concurrente y se basa en el manejo de mensajes. Sobre este punto se hablará en forma extensa mas adelante.
68
Descripción del proyecto
Ambiente gráfico.
Es obvio que al estar programando sobre Windows 3.1, ya contamos con una interfaz gráfica de usuario (GUI), pero es importante señalar que, con el afán de respetar la P O 0 utilizamos la biblioteca de funciones OWL versión 1.0 proporcionada por el compilador IBorland C + + 3.1.
Uso del Winsock.dl1
El soporte para sockets bajo Windows, es conocido coloquialmente como WinSock, esta aplicación fue desarrollada con el objetivo de estandarizar el protocolo TCP/IP bajo Windows.
Muchas interfaces han sido programadas para redes basadas en el modelo TCP/IP. La interfaz mas extendida es la desarrollada por la Universidad de California (Berkeley) como una extensión para el sistema operativo Unix. Comúnmente esta versión de 1Jnix es conocida como Berkeley Software Distribution (BSD - Distribución de Software de Berkeley -) . La versión de Sockets para Windows esta desarrollada en base a los sockets de BSD versión 4.3.
El creciente desarrollo de las redes locales y su integración a través de la red de redes, ha impulsado el diseño de programas que proporcionen el protocolo TCP/IP en plataformas como MS-DOS y Windows (tanto a 16 bits como a 32 bits). Usando los sockets
Un socket es un objeto abstracto en la comunicación, el cual tiene como función conectar a un canal lógico o virtual de la red. Recibe el nombre de socket en virtud de que se parece lógicamente a la terminal con la cual nos enroscamos para alimentar un foco u otro equipo que requiera sockets en vez de clavijas o conectores.
Para establecer una conexión en un canal virtual, se solicita un socket a la función socket(), definida en el archivo de encabezado Wins0ck.h de la manera siguiente:
SOCKET WINAPI socket (int af, int type, int protocol) ;
En donde af es la familia de direcciones, que en este caso solo es soportado el valor PF-INET el cual es designado para la familia TCPAP. type indica el tipo de servicio que se soporta, que puede ser por circuito virtual o por datagramas con valores SOCK - STRAM y SOCK-DGRAM respectivamente. Mientras que protocolo es en general ignorado, aunque se recomienda pasar como cero.
69
Administrador de Redes SNMP
Una vez que se obtenido un socket, este puede ser utilizado. Para los propósitos de esta aplicación, solo se usan dos funciones básicas que son recvfrom y sento, las cuales están definidas de la siguiente forma:
int PASCAL FAR recvfrom (SOCKET S, char FAR “r buf, int len, int flags,
int PASCAL FAR sendto (SOCKET S, const char FAR ’’ buf, int len, int struct sockaddr FAR ‘$from, int FAR fromlen);
flags,const struct sockaddr FAR ‘“to, int tolen); En donde para ambos casos S es el socket por el cual se establece la
comunicación, buf es un apuntador al área en donde debe estar la información, ya sea la que va o la que viene, len indica el tamaño del buffer y flags son banderas de estado que usualmente valen cero. La estructura sockaddr sirve para determinar la dirección IP, ya sea de origen o destino según si es recvfrom o sendto, y para terminar se pasa un apuntador a entero para que se nos informe el tamafio de la estructura o bien pasamos nosotros el tamaño de la estructura, otra vez, depende de si es recvfrom o sendto.
Después de haber utilizado el socket y antes de terminar la sesión, debe cerrarse el socket con la función closesocket que recibe como parámetro el socket que se desea cerrar.
Winsock proporciona otras funciones al estilo Windows, conocidas como extensiones para Sockets Asíncronos de Windows y comienzan con el prefijo WSA (Windows Sockets Asyncronous) dos de estas funciones son necesarias, sirven para la iniciación y terminación de estas funciones asíncronas.
WSAStartup.- Esta función se utiliza para inicializar las funciones asíncronas de Windows. Recibe como parámetros la versión de Winsock que se requiere y un apuntador a una estructura, en la cual se ha de colocar información correspondiente al archivo Winsock.dl1 que se está ejecutando actualmente. Esta estructura regresa la versión mas cercana que puede emular a la que uno solicita, esto se debe a que existen diferentes Winsock en el mercado y, las versiones no son todas compatibles unas con otras, lo que ha llevado a desarrollar un convenio, que consiste en que uno solicita la versión que desea, si esta se soporta, entonces se regresa un valor diferente de cero, en caso contrario se regresa cero y en la estructura se coloca la versión mas cercana a la que se solicito; esto con el fin de que s i el programa soporta varias versiones, pueda ejecutarse. Se regresa información también del rango de versiones que se soporta.
WSAC1eanup.- Esta función se utiliza para terminar las funciones asíncronas de Windows. Se llama sin parámetros al final de la aplicación.
70
Descripción del proyecto
Por último, usamos la función WSAAsybcSelect, esta función sirve para enviar mensajes ha la aplicación, cuando ocurre un evento para el socket que recibe como parámetro. Recibe primero el socket, luego el manejador de la ventana de aplicación, luego el mensaje que ha de enviarse a dicha ventana y por último una bandera para indicar cuando se ha de enviar el mensaje a la ventana. Esta bandera se describe en la siguiente tabla :
Códi o
FD-READ FD WRITE FD OOB
FD ACCEPT FD-CONNECT
FD CLOSE
- Significado
Hay un dato 1.isto para ser leído El socket está listo para enviar datos Urge leer datos para vaciar el buffer (“OUT OF BAND) Se solicita una conexión (un cliente la solicita) Se completó una conexión a un servidor (uno es el cliente) Se cerro el socket
Tabla 14 Banderas para enviar mensaje del estado del socket
Implementación de BER.h y BER.cpp
La implementación de esta biblioteca de funciones, está orientada a objetos y consta de dos archivos BER.h como encabezado y BER.cpp como la implementación de las clases.
El encabezado BER.h comienza con las directivas de compilación : #ifndef YA SE DEFINIO-BER- #define YA-SE-DEFINIOBER-
y termina con la directiva - - -
Bendif las cuales tienen como propósito evitar múltiples declaraciones de los objetos en un archivo.
También se define el tipo BOOL de la misma forma que lo hace Wind0ws.h u 0WL.h con el objetivo de no depender de Windows y de proporcionar un alto nivel de programación. Se añaden las macros FALSE y TRUE para ser consistentes con el tipo BOOL.
En el archivo Tarnañ0s.h se encuentran algunas macros que definen los tamaños de algunos datos que seritn de utilidad en la implementación de la biblioteca, así como macros auxiliarmes en la programación de BER.cpp.
Dado que un valor en BER esth codificado por octetos que forman muchas veces enteros sin signo que pueden ser n x 8 bits con n en los enteros y mayor que uno. Se definen tres tipos de datos importantes que son TByte, TWord,
71
Administrador de Redes SNMP
TDWord, que representan enteros sin signo de 8 16 y 32 bits. Se define también una estructura (TTag) en forma de unión para el manejo de la codificación de datos etiquetados en ASN.l, la cual consta de un byte con el código siguiente:
Figura 34 El tipo TDWord
en donde la C codifica la clase a la que pertenece la etiqueta, la F indica si requiere constructor o no y E es un identificador de la etiqueta.
Para tener mayor control sobre los entero sin signo se codifican en un doble word (32 bits) y se declara la unión TEnteroSinSigno que permite romper en cuatro bytes o dos words.
Se definen las funciones Dump y BinHex al estilo tradicional de C. Dump sirve para ver un vaciado hexadecimal de una lista de datos binarios, los cuales sirven para analizar en tiempo de programación los valores que se han de enviar y los que se reciben.
La función BinHex convierte un byte a una cadena de representación hexadecimal y forma parte de un módulo de la función Dump. Clase TetiquetaASN
Un variable de un tipo de dato definido en ASN.l, es codificada mediante tres campos, donde el primero es precisamente una etiqueta que está formada por tres partes ya conocidas. La clase nos proporciona el alcance del tipo de dato, el constructor es un bit de bandera que indica si el tipo es simple o compuesto, y finalmente el número de etiqueta es un identificador Único para el tipo de dato que se esta especificando.
Cuando esta etiqueta se codifica en BER, puede requerir un byte, en cuyo caso el número identificación es estrictamente menor que 32. O bien, puede ser necesario tomar más bytes, para lo cual se utiliza el atributo Entero, ya que el número de identificación es mayor a 32. Ante esta problemática, este número de identificación no puede crecer en forma indefinida y es necesario limitarlo. Considerando que una PC con procesador 80386 o superior (hasta PENTIUM) maneja con gran tranquilidad entero de 32 bits, se limita el identificador a ser un Entero sin signo (32 bits).
72
Descripción del proyecto
Esta clase requiere solo un constructor que nos permita definir las tres propiedades básicas de una etiqueta, el cual solo tiene que tomar los valores adecuados para producir posteriormente el código BER correspondiente. Obviamente requiere también un método que genere este código y un método que nos proporcione la lectura hexadecimal del mismo.
Como complemento adicional se programó un método que nos indica el tamaño del código BER en bytes.
Clase TLongitudASN
El segundo campo con que se codifica una variable de tipo definido en ASN.l es la longitud en bytes que se requieren para portar su valor, y es precisamente el objetivo de esta clase. Nuevamente es necesario limitar el tamaño de dicho valor y se restringe a 32 bits con el atributo Longitud, y de manera adicional el atributo tam nos indica el tamaño en bytes necesario para codificar este campo.
El constructor de esta clase solo requiere el valor de este campo. Los métodos CodigoBin y CodigoHex sirven para codificar en binario y en hexadecimal a dicho campo.
Clase TTipo
Esta clase es genérica, en virtud de que cualquier variable en el dominio de ASN.1contiene los tres campos (Etiqueta, Longitud y Valor), en donde solo el valor opera de manera diferente, mientras que los otros dos solo cambian en los valores que se pueden tomar, esta clase puede proporcionarnos las características comunes a cualquier variable de cualquier tipo en ASN.l, y nos ahorra código.
La codificación en binario es variable entre los tipos de datos, pero una vez que se tiene, su representación hexadecimal sigue el mismo algoritmo, razón por la cual el método CodigoBin es virtual y abstracto, mientras que el método CodigoHex es común a todos.
Clase TNULL
El tipo de dato más simple que se define en ASN.l es N U L L , el cual no contiene valor en ninguna variable derivada de este tipo y su valor siempre es el mismo. Sin embargo este tipo sirve para indicar fin de listas en tipos de datos compuestos y por ello es de vital importancia.
El método CodigoBin regresa siempre la misma cadena y el método Valorsintaxis que sirve para tener una representación en alto nivel de abstracción a las variables de este tipo, también regresa una valor constante.
73
Administrador de Redes SNMP
Clase TEntero
Esta clase es derivada de TTipo, y tiene como objetivo proporcionar las características de las variables de tipo Integer definidas en ASN.l , para lo cual cuenta con su atributo valor, el cual contiene un entero de 32 bits, que limita a estas variable. La razón de limitar a 32 bits la mayoría de los valores en este programa es la facilidad de programación de los mismos en una PC.
El constructor de esta clase determina cuantos bytes se requieren para codificar el valor de una variable de este tipo, que será utilizado posteriormente en el método CodigoBin para su mejor codificación. Se requiere otro constructor, el cual debe crear una variable de este tipo mediante el código binario que usualmente se obtiene de una lectura de la red. Este contiene los tres campos que se han de descomponer en orden para obtener la información correspondiente.
El método Valorsintaxis proporciona el valor en alto nivel de abstracción para ser presentado al usuario.
Clase TCadena
Esta clase determina las características del tipo String de ASN.l , la cual también es derivada de TTipo y contiene dos constructores. Se usa un parámetro extra en un constructor para distinguirlo del otro, ya que los tipos de datos utilizados son exactamente los mismos.
CZase TIdObj
Esta clase contiene la ruta en el árbol MIB de un objeto de administración. La sintaxis con que debe de suministrarse a su constructor es por una secuencia de números separada por espacios o tabuladores en vez de puntos como se acostumbra, la sintaxis en alto nivel pone los puntos en forma automática para presentarlos y es responsabilidad de la aplicación buscar su nombre en alto nivel de abstracción mediante una estructura definida para este caso. Clases derivadas (TDireccionIP, TContador, TMedidor, TTicksReloj, TComodin)
Todas estas clase son derivadas de los tipos básicos ya definidos, cambian solo su representación en alto nivel de abstracción.
TDireccionIP es por ejemplo derivada de TCadena, contiene siempre cuatro bytes que se representan por una secuencia de números decimales separadas por un punto.
TContador, TMedidor y TTicksReloj son derivadas de TEntero, su utilidad es puramente abstracta, pero se representan en forma diferente.
74
.. .
Descripción del proyecto
TComodin funciona como un buffer, el cual esta basado en la clase TCadena. N o tiene una representación definida y se incluye sólo por que en el protocolo SNMP puede aparecer un valor de este tipo.
Estas clases fundamentalmente hacen una llamada al constructor del cual se derivan y sólo tienen que cambiar su etiqueta, por lo demás son tratados como sus clases principales.
Clase TVarBind
E n el protocolo se envían mensajes a través de la red, los cuales contienen una lista de variables por las que pregunta o responde. Para este fin es necesario definir la estructura de una variable, la cual esta formada por un identificador de variable y su contenido, el cual es NULL cuando se desconoce (cuando se pregunta por ejemplo). Esta estruc:tura la define el tipo VarBind de ASN.l y le corresponde a esta clase codificarlo.
Clases TVarBindNodo y TVarBindList
Una vez que se tiene la estructura de una variable es necesario tener una lista de las mismas. La función de estas dos clases corresponde a esta necesidad. Mientras TVarBindNodo proporciona la lista de la variable, TVarBindList proporciona la etiqueta y longitud que se requieren para este dato compuesto que se ha de transmitir.
Clase TPDU
Esta clase contiene la estructura del mensaje que se ha de enviar para una petición en SNMP versión 1. No le corresponde de manera explícita a este tipo definir si se trata de una petición 40 de una respuesta, pero sienta la base para esto, ya que la diferencia consiste en una etiqueta.
Clases TGetRequest-PDU, TGetNextRequest PDU, TGetResponse-PDU y TSetRequestPDU.
-
Estas cuatro clases determinan la petición, son derivadas todas de T P D U y sólo cambia su etiqueta, por lo que se llama el constructor de su clase principal y se procede a destruir su etiqueta para ser remplazada. Aunque sólo se ocupan dos, las otras se incluyen para tener el conjunto completo. Clase TMensajeSNMP
Finalmente se puede construir el mensaje que ha de ser transportado a través de la red, y precisamente es a esta clase a quién le corresponde crear dicho mensale.
75
Administrador de Redes SNMP
Implementación del proceso de administración
La naturaleza del problema, como la plataforma utilizada nos impone definir de manera precisa como debe de funcionar la administración.
Proponemos primero dividir en grupos de variables y grupos de columnas o tablas a la información que deseamos obtener. Para ello se plantean dos algoritmos.
Obtener variables
1. Obtener el grupo
2. Obtener la lista de variables
3 . Obtener la primera variable
4. Para un conjunto de seis variables a lo más obtener un mensaje
5. Enviar el mensaje a través de la red
Enviar el mensaje por la red
Enviar un mensaje al controlador de la red para que avise cuando se recibe mensajes de la red.
Cuando se recibe el mensaje enviarnos un mensaje Windows para recibir respuesta
6. Esperar a recibir el mensaje de respuesta
7. Si hay más variables regresar al paso 4
¿Hay mas variables?
I. Si, Enviar un mensaje de enviar mensajes
11. No, Enviar mensaje de ver resultados
Regresar al paso 4
Obtener Tablas
1. Obtener el grupo
2. Obtener la lista de columnas
3. Obtener la primera columna
4. Enviar el requerimiento del primer valor de la columna
76
Descripción del proyecto
Enviar un mensaje SNMP GetNextRequest(co1umna)
Enviar un mensaje Windo,ws de esperar respuesta
5. Recibir respuesta
<Corresponde a la columna que yo solicito?
I. Si, Enviar un mensaje SNMP GetNextRequest(Dat-o recibido), ir al paso 5
<Hay más columnas?
I. Si, Enviar un mensaje SNMP GetNextRequest(Columna), ir al paso 5
6. Enviar un mensaje Windows de mostrar resultado Codificación de la administración.
Esta tarea corresponde a la solicitud de leer un grupo, por lo que se ubica en el diálogo de grupos.
Para cumplir con esta tarea! este diálogo contiene ocho métodos que administran ocho mensajes Windows.
Método PedirInformación Pedirvariables Recibirvariables PedirTabla RecibirTabla CrearInformación VerTabla CerrarTabla
Mensaje ID PREGUNTAR
WM PEDIR VARIABLES
WM-RECIBIR-VARIABLES
WM - PEDIR TABLA
WM - RECIBIR-TABLA
ID - CREAR-INFORMACIóN
"M-VER-TABLA
WM - CERRAR-TABLA
-
- -
-
Método PedirInformación
Este método es llamado cuando ya se ha seleccionado un grupo y se desea pedir información a una terminal. La forma de proceder es sencilla, ya que solo se hace la pregunta ¿Este grupo corresponde a variables independientes o a una tabla?. Se concluye con la solicitud de lectura de variables o tablas según el caso. void TDialogoGrupos::PedirInformacion(TMessage &)
char NombreGrupo[ 1001; I
Destruye(DatosDialogoVariab1es.Lista);
77
Administrador de Redes SNMP
for (int i =O;i < IOO;Secuencias[i+ +]=O);//No hay secuencias de datos que estemos esperando Grupo- > GetText(NombreGrupo,lOO);//Obtenemos el nombre del grupo strcpy(NombreGrupoProceso,NombreGrupo); if (Mib.PrimerVariableGrupo(NombreGrupo))//¿Son variables?
variables, enviar mensaje de pedir variables else if (Mib.PrimerColumnaGrupo(NombreGrupo))//¿Son tablas?
mensaje de pedir tabla
PostMessage(HWindow,WM-PEDIR-VARIIABLES,O,OL);//Si son
PostMessage(HWindow,WM-PEDIR-TABLA,O,OL);//Son tablas, enviar
1
Método Pedirvariables
Este método se llama cuando ya se determino que hay que pedir variables, en cuyo caso se recibe como parámetro un cero que indica que es necesario crear la lista de variables que corresponde a este grupo y que será utilizada para enviar por la red en los pasos que sean necesarios. Cuando se recibe un uno se indica que la lista se ha creado y que sólo hay que enviar un grupo de a los más seis variables. Se crea una segunda lista con estas variables y si se tiene éxito, se crea un mensaje SNMP con esta lista y se envía a través de la red. Se habilita la sesión de mensajes de Winsock para que este nos envíe una petición de recibir variables cuando se haya detectado un mensaje de regreso.
void TDialogoGrupos::PedirVariables(TMessage &M)
TByte NumVar = O; TVarBindList Lista= NULL; TListaIdObj '' VarAux; TMensajeSNMP ''. Mensaje; if (M.WParam= =())//¿Hay que pedir la primera variable del grupo?
char NombreGrupo[lOO]; TVariable *Variable=NULL;
{
{//Si, es la primera vez que se llama para esta consulta
Grupo->GetText(NombreGrupo,lOO);//Obtenemos el nombre del grupo
Variable=Mib.PrimerVariableGrupo(NombreGrupo);//Obtenemos la primera variable while (Variable! =NULL)
if (ListaVariablesEnviar)//<Esta creada la lista?
Descripción del proyecto
ListaVariablesEnviar- > Inserta(new TIdObj(Variab1e- >Ruta));/& inserta una nueva
else//NO ListaVariablesEnviar=new TListaIdObj(new TIdObj(Variab1e-
Variable = Variable- > Siguiente;//Recorro las variables >Ruta));//Crea la lista
I }
I
M.WParam= 1;//Idico que ya esta creada la lista
if (M.WParam= = I)//¿Puedo pedir la lista?
while ((ListaVariablesEnviar! =NULL)&&(NumVar < 6))//<Puedo inclui la siguiente?
{//Si
if (Lista)//¿Esta creada la lista? NumVar + +;//La culmto
{ Lista- > Inserta(ListaVariab1esEnviar- > Valor0,new
TNULL);//S', I Inserto '
I {
else//NO, creo
Lista=new TVarBindList(ListaVariab1esEnviar- > Valor0,new TNULL);
I VarAux = ListaVariablesEnviar;
Destruye(VarAux); ListaVariablesEnviar = ListaVariablesEnviar- > Siguiente;
I I {//Si InsertarSecuenciasO;//Inserto una secuencia más Mensaje=new TMensajeSNMP(new TCadena(Comunity),//Creo el
if (Lista)//¿Hay una lista de variables para enviar?
mensaje SNMP new TGetNextRequest_PDU(new TEntero(Secuencia+ +),
new TEntero((TDWord) O), //Sin Error new TEntero((TDWord) O), Lista)
if (Secuencia= =O) );
79
Administrador de Redes SNMP
Secuencia+ +; char BufferEnviar[TAM-MAX-BUF]; int Tam = Mensaje-
> CodigoBin(BufferEnviar,TAM-MAXBUF);//Obtener el tamaño del mensaje
Direccionsin-family = PF-INET; Direccionsingort = htons(Puerto); if (!DatosDialogoVariables.Lista)
DatosDialogoVariables.Lista=new TListBoxData; //Enviar el mensaje atraves de la red sendto(Socket,BufferEnviar,Tam,O,(struct sockaddr far
MensajesSNMP + + ; //Se envió un mensaje más Destruye(Mensaje);//Destruimos el mensaje Lista=NULL;//Ya no hay lista
:$)&Direccion,sizeof(struct sockaddr-in));
Método Recibirvariables
Una vez que Winsock recibe un mensaje con nuestro socket, nos lo hace saber mediante un mensaje de recibir variables, ya que nosotros solo esperamos variables. Entonces recibimos la cadena binaria e intentamos crear un objeto de mensaje SNMP de repuesta, que al tener éxito, colocamos los valores obtenidos en una lista, la cual se ha de desplegar posteriormente.
Si ya no hay más variables que pedir, nos autoenviamos un mensaje para crear y mostrar la información que se ha recibido. Para terminar nos autoenviamos también otro mensaje para pedir más variables, en caso de ser necesario
void TDialogoGrupos::RecibirVariables(TMessage &) c char Buffer[TAM_MAX_BUF“2]; struct sockaddr-in Dir; int Taml,Tam2; TMensajeSNMP “Mensaje = NULL; TVariable “Variable=NULL;
PaquetesRecibidos+ +; //Se ha recibido un paquete más Tam1 =recvfrom(Socket,Buffer,TAM~MAX~BUF~‘2,0,(struct sockaddr
far “)&Dir,(int :‘)&Tam2);
80
Descripción del proyecto
if (Tam1= =-1)//¿Es correcto?
if @ir.sin - addr.s addr= =I>ireccion.sin-addr.s-addr) return;//NO, abortar el proceso
{ -
Mensaje = new TMensajeSNMP(&Buffer[ lU;//Obtener el mensaje SNMP if (ExisteSecuencia(Mensaje- > SecuenciaO))//¿Es de una secuencia esperada?
{//Si if (DatosDialogoVariables.Lista)//¿Existe la lista?
{//SI TVarBindList “Lista=Mensaje- > ListaO;//Obtenemos la lista
recibida
Variable=Mib.PrimerVslriableGrupo(NombreGrupoProceso);//Obt enemos la primera variable del grupo
while (Lista) {
if (Variable)//¿Hay variable? //Si, la agragamos para ser visualizada
DatosDialogoVariables.Lista- > AddString(FormatoVariables(Buffer,Lista- > Nombre- > Valor,Lista- > Valor- > ValorSintaxisO));
Lista= (TVarBindList ‘:-)Lista- > Siguiente;//Recorremos la lista 3
--MensajesSNMP;//Decrementamos el mensaje SNMP HayInformacion =FAISE;//No esta disponible la información
aún if (!ListaVariablesEnviar)//¿Hay que pedir más varibles?
PostMessage(HWindow,ID-CREAR-INFORMACION,O,OL);//N O, podemos mostrar la información
otro conjunto de variables PostMessage(HWindow,WM PEDIR VARIABLES,l,OL);//Pedir - -
} 1
Destruye(Mensaje);//De:;truir el mensaje SNMP obtenido }
1
81
Administrador de Redes SNMP
Método Crearlnformación
Una vez que ya se cuenta con todo, solo falta desplegar la información. Esto se logra con este método, el cual se protege para múltiples llamadas, ya que no puede estar creando diálogos sin control. Para ello ocupa una bandera. Los valores se transfieren al diálogo con la función TrasnferData.
void TDialogoGrupos::CrearInformacion(TMessage &) { if (!HayInformacion)//<Hay información activa?
( / /No HayInformacion = TRUE;//Indicar que ahora ya la hay Dialogo = new TDialogoVariables(this);//Crear el dialogo GetApplicationO- > ExecDialog(Dialogo);//Mostrarlo WSAAsyncSelect(Socket,HWindow,O,O);//Deshabilitar la comunicación
HayInformacion-FALSE;//Ya no hay información activa Dialogo =NULL;//Ya no hay diálogo
de la red
1 else if (Dialogo)//SI, ¿Hay diálogo?
I Dialogo- > TransferData(TF-SETDATA);//Solo transferimos
información I
}
Método pedirtabla
Este método se manda llamar cuando se ha determinado que el grupo contiene una tabla. Es parecido al proceso de pedir variables, solo que este no pide de seis en seis, sino de una en una, ya que puede recibir varios valores correspondientes a una columna, para ello se emplean mensaje GetNextRequest, los cuales nos regresan un vdor siguiente al que solicitamos y al compararlo podemos determinar si se trata de la misma columna o de una nueva.
También es necesario aquí ir definiendo los tamaños que hay que reservar para la presentación de estas columnas según el tipo de sintaxis que tenga.
void TDialogoGrupos::PedirTabla(TMessage &M) { TMensajeSNMP “Mensaje=NULL;
char BufferEnviar[TAM_MAX-BW];
82
Descripción del proyecto
int Tam; int longitud= 150;
switch (M.WParam) {
case O: //Hay que empezar con la tabla Destruye(Tab1aActual);
Columna=Mib.PrimerC:olumnaGrupo(NombreGrupoProceso);//O btener la primera columna
if (!Columna) break;//¿Hubo error? Si, abortar switch(Co1umna- :> Sintaxis)//Definir la longitud dependiendo
de la sintaxis I case DireccionFisica:
longitud= 200; break;
case DireccionIP: longitud= 150;
break;
longitud= :LOO; break;
case Entero32:
case Tiempo: longitud=300;
break; 1
if (TablaActual)//<Ya esta creada la tabla? TablaActual- > InsertaSiguiente(Co1umna-
>Nombre,longitud);//Si, insertamos elemento else TablaActual= new TTabla(Co1umna-
> Nombre,longitud);//No, la creamos case l://Hay que continuar
InsertarSecuenciasO;//insertamos la secuencia Mensaje= new TMt:nsajeSNMP(new
TCadena(Comunity),//Creamos el mensaje SNMP new TGetNextRequestPDU(new TEntero(Secuencia+ +),
new TEntero((TDWord) O), //Sin Error new TEntero((TDWord) O), new TVarBindList(new TIdObj (Columna-
> Ruta),new TNULL))
83
Administrador de Redes SNMP
1; if (Secuencia= =O) Secuencia+ t-; Tam = Mensaje-
> CodigoBin(BufferEnviar,TA"AX_BUF);//Obtenemos el código binario y su tamaño
Direccion.sin family = PF-INET; Direccion.sinqort = htons(Puert0);
sendto(Socket,BufferEnviar,Tam,O,(struct sockaddr far
MensajesSNMP + + ; Destruye(Mensaje);
-
//lo enviamos por la red
;t)&Direccion,sizeof(struct sockaddr-in));
WSAAsyncSelect(Socket,HWindow,WM-RECIBIR_TABLA,FD_R EAD);//Idicamos que reciba información
case 2://Verificar si hay otra columna break;
char far '>ObjetoAnterior= (char far '.')M.LParam; if (MismaColumna(ObjetoAnterior,Columna- > Ruta))//<Es la
misma columna? {//Si InsertarSecuenciasO;
Mensaje= new TMensajeSNMP(new TCadena(Comunity), //Crear el mensaje SNMP
new TGetNextRequest-PDU(new TEntero(Secuencia+ +), new TEntero((TDW0rd) O), new TEntero((TDWord) O), new TVarBindList(new
TIdObj(ObjetoAnterior),new TNULL)) );
if (Secuencia = =O) Secuencia + + ; char BufferEnviadTAM-MAX-BUF];
int Tam=Mensaje- > CodigoBin(BufferEnviar,TA"AX_BUF);
Direcciomsin-family = PF-INET; Direccion.sinqort = htons(Puert0);
//Obtener el binario del mensaje y su tamaño
//Enviarlo por la red
84
Descripción del proyecto
sendto(Socket,BufferEnviar,Tam,O,(struct sockaddr far
MensajesSNMPi- +; Destruye(Mensaje);
")&Direccion,sizeof(struct sockaddr-in));
//Idicar que hay que recibir el resultado
WSAAsyncSelect(Socket,HWindow,MM RECIBIR TABLA,FD-R E D ) ;
- -
}
{ else//NO es la misma columna
if (Columna)//hay más columnas
Columna=Colunma- > Siguiente;//Continuar con la que
if (Columna)
i
sigue
PostMessage(HWindow,WM-PEDIR-TABLA,3,OL);//Pedir una nueva columna
else
PostMessage(HWindow,WM-VER - TABLA,O,OL);//Continuar con la misma columna
} 1
break; case 3://Otra columna
if (Colurnna)//Hay columna switch(Co1umna- > Sintaxis)
case DireccionFisica: longitud=2OO;
break; case DireccionIP:
break;
longitud= 1\30; break;
longitud= 150;
case Entero32:
case Tiempo: longitud=3OO;
85
Administrador de Redes SNMP
break;
if (Columna) if (TablaActual)
> NombreJongitud);
1
TablaActual- > InsertaSiguiente(Co1umna-
else
InserrarSecuenciasO; Mensaje=new TMensajeSNMP(new TCadena(Comunity),
new TEntero((TDWord) O), //Sin Error new TEntero((TDWord) O), new TVarBindList(new TIdObj(Co1umna-
TablaActual= new TTabla(Co1umna- > NombreJongitud);
new TGetNextRequest-PDU(new TEntero(Secuencia+ +),
> Ruta),new TNULL)) >;
if (Secuencia= =O) Secuencia + + ; Tam= Mensaje- > CodigoBin(BufferEnviar,TAM-MAX-BUF); Direccionsin-family = PF-INET; Direccion.sing0r-t = htons(l?uerto); sendto(Socket,BufferEnviar,Tam,O,(struct sockaddr far
MensajesSNMP + + ; Destruyewensaje);
)&Direccion,sizeof(struct sockaddr-in));
WSAAsyncSelect(Socket,HWindow,WM_RCIBIR_TABLA,FD_R EAD);
break; 1
} Al terminar de enviar este mensaje pedimos a Winsock que nos comunique
cuando hemos de recibir el valor solicitado, usando el mensaje de recibir tabla
Otros valores que determinan el comportamiento de este método sirven para indicar que se ha de solicitar un valor de una nueva columna. Este método es también el encargado de autoenviar un mensaje de ver tabla cuando se ha concluido el proceso.
Las acciones a realizar en este método dependen del valor del parámetro y se resumen a continuación.
86
Descripción del proyecto
I . Comienza con la obtención de tablas
2. Enviar un mensaje con solicitud por el valor de una celda de una columna
Obtener la celda anterior
Crear el mensaje SNMP
Enviar el mensaje SNMP
Pedir a Winsock que nos avise cuando se reciba la respuesta.
3. Tratar de obtener más celdas
4.
Si la ultima celda recibida corresponde a esta columna
I. Crear un mensaje SNMP solicitando la siguiente celda para esta columna
11. Enviar el mensaje SNMP por la red
111. Pedir a Winsock que nos avise cuando se reciba la respuesta.
No es de esta columna, pero hay más columnas
I. Enviar un mensaje para solicitar una nueva columna
Ya no hay más columnas
I. Enviar un mensaje para mostrar la tabla
Solicitar el valor de la primera celda de la siguiente columna.
Método RecibirTabla
Este otro método sólo recibe el valor de una celda de la tabla, lo guarda en lista y se envía un mensaje de pedir tabla para que se continúe el proceso.
void TDialogoGrupos::RecibirTabla(TMessage &)
static char Buffer[TAM_MAX_BUF"2]; struct sockaddr-in Dir; int Taml,Tam2; TMensajeSNMP '>Mensaje=NULL;
{
PaquetesRecibidos+ +; //Recibir el mensaje SNMP' Tam1 =recvfrom(Socket,Buffer,TAM~MAX~BUF~~2,0,(struct sockaddr
if (Taml= =-I)//<Todo bien? return;//No, abortar
f ar :,- *)&Dir,(int :>)&Tam2);
87
Administrador de Redes SNMP
if (Dir.sin-addr.s addr= =Direccion.sin addr.s-addr)
Mensaje = new TMensajeSNMP(&Buffer[ 1J; if (!Mensaje)
return; strcpy(Buffer,Mensaje- >Lista()- >Nombre- > ValorSintaxisO); if (ExisteSecuencia(Mensaje- > Secuencia()))
I - -
{ if (Columna) if (MismaColumna(Buffer,Columna- >Ruta))
{ int longitud= 150; strcpy(Buffer,Mensaje- > Listao- >Valor- > ValorSintaxisO); switch(Co1umna- > Sintaxis)
c case DireccionFisica:
longitud=2OO;
break; case DireccionIP:
longitud= 150; break;
longitud= 100; break;
longitud= 300; break;
ConvierteDireccionFisica(Buffer);
case Entero32:
case Tiempo:
1 if (TablaActual)
else TablaActual- > InsertaCadena(Buffer);
TablaActual= new TTabla(Buffer,longitud); 1
strcpy(Buffer,Mensaje- > Listao- > Nombre- >Valor);
PostMessage(HWindow,WM_PEDIR_TABLA,2,(DWORD)((void far “)&Buffer));
Destruye(Mensaje); }
1
88
Descripción del proyecto
Método ver tabla
Este sencillo método, crea una ventana con la tabla y la presenta. Es llamado al terminar de recibir valores de tabla.
void TDialogoGrupos::VerTabla(TMessage &) { if (!Tabla)//¿Hay tabla?
{//No hay tabla Tabla= new TVentanaTabla(this);//Creamos la tabla GetApplicationO- > MakeWindow(Tabla);//Crear la ventana ShowWindow(Tab1a- > HWindow,SW-SHOW);//Mostrar la ventana 1
3 El ambiente gráfico
Como se trata de una ap1ic:ación Windows, que trabaja con redes, es necesario poder dibujar una red en la ventana. Para ello se declaran las clases TBitMap y TGraficaBitMap, las cuales se encargan de poder dibujar la red en la ventana.
El contexto en que se realiza 'el programa requiere auxiliarse de otras clases para poder realizar todas sus funciones.
La clase TVariable se encarga de almacenar la ruta MIB de una variable, su nombre en alto nivel y su sintaxis. Esta clase es la base de la clase TDefinicionGrupos ya que esta crea listas de variables como variables independientes o como columnas de tablas para poder llevar a cabo el proceso de administración.
L a clase TDefinicionGrupos proporciona los grupos que son leídos de un archivo que contiene la MIB bajo 1.a siguiente sintaxis:
1. Grupo <nombre del grupo > Indica que comienza la definición de un grupo.
<nombre del grupo> Es el nombre con que ha de aparecer en el cuadro de diálogo destinado para ello.
2. Variable < nombre > <ruta:> ; < sintaxis > Indica que se está definiendo una variable
89
Administrador de Redes SNMP
<nombre> Indica el nombre con que ha de aparecer cuando se presente el cuadro de diálogo con la información recibida.
<ruta> Es la ruta del objeto en el árbol MIB que identifica a la variable
<sintaxis > Es un valor opcional que indica como deben presentarse los datos en caso de que no este bien definido en ASN.l. Los valores que puede tomar son:
I. Entero32 que indica que es un entero de 32 bits
11. DirecciónFísica que indica que se trata de una dirección física.
111. Tiempo que indica que son ticks de reloj y se descompone en días, horas, minutos, segundos y más.
IV. DirecciónIP que indica que se trata de una dirección IP.
3. Columna < nombre > < ruta> ; <sintaxis > Indica que se está definiendo una variable
<nombre > Indica el nombre con que ha de aparecer cuando se presente el cuadro de diálogo con la información recibida.
<ruta> Es la ruta del objeto en el árbol MIB que identifica a la variable
<sintaxis> Es un valor opcional que indica como deben presentarse los datos en caso de que no este bien definido en ASN.l. Los valores que puede tomar son:
I. Entero32 que indica que es un entero de 32 bits
11. DirecciónFísica que indica que se trata de una dirección física.
111. Tiempo que indica que son ticks de reloj y se descompone en días, horas, minutos, segundos y más.
IV. DirecciónIP que indica que se trata de una dirección IP.
La clase TListaIdObj sirve para tener una lista de variables en la MIB por la cual se ha de preguntar y es un complemento para la administración de la red. La clase TListaCadena tiene como finalidad apoyar también a los métodos para presentar valores en ventanas.
Existen otras clase que definen los diálogos y ventanas que aparecen a lo largo del programa, que forman parte sólo de requisitos al programar en
90
Descripción del proyecto
Windows y los comentarios no obedecen al protocolo SNMP que es de lo que trata el proyecto, por lo que se omiten los comentarios al respecto.
91
Administrador de Redes SNMP
CONCLUSIONES Como resultado final hemos obtenido un Administrador de Redes SNMP
que se ejecuta en redes TCP/IP. A lo largo del desarrollo hemos alcanzado nuestros objetivos poco a poco, siendo lo mas sobresaliente la implementación de una Biblioteca de Funciones Orientada a Objetos, que codifica mensajes SNMP en BER de manera independiente del sistema operativo EN QUE SE TRABAJE. Es decir, no es necesario que corra bajo Windows o DOS.
Al concluir el proyecto, contamos con el conocimiento detallado del protocolo SNMP, ya que para ello fue necesario implementarlo. Hemos aprendido el funcionamiento de Windows mediante mensajes encontrando algunos problemas que tuvimos que resolver, como son la forma de enviar y recibir mensajes SNMP con la ayuda de los Mensajes Windows.
Otro obstáculo que se presento debido al diseño del Sistema Operativo fue el no poder realizar una aplicación 100°/o Orientada a Objetos, ya que el uso de Bibliotecas Dinámicas, que no están diseñadas en esta filosofía, generan cierto tipo de problemas, sin embargo, encontramos una forma adecuada de encapsular esta información y presentar al resto del programa como un programa de Objetos.
92
Manual de usuario
MANUAL DE USUARIO
REQUERIMIENTOS DEL SISTEMA
Q Se requiere Windows 3.1 o superior" Q Se requiere estar conectado a Internet a través de cualquier medio. %+ Se requiere el Archivo WinSock.dl1 versión 1 a 16 bits el cual se
proporciona junto con el software que utiliza para conectarse a Internet. Este archivo no se proporciona con los discos de instalación y es indispensable para poder ejecutar el programa.
Q Se necesitan 380 Kbytes en Disco duro o Disco Flexible para el programa
+% Aunque en principio no requiere mucha memoria, es recomendable un sistema con más de 8 Mb de memoria RAM, ya que en la lectura de tablas grandes puede ser necesaria.
Q El programa fue diseñado para ejecutarse en Windows 3.1 a 16 bits por lo que puede ser ejecutado en un procesador 286, pero es recomendable que se compile con código para procesadores superiores, ya que la transmisión por red es lenta en general.
%+ Se proporciona un disco de instalación y en caso de querer desinstalarlo solo hay que borrar la ruta en que se instaló y el grupo de programas del administrador.
¿ C ó M O INICIAR?
Para comenzar, haga doble clic en el icono de Admin.exe en el Administrador de Archivos o en el grupo SNMP que se creó al momento de instalar el programa, o bien, desde el Administrador de Programas, en el menú Archivo, seleccione la opción EJECUTAR y ejecute el Archivo Admin.exe.
Al comenzar, encontrará una ventana que contiene un icono de una Terminal debajo de la cual aparece un nombre que corresponde al Comunity y su dirección
Este icono representa a la miquina que actualmente se está ocupando, su dirección IP como su Comunity se encuentran en el archivo de Inicialización
disefiado para trabajar a 16 bits, y Windows 95 proporciona funciones de red a 32 bits. La falla lo En las pruebas bajo Windows 95, se detecto un mal funcionamiento, debido a que esta
consiste en que no es capaz de recuperarse después de una cancelación de lectura de variables.
93
Administrador de Redes SNMP
DIALOGO GRUPOS
Al hacer doble click sobre una terminal, o al seleccionar la opción Grupos del menú Comandos se mostrará el siguiente diálogo:
Figura 35 Diálogo Grupos. Para enviar mensajes a las terminales.
En este diálogo se selecciona el grupo que desea preguntar, el cual está definido en el archivo Mib-2.dat que define la MIB que se está utilizando.
Una vez seleccionado, simplemente se presiona preguntar y después de un tiempo se espera la respuesta, la cual se mostrará en forma inmediata.
En caso de querer suspender, solo se presiona OK y los mensajes recibidos a través de la red serán ignorados, sin que cause ningún problema.
94
Manual de usuario
INSERTA UN NODO PARA ADMINISTRARLO
Para Insertar un nodo, seleccione del menú Comandos la opción Insertar.
Se mostrará el cuadro de diálogo:
Figura 36 Diálogo para insertar un nodo.
La dirección debe estar en formato de puntos, por ejemplo 127.32.234.6, en caso de que se de una dirección inválida, se pondrá automáticamente a 0.0.0.0 y si se omite un número se supondrá que es O (cero).
En la línea Comunity se usa:rá por omisión el valor preestablecido, en el ejemplo es public.
95
Administrador de Redes SNMP
CóMO CAMBIAR EL VALOR DE COMUNITY
Para cambiar el valor de Comunity en una terminal, primero debe seleccionarse presionando el botón del ratón sobre la terminal, luego en el menú Comandos la opción comunity presentará el siguiente diálogo:
Figura 37 Diálogo para cambiar el valor del community
En este diálogo, solo hay que cambiar el valor y listo.
Cambiar la dirección IP
Para cambiar la dirección Tp en una terminal, primero debe seleccionarse presionando el botón del ratón sobre la terminal, luego en el menú Comandos la opción Dirección IT presentará el siguiente diálogo:
Figura 38 Diálogo para cambiar la dirección IP
96
Manual de usuario
La dirección 127.32.234.6, en automáticamente (cero) y se coloca
IP debe esta.r en formato de puntos, por ejemplo caso de que se de una dirección inválida, se pondrá a 0.0.0.0 y si se omite un número se supondrá que es O al principio.
Ejemplo
123.32 corresponde a 0.0.123.32
ARCHIVO DE INICIALIZACI~N SNMPADMI.IN1 Este archivo debe encontrarse en el directorio de Windows, contiene solo
un apartado llamado Inicio, el cual contiene dos valores de variables.
Dirección IP que contiene la d.irección IP de la maquina actual
Comunity que contiene el valor de comunity.
N o es necesario que exista este archivo, ya que en ese se asigna la dirección IP 0.0.0.0 y el comunity public.
Ejemplo de un Archivo SNMI’ADMI.IN1
[Inicio]
DirecciónIP=255.255.255.255
Comunity = Universidad
SESIóN TÍPICA DE 1NSTALA.CIÓN
Inserte el disco en la unidad A:
Para instalar seleccione en el “menú Archivo” del administrador de programas la opción “Ejecutar” :Y‘ escriba como se muestra en la siguiente pantalla.
- Linea de comando:
A:ISNMPINST.EXE
Ejecutar minimizado
I
Figura 39 Ejecutar una aplicación desde el administrador de programas
97
Administrador de Redes SNMP
Al presionar el botón de Aceptar se desplegará:
Figura 40 Instalar en: (del instalador)
Seleccione el directorio en dónde se ha de instalar la aplicación, se sugiere C:\SNMP. Al presionar el botón Aceptar comienza la instalación; antes de finalizar esta, el sistema preguntará la dirección IP de la maquina en uso y el valor de Community como a continuación se muestra.
Figura 41 Insertar valores iniciales
98
Manual de usuario
Estos valores se guardan en el archivo de inicio de aplicación “ADMISNMP.ini” situado en el directorio “C:\WINDOWS\”. Al concluir la instalación aparecerá el siguiente mensaje:
Figura 42 Aviso final al instalar
En el administrador de programas se habrá creado el grupo “SNMP” que contiene el archivo aplicación:
Figura 43 Grupo SNMP
99
Administrador de Redes SNMP
SESIóN DE DESINSTALACI~N Para desinstalar la aplicación hay que borrar el grupo de programas
“SNMP”: u Mrninirlrador de pronramao Archiva Qpdoncs Yenlana Anida
m i E J l g j m m l n m SNMP A c c e ~ m Red Pmcpd
Figura 44 Eliminar un grupo
Después se debe borrar el directorio de trabajo de la aplicación ubicado en “C:\SNMP”:
Figura 45 Eliminar los archivos del administrador
100
Apéndice A. Objetos definidos
APÉNDICE A. Objetos definidos Las relaciones de los objetos definidos en esta aplicación se resumen en el
siguiente diagrama a bloques:
ITGraficaBitMap)
[TTablal
lTListaCadsnal
l“l ITListaldObil
ITDefinicionGruposl
1”- TDireccionlP I
ITLongitudASNI
ITEtiaueta4SNI
Diagrama 10 Objetos definidos
10 1
Administrador de Redes SNMP
APÉNDICE B. Código fuente del programa ENCABEZADO DEL ARCHIVO DE CODIFICACIóN (I3ER.H)
#ifndef -YA-SE-DEFINIO_BER- #define -YA-SE-DEFINIO-BER- typedef int BOOL; #define FALSE O #define TRUE 1
#include "Tamaños.h"
typedef unsigned char TByte; //Tipo de 8 bits sin signo
typedef unslgned long TDWord; //Tipo de 32 bits sin signo typedef unsigned int Tnord; //Tipo de 16 bits sin signo
union m a g //Esta tipo de dato pretende tener toda la i struct //una etiqueta ASN.l
//estructura para manjar el primer byte de
( TByteNumber : 5 ; //Contiene el número de etiqueta TByte F TByte Class : 2 ; //Indica la clase a la que pertenece
:l; //Indica si requiere constructor
1 Tag ; TByte Byte; //Contiene el byte completo
) ;
UnionTEnteroSinSigno //Esta union permite descomponer un entero i //sin signo de un doble word en dos words struct //y cuatro bytes
TByte Bl,B2,B3.B4; i
)Byte;
i )word;
struct
Word W1, W2 ;
TDWord DWord; ) ;
char *DumpLchar [ I .TDWord) i char *BinHexlchar dl ;
/ t l t l l t l t l * * * * * * r i i + ~ ~ ~ . ~ * ~ * ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ * ~ ~ . ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ . ~ * ~ ~ ~ ~ * . . . ~ *
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Definiciones de clases
class TEtiquetaASN i protected: TByte tam;
TEnteroSinSigno Entero; TTag Etiqueta;
enum T'ErrOrEtiqueta {SinError=O,MuyGrande)
public: ErrorEtiqueta;
char /*constructor*/ TEtiquetaASN(TByte,TByte,TDWord);
TByte Tam0 (return tam:]; TByte CodigoBin (char *,TDWordl ;
BOOL operator I (TEtiquetaASN etiqueta)(return etiqueta.ErrorEtiqueta'=SinError;);
CodigoHex ( 1 ;
) ;
class TLongitudASN
102
Apéndice B. Código fuente del programa
I protected:
TByte tam; //Guarda el tamalio en bytes del campo tamafio TEnteroSinSigno Longitud; //Guarda el valor del campo tamaño
TByte CodigoBin (char ,TDWord) ; /*Constructor*/ TLongitudASN(TDWol:d!; //Contruye el campo conociendo su valor
char * CodigoHexO; //Genera su codigo hexadecimal en formato ASCII unsigned long TamO(return tam;):
public:
) ;
class ?Tipo ( protected: TDWord tam:
enum TErrorTipo (SinError=O,NoEti~~eta,MuyGrande,NoMemoria,Gener~co) ErrorTipo;//Manejador de E:rrores
TLongitudASN f Longitud;//Campo Longitud TEtiquetaASN Etiqueta;//Campo IXtiqueta /*Constructor*/ Trip00 ;
virtual char * CodigoHexO; /*Destructor*/ -Trip00 ;
virtual TDWord CodigoBin(char *.'rDWord)=O; virtual char Valorsintaxis ( ) = O ; virtual unsigned long TamOIreturn L o n g i t u d - > T a m O + E t i q u e t a , T a m ! ) ; ) ;
public:
) ;
class TNULL:public TTipo I public:
virtual TDWord CodigoBin(char +.'l'DWord 1 ; /*Constructor*/ TNULL 1 ) :
virtual TDWord TamO(return O : ) ; virtual char * ValorSintaxisO ;
) ;
class TEnter0:puhlic Trip0 I protected:
public: TDWord Valor;
/*Constructor*/ TEntero(TDW0rd); TEntero(char *Dato) ;
virtual TDWord CodigoBinIchar * , TDWord) ; virtual char * ValorSintaxisO; virtual TDWord Tam0 (return tam;); BOOL operator ' (TEntero tipo)(return tipo.ErrorTipo==SinError;);
) ;
class TCadena:public TTipo i
char /*Constructor*/ TCadena(char * ) ;
Valor [TAM-MAX-CADI i
vlrtual TDWord CodigoBin(char *,rDword!; TCadena (char * , char * i ;
virtual char ValorSintaxisO; virtual TDWord TamO(return tam;); BOOL operator ! (TCadena tipo)(return tipo.ErrorTipo==SinError;);
public:
) ;
class TId0bj:public ?Tipo
public: char Valor [TF\"MAX-CADI ;
/*Constructor*/ TIdObj(char TIdOhj (char *,char '1 ;
* ! ;
103
Administrador de Redes SNMP
virtual TDWord CodigoBinlchar +.TDWord); virtual char Valorsintaxis 0 ; virtual TDWord Tarn0 (return tam:); BOOL operator I (TIdObj tipo![return tipo.ErrorTipo==SinError;);
1;
class TDireccion1P:public TCadena i public:
TEtiquetaASN(1.0.0););
lEtiqueta);Etiqueta=new TEtiquetaASNll,O,O!;);
/*Constructor*/ TDireccionIPlchar *Cad):TCadenalCad)(delete lEtiqueta);Etiqueta=new
TDireccionIP(char *Dato,char *nn):TCadena(Dato.nn!(delete
BOOL operator , (TDireccionIP tipo!(return tipo.ErrorTipo==SinError;); vlrtual char * ValorSintaxisO;
) ;
class TContador:public TEnterO 1 public:
TEtiquetaASN(1.0.1););
TEtiquetaASN(l.O.l!:);
/*Constructor*/ TContadorITDWord Val):TEntero(Val)[deletelEtiqueta!;Etiqueta=new
TContador(char *Dato):TEnterolDato)(delete (Etiqueta!;Etiqueta=new
BOOL operator 1 (TContador tipo)[return tipo.ErrorTipo==SinError;); ) ;
i class TMedid0r:public TEnterO
public:
TEtiquetaASN(1.0.2););
TEtiquetaASN(l.O.l!;);
/*Constructor*/ TMedidorITDWord Val):TEnterolVal!(delete(Etiqueta!;Etiqueta=new
TMedidorIchar *Dato! :TEntero(Dato)(delete lEtiqueta);Etiqueta=new
BOOL operator 1 ITMedidor tipo)(return tipo.ErrorTipo==SinError;);
c l a s s TTlcksRel0j:public TEntero ) ;
i public:
TEtiquetaASNl1,0,3););
TEtiquetaASNl1,0,1););
/*Constructor*/ TTicksReloj(TDWord ~a~):TEntero(val)[deletelEtiqueta):Etiqueta=new
TTicksReloj(char *Dato):TEntero(Dato)(delete (Etiqueta);Etiqueta=new
BOOL operator , (TTicksReloj tipo)[return tipo.ErrorTipo==SinError;); virtual char * ValorSintaxisO;
1;
class TComodin:public TCadena ( public:
TEtiquetaASNl1,0,4););
TEtiquetaASNl1,0,4););
/+constructor*/ TComodin[char *Cad):TCadena(Cad)[delete (Etiqueta):Etiqueta=new
TComodin(char *Dato,char *nn!:TCadena(Dato,nn! {delete (Etiquetal:Etiqueta=new
BOOL operator ' ITComodin tipo)(return tipo.ErrorTipo==SinError;); ) ;
class TVarBind:public TTipo i protected:
public: TVarBind ( ! ( ) ;
TIdObj f Nombre; //ObjectName TTipo * Valor: //Objectsyntax /*constructor*/ TVarBind(TId0bj *nomhre,TTipo *valor);
TVarBind(char * ) ; -TVarBind I ) ;
virtual TDWord CodigoBin(char *,TDWord); vlrtual char * Valorsintaxis ( ) ; BOOL operator ! (TVarBind tipo)[return tipo.ErrorTipo==SinError;);
104
Apéndice B. Código fuente del programa
virtual TDWord Tam0 (return tam; :.; ) ;
class TVarB1ndNodo:public TVarBlnd i protected:
prlvate:
public:
TVarBindNodoO :TVarBindO { ) ;
char BufferPrivado[TAi-MAX-BUPI ;
TVarBindNodo *Siguiente; /*Constructor*/ TVarBindNodo(TId0hj +nombre.TTipo
*valor) :TVarBind(nombre,valori (Siguient€!=NULL;); TVarBindNodolchar * ) ; -TVarBindNodo í )
( if (Siguiente)
delete(Siguiente1 ;
//TVarBind::-TVarBindO; Siguiente-NULL;
) ; virtual TDWord TamO (return tam; ti vlrtual TDWord CodigoBin(char *:CDWord) ;
virtual char * ValorSintaxisll; virtual void Inserta(TId0bj *nombre,TTipo *valor) ;
virtual char Valorvariable ( ) {return Valor->ValorSintaxis O ; ) ;
BOOL operator I (TVarBindNodo tipo)(return tipo.ErrorTipo==SinError;);
virtual void Inserta(char *Dato) ;
virtual char * Nombrevariablell;
) ;
class TVarBindList:public TVarBindNodo i public: /*Constructor*/ TVarBindList(Tld0bj *nombre.TTipo *valor);
TVarBindList (char * 1 ; virtual TDWord CodigoBin(char +.'rDWordl ; TDWord BOOL operator 1 (TVarBindList tipo)(return tipo.ErrorTipo==SinError;);
TamO ;
) ;
class TPDU:public TTipo
protected: i
TEntero TEntero TVarBindList
TEntero /*Constructor*/ TPDUiTEntero *secuencia,TEntero *errOr.TEntero *indice,TVarBindList
*Error; *IndiceError;
*ListaVarBind; public:
*Secuencia;
'listal ; TPDU (char * 1 ; -TPDU ( 1
i
deleteisecuenciai ; : f (Secuencia)
delete (Error) ; :.f (Error)
:.f (IndiceError) delete ( IndiceErrorl ;
delete(ListaVarBind); : f (ListaVarBindi
Secuencia=NULL; Erxor=NULL; IndiceError=NULL; ListaVarBind=NULL; TTipo: : -miPo ( 1 ;
virtual TDWord CodigoBinlchar *,'cDWordl; ) ;
105
Administrador de Redes SNMP
virtual char * ValorSintaxisO;
virtual TDWord Tam( 1 ; BOOL operator 1 (TPDU tipo)(return tipo.ErrorTipo==SinError:);
virtual TVarBindList *Llsta()(return ListaVarBind;); ) ;
class TGetRequest-PDU:public TPDU i public:
/*Constructor*/ TGetRequest-PDU(TEnter0 +secuencia,TEntero *error.TEntero *indice,TVarBindList *lista)
i :TPDU(secuencia.error,indice,lista)
delete (Etiqueta) ; Etiqueta-new TEtiquetaASN(2,l.O);
) ;
( TGetRequest-PDU(char *Dato):TPDU(Dato)
delete(Etiqueta) ; Etiqueta=new TEtiquetaASN(2,l.O) ;
BOOL operator I (TGetRequest-PDU tipo)(return tipo.ErrorTipo==SinError;}; ) ;
1;
class TGetNextRequest_PDU:public TPDU
/*Constructor*/ TGetNextRequeSt-PDU(TEnter0 *secuencia,TEntero *errOr.TEntero public:
*indice,TVarBindList ‘lista) :TPDU(secuencia,error,indice, lista) i delete (Etiqueta) ; Etiqueta=new TEtiquetaASN(2.1.1) ;
TGetNeXtRequeSt-PDU(char *Dato):TPDU(Dato) ) :
i delete(Etiqueta1 ; Etiqueta=new TEtiquetaASN(2.1.0):
) ; BOOL operator ! (TGetNextRequest-PDU tipo)(return tipo.ErrorTipo==SinError;);
1 ; class TGetResponse-PDU:public TPDU
i public:
/*Constructor*/ TGetResponSe-PDU(TEnter0 ‘secuencia.TEnter0 *errOr.TEnterO *lndice,TVarBindList *lista)
( :~pou(secuencia,error, indice. lista)
delete (Etiqueta) ; Etiqueta=new TEtiquetaASN(2,1,2);
TGetRespOnse-PDU(char *Dato) :TPDU(Dato) ) ;
( delete(Etiqueta); Etiqueta=new TEtiquetaASN(2.1.0):
BOOL operator 1 (TGetResponse-PDU tipo)(return tipo.ErrorTipo==SinError;); 1;
1;
class TSetRequest_PDU:Public TPDU i public:
*Indice.TVarBindList ‘lista) /*constructor*/ TSetRequeSt-PDU(TEnter0 *secuencia,TEntero +error.TEntero
:TP~u(secuencia.error,indice.lista) i delete (Etiqueta) ; Etiqueta=new TEtiquetaASN(2.1.3) ;
106
Apéndice B. Código fuente del programa
TSetRequest-PDUlchar *Dato1 :'rPDU(Dato! ) ;
i delete(Etiqueta1 ; Etiqueta=new TEtiquetaE.SN(2.1, O ) :
) ; BOOL operator ITSetRequest-PDU tipo)(return tipo.ErrorTipo==SinError;);
) :
class TMensajeSNMP:public n i p 0 ( protected:
public: TPDU *Dato;
TCadena TMensajeSNMP(TCadena *comunidad.TPDU 'dato) : TMensajeSNMP(char *Dato) : -TMensaj eSNMP ( !
*Comunidad:
( if (Comunidad)
if (Dato1 delete (Comunidad) ;
delete(Dato1 ; Comunidad=NULL:
TTipo::-TTipoO: Dato=NULL;
virtual TDWord CodigoBin(char +,':DWord) ; virtual char ValorSintaxisO; virtual TvarBindList *ListaO(return Dato->ListaO;) BOOL operator I (TMensajeSNMP tipo)(return tipo.ErrorTipo==SinError:): TDWord secuencia()(return atol(~ato-~Secuencia-zValorSintaxis!~~;}
) :
#endlf ) ;
CODIFICACI~N DEL ARCHIVO DE CODIFICACI~N (BER.CPP) #include <string.h>//Biblioteca para usar cadenas tradicionales de C #include <stdio.h> //Bibliotecas de entrada y salida #include <stdlib.h>
#include "ber.h" //Cabecera para el manejo de datos BER #include "Tamaii0s.h" //Constantes y macros de ayuda
char *ApuntadorCadenaDatos=NULL: //Esta variable apunta al dato que se ha de leer para decodifcar
//una secuecia de bytes en ElER.
/ * Tarea:
Convertir un byte en una cadena con su representación hexadecimal
Byte:Byte de entrada a convertir.
Apuntador a la cadena que contiene la representación hexadecimal del byte de entrada
Esta función es declarada en forma tradicional de C para que tengan acceso a ella cuiquer código. La variable ValorHexadecimal, es dsclarada en forma estática y con un valor inicial
que solo se tiene acceso a ellos mediante esta función. de 3 espacios con el fin de poder regresar siempre 4 bytes (en el segmento de datos)
Argumentos:
Retorno:
Observaciones:
* / char *BinHex(char Byte) { static char *ValorHexadecirnal=NULL; char Nible=Byte>>4:
107
Administrador de Redes SNMP
if ~ValorHexadecimal==NLLI (
ValorHexadecimal=new charL41; ValorHexadecimal=" ' I :
I else
(
ValorHexadecimal=new char(41; ValorHexadecimal=" ' I ;
delete (ValorHexadecirnal) ;
)
Nible&=OxOf; Byte&=OxOf;
if (Nible>9!
else
if (Byte>9)
else
ValorHexadecimal [O1 = (Nible-9) 10x40;
ValorHexadecimal~OI=Nible~Ox30;
ValorHexadecimal I11 (Byte-91 10x40;
ValorHexadecimal[ll=Byte~0x30;
) return ValorHexadecimal;
/ + Tarea :
Generar una representación hexadecimal bien arreglada para determinar
Argumentos: si un dato es correcto.
DatoS:Es una secuencia de bytes, a los cuales se les ha de encontrar su representación hexadecimal y regresarla en una cadena.
Tam:Indica el tamafio de la lista de bytes Retorno:
Observaciones: Apuntador a la cadena que contiene la secuencia hexadecimal
Esta función se ha declarado en forma tradicional de C para tener acceso ella desde cualquier punto del programa La variable CadenaHexadecimal, se declara en forma estAtica para que no plerda su valor al salir de ella y de esta manera se pueda regresar como
un apuntador, al cual se tiene acceso solo desde la función. * /
char *Dump(char Datos [I .TDWord tam) ( static char CadenaHexadecimal[TAb-MAX-BUFI; CadenaHexadecimal [ O ] = O ;
for (TDWOrd i=O;i<tam;i++] strcat(CadenaHexadecimal,BinHex(DatosIil)l;
return CadenaHexadecimal;
/ * Tarea:
Encontrar en una cadena de datos codificadas en BER el tamafio del dato, que se encuentra definido para un tipo
ASN. 1 Argumentos:
Retorno: Lista de valores del dato codificado en BER
El valor en formato numérico Observaciones:
El valor regresado e6 un entero de 3 2 bits ya que la PC puede trabajar con estos datos en buna forma y ASN.l usualmente no excede estos valores.
El tamaño o longitud del dato no puede ser negativo por lo que se regresa del tipo TDWord que es un entero positivo
de 3 2 bits
108
Apéndice B. Código fuente del programa
* /
TDWord RegresaLongitudlchar 'Datos) { TDWord Longitud=lTByte)Datos[Ol; //Asumimos que solo un byte define el tamafio ApuntadorCadenaDatos=&Datos[ll; //Prevenimos que varios bytes definan el tamaño if !IDatos[01&128~==1281 //¿Este byte el que define el tamaño?
i int 1ndice.l; //Indice recorre lor; bytes que pueden definir el tamaiio
Longitud=O; //Inicialmente la longitud es cero !TByte)Datos~Ol&=127;//Obtener el valor de los 7 bits con información válida
switchl(TByte)Datos[Ol)//Según el caso, los 7 bits nos indican cuantos bytes codifican
//No, hay mas bytes para definir el tamaño
el tamaño i case O: //Ningún byte, regresamos cero.
case 4 : //Cuatro bytes definen el tamafio return O;
Longitud<<=8;//0btenemOs el byte m6:: significativo Longitud+= 1TByte)Datos [indice++] ;//:.ndicado por indice y nos
//preparamos para continuar
importa1 case 3://Tres bytes más definen el tamaño (talvez no se paso por cuatro pero no
Longitud<c=B;//Si se paso por 4 entonces salvamos el valor recopilado anteriormente Longitud+=lTByte)Datos[indice++l://lifiadimos el valor (un byte1 indicado por índice
case 2://Dos bytes m6s definen el tam,%ñ0 (talvez no se paso por tres pero no importa) Longitud<<=B;//Si se paso por 3 entonces salvamos el valor recopilado anterior mente Longitud+=(TBytelDatos[indice++l;//liñadimos el valor (un byte) indicado por índlce
Longitudcc=8;//Si se paso por 4 entonces salvamos el valor recopilado anteriormente
ApuntadorCadenaDatos=&Datos[indicel; //Finalmente idicamos que hemos leido fndice Longitud+=lTByte)Datos[indice++l;//l~ñadimos el valor (un byre) indicado por índice
case l://un byte más define el tamaiio (talvéz no se paso por tres pero no importa)
return Longitud; 1
/ * * * t ~ * ~ * * * * * * * * ~ * t + . ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ * ~ ~ . ~ * * . ~ ~ ~ ~ ~ ~ ~ ~ . ~ * ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ . ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ . ~ ~ ~ ~ ~ ~ ~ ~
r + * * * * * * * * t t + + * * * * * * ~ * * * * * * * , * * * ~ * * * * ~ ~ * * * ~ * * * * * * * * * * * * ~ * * * * * * * * * * * * ~ * * * * * * * ~ ~ ~ ~ ~ ~ " * * * * * * *
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
............................................................................................ . . . . ~ ~ ~ , ~ , , , , , , , ~ ~ ~ ~ ~ ~ ~ ~ . ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ * ~ ~ ~ ~ . ~ . ~ ~ * ~ ~ ~ ~ . ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ * * ~ ~ ~ ~ / / *
Tarea:
Argumentos: Construir un objeto TEtiquetaASN
clase: Determina la clase de dato abstracto gue es. constructor.- Idica si se requiere construir el tipo o no
valor . - contiene el va1o.r de la etiqueta Retorno : Observaciones:
TEtiquetaASN::TEtiquetaASN(TByte clase=O,'PByte COnStrUCtor=O,TDWord valor=O) +/
( ErrorEtiqueta=SinError; //Idicamos que no ha ocurrido ningún error TEnteroSinSigno Valor; //Utilizamos sna estructura auxiliar para poder descomponer
Valor.DWord=valor; //Hacemos la copia Idel valor clase&=3; constructor&=l; //validamos el constructor
//validamos la clase
switch (clase) //No podemos asignar en forma directa el valor de la clas
valor
{ case O :
//ya que esta está en una estructura de bits
Etiqueta.Tag.Class=O; //Clase
case 1: break;
109
Administrador de Redes SNMP
Etiqueta.Tag.Class=l; //Clase break;
case 2: Etiqueta.Tag.Class=2; //Clase
break; case 3: Etiqueta.Tag.Class=3; //Clase
break; 1
//No podemos asignar directamente por ser un bit If lconstructorl//iHay constructor?
else
if (Valor.DWord>Oxfffffffi//¿Soportamos el valor recibido?
Etiqueta.Tag.F=l; //Si lo hay, idicamos SI
Etlqueta.Tag.F.0; //No lo hay, idicamos NO
{ //No lo soportamos ErrorEtiqueta=MuyGrande; //Idicamos que hay un error (MuyGrande) return; //Abortamos todo el proceso
) if (Valor.DWord<31) //¿Cabe el valor en 5 bits y no es la bandera de mas grande?
[ //Si cabe y no es la bandera Etiqueta.Tag.Number=Valor.Byte.Bl;//Lo guardamos en su lugar correspondiente tam.1; //Idicamos que la etiqueta ocupa solo 1 byte
)
( else //No cabe o es la etiqueta
Etiqueta.Tag.Number=31; //Colocamos la etiqueta Entero-Valor; //Hacemos una copia fiel Entero,DWord<<=2; //Hacemos espacio para el bit mas significativo
Entero.Byte.Bl>z=l; //Obtenemos el byte 1 Entero.Word.Wl>>=l; //Obtenemos el byte 2
Entero.Word.W?cc=l; //Hacemos espacio para los byte 1 y 2, simultaneamente obtenemos
Entero.Byte.B3>>=1; //Obtenemos el byte 3 if ((Entero.Byte.B4&0x7f) '=Ol//jrequiere 4 bytes?
el byte 4
i //Si requiere
Entero.Byte.B3~=0xGLl; //Idicamos que este byte no es el último Entero.Eyte.B4~=oxGo;//Idicamos que este byte no es el último
Entero.Byte.B2I=Ox80; //Idicamos que este byte no es el último Entero.Byte.B1&=Ox7f; //Idicamos que este byte es el último en definir el valor
tam= 5 ; //La etiqueta ocupa 5 bytes 1 else if ((Entero.Byte.B3&Ox7f) ! = O ) //No requiere 4 . ¿Requiere 3 bytes? { //Si requiere 3 bytes
Entero.Byte.B3(=0xBO;//Idicamos que este byte no es el último
Entero.Byte.Bl&=Ox7f; //Idicamos que este byte es el último en definir el valor Entero.Byte.B2\=0xGO;//IdicamoS que este byte no es el último
tam=4; //La etiqueta ocupa 4 bytes ) else if ((Entero.Byte.B2&0x7fI!=Ol//No requiere 3 bytes ¿Requiere 2 byte?
( //Si requiere 2 bytes Entero.Byte.Bz/=OxBo;//Idicamos que este byte no es el último Entero.Byte.B1&=Ox7f; //Idicamos que este byte es el último en definir el valor tam=3; //La etiqueta ocupa 3 bytes
else if ((Entero.Byte.B1&0x7fi < = O ) //No requiere 2 bytes ¿Basta con uno? i Entero.Byte.B1&=0~7f;//Idicarnos que este byte es el último en definir el valor tam=2; //La etiqueta ocupa 2 bytes
) //¿Pude haber un error, si lo hay se debe validar aqui. Yo digo que no lo hay //y que el ultimo else if debe ser solo un else. Pero para ser metódicos lo
//dejamos con else if. 1
/ * Tarea :
Generar el código binarios BER del una etiqueta ASN.l Argumentos:
110
Apéndice B. Código fuente del programa
Retorno:
Observaciones:
El Buffer donde hay que enviar e:. cbdigo y su tamaño
El númro de bytes con que se cod~.fico
El buffer, simplemente se llena y nc se recorre. Analice como crece i para tener el tamaño.
* /
TByte TEtiquetaASN::CodigoBin(cbar *Buffer.TDWord TamBuf) { TByte i=l; //Por lo menos debe ocupar un byte If (TamBuf<tam) //;Cabe en mi buffer?
if !tam>=ll//;Incluimos la etiqueta?
if !tam>l) //;Basta con la etiqueta?
return O; //No cabe, no hay nada por hacer
BufferIOl=Etiqueta.Byte; //Si la inzluimos
switch(tam) //No. hay que meter los bytes que se nececitan ( case 5 : //se necesitan meter 4
buffer Buffer[i++]=Entero.Byte.B4; //Metemos el 4" y recorremos nuestro indicador de
case 4 : //Se necesitan meter 3 Bufferli++l=Entero.Byte.B3; //Metemos el 3" y recorremos nuestro indicador de
buffer case 3: //Se necesitan mecer 2
buffer Buffer[i++l=Entero.Byte.B2; //Metemos el 2 " y recorremos nuestro Indicador de
case 2: //se necesita meter 1 BufferIi++]=Entero.Byte.Bl; //Metemos el 1' y recorremos nuestro indicador de
buffer )
return tam; //Regresamo el tamaño
/ * Tarea :
Generar el código hexadecimal BER de un etiqueta ASN.l
Ninguno
La cadena con el código hexadecimal
Argumentos:
Retorno:
Observaciones: * /
i char *TEtiquetaASN::CodigoHexO
static char Buffer(51; //usamos un buffer del tamaño máximo para el código Binario BER
return Dump(Buffer,tam); //Lo convertimos a hexadecimal y lo retornamos CodigoBiníBuffer.5); //Encontramos su código binario
/ * Tarea:
Argumentos:
Retorno: Observaciones:
Construir un obejto TLongitudASN
Entero.. El valor de la longitud le el dato ASN.l
Los datos estan limitados a una longitud dada por la capacidad de 32 bits
* /
i
puede usar desde un byte hasta cuatriqo bytes
TLongitudASN::TLongitudASN(TDWord Entero=O)
Longitud.DWord=Entero; //El atributo DWord es capaz almacenar los 4 bytes maximos que
if (Entero<l28) //;Cabe todo en un bytt?? íLa codificación BER) tam= 1 ; //si, entonces solo se necesita un byte para codificar
else if (Entero<=0~000000ff) //No cabe, ;El valor si cabe en un byte?
else if (Enteroc=OxOOOOffff) //No cabe izabe en dos bytes?
se necesitan
tam=2; //Si cabe entonces se requieren 2 bytes para codificar en BER
1 1 1
Administrador de Redes SNMP
tam=3; //Si cabe entonces se requieren 3 bytes para codificar en BER
tam=4; //Si cabe entonces se requieren 4 bytes para codificar en BER
tam=5; //Entonces se requieren 5 bytes para codificar en BER
else if (Enteroc=OxOOffffff) //No cabe ;Cabe en Tres bytes?
else //No cabe (Cabe en cuatro1
i / *
Tarea:
Argumentos:
Retorno:
Observaciones:
Generar el código binario BER de la longitud de un dato definido en ASN.l
El buffer donde se almacena el código binario y su tamaño
El tamaño en bytes que ha ocupado el código binario
En el constructor se obtubo el tamaño en bytes que se requiren para codificar en BER.
Observe como i determina siempre en donde se ha de poner el código binario
TByte TLongitudASN::CodigoBin(char *Buffer,TDWord TamBuf) * /
i TByte i=l;//Se parte de que se necesita un byte if (TamBufctam)//¿Cabe en el buffer el código?
Buffer[fl]=ltam-l) IflxaO;//Se asume que se requieren Tam-1 bytes para indicar la longitud return O; //no cabe, no hay nada que hacer
switch I tam) i case 5 : //Cuatro bytes más el tamaño se requieren
case 4:
case 3 : //Dos bytes más se requieren
case 2:
Buffer[i++l=Longitud.Byte.B4; //se coloca el byte 4
Buffer[i++l=Longitud.Byte.B3; //se coloca el byte 3
Buffer[i++]=Longitud.Byte.B2; //se coloca el byte 2
//Tres bytes más se requieren
Buffer[i++l=Longitud.Byte.Bl; //se coloca el byte 1 //Un byte más se requiere
case I: break;
//se requiere solo un byte para el código BER
//en que se asume Tam-1 bytes es falso y se corrige i Buffer[Ol=Longitud.Byte.Bl; //se coloca el valor. Se ve claro que el paso
return tam;//Se regresa el tamaño en bytes que se han codificado 1
/ * Tarea :
Generar el código hexadecimal BER de la longitud de un dato ASN.l
Ninguno
La cadena con el código hexadecimal
Argumentos:
Retorno:
Observaciones: * / char *TLongitUdASN::CodigoHex() i static char BufferIsl; //Se reserva el tamaño m6ximo que se requiere para el buffer
return Dump(Buffer,tam); //se obtiene su equivalente hexadecimal y se retorna CodigoBin(Buffer.5); //se obtiene su código binario
i / *
Tarea : Crear un objeto genérico TTipo que representa un tipo en ASN.l
Argumentos: Retorno: Observaciones:
ES una clase abstracta que sirve como base para los tipos definidos en ASN.1 * /
i TTipo : : TTipo ( )
Longitud=NULL: //Longitud Nula o desconocia
112
Apéndice B. Código fuente del programa
Etlqueta=NULL; //Etiqueta Nula o no definida ErrorTipoSinError; //No hay error
/ * 1
Tarea:
Argumentos: Retorno: Observaciones:
Destruir un objeto n i p 0
Destruye La etiqueta y la longitud para liberar al programador de estos detalles en lar: clases derivadas
* /
{ TTipo: : -TTipo ( 1
Destruye(L0ngitud); //Destruimos Long:rtud Destruye (Etiqueta) ; //Destruimos Etiqueta
1
/ * Tarea :
Generar el codigo Hexadecimal Btlr de un tipo cualesquiera ASN.l Argumentos: Retorno:
Observaciones: La cadena con el código BER hex.ndecima1.
Todos los tipos definidos en ASN.l y codificados en BER tienen un método parecido o identic0 por lo que se usa la herencia para liberar la programación
* / char *TTipo::CodigoHexO {
de los mismos
TDWord t=CodigoBin(Buffer,TAM-MAX-BUF). //Obtenemos su código binario y su tamaño static char Buffer[TAM-MAX-BUFI; //Rf!servamos un buffer de tamaño máximo
return Dump(Buffer.t); //Obtenemos su equivalente hexadecimal
/ * Tarea:
Argumentos :
Observaclones: Retorno:
Crear un objeto TNULL equivalence al tipo NULL de ASN.l
Pese a que es el tipo más sencillo por metodología usamos los algorltmos del resto de los tipos
* /
i TNULL : : TNULL ( ; : TTipo ( )
constructor ( 0 ) y vale 5 Etiqueta=new TEtiquetaASN(O.O.5); //La etiqueta es de tipo Universal 1 0 1 , no requiere
Longitud=new TLongitudASN((TDWord10); //La longitud es de cero I / *
Tarea:
Argumentos:
Retorno:
Observaciones:
Obtener el códlgo binario del tipo TNULL
El buffer y su tamaño
0 si no cabe en el buffer y 2 en otro caso
Este tipo siempre se codifica igual. por lo que sus valores son constantes por lo que su programac:rón es sencilla
TDWord TNULL::CodigoBin(char +Buffer.TDliord TamBuf) * /
{ if (TamBuf<Z) //;Cabe en el buffer?
Buffer[O]=S; //El primer byte siempre es 5 Buffer[l]=O; //El segundo byte siempre es O
return o; //No cabe, no hay nada que hacer
113
Administrador de Redes SNMP
i return 2; //se codifica en 2 bytes siempre
/ * Tarea:
Argumentos: Retorno:
Describir en forma de cadena su sintaxis
La slntaxis
Siempre se regresa @'(NULL1 Observaciones:
* /
(
i
inline char *TNULL::ValorSintaxis(I
return " (NULL) "; //Regresar 'I (NULL) I'
/ * Tarea :
Crear un objeto TEntero equivalente al tipo Integer de ASN.l
El valor de dicho objeto Argumentos:
Retorno: Observaciones:
por lo que conocemos su valor de antemano. Este constructor sirve para crear un objeto que deseamos enviar por la red
Para el caso de que recibimos de la red es necesario otro constructor * /
i TEntero::TEntero(TDWord valor)
Valor=valor; ErrorTipo=SinError; //No hay error
Etiqueta=new TEtiquetaASN(O,O,Z); //Clase Universal ! O 1 No Constructor ( 0 ) Etiqueta 2 //Copiamos su valor
if (Valorc=OxOOOOOOff) //¿Basta un byte para BER?
else if (Valor<=Ox0000ffffl //NO, ;Bastan 2 bytes?
else if (Valor<=OxOOffffff) //NO, ¿Bastan 3 bytes?
else //NO, deben bastar 4 bytes
if ((Etlqueta==NULL) 1 1 (Longitud==NULL))//¿Habrá ocurrido algún error?
Longitud=new TLongitudASN(tam=ll; //Si, Creamos la longitud con tamaño 1
Longitud=new TLongitudASN(tam=2); //Si, creamos la longitud con tamaño 2
Longltud=new TLongitudASN(tam=3): //Si, creamos la longitud con tamaño 3
Longitud=new TLongitudASN(tam=41; //Creamos la longitud con tamaño 4
ErrorTipo=NoMemoria; //Si ocurrio en error, reportarlo i / *
Tarea : Crear un objeto TEntero a partir de su cbdigo BER en binario
El código BER en binario Argumentos:
Retorno: Observaciones:
Este constructor sirve para crear el objeto de un buffer recibido por la red
TEntero::TEntero(char *Dato1 * /
i tam=RegresaLongltud(Datol; //Obtenemos la longitud de los datos m t i=l; //i debe servirnos para recorrer el buffer
ErrorTipo=SinError;//Asumimos que no hay error Valor=O; //Asumimos que su valor es cero switch(tam1 //Según el tamario que nos reporta el código BER en binario:
( case 4 :
case 3: //Hay tres byte 1169
Valor=(TByte)Dato[it+l; //Obtenemos el cuarto
valor<<=8; //Salvamos el valor acumulado (Si lo hay) Valor+=(TByte)Dato[i++l; //Obtenemos el tercer byte
Valorcc=8; //Salvamos el valor acumulado (Si lo hay) //Hay dos bytes mas
//son cuatro bytes
case 2 :
114
Apéndice B. Código fuente del programa
case 1 : Valor+=(TBytejDato[i++l; //Obtenemos el segundo byte
//Hay un byte más Valorcc=B; //Salvamos el valor acumulado (Si lo hay) Valor+= (TByte) Dato [i++l ; //Obtenemos el primer byte
1
Etiqueta=new TEtiquetaASN(O,O,Z)://Clase Unversal (0) Sin Constructor ( o ) Etiqueta 2 Longitud=new TLongitudASN(tam); //La longitud la da Tam ApuntadorCadenaDatos+=i: //Recorremos el buffer para los demas datos if ((Etiqueta==NLILLj I I (Longitud==NULL)) //;Habrá ocurrido algún error?
)
/ *
ErrorTipo=Generico; //Si hay error, reportarlo
Tarea:
Argumentos:
Retorno:
Observaciones:
Obtener el código binario BER de un objeto TEntero
El buffer y su tamaño
El tamaño en bytes que ocupa el codigo
TDWord TEntero::CodigoBin(char *BUffer.TDWord TamBufj * /
{ if (TamBufctam+Longitud-sTam(j+Etiqueta-,TamOj//~Cabe el código en el butter?
TByte i=Etiqueta-sCodigoBin(Buffer,TamBuf);//Obtenermos el código de la etiqueta TEnteroSinSigno Entero; //usamos un auxiliar para partir el valor
return O; //No cabe, no hay nada que hacer
Entero.DWord=Valor; i=Longitud-~CodigoBin~&Buffer~il,TamBuf-i~;//Obtenemos el código de su longitud
//del entero
switch(tam! { case 4: //Cuatro bytes más
case 3:
case 2:
Buffer[++il=Entero.Byte.B4: //Obtenemos el cuarto //Tres bytes más
Buffer[++il=Entero.Byte.B3; //Obtenemos el tercero
Buffer[++il=Entero.Byte.BZ; //Obtenemos el segundo //Dos bytes más
Buffer[++il=Entero.Byte.Bl; //Obtenemos el primero case 1: //un hyte más
1 return tam+Longitud->Tam!!+Etiqueta-sTamo;//Regresamos el tamaño del código BER
/ * Tarea :
Argumentos: Retorno:
Observaciones:
Obtener el valor en alto nivel del objeto
La cadena con el valor para ser presentado en pantalla
* / char * TEntero::ValorSintaxisO i static char BufferC341: //Definamos un buffer principal char Bufercito[341; //U un buffer auxiliar BufferIOl=O: //Inicialmente el buffer esta vacio if {ErrorTipol //¿Hay error?
return strcat(Buffer,ultoa(Valor,Bufercito,lO)j;//Ohtenemos su equivalente y lo regresamos return ( " E r r o r " ) ; //Si lo hay, valor debe Indicar ERROR
)
I * Tarea:
Crear un objeto TCadena equivalente al tipo STRING de ASN.l
El valor de la cadena Argumentos:
Retorno: Observaciones:
115
Administrador de Redes SNMP
Se utiliza para crear objetos que se han de enviar atraves de la red * / TCadena::TCadena(char *Cad) i
ErrorTipo=SinError: //Sin error strcpy(Valor.Cad) ; //Copiamos la cadena Etiqueta=new TEtiquetaASN(o,O,4);//Clase Universal ( 0 ) sin constructor (01 Etiqueta 4
if ((Etiqueta==NULL) 1 I (Longitud==NULL)) //¿Hubo error? Longitud=new TLongitudASN(tam=strlen(Valor) );//Creamos la longitud
ErrorTipo=Generico;//Si. lo repoertamos i
/ * Tarea :
Crear un objeto TCadena a partir de su código BER en binario
El código BER en binario. Argumentos:
Retorno: Observaciones:
* / TCadena::TCadena(char *Datos,char * )
{
Se pasan dos parámetros para distinguirlo del otro constructor
tam=RegresaLongitud(Datos); //Obtenemos la longitud
memcpy(Va1or. &Datos [11 ,tam) : //Copiamos su valor integro ErrorTipo=SinError; //No hay errores
Valorltaml=O; ApuntadorCadenaDatos=hDatos[taml;//Recorremos los datos leidos en el código Etiquetaxnew TEtiquetaASN(0,0,4);//ClaSe universal(0) sin constructor ( 0 1 etiqueta 4
ApuntadorCadenaDatos++: Longltud=new TLongitudASN(tam): //Creamos la longitud
//Recorremos los datos leidos ApuntadorCadenaDatos++; if l(Etiqueta==NULL)I I (Longitud==NULL)) //¿Hubo error?
ErrorTipo=Generico: //Si hubo, lo reportamos
//Colocamos la marca de fin de cadena por si acaso
/ * Tarea:
Argumentos: Retorno:
Obtener el valor en alto nivel del objeto TCadena
El valor en alto nivel Observaciones:
* / char TCadena::ValorSintaxisO i static char Buffer[TAI-MAX_CADl;
if (ErrorTipoj //¿Hay error? return ("Error"); //Si lo hay, reportarlo
for (int i=O:i<TAI-MRX-CAD;i++) //Obtener el valor Buffer[il=Valor[il;
return Buffer: //Retornarlo )
/ * Tarea:
Obtener el codigo BER en binario del objeto TCadena
El buffer y su tamaño
El tamaño en bytes que ocupa el código binario BER
Argumentos :
Retorno:
Observaciones:
TDWord TCadena::CodigoBin(cbar *Buffer,TDWord TamBuf) * /
(
return O; //no cabe, no hay nada por hacer if (TamBuf<tam+Longitud->TamO+Etiqueta->TamO) //¿Cabe en el buffer?
TDWord i=Etiqueta->CodigoBin(Buffer,TamBuf); //Obtener el código de la etlqueta it=Longitud-~CodigoBin~&Buffer~il,TamBuf-i~;//Obtener el código de la longltud
116
Apéndice B. Código fuente del programa
return i+strlen(Valor);//Retornar el tamaño resultado strcpy(&BufferIil.Valor);//Obtener el valor
I
/ * Tarea:
Argumentos: Crear un objeto TIdObj equivalente al tipo Identificador de ANS.1
El valor del objeto Retorno: Observaciones:
El valor del objeto es una cadena de números separados por una serie de espacios tahuladores o retornos de carro
TId0bj::TIdOhjlchar 'CadenaParametro) * /
char *Cad=new char [strlen(CadenaParametrol+ll i char Buffer ITAM_MAX-BUFI,
unsigned long i=-1; *Buf;
ErrorTipo=SinError; //NO hay errores strcpy(Cad.CadenaParametro); //Copiamos su valor en una variable auxlliar
Buf=strtok(Cad." \r\n\t") ; //Buscams eL primer número Buffer[Ol=O; //Idicamos el fin del buffer
while (Buf'=NULL) //Mientras encontremos números ( it+;
strcat (Buffer.Buf) ; //los aiiadimos Strcat (Buffer, '' " 1 ; //los separamos con un espacio
//Los contamos
) Buf=strtok(NULL," \r\n\t"); //Buscamos el siguiente número
strcpy(Valor.Buffer); //Copiamos su valor obtenido Etiqueta=new TEtiquetaASNI0,0,6);//Clase universal ( O ) sin COnStruCtoL ( 0 1 etiqueta 6
if (lEtiqUeta==NULL) I j lLongitud==NLnL)) //¿Ocurrió algún error Longitud=new TLongitudASN(tam=i); //Creamos la longitud
ErrorTipo=Generico;//Si ocurrió, reportarlo 1
/ * Tarea :
Crear un objeto TIdObj apartir de su código BER en binario
El código en binario Argumentos:
Retorno: Observaciones:
Se reciben dos parametros para distinguirlo del otro constructor Se usa para l o s datos recibidos por la red
* / TIdObj : :TIdObj (char *Dato, char * I
tam=RegresaLongitud(DatoI; //Obtenemos el tamaño char BUFFER [TAM-MAX-BUF] ;
char BuffercltoIl71 : char 'Datos; ErrorTipo=SinError: //no hay error
Datos=ApuntadorCadenaDatos; //Obtenemos los datos BUFFER101 = O ;
ApuntadorCadenaDatos+=tam; //y reportamos lo que hemos de leer for (int x=o;i<=tam;i++) //para cada valor
( if ( i > l l //Si no es el Segundo ni el primero
{ strcat(BUFFER.ultoa~~TByte~Datos[i-ll,Buffercito,lO)~: //Simplemente lo obtenemos
If (i==O) //Si es el primero else
I
117
Administrador de Redes SNMP
seguir la convención BER-ASN.l strcat~BUFFER,ultoa~~TByte)DatoslOl/4O,Buffercito,lO~~; //lo dividimos para
) else if (i==l) //Si es el segundo
para segulr la convención BER-ASN.l strcat~BUFFER,ultoallTByte~Datos[Ol%40,Buffercito,lO~~;//Lo añadimos al primero
strcat(9UFFER." "1; //los separamos con un espacio I
Longitud=new TLongitudASNftam): //Creamos la longitud Etiqueta=new TEtiquetaASN(0,0,6);//Clase universal(0) sin COnstrUCtOr(O~ etlqueta 6
if I(Etiqueta==NULL) 1 1 (Longitud==NULL)) //¿Hubo errores? strcpy (Valor, BUFFER) ; //Copiamos el valor obtenldo
)
/ *
ErrorTipo=Generico;//Si lo hubo, lo reportamos
Tarea: Obtener el valor en alto nivel del objeto TIdObj
Argumentos: Retorno:
Observaciones: ~l valor en alto nivel
* /
i char * TIdObj : :Valorsintaxis 0
static char Buffer[TAf"MAX-CADI ; if (ErrorTipol //¿Hubo errores?
return i"Error"); //Si, lo reportamos strcpy(Buffer.Valor): //Copiamos su valor
)
/ *
return Buffer://Lo regresamos
Tarea :
Argumentos:
Retorno:
Obtener el código binario BER del objeto TIdObj
El buffer y su tamaño
El tamaño en bytes del código BER Observaciones:
TDWOrd TIdObj::CodigoBin(char *Buffer.TDWord TamBufl * /
i if (TamBuf<tam+Longitud->Tam(lrEtiqueta-rTamO) //¿Cabe?
return O; //No cabe, no hay nada que hacer TDWord i=Etiqueta->CodigoBin(Buffer,TamBuf);//Obtenemos el código de la etiqueta char Buf [TAM-MAX-BUFI ;
char *buf; i+=Longitud-sCodigosin(&Buffer[il,Ta~uf~i);//Obtenemos el códio de la longitud
buf=strtokfBuf, '' \r\n\t") : //Obtenemos el primer número strcpy(Buf.Valori; //descompondremos el valor para obtener su código
if (huf! //¿Todo bien?
else //NO
buf=strtok(NULt," \t\n\r");//Obtenemos el segundo número if (buf) //¿Todo bien?
Buffer[i]=atoi!buf)*40; //Si, construimos la primera parte
return O; //Abortamos el trabajo
BufferIil+=atoi(buf); //Si, construirnos la segunda parte y creamos el primer byte
return O: //Abortamos el trabajo else //No
buf=strtokiNULL, 'I \t\n\r") ;//Buscamos el tercer número i++;
while(buf'=NULL) //¿Encontramos un número? i //Si Buffer[i++]=atoi(buf); //Lo codificamos buf=strtok INULL, Ir " 1 ; //Buscamos el siguiente número
) return tamtLongitud->TamO+Etiqueta->TamO;//Regresamos el tamaiio del código binario BER
118
Apéndice B. Código fuente del programa
I
/ f Tarea:
Argumentos: Retorno:
Obtener el valor en alto nivel de un objeto TDireccionIP
Observaciones: El valor en alto nivel
Este objeto es heredero de TCadena * /
char TDireccion1P::ValoiSintaxisO i static char Buffer[TAM_MAX_CADI ;
char Buffercitol201 ; if (ErrorTipo) //;Hubo algún error?
BufferIOl=O; strcat~Buffer.ultoa~(TByte!Valor~Ol,Buffercito.lO~); //Obtenemos el primer byte strcat (Buffer. I' . ' ' ) ; strcat~Buffer.ultoa~iTByte~Valor~1l.Buffercito,l0ll; //Obtenemos el segundo byte strcat(Buffer,"."); //Le añadimos su punto strcat(Buffer.ultoa~iTByte!Valor~2l,Buffercito.l0~!; //Obtenemos el tercer byte Strcat (Buffer. * I . ' I ) ; //Añadimos su punto strcat (Buffer,ultoai (TBytelValor[31 ,Buffercito, 10) ) ; //Obtenemos el cuarto byte
return ("Error"1 ; //Si, lo reportamos
//Le añadimos su punto
return Buffer;//Regresamos el resultado
/ * Tarea :
Obtener el valor en alto nivel del objeto TTicksReloj Argumentos: Retorno:
Observaciones: El valor en alto nivel
Este objeto es heredero de TEnterO * / char + TTicksReloj::ValorSintaxis(l
statlc char BufferlTAM-MAX-BUFI ;
TDWord ValorA=Valor; char Bufferclto[l81;
i
Buffer[Ol=O;
Strcat (Buffer,'' Días I " ) ;
strcat (Buffer,itoa( (ValorA/8640000! ,Buffercito,lO) 1 ; //Calculamos los días
strcat (Buffer,itoa((ValorA=ValorA%86400OO!/36OOOO,Buffercito,10l~;//Calculamos las //aAadimos la palabra Días
holas strcat (Buffer," Horas " I : Strcat !Buffer,itoa((ValorA=ValorA%36OOOO~/6OOO,Buffercito,lOlI://Calculalnos los
strcat (Buffer. " Minutos ' O ; //Añadimos la palabra minutos strcat ~Buffer.itoa~~ValorA~ValorA%6000~/lOO,Buffercito,lO~l;//Calculamos los
strcat (Buffer, '' Segundos" ! ; //Añadimos la palabra segundos
//Añadimos la palabra Hora5
minutos
segundos
return (Buffer);//Regresamos el resultado I
/ * Tarea :
Crear un objeto TVarBind equivalente el tipo VarBind ASN.l
El nombre y s u valor Argumentos:
Retorno: Observaciones:
TvarBind::TVarBind(TIdObj *nombre,TTipo *valor1 * I
i ErrorTipo=SinError;//No hay error
119
Administrador de Redes SNMP
Destruye!Etiqueta);//Destruye la etiqueta creada con los constructores de herencia
Etiqueta=new TEtiquetaASN(0,1,1G);//Clase Universal(0) con Constructor íli etiqueta 16 Longitud-new TLongitudASN!tarn=nombre->TamO+valor->Tamo+
Destruye(L0ngitud); //Destruye la longitud creada con los constructores de herencia
nonbre->Etiqueta->TamO+ valor->Etiqueta->Tam(!+ nombre->Longitud->TamO+ valor >Longitud->Tam()); //Obtenemos la longitud
Nombre=nomhre; //Copiamos el nombre Valor=valor; //Copiamos el valor if ((Etiqueta==NULL) 1 1 ILongitud==NULL))//¿Hubo error?
ErrorTipo=NoMemoria;//Si hubo, lo reportamos
Tarea: Crear un objeto TVarBind a partir de su código binario BER
El código binario BER Argumentos:
Retorno: Observaciones:
TVarBind::TVarBind(char *Dato) i TDWoId tarn=RegresaLongitud(Datoi; char *DatoExtra=ApuntadorCadenaDatos+tam; ErrorTipo=SinError; //No hay error
Nomhre=new TIdObj (Dato,Dato) ; Dato=ApuntadorCadenaDatos+l;
Dato=ApuntadorCadenaDatos+l; switch(ApuntadorCadenaDatos[D1) //Obtenemos el valor dependiendo de:
//Obtenemos el identificador
i case 2: //Etiqueta de Entero Valor=new TEntero(Dat0); break;
Valor=new TCadena (Dato, Dato) ; break;
Valor=new TNULLO; break;
Valor=new TIdObj (Dato,Dato) ;
case 6 4 : //Etiqueta de Direccion IP break:
Valor=new TDireccionIP(Dat0,Dato);
case 6S://Etiqueta de Contador break;
Valor=new TContador(Dat0); break;
case 66://Etiqueta de Medidor Valor=new TMedidor(Dat0); break;
ca8e 67://Etiqueta de TicksReloj Valor=new TTicksReloj (Dato) ;
case 68://Etiqueta de Comodin break;
Valor=new TComodin (Dato, Dato) ; break;
case 4: //Etiqueta de cadena de OCtetOS
case 5: //Etiqueta de NULL
case 6: //Etiqueta de Identlficador de Objeto
)
Longitud=new TLongitudASNítam); Etiqueta=new TEtiquetaASN(0.1.16); //Creamos la etiqueta
If !(Etiqueta==NULLl 1 I (Longitud==NULLii //iOcurrio algún error?
//Creamos su longitud ApuntadorCadenaDatos=DatoExtra; //reportamos los datos que hemos leido
ErrorTipo=NoMemoria;//Si ocurrio. lo reportamos I
/ * Tarea :
120
Apéndice B. Código fuente del programa
Obtener el valor en alto nivel del objeto TVarBind Argumentos: Retorno:
Observaclones: El valor en alto nivel
* / char * TVarBind::ValorSintaxis(l
static char Buffer[TAM-MAX-BUFl ;
if (ErrorTipo) //iHay error?
Buffer[Ol=O; strcat(Buffer.Nombre~>ValorSintaxisO)://Obtenemos el valor del indetificador strcat(Buffer,": " ) ; //Lo separamos strcat(Bu€€er,Valor~>ValorSintaxisO)://obtenemos el valor de su valor
return ("Error"); //Si lo hay, reportamos
return Buffer;//Reqresamos el resultado 1
/ * Tarea :
Argumentos:
Retorno:
Obtener el código Binario BER
El buffer y su tamaAo
El número en bytes que ocupa el código Observaciones:
TDWord TVarBind::CodigoBin(char *Buffer.TDWord TamBuf! * /
i if (TamBuf<tam+Longitud~zTamO+Etiqueta-rTamO)//¿Cabe el código en el buffer?
return O;//No, no hay nada que hacer TDWord i=Etiqueta-sCodigoBin(Buffer.TamBuf);//Obtenemos el código de la etiqueta
i+=Longitud-zCodigoBin(&Buffer[il,TamBuf-i!;//El código de la longitud i+=Nombre->CodigoBin(&Buffer[il,TamBuf-i);//El código del nombre i+=Valor->CodigoBin(&Buffer[i],TamBuf-i!;//El código del valor
return i://Regresamos el tamaño del código 1
/ * Tarea :
Argumentos:
Observaciones: Retorno:
Destrur el objeto TVarBind
El destructor que hereda de TTipo libera la etiqueta y su longitud * /
{ TVarBind::-TVarBindO
Destruye (Nombre) ;//Destruimos el nombre Destruye(Valor)://Destruimos el valor
) ;
Í* Tarea :
Crear un objeto TVarBinclNodo para poder crear el obleto TVarBindList Argumentos:
Retorno: Observaciones:
El código Binario BER
* /
I TVarBindN0do::TVarBindNodoíchar 'Dato) :TVarBind(Dato)
Srguiente=NULL: /ÍSiguiente es NULO
/ * Tarea:
Encontrar el valor en alto nivel de la lista
121
Administrador de Redes SNMP
Argumentos : Retorno:
Observaciones: Valor en alto nivel
* / char TVarBindNodo::ValorSintaxisO i
if (ErrorTipo) //¿Hay error?
BufferPrivadolOl = O : strcat(BufferPrivado.TVarBind::ValorSintaxisO);//Ohtener el valor para este nodo if (Siguiente'=NULL)
return ("Errorll) ://Si, reportarlo
i strcat!BufferPrivado, "\n") ; strcat(BufferPrivado.Siguiente->ValorSintaxisO);//Ohtener el resto de los valores
i return BufferPrivado://Regresar el resultado
/ * Tarea :
Insertar otro nodo
~l nombre y su valor Argumentos:
Retorno: Observaciones:
* / void rVarain~odo::Inserta(TldObj +nombre,TTipo *valor) i if (Siguiente==NLILL) //;se puede insertar en forma inmediata?
e l s e Siyuiente=new TvarBin~odo(nombre.valor);//Si. lo insertarnos
Siguiente-zInserta(nombre,valor);//No hacemos una lamada recursiva 1
/ * Tarea:
Argumentos:
Observaciones: Retorno:
Insertar otro nodo a partir del código binario
El código binario
* /
( void TVarBindNodo::Inserta(char 'Dato)
if :Siguiente==WLL)//(Se puede insertar en forma inmediata?
else Siguiente=new TVarBindNodo(Dato)://Si. lo insertamos
Siguiente-zInserta(Dato);//No. hacemos la llamada recursiva 1
/ * Tarea:
Argumentos : Retorno:
Observaciones:
Obtener el nombre de la variable en alto nivel
La cadena con el nombre de la variable
* /
{
i
/ *
inline char * TVarBindNodo: :Nombrevariable 0
return Nombre->valorSintaxisO: '
Tarea:
Argumentos : Obtener el código hinario BER
El buffer y su tamaiio
122
Apéndice B. Código fuente del programa
Retorno: El tamaño en bytes del código
Observaciones:
TDWord TVarBindNodo::CodigoBin(char *Buffer.TDWord TamBuf) * /
i TDWord i=TVarBind::CodigoBin(Buffer,TamBuf)://Obtenemos el código de este nodo if (Siguiente)//¿Existen más nodos?
forma recursiva ~+=Siguiente->CodigoBín(&Buffer[il,TamBuf~i~l);//Si, obtenemos los que siguen en
i
/ *
return i;//Regresamos el valor obtenido
Tarea: Construir un objeto WarBindList equivalente al tipo VarBindList de ASN.l
El nombre y v a l o r del primer elemento Argulnentos:
Retorno: Observaciones:
* / Se manda llamar a su ansestro
TvarBindList::TVarBindList(TldObj *nombre,TTipo *valor!
( )
/ *
:TVarBindNodo (nombre, valor)
Tarea:
Argumentos:
Retorno: Observaciones:
Construir un ob'jeto TVarBindLiSt a partir de su código binario BER
El código binario
* /
i TVarBindList::TVarBindList!char *Dato):TVarBindNodo(l
RegresaLongitudlDato);//Obtenemos la longitud Siguiente=wLL;//Asumimos que es el último if (ApuntadorCadenaDatos[Ol==Ox3O~//¿Es correcto el tipo?
while !ApuntadorCadenaDatoslOl==Ox30)//¿Sigue otro? TVarEin~odo::TVarBindNodo(++ApuntadorCadenaDatos!;//Si, llamamos al ansestro
(
1 Inserta(++ApuntadorCadenaDatosl; //Si sigue otro, lo creamos
/ * Tarea :
Argumentos: Retorno:
Observaciones:
Obtener el tamaño del código binario BER
El tamafio en bytes del código BER en binario
* /
{ TDWord TVarBindList::TamO
char Buffer [TAM_M=-BUFI ;
tamcTVarBindNodo::CodigoBin(Buffer.TAM_MAX_BUF~;//Obtenemos el códlgo BER y el nos regresa
return tam;//Y lo reportamos su tamaño
)
/ * Tarea:
Argumentos:
Retorno:
Obtener el código binario BER
El buffer y su tamaño
123
Administrador de Redes SNMP
El tamaño en bytes del código Observaciones:
* / TnWord TVarBindList::CodigoBin(char *Buffer.TDWord TamBuf) i TEtiqUetaASN EtiqAux(O,l.l6);//Creamos una etiqueta TLongitudAsN LongAux(tam);//Creamos su longitud TDWord i=EtiqAux.CodigoBin(Buffer,TamBuf);//Obtenemos el código de la etiqueta i+=LongAux.CodigoBin~&BufferIil,TamBuf-i~;//Obtenemos el código de la longitud i+=TVarBindNodo::CodigoBinI&BufferIil,TamBuf~i);//Obtenemos el código de la lista
return i;//Regresamos su tamaño encontrado )
/ * Tarea :
Argumentos:
Observaciones: Retorno:
Crear un objeto TPDU equivalente al tipo PDU de ASN.l para SNMP
La secuencia, el error. s u indice y la lista de objetos
* /
i TPDU::TPDUlTEntero +secuencia,TEntero *error.TEntero *indice,WarBindList *lista!
ErrorTlpo=SinError; //No hay error
ErrOr=errOr; //Obtenemos el error Secuencia=secuencia; //Obtenemos la secuencia
IndiceError=indice; //Su indice ListaVarBind=lista; //La lista
Longitud=new TLongitudASN(tam.-Secuencia->TamO+ Etiqueta=new TEtiquetaASN(0,1,16);//Creamos la etiqueta
Error- >Tam() + IndiceError- >Tam 1) + ListaVarBind->Tamo+ Secuencia->Etiqueta->TamO+ Error->Etlqueta->TamO+ IndiceError->Etiqueta->TamO+ LlstaVarBind->Etiqueta->TamO+
Error >Longitud- >Tam ( ) + Secuencia->Longitud->TamO+
IndiceError->Longitud->TamO+ ListaVarBind->Longitud->TamO );//Creamos su longitud
If (íEtiqueta==NULL) 1 1 (Longitud==NULL))//¿Hubo algún error? ErrorTipo=Generico;//Si lo hubo, lo reportamos
)
/ * Tarea :
Argumentos:
Retorno: Observaciones:
Crear un objeto TPDU a partir de su código Binario BER
El código BER en binario
* /
i TPDU::TPDU(char 'Dato)
Tnword tam=RegresaLongitud(Dato);//Obtenemos su tamaño char Buffer [TAM-MAX-BUF] :
ErrorTipo=SinError;//No hay error Longitud=new TLongitudASN(tam!;//Creamos su longitud Etiqueta=new TEtiquetaASN(Oll,16!;//Creamos su etiqueta if (ApuntadorCadenaDatos[Ol==OxO2) //¿ES un entero de Secuencia?
i //Si lo es
memcpyiBuffer,ApuntadorCadenaDatos.tam); ApuntadorCadenaDatos++;
Secuencia=new TEntero(ApuntadorCadenaDatos);//Creamos la secuencia
if (ApuntadorCadenaDatos~Ol==OxO2) //¿Es otro entero?. [Contiene Error) --ApuntadorCadenaDatos;
i Error=new TEntero(++ApuntadorCadenaDatos);//Creamos su error
124
Apéndice B. Código fuente del programa
if (ApuntadorCadenaDatos[O]==OxO2) //¿Es el otro entero con el Indice de error? --ApuntadorCadenaDatos;
IndrceError=new TEntero (++ApuntadorCadenaDatosi; //Obtenemos el indice
if lApuntadorCadenaDatos[Ol==Ox3O~//¿Hay lista?
i --ApuntadorCadenaDatos;
ListaVarBlnd=new TVarBindList(++ApuntadorCadenaDatosl;//Obtenemos la lista {//Si la hay
I )
) 1
if I lEtiqueta==NULL) I I (Longitud==NULL) 1 1 (ListaVarBind==NULL) 1 1 (Error==NULL) 1 I lIndiceError==NULLi 1 I (Secuencia==NULL))//;Hubo error?
ErrorTipo=NoMemoria;//Si lo bubo, lo reportamos
/ * Tarea!
Obtener el valor en alto nivel Argumentos : Retorno:
Observaciones: La cadena con el valor en alto nivel
char *TPDU::ValorSintaxisO * /
( static char Buffer[TAM-MAX-BUFI ;
if lErrorTipo)//¿Hay error?
Buffer[Ol=O; strcatlBuffer,L~staVarBind-~ValorSintaxisl~~;//Obtenemos su valor
return 1"Error") ;//Si lo hay, lo reportamos
) return Buffer://Lo regresamos
/ * Tarea :
Argumentos:
Retorno:
Observaciones:
Obtener el código binario BER
EL buffer y su tamaño
El tamaño en bytes del código binario BER
TDWord TPDU::CodigoBin(char +Buffer,TDWord Tamufl * /
i TDWord i=Etiqueta-sCodigoBin(Buffer,TamBuf); //Obtener el código de etiqueta ~+=Longitud~~CodigoBinl&Bufferlil,Ta~uf~i~;//Obtener el código de longitud i+=Secuencia-~CodigoBinl&Buffer~il.TamBuf-i~; //Obtener el código de secuencia ~+=Error->CodigoBin(&Buffer[i],TamBuf-i); //Obtener el código de error i+=IndiceError-~CodigoBinl&Buffer[il.TamBuf-il; //Obtener el código de índice de error i+=ListaVarBind~~CodigoBin(hBuffer[il,TamBuf-i~;//Obtener el código de la lista
return i;//Retornar el tamaño del código
/ * Tal ea :
Obtener el tamaño en bytes del código binario BER Argumentos: Retorno:
Observaciones: El tamaño en bytes del código binario BER
TDWord TPDU::TamI) * /
i char Buffer [TAb_MAX_BUF] ;
tam=CodigoBinlBuffer,TAM-MAX-EUF);//Obtenemos el código return tarn;//regresamos el tamaño
1
125
Administrador de Redes SNMP
/ * Tarea :
Crear un objeto TMensajeSNMP a partir del código binario BER Argumentos:
Retorno : Observaciones:
El código binario BER
* / TMensajeSNMP: :TMensa]eSNMP(char *Datos) { TDWord tam=RegresaLongitudlDatos);//Obtenemos su longitud TEntero *VersionSNMP;//Necesitamos ver su versión ErrorTipo=SinError; //No hay error hasta aqui Destruye(Etiqueta!; //Destruye Etiqueta
Etiqueta=new TEtiquetaASNi0,1,16);//Crea su etiqueta Destruye(L0ngitud); //Destruye longitud
Longitud=new TLongitudASN(tam);//Crea su longitud if lApuntadorCadenaDatoslO]==2) //¿Hay campo de versión?
{//S1 hay VersionSNMP=new TEnterol++ApuntadorCadenaDatos);//Crear la versión
{//Si es correcta if lstrcmplVersionSNMP-sValorSintaxisO,"O")!=O)//¿Es correcta?
Comunidad=NLlLL; Dato=NULL;
if (*(ApuntadorCadenaDatos-l)==4) //¿Viene un cadena?
switch((TByte!*(ApuntadorCadenaDatos-l))//¿Qu biene de lista de datos?
case OxaO://Viene GetRequeSt
1
Comunidad=new TCadena(ApuntadorCadenaDatos,NULL);//Si. obtener la comunidad
{
Dato=new TGetRequest-PDU(ApuntadorCadenaDat0.s); break;
Dato=new TGetNextRequest-PDUiApuntadorCadenaDatos); break;
Dato=new TGetResponse-PDU(ApuntadorCadenaDat0s); break;
Dato=new TSetRequest-PDU(ApuntadorCadenaDat0s); break:
Dato=new TPDUlApuntadorCadenaDatos); break;
Dato=NULL;//QuiCn sabe que vino.
case Oxal://Viene GetNextRequest
case OxaZ://Viene GetResponse
case Oxa)://Viene TSetRequest
case Ox30://Viene un TPDU desconocido
default :
! i f l(Etiqueta==NULL) 1 I (Longitud==NULL))//¿Hubo errores?
) ErrorTipo=NoMernoria;//Si, l o s reportamos.
/ * Tarea:
argumentos:
Retorno: Observaciones:
Crear un MensajeSNMP
La comunidad y la lista de variables
TMensajeSNMP::TMensajeSNMP(TCadena *comunidad,TPDU *dato) * /
i Destruye (Etiqueta) ; Destruye (Longitud) ; ErrorTipo=SinError; Comunidad=comunidad;//Copiamos la comunidad Dato=dato;//Copiamos la lslta
126
Apéndice B. Código fuente del programa
Etiqueta=new TEtiquetaASN(O,l.l6);//Creamos la etiqueta Longitud=new TLongitudASN(tam=Comunidad->Tamo+
Comunidad->Etiqueta->TamO+ Comunidad->Longitud->Tamo+ Dato->TamO+3);//Creamos la longitud
if ((Etiqueta==NULL) / I (Longitud==NULL))//;Hubo error? ErrorTipo=NoMemoria;//SI. lo reportamos
/ * Tarea:
Obtener su valor en alto nivel Argumentos: Retorno:
Observaciones: Valor en alto nivel
char *TMensajeSNMP::ValorSintaxisO
static char Buffer[TAM-MAX_BUFI ;
* /
(
if (ErrorTipo)//¿Hay error?
Buffer[Ol=O; strcat(Buffer,Dato-~valorSintaxisO);//Obtnemos su valor
return ("Error") ;//Si, lo reportamos
return Buffer;//Lo reportamos )
/ * Tarea:
Obtener el código binario BER
El buffer y su tamaño
El tamaño en bytes del código.
Argumentos:
Retorno:
Observaciones:
TDWord TMensajeSNMP::CodigoBinlchar *Buffer.TDWord TamBuf) * /
( if (ErrorTipo)//;Hay error?
return O;//Si, lo reportamos TEntero Verslon((TDWord)O);//Creamos la versión que soportamos TDWord i=Etiqueta~>CodigoBin(Buffer,TamBuf);//Codificamos la etiqueta i+=Longitud->CodigoBin(&Buffer[il.TamBuf~i);//Codificamos la longitud
i+=Comunidad-~CodigoBin~hBuffer~il,TamBuf-i~;//Codificamos la comunidad i+=Version.CodigoBin(&Buffer[i],TamBuf-i);//Codificamos la versión
i+=Dato-sCodigoBin(&Buffer[il,TamBuf-i);//Codificamos el mensaje return i;//Regresamos el tamaño del código.
ARCHIVO DE ENCABEZADO PRINCIPAL (SNMPADMI.H) #define Entrar 110 #define MENU-AYUDA 100 #define MENU_INDICE101 #define ICONO-LOGO 200 #define SD-FILESAVE32513 #define SD-FILEOPEN32512 #define ID-FNAME4095 #define ES-OEMCONVERT 0x00000400L
#define ID-FPATH 4094 #define ES~AUTOHSCROLLOx0000008OL
#define ID-FLIST 4093 #define ID-DLIST 4092 #define BS-DEFPUSHBUTTON OxOOOooOOlL #define CM-EXIT 24340 #define BITMAP-DOS 1 0 0 #define BITMAP-GETWAY 101 #define BITMAP-TERMINAL 102
127
Administrador de Redes SNMP
#define CURSOR-TERMINAL 103 #define CM-NUEVO 104 #define MENU-PRINCIPAL 105 #define CM_SOCKET_LISTO_LEER 106 #define CM-PEDIR-INFORMACION 107 #define CM-RECIBIR-MENSAJE 108 #define ID-LISTA-VARIABLES 109 #define DIALOGO-VARIABLES 110 #define CM-PARAR 111 #define ID-PREGUNTAR #define ID-GRUPOS
112
#define ID-CAJA-GRIS-1 114 113
#define DIALGO-GRUPOS #define ID-CREAR-INFORMACION 116
115
#define CM-ENVIAR-VARIABLES 117 #define CM-ENVIAR-TABLA #define CMVER-TABLA
118 119
#define CM-COMANDO-GRUPOS 120 #define CM-INSERTAR 121
#define CM-DIRECCION-IP #define CM-COMUNITY 122
123 #define CM-ABRIR 124 #define CM-GUARDAR #define DIALOGO-COMUNITY 126
125
#define ID-DIRECCION-IP 127 #define ID-DIRECCION-NOMBRE 128 #define ID-COMUNITY 129 #define ID-BG-INFORMACION 130
#define DIALOGO-DIRECCION-IP 132 #define ID-BG-COMUNITY 131
#define DIALOGO-INSERTAR 133 #define WM-CERRAR-TABLA WM-USER + O #define WM-PEDIR-VARIABLES WM-USER + 1 #define WM-PEDIR-TABLA WM-USER + 2 #define WM-RECIBIR-VARIABLE WM-USER + 3 #define WM-RECIBIR-TABLA WM-USER + 4 #define WMVER-TABLA WM-USER + 5
ARCHIVO FUENTE SNMPADMI.CPP #Include <owl.h> #include <strstream.hz #include <bwindow.hz #include rstdio.h> #include <strlng.h> #include sbgrpbox.h> #include ccombobox.h> #Include cbbutton.h> #include <bstatic.h> #Include <edit.h> #Include cflledial.h>
#include "wlnsock.h" #include "ber.h" #include "snmpadmi . h '
#defme TAM-COMUNITY 50 int OX=O.OY=O; Int TamHorizontalVentana=O; int TamVerticalVentana=O; int TamHOrizOntalMapa=10000; int TamVerticalMapa=lOOOO; int PresicionHorizontal=lO; int Presicionvertical=lO; BOOL Estapresionado; enum TSintaxis (PorOmision=O.
DireccionIP, DlreccionFisica,
Entero32,
128
Apéndice B. Código fuente del programa
Tiempo) :
typedef struct [ TDWord DireccionIP:
]TDatosTerrninal;//Tipo para el intercambio de informacih con el diálogo char Cornunity [TAM-COMUNITYI ;
DatosTerminal
HWND TDWord TDWord TDWord TDWord TDWord TDWord TWord char
TDWord char
Ventana; //Manejador de la ventana global para enviarle mensales Secuencia=l; //Secuencia para llevar control de las secuencias
MensajesSNMP=O; / / Secuencias[l001; //Lista de las secuencias recibidas
VecesOs1o=O; PaquetesRecibidos=O: //Numero de paquetes recibidos
MaximoTiempoEspera=S; Puerto=161;
NombreGrupoProceso[1001 i *Comunity="public":
Direccion-IP:
TDatosTerminal DatosTerminal://Su variable
/ * Tarea:
Determinar si el objeto recibido ateriormente y este nuevo pertenecen a la misma columna de la tabla
Argumentos:
Retorno:
Observaciones:
Los dos objetos
S I /NO
y si se encuentra uno que no lo es se regresa falso. Solo el último El algoritmo es sencillo, consiste en verificar que cada elemento sea igual
cambia. * / BOOL MismaColumna(char far ObjetolIl ,char Objeto211 i char *Varl=new char [strlen(Objetol)+ll.+Var2=new char Istrlen(Objeto2)+1]; strcpy!Varl.Objetol! : strcpy(Var2.0bjeto2); TByte L [201 : L[O1=atoi!~trtok(Varl," \r\n',)); for (int i=l;i<lO;i++)
( char *CadAux=strtok(NULL, I' \r\n") ; it 1 'CadAux)
delete (Varli : delete (Var2) : return FALSE;
(
1 L[il=atoi(CadAux):
) L[lOI=atoi(strtok(Var2," \r\nl')): for (i=ll;i<2O;i++)
( char *CadAux=strtok(NULL, '' \r\n$I) ; if ! !CadAux)
i delete (Varl) ; delete (Var2) ; return FALSE:
I L[il =atoi (CadAux) ;
I delete IVarl! ; delete lVar2) ;
for li=O;iclO:i++i
129
Administrador de Redes SNMP
if (~[il !=LIi+lol) return FALSE;
return TRUE; I
/ * Tarea :
Argumentos:
Observaciones: Retorno:
Insertar una secuencia en la lista
+ / void InsertarSecuencias(1 i int i=O;
while (Secuencias[i++l j ;
Secuencias[i-ll=Secuencia; if (iclol)
i / *
Tarea : Verificar si existe un valor de secuencia en la lista de espera
El valor de la secuencia Argumentos:
Retorno: SI/NO
Observaciones: * /
i BOOL ExisteSecuencia(TDW0rd S)
int i=o; while (Secuencias[il 1
i if (Secuencias [il = = S )
i while (Secuenciaslil ( Secuencias [il =Secuencias [ i + l l ;
) i++;
) return TRUE;
1++:
) return FALSE;
1
/ * Tarea :
Eliminar los espacios y tabuladores de una cadena Argumentos:
Retorno:
Observaciones:
La cadena
La cadena sin espacios ni tabuladores
* / char *SinEspaciosichar Cadenall) i int i=O. j=1;
for (;jcstrlen(Cadena);j++l
whlle ((Cadenari] ' = ' ')&&(Cadena[il '='\t')hh(icj))
if ((Cadenalil==' ' ) 1 1 (Cadena[il=='\t'l)
i I++:
( Cadena[il=Cadena[jl;
) Cadena [ j 1 = ' ' ;
130
Apéndice B. Código fuente del programa
) for (i=strlen(Cadena)-1; (Cadena[il==' ' ) 1 1 (Cadena[il=='\t'!;Cadenali--l=Oi;
1 return Cadena;
/ * Tarea:
Argumentos:
Retorno:
Observaciones:
Determinar la sintaxis no definida en ASN.l de un objeto
El objeto
Su sintaxis
* /
í TSintaxis LaSintaxis!char 'cad)
if (cad! I if ! Istrcmp(cad. "DireccionFísica"j j
if 1 'strcmp!cad, "DireccionIP"! ) return IDireccionFisica) ;
return (DireccionIP); if [Istrcmp(cad,"Entero32") j
if I lstrcmp(cad, "Tiempo") j return !Entero32):
return !Tiempo! ;
return PorOmision; )
1
/ * Tarea :
Proporcionar las reglas de una variable SNMP Observaciones:
Esta clase permite enlistar una serie de variables SNMP. las cuales contienen un nombre en alto nivel de abstracción y la ruta correspondiente al árbol definido en la base de datos de administración (MIB!. De manera adicional contiene la sintaxis de alto nivel que debe usarse para
presentar los datos de manera adecuada
class "variable * /
I protected: public:
char + Nombre; //Nombre de Alto Nivel de la variable SNMP char * Ruta; //Ruta en la MIB TSintaxis Sintaxis; //Sintaxis de alto nivel TVariable * Siguiente; //Liga a la siguiente variable TVariable ( ) ;
TVariable(char *,char *,TSintaxis,Wariable * ) ; virtual void Insertar(char +.char *.TSintaxis);
char * char f NombreVariable(char + ) ;
"Wariable ( 1 ; NombreVariable!char *.TSintaxis &j;
1;
/ * Tarea:
Construlr una variable SNMP definida en la MIB Argumentos: Retorno: Observaciones:
Este constructor inicializa todo a la forma más sencilla * / TVariab1e::TVariableO ( Nombre=Ruta=NLlLL; Siguiente=NULL;
13 1
Administrador de Redes SNMP
) Sintaxis=PorOmision;
/ * Tarea :
Argumentos:
Retorno: Observaciones:
Crear una variable SNMP
Notbre,Ruta,Sintaxis y la variable que le sigue
Tvariable::TVariable(char *nombre,char *ruta.TSintaxis sintaxis.Tvariable *siguiente=NLILL) * /
(
Nombre=new char Istrlen(nornbrejtl1 i Sintaxis=sintaxls;
if \Nombre)
Ruta=new char [strlen(ruta)+ll; if (Ruta1
strcpy(Nombre,nombrel;
i strcpy(Ruta.rutaj; for (int i=o;i<strlen(ruta);i++)
if (Ruta[il=='.') Ruta[il=' ' ;
1
)
/ *
Siguiente=siguiente:
Tarea: Insertar una variable a la lista.
Nombre,Ruta y sintaxls Argumentos:
Retorno: Observaciones:
Siempre inserta al final de la lista.
* / vold TVarlable::Insertar(char *nombre,char *ruta,TSintaxis sintaxis)
Utiliza un algoritmo recursivo por simplicidad
i if (Siguiente)
else sigulente->Insertar(nombre,ruta,sintaxis);
Siguiente=new TVariable(nombre,ruta,sintaxis); 1
/ * Tarea :
Argumentos:
Retorno:
Obtener el nombre de una variable en la lista a partir de su ruta
La ruta de la variable
El nombre de la varible Observaciones:
char f TVarlable::NombreVariable(char *ruta) * /
{ int i=O; lnt Cond=l;
//comparamos caracter por caracter en la ruta for l;icstrlen(Ruta) :i++)
if (Cond&&(ruta[i]==' ' I 1 //¿son iguales?
if (Siguiente)//No son iguales, ;Hay otra varible en la lista?
Cond=Cond&&(Ruta[il==ruta[il I i
return Nombre;//Si, regresamos el nombre
return Siguiente->NomhreVariable(ruta);//Si la hay, regresamos lo que encuentre la alguente varible
como su ruta return ruta://No la hay, regresamos la ruta misma, ya que su nombre puede ser interpretado
132
Apéndice B. Código fuente del programa
)
/ * Tarea :
Encontrar el nombre de una variable y su sintaxis
La ruta Argumentos:
Retorno: Nombre de la varible
Observaciones: Su sintaxis
* /
{
~a sintaxis se regresa por la variable de argumento sintaxls
char TVariab1e::NombreVariableíchar *ruta.TSintaxis &sintaxis)
int i=O: int Cond.1;
//Comparamos la ruta caracter a caracter for (;icstrleníRuta);i++)
if íCondh&(ruta[i]==' 'il//;Son iguales? Cond=Cond&&íRuta[il==ruta[il) ;
i //Si son iguales
return Nomhre;//Retornar el nombre sintaxis=Sintaxis; //Retornar la sintaxis
) if (Siguiente)//No son iguales ¿Hay m6s viriables?
siguiente return Siguiente->NombreVariable(ruta,sintaxis);//Si, Regresamos lo que diga la
slntaxis=PorOmision;//No hay más variable, regresamos la sintaxis por omision return ruta;//Regresamos la ruta
)
/ + Tarea:
Destruir una variable Argumentos:
Ohservaciones: Retorno:
TVariab1e::-TVariableO * /
( Destruye (Nombre) ; Destruye íRuta) ; Destruye(Si9uiente) ;
)
/ * Tarea:
Observaciones: Proporcionar el manejo de grupos de variables SNMP
Los grupos de variables, corresponden a diferentes ramas del árbol de la MIB Las columnas son conjuntos de variables que forman parte de una tabla, las cuales
tienen la misma estructura.
class TDefinlclonGrupos
protected:
* /
(
char * NombreGrupo; //Nombre del grupo TVariable * Variable; //Lista de variables ?Variable Columna;//Lista de columnas TDefinicionGrupoS(F1LE *,char * ) ;
TDefinicionGrupos *Siguiente; //Siguiente grupo TDefinicionGrupos(char * ) ; virtual char Grupo0 {return NombreGrupo;); TVariable PrimerVariableGrupo(char [ I ) ; TVariable * PrimerColumaGrupo(char [ I ) ;
char * NombreVariable(char *,TSintaxis & ) ; NombreVariable(char * ) ;
public:
char
133
Administrador de Redes SNMP
char NombreColumna(char *,TSintaXiS 61;
-TDefinicionGrupos(i; 1;
/ * Tarea:
Crear un grupo de variables a partir de una base de datos MIB definida en un archivo y que continua de otros grupos ya ablertos.
Argumentos:
Retorno: Ohservaclones:
El archivo y la informaci6n anterior leida para continuar leyendo
Este constructor sirve de apoyo al constructor público, el cual tiene que insertar en su lista los siguientes grupos.
* /
i TDefin=clonGrupos::TDefinicionGrupos(FILE *Definicion,char *Buffer)
char 'Buf; Variable=Columna=NULL; //Asumimos que est8 vacio NombreGrupo=NULL; Siguiente=NULL; Buf=strtok(NULL,' \t\r\n;");//Obtenemos el nombre del grupo NombreGrupo=new char [strlen(Buf) t l l ;
while~fgetsiBuffer,2OO,Definicionl)//Mientras podamos leer el archivo strcpy(NombreGrupo,Bufi; //Asignamos el nombre
( Buf=strtokiBuffer, '' \t\r\n;"l ;//Obtenemos un dato
if (strclnp(Buf,"Grupo"i==Oi//¿Es la palabra reservada Grupo? if (Buf)
( if iNombreGrupo!//¿Ya tengo nombre?
(//Si, entonces hay que insertar otro grupo.
pasamos el archivo y la última linea leida Siguiente=new TDefinicionGruposiDefinicion,Bufferl;//Creamos el otro grupo,
) return;//Terminamos
else//No tengo nombre (
Buf=strtok(NULL," \r\n\t"i;//Lo obtengo de la linea NombreGrupo=new char Istrlen(Buf)+ll ;
strcpy(NombreGrupo,Bufl;//Me lo asigno
) 1
else if (strcmp(5uf. "Variable"i==O)//No es Grupo, ¿ES Variable? ( char *Nombre; char *Ruta;
Nombre=strtok [NULL, I' \r\n\t"l : //Obtenemos su nombre Ruta=strtok(NULL, " ; " ) ; //Obtenemos su ruta Sintaxis=strtok(NULL," \r\n\t:"l; //Obtenemos su sintaxis if ((Nombre)h&(Rutail//Encontramos nombre y ruta
char *Sintaxis:
i //Si los encontramos slnEspacios(Nombre);//Les quitamos los espacios por si tienen SlnEspacios (Ruta) ; ~f (Variable)//¿Ya Cree una variable antes?
(//Si ya la cree
>Insertar(Nombre,Ruta,~aSintaxis(Sintaxis));//Inserta la nueva Variable-
) else
(//No he creado variables antes. Variable=new TVariable(Nombre,Ruta,LaSintaxis(Sintaxisll;//Creo la primera
variable )
else if istrcmp(Buf. "Columna")==OI//No es variable ¿ES columna?
134
Apéndice B. Código fuente del programa
( char *Nombre: char *Ruta;
Nombre=strtok(NULL. '' \r\n\t") ; //Obtengo su nombre Ruta=strtok(NLILL.";"); //Obtengo su ruta Sintaxis=strtok(NULL," \r\n\t;"); //Obtengo su sintaxis if ((Nombrel&&(Ruta)) //;Encontre nombre y ruta?
char 'Sintaxis;
i SinEspacios(Nombrel;//Le quitamos espacios SinEspacios (Ruta) ; if (Columna1 //¿Ya cree la columna?
//Si encontré nombre y ruta
{//Si ya está creada.
)
(
Columna-zInsertar(Nombre,Ruta,LaSintaxis(Sintaxis));//Inserto la nueva
else//no esta creada
la nueva Columna=new TVariable(Nombre,Ruta,LaSintaxis(Sintaxis));//La creo a partir de
/ * Tarea:
Crear una lista de grupos a partir de un archivo quer contiene una base de datos MIB con una sintaxis preestablesida
Argumentos:
Retorno: Observaciones:
El nombre del archivo con todo y ruta.
Para ver la sintaxis preestablecida vea la ayuda del programa.
TDefinicionGrupos::TDefinicionGrupoS(char 'Nom) * /
{ FILE *Definicion=NULL; char Buffer[Z001 ; char *Buf;
Variable=Columna=NuLL; NombreGrupo=NULL: Siguiente=NULL; Definicion=fopen(Norn,"rt"l://Abrimos el archivo if !'Definicionl//;Se abrió correctamente?
return://No. entonces abortamos la operación while (fgets(Buffer,200,Definicion))//Mientras se puede leer el archivo
Buf=strtok(Buffer." \t\r\n;");//Buscamos la primera palabra reservada if (Buf) //Encontramos una palabra
i
i if !Buf[Ol=='/')//;Es comentario?
continue;//Si es comentario, nos lo saltarnos lf (strcrnp (Buf, "Grupo") = = O ) //;Es la palabra Grupo?
(//Si lo es, entonces se trata de un grupo
(//Si yo ya lo tengo. se trata de otro grupo if (NombreGrupo)//¿Ya tengo un nombre?
Siguiente=new TDefinicionGrupos(Definicion,Buffer);//Contruimos otro grupo break;//le pasamos el archivo y la ultima linea leida
)
{ else//No tengo nombre, entonces es el mi0
Buf=strtok(NULL," \r\n\t;"); NombreGrupo=new char Istrlen(Buf)+ll ; strcpy(NombreGrupo.Buf1; //Me lo asigno
)//No es la palabra grupo )
else if (strcmp(Buf, "Variable")==O)//;Es Variable? (
135
Administrador de Redes SNMP
char *Nombre; char 'Ruta; char *Sintaxis;
Nombre=strtok(NULL," \r\n\t"); Ruta=strtok(NULL,";"); Sintaxis=strtok(NULL. " \r\n\t:") ; if ((Nombre) &&(Ruta) )//¿Hay nombre y ruta?
ííobtenemos su nombre, su ruta y su sintaxis
( SinEspacios(Nombre);//Les quitamos sus espacios SinEspacios (Ruta) ; if (Variable)//¿Ya cree la varible?
//Si hay nombre y ruta
(//Si ya exlste.
I Variable-~Insertar~Nombre,Ruta,LaSintaxis~Sintaxis~~;//Inserto otra
else//No exlste {//Creamos la variable Variable=new TVariable(Nombre,Ruta. laSintaxislSintaxis)) ;
i )
)//NO es variable
{//Si lo es else if (strcmp(Buf."Columna")==O)//iEs columna?
char 'Nombre; char *Ruta; char *Sintaxis=strtoklNULL," \r\t\n;"l i
Nombre=strtok(NULL, " \r\n\t") ; //Obtenemos su nombre y ruta
Ruta=strtok(NULL,";"); if ( (Nombre) h& (Ruta) )//¿Hay nombre y ruta?
SinEspacios (Ruta) i SinEspacios(Nombre);//Les quitamos espacios
if lColumna)//¿Existe ya la lista de columnas? (//SI ya existe
(//Si hay
Columna->Insertar(Nombre,Ruta,Lasintaxis(Sintaxis));//Insertamos una más
else//No existe { Columma=new TVariable(Nombre,Ruta,LaSintaxis(Sintaxis));
//La creamos
I I
i )
i fclose(Definicion)://Cerramos el archivo
/ * Tarea:
Argumentos:
Retorno:
Observaciones:
Obtener la primera variable de la lista de un grupo
Nombre del grupo
Primera variable de la lista
Si no se encuentra el grupo se envia NULL
"Variable + TDefinicionGrupos::PrimerVarlableGrupo(char Nombre[]) *í
{ if (strcmp(Nomhre,NombreGrupo)==O)//¿Es este grupo?
lf (Siguiente! //No. ¿Hay mas grupos?
return NULL://No. enviar señal de error
return Variable;//Si, regresamos el la variable
return Sigulente->PrimerVariableGrupo(Nombre);//Si, buscar en los otros grupos
J I*
136
Apéndice B. Código fuente del programa
Tarea:
Argumentos:
Retorno:
Obtener la primera columna de un grupo
Nombre del grupo
La primera columna
si no se encuetra el grupo se envia un NUL Observaciones:
* / marlable TDefinicionGrupos::PrimerColumaGrupoíchar Nombrelll i xf ístrcmplNombre,NombreGrupo)==Ol //¿Es este grupo?
if !Slguiente)//;Hay más grupos?
return NULL;//No. Regresar NULL
return Columna;//Si. enviar la columna
return Siguiente-~PrimerColumnaGrupo!Nombrel;//Si. buscar en los siguientes grupos
I
/ * Tarea:
Buscar el nombre de una variable dentro de un grupo a partir de su ruta
La ruta
El nombre de la variable
Si no se encuentra su nombre se regresa su ruta
Argumentos:
Retorno:
Observaciones:
char * TDefinicionGrupos::NombreVariable(char *Cadena) * /
{ int Cond.1; static char BufferllTAM-BUF] ;
static char Buffer2 [TAM-BUFI ; static char *Bufl,*Buf2; for (int i=O;icTAl_BUF;i++)
if (Variable) //¿Hay variables?
strcpy(Buffer1,Cadena);
Bufl=strtokíBufferl," " 1 ; strcpyíBuffer2,Variable->Ruta);
Buf2=strtok!Buffer2, " 1 ; for íint i=O:ic7;i++) //Buscar si son iguales
Bufferl[i]=Buffer2[i]=0;
(//Si hay variables
( Cond=Cond&&!strcmp(Bufl,Buf2)==0); for í;*Bufl~=O;Bufl++); for (;*Buf2l=O;Buf2++); Bufl=strtokl++Bufl, " ) ; Buf2=strtokl++Buf2," " ) ;
);//while líBufl)&&íBuf2));
if ííCond)&&(Variablell//~Son iguales?
else//No
)
return Varlahle->NombreVariableíCadena);//Si buscar su nombre y regresarlo
if (Siguiente) //iHay más grupos? return Siguiente->NombreVariable(Cadena);//Si, buscar en los siguientes grupos
return Cadena://Regresar su ruta 1
/ * Tarea :
Argumentos:
Retorno:
Buscar el nombre de una variable en un grupo y su sintaxis de alto nivel
Ruta de la variable
Nombre de la variable Sintaxis
Observaciones: La sintaxis se regresa en el argumento sintaxis
137
Administrador de Redes SNMP
Si no se encuentra su nombre se regresa su ruta * /
{ char * TDefinicionGrupos::NombreVariable(char *Cadena,TSintaxiS &sintaxis)
int Cond=l; static char Buffer1 [TAM-BUPI ; static char Buffer2 [TAP-BUFI ; static char *Bufl,'BufZ:
f o r (int i=U;icTAM-BUF;i++)
rf IVariable)//¿Hay variables?
strcpy(Buffer1,Cadena);
Bufl=strtok(Bufferl, '' 'O ; strcpy(Buffer2,Variable-~Rutal;
Buf2=strtok(Bufferl,'~ 'O; for (int i=O;ic7;i++)//Buscar si es de este grupo
Bufferl[il=Buffer2[i]=O:
(//Si hay
( Cond=Cond&&(strcmp(Bufl,Buf2)==0); for (;*Bufl!=U;Bufl++);
Bufl=strtokl++Bufl," ' I ) ;
for (;+Buf2~=O;Buf2++);
BufZ=strtok(++BufZ. '( " ) ; );//while ((Bufll&&(Buf2) ;
) if (lCond)&&(Varlable))//¿Es de este grupo?
slntaxls return Variable->NombreVariable(Cadena,sintaxisl;//Si, buscar su nombre y
else if (Sigulentel//No, iHay más grupos?
return Siguiente-sNombreVariable(Cadena,sintaxis);//Si, Bucar en los demas grupos return Cadena;//Regresar su ruta
/ * Tarea:
Argumentos:
Retorno:
Buscar el nombre de una columna y su sintaxis
La ruta de la columna
Su nombre y su sintaxis Observaciones:
La sintaxis se regresa en el argument sintaxis Si no se encuentra su nombre se regresa su ruta
* /
{ char TDefinicionGrupos::NombreColumna(char *Cadena.TSintaxis &sintaxis)
lnt Cond=l; statlc char Bufferl[TAM-BUFI ;
statlc char Buffer2 [TAM-BUFI ; static char *Bufl.*Buf2; for ( m t l=O;icTAM_BUF;i++)
If (Columna) //¿Hay columnas? BufferlIil=Buffer2[iI=O;
(//Si hay strcpy(Buffer1,Cadenaj;
Bufl=strtok(Bufferl, I' ' I ) ;
~ t r ~ p y ( B ~ f f e r 2 , C 0 l u m n a > R u t a ) ;
Buf2=strtok(Buffer2." ' I ) ;
for tint i=O;ic7;i++)//Buscar si son de este grupo { Cond=Cond&&(Strcmp(Bufl,Buf2)==0); for (;+Bufl~=U;Bufl++); for (;*Buf2'=O;Buf2++); BUfl=strtok(++Bufl, I' " ) ; BufZ=strtok(++Bufa, I' " ) ;
) ; )
if ((Cond)&&(Columnaji//¿Son de este grupo?
138
Apéndice B. Código fuente del programa
sintaxis y regresarlo return Columna->NombreVariable(Cadena,sintaxisl://Si, Buscar su nomhre y
else if (Siguientel//No. ¿Hay mas grupos?
regresar resultado return Siguiente->Nomb+eColumna(Cadena,sintaxisl;//Si. Buscar en los grupos y
i return Cadena://Regresar su ruta
/ + Tarea:
Destruir el objeto Argumentos: Retorno: Observaclones:
* / TDefinicionGrup0s::-TDefinicionGruposO ( Destruye(NomhreGrup0); Destruye (Siguiente) ; Destruye(Variab1e) ;
)
/**********""'**'****""*'*"""/ //Variable global MIB
TDefinicionGrupos Mlb("Mib-2.dat");
/ * Tarea :
Observaciones: Suminstrar una lista de objetos
Esta clase se explica por si sola * / class TListaIdObj
{ public:
TIdObj 'Objeto; TListaIdObj f Siguiente; TListaIdObj(T1dObj + I ; virtual void Inserta(TId0bj * ) ;
TIdObj valorO(return Objeto;}; ) ;
TListaId0bj::TListaIdObjiTIdObj 'Valor) i Ob,eto=Valor; Siguiente=NULL;
1
void TListaIdOb~::Inserta(TIdObj +Valor) i if ( 'Objeto)
{
) Objeto=Valor;
else If (Siguiente) i
1 Slguiente->InsertaiValorj.
else
Siguiente.net., TListaIdObj (Valor) ;
TListaIdObj*ListaVariablesEnviar=NULL; //Lista global de variables a enviar TListaIdObj*ListaColumnasEnviar=NULL; //Lista global de columnas a enviar TListaIdObj*Pendiente=NULL; //Lista global de objetos pendientes
139
Administrador de Redes SNMP
/ * Tarea :
Observaciones: Suministrar el manejo de mapas de bits
Los objetos de esta clase se pretenden usar en una grsfica, por lo que la clase TGraficaBitMap es su amiga
* / class TBitMap
{ friend TGraficaBitMap; protected:
HBITMAP HINSTANCE Programa: //Manejador del programa
MapaBits; //Manelador de mapas de bits
TWord Identificador; //Identificador de recurso de mapa de bits int Largo, //Largo en bits del objeto
Ancho; //Ancho en bits del objeto int x.y; //Posición x.y
HWND Manejadorventana; //Manejador de la ventana
TBitMap void BOOL void int int
lnt int
int -TBitMap
int
1 ;
TDatosTerminal Datos; publlc:
(HBITMAP,HINSTANCE,TWord,HWND,TDatosTerminali; //Datos del mapa de bits (representa una terminal)
Dibuja(HDC! ; colision(int. int) ; ObtenDatos ( ) ; xO(return x;); Yo(return y;);
Y (int yy) {return ( Y = w ) ; J ; largo0 {return Largo;);
ancho0jreturn Ancho;);
x(int XXI (return (x=xx!;);
/ * Tarea :
Crear un mapa de bits Argumentos:
Manejadores de: mapa de bits Identificador
Datos Retorno: Observaciones:
* /
programa,ventana
T ~ ~ ~ M ~ ~ : : T B ~ ~ M ~ ~ ( H B I T M A P ~ ~ ~ ~ ~ ~ ~ ~ , H I N s T A N c E programa.Tword identificador,HWND MV,TDatosTerminal datos) i BITMAP Auxiliar; Programa=programa:
ManejadorVentana=MV; Identificador=identificador;
x.10; y.10; MapaBits=mapabits; Getobject (mapabits. sizeof (BITMAP), &Auxiliar1 ; Largo=Auxiliar.bmWidth;//Obtener su largo Ancho=Auxiliar.bmHeight;//Obtener su ancho Datos=datos;
I
/ * Tarea:
Argumentos:
Re torno :
Determinar si un punto choca con un mapa de bits
El punto
SI/NO
140
Apéndice B. Código fuente del programa
Observaciones: * / BOOL TBitMap::Colision(int px,int pyl i
) return ( (px>x) h&(py>y) &&lpxcx+Largo) h&lpy<y+Ancho) ) ;
struct //Estructura para el intercambio de información con el diálogo de dirección IP i
char DireccionlP[ZO1 ;
charComunity[501 ;
char DireccionNombre L2001 ; }DialogoComunityDatos,DialogoDireccionIPDatos;
/ * Tarea :
Argumentos: Retorno:
Obtener los datos de un mapa de bits
Observaciones: Los datos
Se regresan en la variable global DatosTerminal
void TRitMap::ObtenDatosO * /
I
1
/ *
DatosTerminal=Datos:
Tarea:
Argumentos:
Retorno: Observaciones:
Dlbujar un mapa de vits en la ventana
Manejador del dispositivo de contexto
* /
{ void TBitMap::Dibuja(HDC Ventana)
TEXTMETRIC tm; HDC dc=CreateCompatibleDC(Ventanal;
struct in-addr DireccionAux: char Buffer[2Ol ;
if ('GetTextMetricslVentana,&tm))
DireccionAux.S_un.S-addr=Datos.DireccionIP;//Obtener la dirección IP
RitBltlVentana,x,y.Largo,Ancho,dc.O.O.SRCCOPY) ;//Dibujar el mapa de bits SelectObject(dc,MapaBits);
TextOut~Ventana.x+Largo/2,y+Ancho,Datos.Comunity,strlenlDatos.Co~~unityll;//Escribir
TextOutlVentana,x+Largo/2,y+Ancho+tm.tmHeight,Buffer,strlen(Buffer~ !://Escribir la
DeleteObject(dc);
tm.tmHeight=lO;//Los mensajes serán de 10 puntos
strcpy(Ruffe1,inet-ntoa(DireccionAux));
el comunity
dirección IP
)
struct (//Estructura para el intercambio de información en el dialogo grupos TComboBoxData *Grupo;
)DatosDialogoGrupos;
/ * Tarea:
Observaciones: Proprocionar una lista de mensajes
La implementación se explica por si misma * / class TListaCadena
I protected:
141
Administrador de Redes SNMP
TLiStaCadena 'Siguiente; //Siguiente char "Cadena; //Mensaje
TListaCadena(char * ) ; vold Inserta(char * I ;
-TListaCadenail (Destruye (Cadena1;DestruyelSiguientel;);
public:
int Escribe(HDC. int, int. int) ;
) ;
TListaCadena::TListaCadenaichar 'cad) i Cadena=new char [strlen(cadl+ll ;
Siguiente=NULL; strcpy(Cadena,cadl ;
)
veld TListaCadena::Inserta(char *cad) { if ISigulente)
else Siguiente->Insertaicad);
Siguiente=new TListaCadena(cad1; )
/ * Tarea:
Argumentos:
Retorno: Observaciones:
Escribir los mensajes
El dispositivo de contexto, las cordenadas y el alto de los caracteres
+ / int TListaCadena::Escribe(HDC dc,int x.int y,int alto) ( TextOut(dc ,x .y ,Cadena .s t r len(Cadenal~: if (Siguiente)
return yialto; return Siguiente->Escribe(dc,x,y+alto,alto);
I * Tar ea :
Observaciones: Proporcionar el manejo de una tabla en pantalla
La mayoría del código se explica por S € mismo * / class TTabla
( protected:
TListaCadena *Listacadena; TTabla *Siguiente;
TWord Longitud; public:
void TTabla(char * , Twordl ;
InsertaCadena(char * ) ;
void void InsertaSiguiente(char '.?Word);
-TTabla() (Destruye(ListaCadena);DestruyeiSiguientel;); Escribe (HDC, int. int, intl ;
1;
TTab1a::TTablaichar *cad.TWord longitud) I Longitud=longitud; ListaCadena=new TListaCadena(cad); Slguiente=NULL;
void TTab1a::InsertaCadenalchar *cad1 (
142
Apéndice B. Código fuente del programa
if (Siguiente)
else Siguiente->InsertaCadena!cad);
Listacadena->Inserta(cad); 1
void TTab1a::InsertaSlguienteichar *cad,TWord 1) i if (Siguiente1
else Slguiente->InsertaSiguiente(cad.l);
Siguiente=new TTabla(cad,l) : )
void TTabla: :Escribe (HDC dc, int x, int y , int alto1 i Listacadena->Escribe(dc,x,y,altol ; if (Slguientel
i
I Sigulente->Escribe(dc,x+Longitud,y,altol.
1
TTabla *TablaACtual=NULL; //Variable global que indica cual e s la tabla actual
I' Tarea :
Observaciones: Proporcionar una ventana que muestre una tabla
* / class TVentanaTab1a:public Twindow
i public:
TVentanaTabla!PTWlndowsObject);
-TVentanaTablaO; virtual void Paint (HDC, PAINTSTRUCT -FAR & ) ;
1;
/ * Tarea :
Dibujar en la ventana la tabla
El dispositivo de contexto Argumentos:
Retorno : Observaclones:
void TVentanaTabla::Paint!HDC dc.PAINTSTRUCT -FAR & ) * /
{ HFONT FontActua1,FontNueVa; PSTR NombreLetra="Courler New";
S e t B k C o l o r ( d c . R G B ( l 9 2 . 1 9 2 . 1 9 2 ) ) ; FontNueva=CreateFont (-12, O , O . O , O . O . O , O , O , O . O, O, 0,NombreLetral ; FontActual=(HFONTlSelectObject(dc,FontNueva1; if ITablaActual)
Selectobject (dc, FontActual) ; DeleteObject(FontNueva1:
TablaActual->Escribe(dc,O,O,2O);//Escribir la tabla actual
TVentanaTahla::TVentanaTabla(PTWindowsObject pariente)
i :TWindow(pariente, "Tabla encontrada")
Attr .Style=WS_OVERLAPPEDWINDOW/WS_VSCROLL/WSSCROLL; Scroller=new TScro11er(this,10.10,200,200~;
TVentanaTab1a::-TVentanaTablaO i PostMessage(Parent-~HWindow,WM-CERRAR-TABLA,O,OL).
143
Administrador de Redes SNMP
J BOOL HayTabla://Variable global que determina si hay una tabla
/ * Tarea:
Proporcionar el dialogo que muestra las variables que se han leido
Observaciones: atraves de la red
* / c l a s s TDialogoVariab1es:public TDialog
TListBox + ListaVariables: WentanaTabla * VentanaTabla;
TDialogoVariables(PTWindows0bject); virtual void VerTabla(TMessage &)=LWM_FIRST+WM_VER_TAELAI; virtual void CerrarTabla(TMessage h)=IWM_FIRST+WM_CER~_ThB~l;
protected:
public:
) :
I* Tarea:
Argumentos: Retorno: Observaciones:
* / void TDialogoVariables::VerTabla(TMessage & )
( if I I 'VentanaTabla) &&(HayTabla) )
( VentanaTabla=new TVentanaTabla(this); GetApplicationO ->MakeWindowiVentanaTabla); ShowWindow(VentanaTab1a->HWindow,SW-SHOW);
) i inline void TDialogoVariables::CerrarTabla(TMessage & )
VentanaTahla=NULL: )
struct (//Estructura para intercambio de información con el diálogo de variables TListBoxData *Lista: )DatosDialogoVariahles;
/ * Tarea:
Argumentos: Retorno: Observaciones:
Crear un diálogo que permita presentar los valores de varias variables
* / TDialogoVariables::TDialogoVariables(PTWindowsObject pariente)
( :TDialoglpariente.DIALOGO-VARIABLES)
VentanaTabla=NULL; ListaVariahles=new TListBOX(thiS,ID_LISTA-VARIAELES);
HayTabla=FALSE; TablaActual=NULL; TransferBuffer=(LPSTR~LDatosDialogoVariables;
i / *
Tarea :
Argumentos: Permitir dar formato a las variables
144
Apéndice B. Código fuente del programa
Retorno: Observaciones:
* / char * FormatoVariables(char BufferL1,char *Datol.char *DatoZ) i int i=O; TSintaxis Sintaxis; for (;icTRM-MAX-BUF;Buffer[i++l=' ' ) ; strcpy(Buffer,Mib.Nombrevariable(Datol,Sintaxis~l; switch(Sintaxis1
{
char MiBuf (61 ; for (register int i=O;ic6;MiBuf [il =Dato2 [il ,i++) , Dat02[01=0; for !i=O;1<6;i++)
case DireccionFisica:
{ strcat (DatoZ.BinHex!MiBuf [il ) ) ;
DatoZ[strlen(Dat02)-11=':'; )
break;
for (1=0;1<2l;i++) )
if (BufferIil==O) Buffer[il=' ' ;
Buffer[2ll=' ' ; Buffer[201=':';
Buffer[EZI=O; strcat!Buffer,Dat02);
return Buffer; i I*
Tarea:
Observaciones: Proporcionar un diálogo para preguntar por un grupo de valores a una terminal
* / class TDia1ogoGrupos:public TDialog
{
~Covbo~ox * Grupo; //Proporciona el grupo TVariable Columna;//Sirve para obtener las columnas TDialogoVarlables *Dialogo;//Proporciona un diálogo de variables
TBGroupBox CajaGrisl; SOCKET Socket: //Guarda el socket de comunicación Struct sockaddr-in Direccion; //Guarda la dirección IP char char *
Nombre; //Nombre de la terminal Comunity; //su comunidad
protected:
TVentanaTabla * Tabla; //Proporciona un ventana para las tablas
public: BOOL HayInformacion; //Bandera
TDialogoGrupos(PTWindowsObject,int,SOCKET,char +,TDWord.char *,char * ) ;
-TDialogoGrupos~) (WSAAsyncSelect(Socket,O,0,O);]; virtual void PedlrInformacion(TMessage &)=[ID_FIRST+ID_PREGUNTARI;
virtual void RecibirVariables(TMessaqe h)=[WM-FIRST+WM-RECIBIR-VARIABLEI; virtual void PedirVariables(TMessage &)=[WM-FIRST+WM-PEDIR-VAP.lABLESl;
virtual void PedirTablalTMessage &)=[WM-FIRST+WM_PEDIR-TABLAl: virtual vold RecibirTabla(TMes5age &)=IWM~FIRST+WM~RECiBiR~TABLAl:
virtual void VerTabla(TMessage &)=[WM-FlRST+WM_VER-TABLAl; vlrtual void CrearInformacion(TMessage h)=[WM-FIRST+ID-CREAR-lNFORMACiONl;
virtual void CerrarTabla(TMessage h)=[WM_FIRST+WM_CERRAR-TABLAI (Tabla=NULL;) ) ;
/ * Tarea:
Argumentos: Retorno:
Mostrar una tabla en una ventana
145
Administrador de Redes SNMP
Observaciones: * / void TDlalogoGrupos::VerTabla(TMessage &I
if I 'Tabla) //¿Hay tabla? {//No hay tabla Tabla=new TVentanaTablalthis);//Creamos la tabla GetApplicationO->MakeWindow(Tabla);//Crear la ventana ShowWindow(Tab1a->HWindow,SW-SHOW);//Mostrar la ventana
1 1
/ * Tarea:
Contruir un diálogo que permita preguntar por un grupo de variables Argumentos :
La ventana pariente, el modo de visualización,el socket, el título, la dirección IP, el nombre y la comunidad
Observaciones: Retorno:
* / TDialogoGrupos::TDialogoGrupos(PTWindowsObject pariente.int r.SOCKET s,char *Titulo,TDWord direccion,char *nombre,char tcomunity):
TDialogipariente, r) i Haylnformac3on=FALSE; //En un principio, no hay información
Tabla=NULL; Columna=NULL: //No hay columnas
//No hay tablas Direccion.sin-addr.s-addr=direccion;//Asignar la dirección IP Nombre=nombre; Comunlty=comunity:
BOOL b=TRUE; TDefinicionGrupos +grupo=&Mib;
Socket=s; SetCaption(Titu1o) ;
Grupo=new TComboBoxIthis,ID-GRUPOS.50); CajaGrisl=new TBGroupBox(this,ID-CAJA-GRIS-11;
DatosDialogoGrupos.Grupo=new TCOmboBOxData; while (grupo)
i //Llenamos los nombres de los grupos
DatosDialogoGrupos.Grupo-,AddString~grupo-~Grupo(l,bl: b=FALSE; grupo=grupo-Siguiente;
) TransferBuffer=(LPSTR)hDatosDialogoGrupos;//Definimos el buffer de intercambio de información 1
/ * Tarea :
Argumentos: Retorno: Observaclones:
Pedir información atravez de la red
* /
{ void TDialogoGrupos::PedirInformacion(TMessage 6)
char NombreGrupoI10Gl ; Destruye(DatosDialogoVariables.Lista~; for ( m t i=G;i~l0O:Secuencias[i++l=O);//No hay secuencias de datos que estemos esperando Grupo-~GetText~NombreGrupo,100); //Obtenemos el nombre del grupo strcpy(NombreGrupoProceso,NombreGrupo); if (Mib.PrimerVariableGrupo(NombreGrupo))//¿Son variables?
PostMessage(HWindow.WM~PEDIR~VARIABLES,O,GL);l/Si son variables, enviar mensaje de pedir variables
else if (Mib.PrimerColumnaGrupo(NombreGrupol~/l¿Son tablas?
i POStMesSage(HWindow,WM~PEDIR~TABLA,O,OL);//Son tablas, enviar mensaje de pedir tabla
146
Apéndice B. Código fuente del programa
Tarea: Pedir el valor de una variable
Argumentos: Un indicador que nos dice si hay que crear la lista de variables o ya esta
Retorno: Observaclones:
creada.
Se plden de 6 en 6 . Esto fue resultado de varias pruebas, para tener los valores de manera eficiente y relativamente rapida.
void TDialogoGrupos::PedirVariables(TMessage &M)
TByte NumVar=O; TVarSindList * Lista=NULL: TLlstaIdObj * VarAUX; TMensajeSNMP * Mensale; if (M.WParam==O)//¿Hay que pedir la primera variable del grupo?
(//si, es la primera vez que se llama para esta consulta char NombreGrupo[1001 ; TVariable *Variable=NULL;
Grupo->GetText(NombreGrupo.lOo!;//Gbtenemos el nombre del grupo Variable=Mib.PrimerVariableGrupo(Norr$reGrupo);//Gbtenemos la primera varlable while (VariableI=NULL)
(
ListaVariablesEnviar->Inserta(new TIdObj (Variable->Ruta!l;//Si. entonces inserta if !ListaVariablesEnviarl//;Esta creada la lista?
una nueva
ListaVariablesEnviar=new TListaIdObj (new TIdObj(Variab1e-sRuta));//Crea la lista else//NO
Variable=Variable->Siguiente;//Recorro las variables )
1 M.WParam=l;//Idico que ya esta creada la lista
r f (M.WParam==ll //¿Puedo pedir la lista? 1
while (iListaVariablesEnviar'=NULL!&&(NumVar<6li//¿Puedo lnclui la siguiente? {//si
NumVar++://La cuento if lListai//¿Esta creada la lista?
(
1
i
I
Lista->InsertaLListaVariablesEnviar->ValorO,new TNULL);//Si, inserto
else//NO. creo
Lista=new TVarBindListlListaVariablesEnviar->ValorO,new TNULL!;
ListaVariablesEnviar=ListaVariablesEnviar-,Siguiente; VarAux=ListaVariablesEnviar:
Destruye(VarAux) i 1
) if (Lista!//¿Hay una lista de variables para enviar?
Inser tarSecuenc iasO;//lnser to una secuencia más Mensaje=new TMensa]eSNMP(new TCadena(Comunity!,//Creo el mensale SNMP
{//si
new TGetNextReqUeSt-PDU(new TEntero(Secuencia++i. new TEnterO((TDW0rd) O ) . //Sin Error new TEntero( (TDWordi O), Lista1
> ;
Secuencia++; i f (Secuencia==O)
char SufferEnviar[TAM_MAX-BUFI ; int Tam=Mensaje-sCodigoBin(BufferEnviar,TAM-M~V(_BUF)://Gbtener el tamaiio en bytes del
Direccion.sin-family = PF-INET; Direccion.singort = htons(Puert0); if ('DatosDialogoVariables.Lista)
mensaje
147
Administrador de Redes SNMP
DatosDialogoVariables.Lista=new TListBoxData: //Enviar el mensaje atraves de la red sendto(Socket .Buf ferEnviar .Tam.0 , (struct sockaddr far *)&Direccion,sizeofistruct
MensajesSNMP++; //Se envió un mensaje más Destruye(Mensaje);//Destruimos el mensaje Lista=NULL;//Ya no hay lista WSMsyncSelect~Socket,HWindow.WM~RECIBIR~VARIABLE,FD~READ);//Enviamos un mensaje de
sockaddr-in1 ! ;
recivlr variable )
i / *
Tarea :
Argumentos: Retorno: Observaclones:
Recibir variables
* /
( void TDialogoGrupos::RecibirVariables(TMessage &)
struct sockaddr-in Dir; char BufferLTAM-MAX_BUF+21 ;
int Taml, Tam2; TMensajeSNMP *Mensaje=NULL: TVariable *Variable=NULL:
Taml=recvfrom(Socket,Buffer.TAi-~MAX-BUF*2.0, (struct sockaddr far *\&Dir, i i n t PaquetesRecibidos++; //Se ha recibido un paquete más
if (Taml==-l!//;Es correcto?
if (Dir.sin_addr.s_addr==Direccion.sin-addr.s-addr) return;//NO, abortar el proceso
{ Mensaje=new TMensajeSNMP[&Buffer[ll);//Obtener el mensaje SNMP if (Existesecuencia(Mensaje->SecuenciaO))//¿Es de una secuencia esperada?
(//Si if (DatosDialosoVariables.Lista)//;Existe l a lista?
) &Tam2 ) ;
{ / / S I
Var~able=Mib.PrimerVariableGrupo~No~reGrupoProceso~;//Obtenemos la prlmera variable TVarBmdList *Lista=Mensaje->Lista();//Obtenemos la lista recibida
while (Lista! del grupo
i if (Variable)//iHay variable?
DatosDialogoVariables.Lista->AddString(Fariables(Buffer.Lista~~Nombre //Si, la agragamos para ser visualizada
~ v a l o r , L i s t a - ~ V a l o r - ~ V a l o r S i n t a x i s ( l ) 1; Lista=(TVarBlndList +)Lista-sSiguiente;//Recorremos la lista
MensajesSNMP;//Decrementamos el mensaje SNMP i
HayInformacion=FALSE;//No esta disponible la información aún
PostMeSsage(HWindow,ID~CREAR_INFORMACION,O,OL);//NO. podemos mostrar la if ('ListaVariablesEnviar)//iHay que pedir más varibles?
Información PostMessage(HWindow,WM_PEDIR_VARIABLES.l.OL);//Pedir otro conjunto de variables
i i
Destruye(Mensaje)://Destruir el mensaje SNMP obtenido
/ * Tarea :
Argumentos: Re torno :
Observaciones:
Mostrar la información
* / void TDialogoGrupos::CrearInformacion(TMessage h )
148
Apéndice B. Código fuente del programa
if ('HayInformacion)//iHay información activa? {//NO HayInformacion=TRUE;//Indicar que ahora ya la hay Dialoyo=new TDialogoVariables(this);//Crear el dialogo GetApplicationO ->ExecDialog(Dialogo);//Mostrarlo WSAAsyncSelect(Socket.HWindow,O,O);//Deshabilitar la comunicación de la red HayInformacion=FALSE;//Ya no hay información activa Dialogo=NULL;//Ya no hay di61ogo
else if !Dialoqo)//SI, ¿Hay diálogo?
DlaloyO->TranSferData(TFSETDATA);//Solo transferimos información )
/ * Tarea :
Argumentos: Retorno: Observaciones:
Pedir una tabla
void TDialogoGrupos::PedirTabla(TMessage &M) * /
{ TMensajeSNMP *Mensa]e=NULL;
char BufferEnviar[TAM-MAX-BUFl; m t Tam; m t longitud=150; switch !M.WParam!
case O: //Hay que empezar con la tabla Destruye!TablaActual);
Columna=Mib.PrimerColumnaGrupo(NombreGrupoProceso1;//Obtener la prlmera
if ('Columna) break;//iHubo error? Si, abortar switch(Co1umna->Sintaxis)//Definir la longitud dependiendo de la slntaxis
columna
{ case DireccionFisica:
longitud=200; break;
lonyitud=150; case DireccionIP:
break; case Entero32:
longitud=100; break;
longitud=300; case Tiempo:
break; )
TablaActual~sInsertaSiguiente(Columna~~Nombre,longitudl;//S~. insertamos if (TablaActual)//¿Ya esta creada la tabla?
elemento else
case l://Hay que continuar TablaActualaew TTabla(Co1umna->Nombre,longitudl;//No, la creamos
InsertarSecuenciasO;//insertamos la secuencia Mensaje=new TMensajeSNMP(new TCadena(Comunity!.//Creamos el mensale SNMP new TGetNextRequest-PDU(new TEntero(Secuencia++),
new TEntero((TDWord1 O), //Sin Error new TEntero( (TDWord1 O), new TVarBindList (new TIdObj (Columna->Ruta1 .new TNULL) !
1; if (Secuencia==O)
Tam=Mensaje~,CodigoBin(BufferEnviar,T~-MAX-BUF1;//Obtenemos el código binario
Direccion.sin-family = PF-INET;
Secuencia++;
y su tamaño
149
Administrador de Redes SNMP
Direccion.singort = htons(Puert0);
sendto(Socket .BufferEnviar.Tam.0. (struct sockaddr far
MensajesSNMP++; Destruye(Mensa1e) ; WSMsyncSelect(Socket.HWindow,WM_RECIBIR_T~LA,FD_RERO);//Idicamos que reciba
break;
char far *ObjetoAnterior=(char far *)M.LParam;
//lo enviamos por la red
*)&Direccion.sizeof(struct sockaddr-in));
información
case 2://Verificar si hay otra columna
if (MismaColumna(ObjetoAnterior,Columna-~Ruta))//iEs la misma columna? {//Si Insertarsecuencias ( ) ;
MenSaje=new TMensajeSNMP(new TCadena(Comunity1, //crear el mensaje SNMP
new TGetNextRequest-PDU(new TEntero(Secuencia++), new TEntero ( (TDWord) O ) , new TEntero ( (TDWord) O ) , new TVarBindList(new TIdObj (ObjetoAnterior) .new TNULL))
if (Secuencia==O)
char BufferEnviar [TAM-MAX-BUFI ;
Direccion.sin-family = PF-INET; int Tam=Mensaje->CodigoBin(BufferEnviar,TAM-MAX-BUF);
Dlreccion.singort = htons(Puerto);
sendto(Socket,BufferEnviar,Tam,O,(struct sockaddr far //Enviarlo por la red
MensajesSNMP++; Destruye(Mensaje) ;
WSMsyncSelect(Socket,HWindow,WM_RECIBIR_TABLA,FD-READ);
) ;
Secuencia++;
//Obtener el binario del mensaje y su tamaiío
*)&Direccion.slzeof(struct sockaddr-in));
//Idicar que hay que recibir el resultado
I
( else//NO es la misma columna
if (Columna)//hay más columnas (
Columna=Columna~>Siguiente;//Continuar con la que sigue if (Columna)
else PoStMesSage(HWindow,WM~PEDIR~TABLA,3,OL~;//Pedir una nueva columna
PostMessage(HWindow,WM_VER_TABLA.O.OL);//Continuar con la misma columna I
)
case 3://Otra columna break;
if lColumna)//Hay columna switch(Co1umna->Sintaxis) i case DireccionFisica:
lonqitud=200; break;
longitud=l50; case DireccionIP:
break; case Entero32:
longitud=100;
case Tiempo: break;
longitud=300; break;
I
if (TablaActual) if (Columna)
else TablaActual~~InsertaSiguiente(Columna->Nombre,longitud);
150
Apéndice B. Código fuente del programa
InsertarSecuenciasO; Mensaje=new TMensajeSNMP(new TCadena(Comunity),
TablaActual=new TPablaiColumna-zNombre,longitud);
new TGetNextRequest-PDU(new TEntero(Secuencia++!, new TEntero((TDWord1 O ) , //Sin Error
new TVarBindList(new TIdObj(Columna->Ruta).new TNULL)) new TEntero( (TDWord) O),
) ; if (Secuencia==O!
Tam=Mensaje->CodigoBin(BufferEnviar.T?+"MAX-BUF); Direccion.sin-family = PF-INET; Direccion.singort = htonslPuerto); sendto(Socket.BufferEnviar,Tam,O, (struct sockaddr far
*!&Direccion.sizeof(struct sockaddr-in)); MensajesSNMP++; Destruye(Mensaje) ; WSRAsyncSelect(Socket,HWindow,WM_RECIBIR_TABLA,FD-READ); break;
Secuencia++;
) 1
/ * Tarea:
Argumentos: Retorno: Observaclones:
Convertir al formato de dirección física
void ConvierteDireccionFisica(char +Cad) * I
( char DirecI61 ; int i=o; for (;i<6;DirecIil=Cad[ij,i++~; Cad[Ol=O: €or (i=O;ic6;it+)
( strcat(Cad,BinHex(DirecIil));
CadIstrlen(Cad)-ll=':';
I / *
I
Tarea :
Argumentos: Retorno: Observaciones:
Recibir la información de una tabla
* /
i void TDialagoGrupos::RecibirTabla(TMessage & )
struct sockaddr-in Dir; static char Buffer[TAM-MAX-BUF*2] ;
int Tam1 , Tam2 : TMensajeSNMP *Mensaje=NLlLL;
PaquetesRecibidos++;
Taml=recvfrom(socket,Buffer,TAM~MAX-BUF*2.0, (struct sockaddr far * l & D i r . (lnt //Recibir el mensaje SNMP
lf (Tarnl==-l)//;Todo bien?
if (Dlr.sin-addr.s-addr==Direccion.sin-addr.s-addr! return;//No, abortar
{ Mensaje=new TMensajeSNMP(hBufferI11); if (!Mensaje)
strcpy~Bu€fer.Mensaje-~Lista~!-~Nomhre-~ValorSintaxisO~; return;
if (ExisteSecuencia(Mensaje->SecuenciaO))
! &Tam2 ! ;
if icolumna)
15 1
Administrador de Redes SNMP
i if lMismaColumna(Buffer,Columna->Ruta))
int longitud=150; strcpy~Buffer.Mensaje-,listaO-~Valor->ValorSintaxisO); switch(Columna->Sintaxis)
case DireccionFisica: i
longitud=200;
break; ConvierteDireccionFisica(Buffer1;
case DireccionIP:
break; longitud=150;
longitud=100; break;
longitud=300; break;
case Entero32:
case Tiempo:
) if (TablaActual)
else TablaActual->InsertaCadena(Buffer);
TablaActual=new TTabla(Buffer.longitud1 : )
strcpy(Buffer,Mensaje->ListaO->Nombre->Valorl; PostMeSsage(HWindow,WM-PEDIR-TABLA,2,(DWORD) ((void far ')&Buffer)!;
)
1 Destruye(Mensaje1 ;
I* Tarea: Argumentos: Retorno: Observaciones:
* I I*
Tarea :
Observaciones: Presentar la red dibujada
* I class TGraficaBitMap
{
TBi tMap TGraficaBitMap *Siguiente; PTWindowsObject Pariente;
BOOL SOCKET Socket;
Termino; TDWord char NombreTerminal I 1 0 0 1 ;
DireccionIP;
HINSTANCE Programa; char Comunity[200~ ;
protected: *Nodo;
HWND public:
mv;
TGraficaBitMap (PTWindowsObject,HBITMIP.HINSTANCE,TWord,HWND,
TGraficaBitMap (PTWindowsObject,HBITMAP.HINSTANCE,TWord,HWND,
void void Dibuja(HDC Ventana) ;
Inserta (HBITMAP, TWord. TDatoSTermina1,TDWOrd. char * ! ;
T D a t o s T e r m i n a l , S O C K E , T D W o r d . c h a r * ) ;
SOCKET, FILE * ) ;
BOOL Colision(int. int) ;
BOOL ObtenDatos(int.int); void TGraficaBitMap* obtenActivo(int,intl;
VerDatos(int,int):
TBitMap' BitMapO {return Nodo:); char ObtenDireccionIPO;
152
Apéndice B. Código fuente del programa
char ObtenDireccionNombreO; char * void OrdenaGraflcaO;
-TGraficaBitMap!l;
ObtenComunityO(return Comunity;);
void Guardar!FILE * I ;
) ;
TGraficaBitMap *NodoActivo=NULL;
TGraficaBitMap::TGraficaBitMap(PTWindowSObject pariente,HBITMAP Dibujo.HINSTANCE programa, TWord identificador,HWND MV,TDatosTerminal datos, SOCKET s,TDWord ip,char *comunityI
i NombreTerminal[Ol=O; Siguiente=NULL; Programa=programa; mv=MV: Nodo=new TBitMap!Dibujo.programa,identificador,MV,datos); Pariente=pariente;
TerminO=FALSE; Socket=s;
DlrecclonIP=ip; strcpy IComunity. comunity) ;
1
TGraficaBitMap::TGraficaBitMap(PTWindowsObject pariente,HBITMAP Dibujo.HINSTANCE programa TWord identificador,HWND "J. SOCKET s,FILE *Archivo)
i static char Buffer[1001 :
NombreTerminal IO] = O ; Siguiente=NULL; Programa=programa; mv=MV;
Buf=strtok(Buffer."\r\t\n"l; fgets!Buffer,100,ArchivoI;
DatosTerminal .DireccionIP=inet_addr(Buffer) ;
Buf=strtok!Buffer, "\r\t\n"l ; fgets!Buffer,TAM~COMUNITY.Archivol;
strcpy(DatosTerminal.Comunity.Buf1; Nodo=new TBitMap(Dibujo.programa,identificador.MV.DatosTerminal); Pariente=pariente:
Termino=FALSE; Socket=s:
DireccionIP=DatosTerminal .DiseccionIP; strcpy(Comunity.DatosTenninal.Comunity1; if I feof (Archivo)
else
OrdenaGraficaO;
char 'BUf;
Sigulente=new TGraficaBitMap(pariente,Dibujo,programa,identificador,MV,s,Archivol;
Siguiente=NULL;
1 void TGraficaSitMap::Inserta(HBITMAP Dibuj0,TWord identificador.TDatosTermina1 datos
, TDWord ip.char 'comunity) ( if (Siguiente)
else Siguiente->Inserta!Dibujo.identificador,datoS,ip,comunity);
Siguiente=new TGraficaBitMap(Pariente,Dibujo,Programa,identificador,mv,datos,Socket,lp,comunityl; 1
"old TGraficaBitMap::Dibuja!HDC Ventana)
MoveTo!Ventana,Nodo-~x!)+Nodo~~anchoO/2.Nodo-~YO+Nodo~~largo!l/2l; if (Siguiente)
{
if I'EstaPresionado)
153
Administrador de Redes SNMP
~Y~!+Siguiente-~Nodo-.largo~)/21;
Nodo->Dibuja(Ventanal; If (Siguiente)
LineTolVentana,Siguiente~~Nodo-~X~l+Siguiente-~Nodo-~ancho~)/2,Siguiente~zNodo
{
) Siguiente-zDibu]a(Ventana);
)
BOOL TGraficaBitMap::Colision(int px.int py) 1 if (Nodo->Colision(px.py)i
if !Siguiente! return 1;
return O : return S i g u i e n t e - > C o l i s i o n ( p x . p y ) ;
)
TGraficaBitMap* TGraficaBitMap::ObtenActivo(int px.int py) ( if (Nodo-sColision(px,py) I
if (Siguiente)
return NULL;
return thls;
return Siguiente-zObtenActivo(px,py);
j
BOOL TGraficaBitMap::ObtenDatos(int px.int PYI { if (Nodo~>Collsion(px,py))
Nodo-,OhtenDatos ( 1 ; return 1;
i
1 return O;
void TGraficaBitMap::VerDatos(int px,int py) i if (Nodo >Colision(px.py))
{ char Buffer [TAP-COMUNITYI ; ostrstrearn Datos(Buffer,TAb_COMUNITY); struct in-addr aux; TDialogoGrupos *Dialogo; Nodo->ObtenDatosO; DireccionIP=aux.S_un.S_addr=DatosTerminal.DireccionIP; Datos<cinet-ntoa(aux)<<'* "; Dat0scc"Cornunity: "<cDatosTerrninal.Comunityccends; Dialogo=new
TDialogoGrupos!Pariente,DIALGO~GRUPOS,Socket,Buffer,DireCCionlP.NomhreTerminal.DatosTerrnina 1.Comunity) :
Parlente-~GetApplication()-~ExecDialog(DialOgoi;
else if (Siguiente) Siguiente-sVerDatos(px,py) ;
char * TGraficaBitMap::ObtenDireccionIP(l { struct in-addr aux;
return inet-ntoa(aux1: aux.S-un.S-addr=Nodo-sDatos.DireccionIP:
i
char TGraficaBitMap::ObtenDireccionNombre~)
static char BufferlZOOl ;
154
-
Apéndice B. Código fuente del programa
/ / if (Host) //struct hostent far * Host=gethostbyaddr((const char far *)ntohl(DireccionIP!,4,PF~INET);
/ / strcpylBuffer,Host->h-name); / / else
return Buffer; StrcpylBuffer, "No se encontro su nombre") ;
1
void TGraficaBitMap::OrdenaGrafica() i if (Siguiente)
i if I N o d o - > X O > S O O )
{ Siguiente->Nodo->Xl-30); Siguiente-zNodo-,YlNodo->YO+lOO);
Siguiente->Nodo->X(Siguiente-zNodo-sX(1+10Ol; Siguiente-zOrdenaGrafica0;
void TGraficaBitMap::GuardarlFILE 'Archivo) I struct in-addr aux; aux.S-un.S_addr=Nodo->Datos.DireccionIP; fprintf (Archivo, "\n!'l ; fputs(inet_ntoa(aux).Archivo); fprintf (Archivo. "\n") ; fputsfNodo-sDatos.Comunity.Archivo1; if (Siguiente)
Slgulente-.Guardar(Archivo);
TGraficaBitMap::-TGraficaBitMapO i Destruye (Nodo) : Destruyelsiguiente) ;
)
class TDia1ogoComunity:public TDialog { protected:
TEdit * Comunity; TBStatic * DireccionIP; TBStatic * DireccionNombre;
TBGroupBox GComunity; TBGroupBox * Informacion;
TDialogoComunity(PTWindows0bject); -TDialog~Comunity(l;
publlc:
) ;
TDialogoComunity::TDialogoComunity(PTWindowsObject pariente)
{ TDialoglpariente.DIALOGO~COMLJNITY)
GCoinunlty-new TBGroupBoX(thiS,ID-BG_COMUNITY); Informaclon=new TBGroupBoxlthls.ID~BG~INFORMACION1;
Comunlty=new TEdit(this,ID_COMUNITY,50);
DireccionNombre=new TBStatiC(this,ID~DIRECCION~NOMBRE,200); DireccionIP=new TBStatic(this.ID~DIRECCION~IP.2OI;
DireccionIP->EnableTransfer(); DireccionNombre->EnableTransferO; Comunity->EnableTransferO; TransferBuffer=(LPSTR) &DialogoComUnityDatos;
i
TDia1ogoComunity::-TDialogoComunityO i
155
Administrador de Redes SNMP
class TDialogoDireccion1P:puhlic TDialog (
TBStatic Comunity; TEdit TBStatic * DireccionNombre;
DireccionIP;
TBGroupBox * Inforrnacion; TBGroupBox GComunity:
TDialogoDireccionIP!PTWindowsObject); -TDialogoDireccionIP();
protected:
public:
) :
TDialogoDireccionIP::TDialogoDireccionIP~PTWindowsObject pariente):
{ TDialog(pariente.DIALOGO~DIRECCION~IP1
GComunity=new TBGroupBox(this,ID-BG-COMUNITYI; Informacion=new TBGroupBox(this,ID~BG~INFORMACION);
Comunity=new TBStatic(this,ID-COMUNITY.50); DireccionIP=new TEdit(this.ID-DIRECCION-IP.20l; DireccionNomhre=new TBStatic(this.ID~DlRECCION~NOMBRE.200);
DireccionNomhre-sEnableTransfer0; DireccionIP->EnableTransferO;
Comunity->EnableTransferO; TransferBuffer=(LPSTR) &DialoqoDireccionIPDatos;
J
TDialogoDirecci0nIP::-TDialogoDireccionIPO
) {
struct ( char Comunity[SOI ; char DirtccionIP[2Ol ;
}DialogoInsertarDatos;
class TDialogo1nsertar:public TDialog i
TEdit Comunity; TEdit DireccionIP;
TDialogoInsertar(PTWindowsOhject1;
protected:
public:
J ;
TDialogoInsertar::TDialogoInsertar(PTWindowsOhject pariente):
{ TDialogIpariente.DIALOG0-INSERTAR)
Comunlty=new TEdit(this.ID-COMUNITY.50); DireccionIP=new TEdit!this.ID-DIRECCION-IP,ZO); DireccionIP->EnableTransferO;
TransferBuffer=(LPSTR) hDialogoInSertarDatoS; Comunity~sEnableTransferO;
I
class TBarras:public TScroller { public: TBarras(TWindow *Ventana,int UnidadesX.int UnidadesY,
long RangoX,long RangoY) :TScroller(Ventana,UnidadesX,UnidadesY,RangoX.RangoY) i 1 ;
) ;
_CLASSDEF(TVentanaPrincipall;
156
Apéndice B. Código fuente del programa
class TVentanaPrincipa1:public TWindow ( protected:
SOCKET Socket;
HBITMAP MSDOS; HBITMAP Terminal; HBITMAP
HCURSOR CursorTerminal; Getway;
HCURSOR CursorFlechaNormal; HWND Ventana;
HINSTANCE Programa;
l l BOOL BOOL CambiarCursor;
EstaPresionado:
TGraficaBitMap 'RedBMP;
virtual void WMLButtonDownlTMessage &)=[WM-FIRST + WM-LBUTTONDOWNI; virtual void CursorRatOnlRTMeSSage Msg!=IWM-FIRST + WM-MOUSEMOVEI;
virtual void WMLButtonDblClklTMessage h)=[WM-FIRST + WM-LBUTTONDBLCLKI; virtual void WMLButtonUp (message h)= [WM-FIRST + WM-LBUTTONUPI ;
virtual void ComandoGruposlTMessage h!=ICM-FIRST + CM-COMANDO-GRUPOSI;
virtual void ComandoComunity(TMessage h)=ICM-FIRST + CM-COMUNITYI; virtual void ComandoInsertarlTMessage &)=[CM-FIRST + CM-INSERTAR]: virtual void ComandoAbrirlTMessage h!=lCM-FIRST + CM-ABRIR]; virtual void ComandoGuardar (TMessage & ) = [CM-FIRST + CM-GUARDAR1 ; vlrtual vold ComandoNuevo(TMessage 6) = [CM-FIRST + CM-NUEVO1 ; virtual vold WMVScroll(RTMessage)=[WM_FIRST + WM-VSCROLLI: virtual void WMSizelRTMessage) = IWM-FIRST + WM-SIZE];
TVentanaPrincipal(1 :
vlrtual void GetWindowClass(WNDCLSS -FAR &!; -TVentanaPrincipall);
void CargaBitMaps (HINSTANCE,HWND) : virtual void Paint(HDC,PAINTSTRUCT -FAR & ) ;
TWord Posx,PasY;
virtual void AyudaIndice(TMessage &!=[CM-FIRST + MEW-INDICEI;
virtual void ComandoDireccionIPlTessage h)=[CM-FIRST +CM_DIRECCION-IPI;
public:
) :
void TVentanaPrincipa1::AyudaIndicellMessage &! i
1
i
WinHelp IHWindow, "SNMPADMI .HLP",HELP-CONTENTS.NULL! :
void TVentanaPrinclpal::WMSize(RTMessage Mensaje)
TamHorizontalVentana=Mensaje.LP.Lo; TamVerLlcalVentana=Mensaje.LP.Hi;
Scrolles~~YRange=(long!PresicionVertical*TamVerticalMapa/TamVerticalVentana; !/YRange indlca el número de pasos que hay en la barra
Scroller-~XRange=(long)PresicionHorizontal*TamHorizontalMapa/TamHor~~ontalVentana: Scroller->SetSBarRanqe(); //YUnit Indica el número de pixeles que vale cada paso en la barra Scrolles-~YUn~L=TamVerticalMapa/Scroller-~YRange; Scroller~~XUnit=TamHorizontalMapa/Scroller~>XRange; Scro~les~sSetSBarRangeO;
//YPaqe indica el número de pasos que se avanza por página Scroller~~YPage=TamverticalVentana/Scsoller-~Y~nit; Scroller-~XPage=TamHorizontalVentana/Scroller->XUnit; Scroller-sSetSBarRange0; //YLine indica el número de pasos que se avanza por linea
Scroller-~XLine=Scroller->XPage/lO; Scroller-sYLine=Scroller-,YPa9e/lO;
Scroller->SetSBarRange(!; !/**'***'lt*'.
157
Administrador de Redes SNMP
PAINTSTRUCT aux; HDC dc=GetDC(HWindow); SetWindowOrg(dc.Scroller~~XPos*Scroller-~xUnit,Scroller-~YPos*Scroller-~YUnit); Paint (dc, aux) ;
i ReleaseDC(HWindow.dc);
void TVentanaPrincipal::WMVScroll(RTMessage Mensaje) i
/ * switch(Mensaje.WParam)
case SB-PAGEDOWN: i
OY-=%roller->YPos*Attr.W/Scroller->YRange; break;
case SB-LINEDOWN:
break; OY-=50;
case SE-PAGEUP: OY+=50;
break;
OY+=50; break;
break;
break;
case SB-LINEUP:
case SE-THUMBPOSITION:
case SB-THUMBTRACK:
) * I TWindow::WMVScroll(Mensajei;
char Buffer[25Ol ; / / OY=Scroller->YPos*TamVertical/lO;
/ / MessageBox(Ventana,itoa~TamVertical,Buffer,10~,"nn",MB~OK~; )
BOOL EsGrupoSystem(char Cad[] 1 i if((Cadlo]=='l')&&(Cad[21=='3')&&(Cad[41=='6')&&
( C a d [ 6 ] ~~~l')&&(Cad[8]~='2'~&&~CadilOl=='l'~&& (Cad[lZI=='l')l return TRUE;
) return FALSE:
BOOL EsGrupoInterfaces(char Cadi]) t if(lCadlOl=='l'~h&~Cad[2]=='3'~&&~Cad~41=='6'~&&
~ C a d [ 6 ] = ~ ' l ' ) & & ( C a d [ 8 l = = 1 2 1 ) & 6 ( C a d 1 1 0 l . . ' l ' ~ & & !Cad[121=='2')) return TRUE;
1 return FALSE:
void TVentanaPrincipal::CursorRaton(RTMessage Msg) 1 //Esta función se manda llamar cuando se mueve el cursor del ratdn dentro del
static BOOL NoSalto=TRUE; //area de la ventana que corresponde a esta aplicación
if (Nosalto)
NoSalto=FALSE;
SetWindowOrg(dctemporal,Scroller-sXPos*Scroller-sXUnit.Scroller-~YPos*Scroller>yUnit); DWORD Tam=GetWindowOrg (dctemporal) : ReleaseDC(HWindow,dctemporal);*/ int PosicionX=Msg.~P.~o+Scroller-~XPos*Scroller-~XUnit;
I
/ * HDC dctemporal=GetDC(HWindow);
158
Apéndice B. Código fuente del programa
int Pos~cionY=Msg.LP.Hi+Scroller->YPos~Scroller~~YUnit; if (RedBMP->Colision!PosicionX,PosicionY)j
{ if (CamhiarCursorI
i
CambiarCursor=FALSE; SetCursor!CursorTerminal) ;
( if !'CambiarCursorj
{ SetCursor(CursorFlechaNonna1); CambiarCurso+=TRUE;
) )
( if !!EstaPresionadoj&&!NodoActivoj)
Rect.left=NodoActi~o-~BitMapo-,X()-NodoActivo-~BitMap!~-~anchol~/2; RECT Recti
Rect.top=NodoActivo->BitMapO->Y!j+l; Rect.right=NodoActivo~~BitMap(j~~XO+2*NodoActivo-sBitMap!j~>ancho!!; Rect.bottom=NodoActivo-~BitMap!~-~Y!~+2*NodoActivo~~BitMap!~ ->ancho(:;
NodoActivo-zBitMap!j ->X!NodoActivo->BitMapO -zX!j+PosicionX-PosX); NodoAct~vo-sBitMapO-sY!NodoActivo~~BitMap!~-~YO+PosicionY-PosY~;
Rect.left~=Scroller->XPos+Scroller-,XUnit; Rect. top-=Scroller->YPos*Scroller,YUnit:
PosX=PosicionX; PosY=PosicionY; InvalidateRect!HWindow,&Rect,TRUE);
) NoSalto=TRUE; )
)
veld TVentanaPrincipa1::WMLButtonDownlTMessage &m) ( //Esta función se manda llamar cuando el botón izquierdo del ratón se presiona int PosicionX=m.LP.Lo+Scroller-~xPos*Scroller-~xUnit; int Posic ionY=m.LP.Hi+Scro l le r ,YPos+Scrol le r -~YUni t ; NodoActivo=RedBMP-zObtenActivo(PosicionX,PosicionY): PAINTSTRUCT aux; HDC dc=GetDC!HWindow); SetWindowOrgldc.Scrol~er-sXPos'Scroller-~XUnit,Scroller-~YPos*Scrolle~~~YUnit~; Paint(dc, aux) ;
ReleaseDC!HWindow,dcj ; EstaPresionado=TRUE: PosX=PosicionX; PosY=PosicionY;
)
void TVentanaPrincipa1::WMLButtonUp (TMessage & )
( //Esta función se manda llamar cuando el botón izquierdo del ratón se libera if !EstaPresionadoj
EStaPreSionado=FALSE; InvalidateRgn (HWindow, NULL, TRUE) ;
void TVentanaPrincipal::WMLButtonDblClk!TMessage &Mensaje1
I / Esta función se manda llamar cuando el botón izquierdo del ratón hizó / / doble clic int PosicionX=Mensaje.LP.Lo+Scro~ler-~XPos~ScIo~ler-~XUnit; int PosicionY=Mensaje.LP.Hi+Scroller~sYPos*Scroller,Wnit;
(
159
Administrador de Redes SNMP
if I 'CambiarCursor)
) RedBMP->VerDatos(PosicionX.PosicionY);
void TVentanaPrincipal::ComandoGrupos(TMessage & I i if INodoActivo)
i
1 RedBMP~zVerDato~(N0doActivo-~EitMap()-,X~~+5,NodoActivo~~EitMapO-zY~~+5~;
else
variables" ,ME-ICONEXCLAMATION) : MessageBox(HWind0w. "NO se ha seleccionado ningún nodo", "Ver información de grupos de
)
void TVentanaPrinclpal::ComandoDireccionlP(TMessage & )
i if (NodoActlvo)
i TDialogoDireccionIP *Dialogo=new TDialogoDireccionIP(this); strcpy~DialogoDireccionIPDatos.Comunity,NodoActivo-~EitMapO-sDatos.Comunityl; strcpy(DialogoDireccionIPDatos.DireccionNombre,NodoActivo-~ObtenDireccionNomhreO 1 ; s t rcpy(Dia logoDirecc ionIPDatos .Direcc ionIP ,NodoAct ivo-~ObtenDirecc ionIP~~~: if (GetApplicationO->ExecDialog(Dialogo).=IDOK)
i / / strcpy(NodoActivo~~BitMapO-sDatos.Comunity,DialogoComunityDatos.Comunity):
NodoActivo-~EitMap()-sDatos.DireccionIP=inet~addr~DialogoDireccionIP~atos.DireccionIP~; RECT Rect; Rect.left=NodoActivo~~BitMap~)-~XO-NodoActivo-~BitMapl~-sanchoO/2; Rect.top=NodoActivo-.sitMapO-zYO+l; R e c t . r i g h t ~ N o d o A c t i v o z B i t M a p ~ ) > X o + 2 * N o d o A c t i v o - ~ E i t M a p O - ~ a n c h o ~ ~ ; Rect.bottom=NodoActivo->EitMapO -,YO+2*NodoActivo->EitMapO -zanchoO;
InvalidateRect(HWind0w. &Rect,TRUE) :
else
) MessageBox(HWindow,"No se ha seleccionado ningún nodo"."Comunity",MB-ICONEXCLAMATION);
void TventanaPrincipal::ComandoComunity(TMessage & )
i if INodoActivoI
i TDialogoComunity *Dialogo=new TDialogoComunity(this1; strcpy~DialogoComunityDatos.DireccionIP,NodoActivo-~ObtenDireccionIP~l~ ;
strcpy(DialogoComunityDatos.DireccionNombre,NodoActivo-~ObtenDireccionNo~re~~ ) ;
strcpy(DialogoComunityDatos.Comunity,NodoActivo-,BitMapO~~Datos.Comunity); if (GetApplicationO-sExecDialog(Dialogo)==IDOK)
!
RECT Rect: strcpy(NodoActivo~>BitMap()~~Datos.Comunity,DialogoComunityDatos.Comunity):
Rect.left=NodoActivo~sBitMapO-,XO-NodoActivo->BitMapl)->anchoI)/2; Rect.top=NodoActivo->EitMapO->YO+l; Rect.right=NodoActivo~~EitMap()-~XO+2*NodoActivo-sBitMap~~,anchoo; Rect.bottom=NodoActivo->EitMapO -~YO+2*NodoActivo->BitMap~) ->anchoO;
InvalidateRect(HWindow,&Rect,TRUE);
else MessageBox(HWindow,"No se ha seleccionado ningún nodo","Comunity".ME-ICONEXCLAMATION);
)
void TventanaPrincipal::ComandoInsertar(TMessage & )
( strcpy(DialogoInsertarDatos.Comunity,"public"); DialogoInsertarDatos.DireccionIPlOl=O: if (GetApplicationO->ExecDialog(new TDialogoInsertar(this))==IDOK)
I DatosTerminal.D~IeccionIP=inet_addrlDialogoInsertarDatos.DireccionIP);
160
" -
Apéndice B. Código fuente del programa
strcpy(DatosTerminal.Comunity,DialogoInsertarDatos.Comunity); if (DatosTerminal.DireccionIP==O)
RedBMP- return;
unity) ; ~l~lserta~Terminai,BITMAP~TERMINAL,DatosTerminal,DatosTerminal.DireccionIP,DatosTerminal.Com
RedBMP->OrdenaGraficaO; RECT Rect; Rect.left=O; Rect.top=O; Rect.right=Attr.W-1: Rect.bottom=Attr.H-1; InvalidateRgn(HWindow,NULL,TRUE);
)
void TVentanaPrincipal::CornandoAbrir(TMessage & )
char NombreArchivo[2001 ;
TFileDialog(this,SD_FILEOPEN,strcpy(NombreArchivo,"*.red'~)i)==IDOK~ if iGetApplicatlon0 -sExecDialog(new
i if (Archivo: FILE *Archivo=fopen(NombreArchivo. "rt") ;
i char Buf (1001 ;
Destruye!RedBMP) ; fgets!Buf,100,ArChivo);
RedBMP=new TGraficaBitMap!this,Terminal,Programa,BITMAP_TERMINAL.Ventana,Socket,Archivo);
Rect.left=O; RECT Rect;
Rect.top.0; Rect.rlght=Attr.W-1; Rect.bottom=Attr.H-1; NodoActivo=RedBMP;
fclose (Archivo) ; InvalidateRect(HWindow.&Rect,TRUE);
1 else
) MessageBox (HWindow, "NO se pudo guardas el archivo", "Error", MB-OK) :
InvalidateRgn(HWindow,NLlLL,TRUE); 1
vold TVentanaPrincipal::ComandoGuardar(TMessage & )
{ char NombreArchivo 12001 ;
TFileDialog(this. SD-FILESAVE, strcpy(NombreArchiv0, " * .red"! 1 ) ==InOK) if (GetApplicationO ->BxecDialog(new
i FILE *Archivo=fopen(NombreArchivo, "wt") ;
if (Archivo) ( RedBMP->Guardar(Archivo);
fciose (Archivo) ; )
else MessageBox(HWind0w. "NO se pudo guardar el archivo", "Error".MB_OK) ;
) 1
veld TVentanaPrincipal::ComandoNuevo(TMessaqe & )
i DatosTerm~nal.DireccionIP=Direccion-IP;//inet~addr("148.206.49.251"!, strcpy(DatosTerminal.Comunity,Comunity); Destruye(RedBMP) ;
161
Administrador de Redes SNMP
RedBMP= new TGraficaBitMap~this,Terminal,Programa,BITMAP~TERMINAL,Ventana,DatosTerminal.Socket.DatosTer mina1 .DireccionIP. "private") ; RECT Rect; Rect.left=O; Rect.top=O; Rect.ri9hkAttr.W-1; Rect.bottom=Attr.H-1; NodoActivo=RedBMP: InvalidateRect IHWindow, &Rect, TRUE) ;
I
TVentana?rincipal::TVentanaPrincipal():TWindow(NULL."Administrador de Redes SNMP".NULL) i AssignMenuiMENU-PRINCIPAL); EstaPresionado=FALSE;
WORD VersionWinSockDLL=OXOlOl: //Requerimos un WinsockDLL versión 1.1 CambiarCursor=TRUE;
WSADATA DatosWinSockDLL; //Al iniciar nos da información del WINSOCK.DLL
if !Resultado1 int Resultado=WSAStartup(VersionWinSockDLL,&DatosWinSockDLL);
Estatus=-7;
//Iniciamos la comunicación
else
/ * * ' * * * t * * * * * * l * ~ * t * ~ * * * , * ~ * ~ * ~ ~ ~ ~ . ~ ~ ~ . ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ * ~ * ~ ~ ~ . ~ ~ . ~ ~ ~ * ~ ~ / i / + t t * t l * * t l * * + * * * + * . ~ ~ ~ ~ ~ * ~ ~ ~ * ~ ~ ~ ~ * ~ ~ * ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ , ~ ~ ~ ~ ~ ~ . ~ ~ ~ ~ ~ ~ ~ * ~ /
if ~(Socket=socket(PF~INET,SOCK~DGRAM,IPPROTO~UDP~~==INVALID~SOCKET~ Estatus=-8;
Attr.Style1-WS_HSCROLL(WS"JSCROLL; Scroller=new TBarras(this,100,100,10,10);
)
/ / Scroller->YPage=Attr.H/lO; / / Scroller->XPage=Attr.W/lO; / / Scroller->YLine=Attr.H/lOO; / / Scroller->XLine=Attr.W/lOO; / / stroller->SetUnitsiAttr.W,Attr.H); / / Scroller->AutoOrg=O; i wentanaPrincipa1::-TVentanaPrincipalO ( if (Socket'=INVALID-SOCKETi
closesocket(Socket); WSACleanup ( I ; #define Destruyeo(0bjeto) if (Objeto) DeleteObject(Objet0) #define DestruyeC(0bjetoi if (Objeto) DestroyCursorfObjeto) DestruyeO(MSD0S) ; DestruyeOiTerminall; DestruyeO(Getway1 ; DestruyeC(CursorTerminal1; Destruye (RedBMP) ;
vold TventanaPrlncipal::GetWindowClass(WNDCLASS -FAR .s Info) i TWindow::GetWindowClassfInfo); Info.Style=CS_HREDRAW CS-VREDRAW I CS-DBLCLKS; Info.hCursor=NULL;
Info.hbrBackground~CreateSolidBrush~RGBf180,192,192jj;//(HBRUSHjGetStockObject~LTGRAY~BRUSH 1;
) Info.hIcon=LoadIcon~Info.hInStance,~KEINTRESOURCEfICONO~LO~~~ ,
vord LeeArchivoIni ( 1 (
162
Apéndice B. Código fuente del programa
char Buffer [TAM-MAX-BUF] :
GetPrivateProfileString("Inicio","DirecciónIP","O.O.O.0",Buffer,TAM~MAX~BUF."snmpadmi.ini'~)
Direccion-IP=inet-addr(Buffer); GetPrivateProfileString("Inicio~',"Comunity","public".Buffer.TAM~MAX~BUF,'~snmpadmi.ini"i; Comunity=new char[strlen(Buffer)+ll; strcpy1Comunity.Buffer);
I
void TVentanaPrincipal::CargaBitMaps(HINSTANCE programa.HWND MV) ( MSDOS. LoadBitmap(programa.MAKEINTRESOURCElBITMAP~DOSll; Terminal= Loadsitmap (programa, MAKEINTRESOURCE (BITMAP-TERMINAL1 i ; Getway= LoadBitmap(programa.MAKEINTRESOURCElBI'IMAP~GETWAYll; CursorTermlnal= LoadCursor(programa.MAKEINTRESOURCElCURSOR~TERMINAL1 I , CursorFlechaNormal= LoadCursor(NULL. MAKEINTRESOURCEl32512)); LeeArchivoIniO;
Ventana=MV; TMessaqe aux;
Programa=proqrama; RedBMP=NULL; ComandoNuevo(aux); I
void TVentanaPrincipal::Paint(HDC dc,PAINTSTRUCT -FAR & )
( HFONT Fontl. FontZ=CreateFont 1-10 , O. O. O. O. O. O . O . O . O . O. O. O. "Arial"1 : Fontl=(HFoNT)selectObject(dc,Font2); SetTextAlignfdc.TA_CENTERl ;
RedBMP->Dibuja(dcl ; S e t B k C 0 l o r ( d c . R G B 1 1 9 2 . 1 2 3 . 1 9 2 ) ) ;
SetBkColor(dc,RGB(234,234,0)); if (NodoActivo)
Selectobject (dc, Font11 ; NodoActivo->BitMapl) ->Dibuja(dc);
) DeleteObject(Font2);
class TPr0qrama:public TApplication ( protected:
HINSTANCE ProgramaActual: TVentanaPrincipal public:
TPrograma(H1NSTANCE Programa,HINSTANCE ProgramaAnterior,LPSTR LineaComandos, int Ver): TApplication("Administrador SNMP",Programa,ProgramaAnterior.LineaComandos.Ver)
WentanaPrincipal;
i
I; ProgramaActual=Programa;
virtual void InitMainWindowO; ) ;
void TProqrama::InitMainWindowO { //No es necesario incluir en el destructor, ya que el destructor heredado //Destruye a Mainwindow VentanaPrincipal=new TVentanaPrincipalO; MalnWindow=VentanaPrincipal; VentanaPrincipal~~CargaBitMaps~ProgramaA~tual,VentanaPrincipal-~HWindowl :
I
Int PASCAL WinMain (HINSTANCE Programa.HINSTANCE ProgAnterior,LPSTR LineaComandos. int Ver)
for (int i=O;iclOO;i++) Secuencias Lil =O;
DatosDialogoVariables.Lista=NULL;
163
Administrador de Redes SNMP
TPrograma Prog( Programa ,ProgAnterior ,LineaComandos , Ver ) i
Prog . Run ( I ;
i return Prog.Estatus;
ARCHIVO DE RECURSOS (SNMPADMI.RC) #include "snmpadmi .ha'
MENU-PRINCIPAL MENU BEGIN
POPUP "&Archivo" BEGIN
MENUITEM "&Nuevo", CM-NUEVO MENUITEM "&Abrir", CMABRIR MENUITEM "&Guardar", CM-GUARDAR MENUITEM SEPARATOR MENUITEM "&Salir", CM-EXIT
END
POPUP "&Comandos" BEGIN
MENUITEM "&Insertar", CM-INSERTAR MENUITEM "&Grupos", CM-COMANDO-GRUPOS
MENUITEM "&DireccionIP'*. CM-DIRECCION-IP MENUITEM "hComunity", CM-COMUNITY
END
BEGIN POPUP "A&yuda"
END MENUITEM "&Indice", MENU-INDICE
END
//BITMAP-DOS BITMAP "dos.bmp" BITMAP-TERMINAL BITMAP "terminal.hmp" //BITMAP-GETWAY BITMAP "gw-16.bmp"
CURSOR-TERMINAL CURSOR "terminal.cur"
DIALGO-GRUPOS DIALOG 18, 18. 196. 198
CLASS "bordlg" STYLE DS-MODALFRAME 1 WS-POPUP 1 WS-CAPTION 1 WS-SYSMENU
BEGIN
10, 164, 33, 21 CONTROL "Button", IDOK. "BorBtn". BS-PUSHBUTTON I WS-CHILD I WS-VISIBLE 1 WS-TABSTOP.
CONTROL " " , ID-GRUPOS. "COMBOBOX". CBS-DROPDOWNLIST 1 WS-CHILD I WS-VISIBLE 1 WS-VSCROLL
DEFPUSHBUTI'ON "Preguntar", ID-PREGUNTAR, 77, 166, 42, 18, WS-CHILD I WS-VISIBLE 1
CONTROL "Parar". CM-PARAR, "BUTTON", BS-PUSHBUTTON I WS-CHILD I WS-VISIBLE 1 WS-DISABLED
CONTROL I"*, 114, "BorShade", 32769 I WS-CHILD I WS-VISIBLE, 18, 12, 161, 149
1 WS-TABSTOP. 21, 15, 156, 143
WS-TABSTOP
1 WS-TABSTOP, 139, 167, 46, 17
END
DIALOGO-VARIABLES DIALOG 2 6 , 40, 308, 274 STYLE DS-MODALFRAME 1 DS-NOIDLEMSG I WS-POPUP I WS-CAPTION I WS-SYSMENU CLASS "hordlg" FONT 10, "Courier" { LISTBOX ID-LISTA-VARIABLES, 16, 20, 276, 217, LBS-NOTIFY 1 WS-CHILD 1 WS-VISIBLE ~
CONTROL "Button", IDOK, "BorBtn", BS-PUSHBUTTON 1 WS-CHILD 1 WS-VISIBLE 1 WS-TABSTOP. 139, WS-BORDER I WS-VSCROLL
242, 29, 25
164
Apéndice B. Código fuente del programa
LTEXT 'Variables Encontradas". - 1 , 1 3 5 , 4, 3 7 , 8 , WS-CHILD 1 WS-VISIBLE 1 WS_GROUP )
DIALOGO-DIRECCION-IP DIALOG 2 7 , 7 2 , 2 5 5 , 98
CLASS "bordlg" STYLE DS-MODALFRAME 1 WS-POPUP 1 WS-CAPTION 1 WS-SYSMENU
CAPTION "Direccion IP" { CONTROL " " , ID-BG-INFORMACION, "BorShade", /*BSS-GROUP I BSS-LEFT I * / WS-CHILD I
CONTROL I"', ID-BG-COMUNITY. "BorShade", /*BSS-GROUP 1 BSS-LEFT I + / WS-CHILD 1 WS-VISIBLE,
CTEXT '"', ID-COMUNITY. 7 1 , 10, 1 1 2 . 8 . WS-CHILD 1 WS-VISIBLE 1 WS-GROUP
LTEXT "Direccion IP", -1. 1 8 , 4 8 , 4 8 , 8 , SS-LEFT 1 WS-CHILD 1 WS_VISIBLE CTEXT '"*, ID-DIRECCION-NOMBRE, 2 5 , 2 5 , 2 0 4 , 8 . WS-CHILD I WS-VISIBLE 1 WS-GROUP
EDITTEXT ID-DIRECCION-IP, 1 1 1 . 4 6 , 1 2 5 , 12, ES-LEFT I WS-CHILD 1 WS-VISIBLE 1 WS-BORDER 1
WS-VISIBLE 1 WS-GROUP, 14, 6, 2 2 7 , 3 3
13, 4 3 , 2 2 8 . 1 9
WS-TABSTOP
4 5 , 7 1 , 3 3 , 2 1 CONTROL "Button", IDOK. "BOrBtn", BS-DEFPUSHBUTTON I WS-CHILD 1 WS-VISIBLE 1 WS-TABSTOP.
1 7 7 , 7 1 , 3 3 , 2 1 CONTROL "Button". IDCANCEL, "BorBtn", BS-PUSHBUTTON I WS-CHILD j WS-VISIBLE 1 WS-TABSTOP,
DIALOGO-COMUNITY DIALOG 2 7 , 7 2 , 2 5 5 , 98 STYLE DS-MODALFRAME 1 WS-POPUP 1 WS-CAPTION I WS-SYSMENU CLASS "bordlg" CAPTION "Comunity" ( CONTROL I"', ID-BG-INFORMACION, "BorShade", /*Bss_GROuP 1 BSS-LEFT 1 */wS-CHILD 1 WS-VISIBLE I WS-GROUP, 1 4 , 6 , 2 2 7 , 3 3 CONTROL " " , ID-BG-COMUNITY. "BorShade", /'BSS-GROUP 1 BSS-LEFT j */WS-CHILD 1 WS-VISIBLE.
CTEXT " " , ID-DIRECCION-IP, 9 8 . 10, 59, 8 . WS-CHILD 1 WSVISIBLE 1 WS-GROUP CTEXT " ' I , ID-DIRECCION-NOMBRE. 2 5 , 2 5 . 2 0 4 , 8 , WS-CHILD 1 WS-VISIBLE , WS-GROUP LTEXT "Comunity", -1, 18, 4 8 , 4 8 , 8 . WS-CHILD 1 WS-VISIBLE EDITTEXT ID-COMUNITY, 1 1 1 , 4 6 , 1 2 5 , 1 2 , ES-LEFT 1 WS-CHILD 1 WS_VISIBLE I WS-BORDER I
13, 4 3 , 2 2 8 , 1 9
WS-TABSTOP
4 5 , 7 1 , 3 3 , 2 1 CONTROL "Button", IDOK, "BorBtn", BS-DEFPUSHBUTTON 1 WS-CHILD I WS-VISIBLE I WS-TABSTOP.
CONTROL "Button", IDCANCEL, "BorBtn", BS-PUSHBUTTON I WS-CHILD 1 WS-VISIBLE 1 WS-TABSTOP, 1 7 7 , 7 1 , 3 3 , 2 1
DIALOGO-INSERTAR DIALOG 9 5 , 5 9 , 1 3 4 . 9 8 STYLE DS-MODALFRAME 1 WS-POPUP 1 WS-CAPTION 1 WS-SYSMENU CLASS "bordlg" CAPTION "Insertar un nodo a la red" i LTEXT "Direccion IP". -1. 46, 11, 41, 8 EDITTEXT ID-DIRECCION-IP, 1 4 , 2 2 , 1 0 5 , 1 2 , ES-LEFT I WS-CHILD I WS-VISIBLE 1 WS-BORDER 1
LTEXT "Colnunity", -1. 5 1 . 46, 3 2 , 8 EDITTEXT ID-COMUNITY, 14, 56, 1 0 5 , 1 2 . ES-LEFT I WS-CHILD 1 WS-VISIBLE I WS-BORDER 1
CONTROL "Butcon", IDOK, "BorBtn", BS-PUSHBUTTON I WS-CHILD j WS-VISIBLE I WS-TABSTOP, 1 4 .
CONTROL "Button", IDCANCEL, "BorBtn". BS-PUSHBUTTON I WS-CHILD I WS-VISIBLE 1 WS-TABSTOP,
WS-TABSTOP
WS-TABSTOP
7 2 , 3 3 . 2 1
8 5 , 7 2 , 3 3 , 2 1
1
SD FILEOPEN DIALOG 2 0 . 2 4 . 2 0 2 . 1 7 7 STYLE WS-TILED I WS-CAPTION 1 WS-SYSMENU I DS-SETFONT I DS-MODALFRAME CLASS "bordlg" CAPTION " A b r i r un archivo de RED" FONT 8 , "Helv" ( LTEXT "&Nombre del Archivo". -1. 6 , 8 . 7 3 , 10
165
Administrador de Redes SNMP
WS-TABSTOP 1 ES-AUTOHSCROLL EDITTEXT ID-FNAME. 98, 6, 98, 1 2 , ES-OEMCONVERT 1 WS-CHILD 1 WS-VISIBLE 1 WS-BORDER 1
LTEXT "Directorio:". -1, 6, 20, 3 6 , 10. WS-CHILD 1 WS-VISIBLE 1 WS-GROUP LTEXT '"I, ID-FPATH. 42, 2 0 , 154. 1 0 LTEXT "&Archivos", -1, 6 , 3 2 , 92, 10 , WS-CHILD 1 WS-VISIBLE 1 WS-GROUP LISTBOX ID-FLIST, 6 , 44, 92, 100, LBS-STANDARD I WS-CHILD I WS-VISIBLE LTEXT "&Directorios", -1. 106, 3 2 , 89, lo, WS-CHILD 1 WS-VISIBLE 1 WS-GROUP LISTBOX ID-DLIST, 104, 44, 91, 101, WS-CHILD 1 WS-VISIBLE 1 WS-TABSTOP ! LBS-STANDARD CONTROL "Button", IDOK, "BorBtn", BS-PUSHBUTTON I WS-CHILD I WS-VISIBLE 1 WS-TABSTOP, 43,
149. 37, 25
122, 149. 37, 25 CONTROL "Button", IDCANCEL, "BorBtn". ES-PUSHBUTTON 1 WS-CHILD I WS-VISIBLE I WS-TABSTOP,
1
SD-FILESAVE DIALOG 2 0 , 24, 204, 210 STYLE WS-TILED I WS-CAPTION I WS-SYSMENU I DS-SETFONT I DS-MODALFRAME CLASS "bordlg" CAPTION "Guardar un archivo de RED" FONT 8, "Helv" 1 LTEXT "&Nombre : " , - 1, 8, 8 , 3 6 , 10 EDITTEXT ID-FNRME, 44, 6, 151. 12, ES-OEMCONVERT I WS-CHILD 1 WS-VISIBLE I WS-BORDER I
LTEXT " ' I , ID-FPATH. 44, 20, 150, 10 LTEXT "Directorio:", -1, 8 , 20, 36, 10
LTEXT "&Directorios:". -1. 8 , 32, 1 8 6 , 10 LISTBOX ID-DLIST, 8 , 44, 186, 130. LBS-STANDARD I LBS-MULTICOLUMN I WS-CHILD I WS-VISIBLE
CONTROL "Button", IDOK, "BorBtn". BS-PUSHBUTTON 1 WS-CHILD I WS-VISIBLE 1 WS-TABSTOP. 49,
CONTROL "Button", IDCANCEL. "BorBtn", BS-PUSHEVITON I WS-CHILD 1 WS-VISIBLE 1 WS-TABSTOP.
WS-TABSTOP I ES-AUTOHSCROLL
1 WS-TABSTOP
177. 3 7 , 2 5
118, 177, 37, 25
//Entrar ICON "comenzar.ico" ICONO-LOGO ICON "1ogo.ico" )
ARCHIVO DE DEFINICIONES (SNMPADMI.DEF) EXETYPE WINDOWS CODE PRELOAD MOVEABLE DISCARDABLE
HEAPSIZE 1 0 0 0 0 DATA PRELOAD MOVEABLE MULTIPLE
STACKSIZE 14000
166
"
Bibliografía
BIBLIOGFUFÍA 0 Windows Network Programming
Ralph Davis Addison-Wesley 1993
Programación Orientada a Objetos 2" edición Ted Fason Pretice Hall Hispanoamericana S.A. 1993
0 The Simple Book Marshall T. Rose Prentice Hall RFC155 SMI Marshall Rose RFC156 MIB K. McCloghrie RFC157 SNMP J. Case
Marshall Rose RFC768 UDP J. Posetel RFC791 IP Defense Advanced Research Projects Agency
Borland C + + 3.1
RFC158 MIB-I1
0 RFC793 TCP Defense Advanced Research Projects Agency
167
Índice de tablas
ÍNDICE DE TABLAS Tabla I Clases de direccinamiento en IP 6 Tabla 2 Opciones en el encabezado IP i1 Tabla 3 Títulos universales en ASN.1 30 Tuhla 4 Grupos de la MIB-I 34 Tabla 5 Grupos de la MIB-II 34 Tabla 6 Valor ejemplo de una variable - objeto pura el grupo system 36 Tabla 7 Un valor ejemplo de la variable - objeto para el renglón correspondiente u la primera interfaz 38 Tubla 8 Un valor ejemplo de la variable - objeto en la tabla address translation39 Tabla 9 Ejemplo de la tabla ip address 40 Tabla I O Ejemplo de la tabla de ruteo IP 41 Tuhlu I I Ejemplo de la tabla de interpretación de direcciones IP 42 Tabla 12 Ejemplo de la tabla TCP 45 Tuhlu 13 Ejemplo de I r tabla UDP 46 Tulda 14 Banderas para enviar mensaje del estado de1 socket 71
1
Administrador de Redes SNMP
ÍNDICE DE DIAGRAMAS Diagrama I Relaciones entre Protocolos Diagrama 2 Forma en que viaja un paquete IP Diagrama 3 Vuriables relacionadas al espacio de secuencia Diagrama 4 Espacio de secuencia etiquetado Diagrama 5 Estados de TCP Diagrama 6 Casos para el grupo Interfaces Diagrama 7 Casos para el grupo IP Diagrama 8 Casos para el grupo ICMP Diagrama 9 Entidades de aplicación que usen TCP/IP Diagrama I O Objetos definidos
11
4 5
21 22 24 37 40 43 44
101
Índice de fig,
ÍNDICE DE FIGURAS Figuru I Encabezudo 1P 7 Figuru 2 Tipo de servicio en IP 8 Figura 3 Banderas en encabezado IP 9 Figura 4 Mínimos datos que debe llevar un datagrama I I Figura 5 Datagrama de tamaño medio 12 Figura 6 Primer fragmento de la división de un datagrama 12 Figuru 7 Segundo fragmento de la división de un datagrama 12 Figura 8 Datagrama con opciones 13 Figura 9 lnterpretación de cada bit dentro de una trama según el orden en que se transmite Figura 10 diagrama que representa el número decimal I70 Figura I I Diagrama de protocolos de nivel Figuru I2 Lugar que ocupa TCP en la jerarquía clc protocolos Figura 13 Formato del encabezarlo TCP Figura 14 Formato del encabezado de un datagrama UDP Figura 15 Encabezado de UDP Figura 16 Primer nivel del corte del úrbol para normalizar variables Figura I7 Primer nivel del subúrbol IS0 Figura 18 Etiquetu TL V Figuru I9 Un octeto que viaja por la red Figura 20 Cumpo tag de una TLV Figura 21 Clases de tipos en BER Figura 22 Codlficación del campo tag de una TL V Figura 23 Cod#icación del valor 100 Figurn 24 Cotl(ficación de una curiena Figura 25 Código ver de NULL Figura 26 Código BER de un objeto identlficador Figura 27 Código BER del tipo VarBind en forma definidu Figura 28 Código BER del tipo VarBind en forma indejinidu Figura 29 Código BER de un SECUENCE OF Figura 30 Código de una cadena Figura 31 código del cuerpo de un choice Figura 32 Código BER de un identlficador de objetos Figura 33 Código BER de una cadena Figura 34 El tipo TD Word Figura 35 Didogo Grupos. Para enviar mensajes a las terminules. Figuru 36 Diúlogo pura insertar un nodo. Figura 37 Diúlogo para cambiar el valor del community Figuru 38 Diúlogo para cambiar la dirección IP
13 13 14 16 19 24 25 32 32 51 52 52 53 53 55 55 55 56 57 57 59 61 61 62 62 72 94 95 96 96
111 ...
Administrador de Redes SNMP
Figura 39 Ejecutar una aplicación desde el administrador de programas 97 Figura 40 Instalar en: (del instalador) 98 Figura 41 Insertar valores iniciales 98 Figura 42 Aviso,final al instalar 99 Figura 43 Grupo SNMP 99 Figura 44 Eliminar un grupo I O 0 Figura 45 Eliminar los archivos del administrador I 00
iV
Índice completo
iNDICE COMPLETO Introducción Protocolos más importantes de l a familia TCP/IP
Protocolo IP (Internet Protocol) Propósito
Alcance
Interfaces
Operación
Relación de IP con otros protocolos
Modelo de Operación
Fragmentación de un datagrama
Ruteadores o Gateways
Especificación TCP
Introducción
Alcance
Interfaces
Áreas básicas en las que se usa TCP.
Transferencia Básica de Datos.
Confiabilidad.
Control de Flujo.
Multiplexión.
Conexiones.
Precedencia y Seguridad.
Elementos del Sistema InterRedes.
Modelo de operación.
Interfaces
Comunicación confiable.
4
6
7
7 14
14
14
14
14
15
15
15
15
15
16
16
16
16
17
V
Administrador de Redes SNMP
Establecimiento y Liberación de la Conexión
Comunicación de Datos.
Precedencia y Seguridad.
Principio de Robustez.
Especificación funcional
Formato del encabezado
Formato del encabezado TCP
Terminología
Variables de secuencia de envío UDP (User Datagram Protocol)
Campos de UDP
Interfaz de Usuario.
Interfaz IP
Protocolo SNMP ASN. 1
MÓDLJLOS
Tipos y Valores
Tipos Simples
Tipos Construidos
Tipos Etiquetados
Subtipos
Identificador de Objetos (OBJECT IDENTIFIER) MIB .
La MIB Estándar - Internet
Grupo System
Grupo Interfaces
Grupo Address Translation
Grupo IP
Grupo ICMP
Grupo TCP
vi
17
18
18
18
18
18
19
21
21 24
25
25
26
27 27 27
28
28
29
29
31
31 _.
35
35
36
38
39
42
43
Índice completo
Grupo UDP
Grupo EGP SNMP
Introducción
Arquitectura de la administración SNMP.
CaracIerísticas del protocolo SNMP
Elementos de la arquitectura
El protocolo SNMP - BER
CODIFICACION DE DATOS
Orden de los Bits
Campo Etiqueta
Campo Longitud
Campo Valor
Tipos Simples
INTEGER
OCTET STRING NULL
OBJECT IDENTIFIER
Tipos Constructores
SEQUENCE
SEQUENCE OF
Tipos etiquetados
U n ejemplo
Descripción del proyecto Objetivos Plataforma
Como administra Windows la memoria.
Estructura de un programa para Windows.
La multitarea de Windows
45
46 46
46
46
47
47
50 51
51
52
52
53
54
54
55
55
55
56
56
56
58
58
59
64 64 64
65
65
66
vii
Administrador de Redes SNMP
Los archivos DLL de Windows.
Los dispositivos de contexto Estructura
Comunicación TCP/IP
Codificación en BER para USO del protocolo SI".
Proceso de administración en SNh4p.
Ambiente gráfico.
Uso del Winsock.dl1
Usando los sockets
Implementación de BER.h y BER.cpp
Clase TetiquetaASN
Clase TLongitudASN
Clase TTipo
Clase TNULL
Clase TEntero
Clase TCadena
Clase TIdObj
Clases derivadas (TDireccionIP, TTicksReloj, TComodin)
Clase TVarBind
Clase TPDU
Clase TMensajeSNMP
Implementación del proceso de administración
Obtener variables
Obtener Tablas
Codificación de la administración.
Método PedirInformación
Método Pedirvariables
Método Recibirvariables
Vl l l ...
66
67 67 67
68
68
69
69
69
71
72
73
73
73
74
74
74
TContador , TMedidor , 74
75
75
75
76
76
76
77
77
78
80
Índice completo
Método CrearInformaciÓn
Método pedirtabla
Método RecibirTabla
Método ver tabla
El ambiente gráfico
Conclusiones
Manual de usuario Requerimientos del Sistema <Cómo Iniciar? Diálogo Grupos Inserta un nodo para administrarlo Cómo cambiar el valor de cornunity Archivo de inicialización SNMPADMLINI Sesión típica de Instalación Sesión de Desinstalación
Apéndice A. Objetos definidos
Apéndice B. Código fuente del programa Encabezado del archivo de codificación (l3ER.H) Codificación del archivo de codificación (BER.CPP) Archivo de encabezado principal (snmpadmi.h) Archivo fuente principal Archivo de recursos (SnmpAdmi.rc) Archivo de definiciones (SNMPADMLDEF)
Bibliografía
82
82
87
89
89
92
93 93 93 94 95 96 97 97
100
10 1 102 102 107 127 128 164 166
167
1x