diff options
author | mks <mks@FreeBSD.org> | 1999-01-20 00:56:21 +0000 |
---|---|---|
committer | mks <mks@FreeBSD.org> | 1999-01-20 00:56:21 +0000 |
commit | 5f3006942fd798125287d4697f71b6303a0403de (patch) | |
tree | fd229a97678429628f58cb0aeda90d6e3514ccdc | |
parent | 6f731db02ec0f2dfd49ba289c3dff40dbfce8fd6 (diff) | |
download | FreeBSD-src-5f3006942fd798125287d4697f71b6303a0403de.zip FreeBSD-src-5f3006942fd798125287d4697f71b6303a0403de.tar.gz |
Re-write of ilmi daemon. Among the major changes, it does not use predefined
PDUs and should handle multi-request OIDs on GETs.
-rw-r--r-- | sbin/atm/ilmid/ilmid.c | 2830 |
1 files changed, 1275 insertions, 1555 deletions
diff --git a/sbin/atm/ilmid/ilmid.c b/sbin/atm/ilmid/ilmid.c index e515a10..9da2424 100644 --- a/sbin/atm/ilmid/ilmid.c +++ b/sbin/atm/ilmid/ilmid.c @@ -23,7 +23,7 @@ * Copies of this Software may be made, however, the above copyright * notice must be reproduced on all copies. * - * @(#) $Id: ilmid.c,v 1.9 1998/08/13 20:15:28 jpt Exp $ + * @(#) $Id: ilmid.c,v 1.1 1998/09/15 08:22:47 phk Exp $ * */ @@ -45,40 +45,24 @@ * */ -#ifndef lint -static char *RCSid = "@(#) $Id: ilmid.c,v 1.9 1998/08/13 20:15:28 jpt Exp $"; -#endif - -#include <sys/types.h> #include <sys/param.h> -#if (defined(BSD) && (BSD >= 199103)) -#include <err.h> +#ifndef lint +__RCSID("@(#) $Id: ilmid.c,v 1.1 1998/09/15 08:22:47 phk Exp $"); #endif -#ifdef BSD -#if __FreeBSD_version < 300001 -#include <stdlib.h> -#ifdef sun -#include <unistd.h> -#endif /* sun */ -#else -#include <unistd.h> -#endif /* __FreeBSD_version >= 300001 */ -#endif /* BSD */ - +#include <err.h> +#include <errno.h> #include <stdio.h> #include <stdlib.h> -#include <time.h> -#include <sys/errno.h> #include <string.h> -#include <fcntl.h> -#include <sys/ioctl.h> #include <syslog.h> +#include <time.h> +#include <unistd.h> #include <sys/socket.h> +#include <sys/sockio.h> #include <net/if.h> #include <netinet/in.h> - #include <netatm/port.h> #include <netatm/atm.h> #include <netatm/atm_if.h> @@ -86,36 +70,30 @@ static char *RCSid = "@(#) $Id: ilmid.c,v 1.9 1998/08/13 20:15:28 jpt Exp $"; #include <netatm/atm_sap.h> #include <netatm/atm_sys.h> #include <netatm/atm_ioctl.h> - #include <dev/hea/eni_stats.h> #include <dev/hfa/fore_aali.h> #include <dev/hfa/fore_slave.h> #include <dev/hfa/fore_stats.h> -#include <netatm/uni/unisig_var.h> + +#include <libatm.h> #define MAX_LEN 9180 #define MAX_UNITS 8 /* - * Time to sleep between loops - */ -#define SLEEP_TIME 10 -/* - * Time to pass between sending coldStart TRAPs - */ -#define TRAP_TIME 5 - -/* * Define some ASN types */ #define ASN_INTEGER 0x02 #define ASN_OCTET 0x04 +#define ASN_NULL 0x05 #define ASN_OBJID 0x06 #define ASN_SEQUENCE 0x30 #define ASN_IPADDR 0x40 #define ASN_TIMESTAMP 0x43 +static char *Var_Types[] = { "", "", "ASN_INTEGER", "", "ASN_OCTET", "ASN_NULL", "ASN_OBJID" }; + /* * Define SNMP PDU types */ @@ -125,360 +103,167 @@ static char *RCSid = "@(#) $Id: ilmid.c,v 1.9 1998/08/13 20:15:28 jpt Exp $"; #define PDU_TYPE_SET 0xA3 #define PDU_TYPE_TRAP 0xA4 -/* - * Every SNMP PDU has the first four fields of this header. The only type - * which doesn't have the last three fields is the TRAP type. - */ -struct snmp_header { - int pdulen; - int version; - char community[64]; - int pdutype; - int reqid; - int error; - int erridx; -}; -typedef struct snmp_header Snmp_Header; +static char *PDU_Types[] = { "GET REQUEST", "GETNEXT REQUEST", "GET RESPONSE", "SET REQUEST", + "TRAP" }; /* - * Define our internal representation of an OBJECT IDENTIFIER + * Define TRAP codes */ -struct objid { - int oid[128]; -}; -typedef struct objid Objid; +#define TRAP_COLDSTART 0 +#define TRAP_WARMSTART 1 +#define TRAP_LINKDOWN 2 +#define TRAP_LINKUP 3 +#define TRAP_AUTHFAIL 4 +#define TRAP_EGPLOSS 5 +#define TRAP_ENTERPRISE 6 /* - * Define some OBJET IDENTIFIERS that we'll try to reply to: - * - * sysUpTime: number of time ticks since this deamon came up - * netpfx_oid: network prefix table - * unitype: is this a PRIVATE or PUBLIC network link - * univer: which version of UNI are we running - * devtype: is this a USER or NODE ATM device - * setprefix: used when the switch wants to tell us its NSAP prefix - * foresiggrp: FORE specific Objid we see alot of (being connected to FORE - * switches...) - */ -Objid sysObjId = { 8, 43, 6, 1, 2, 1, 1, 2, 0 }; -Objid sysUpTime = { 8, 43, 6, 1, 2, 1, 1, 3, 0 }; -Objid foresiggrp = { 18, 43, 6, 1, 4, 1, 326, 2, 2, 2, 1, 6, 2, 1, 1, 1, 20, 0, 0 }; -Objid portidx = { 12, 43, 6, 1, 4, 1, 353, 2, 1, 1, 1, 1, 0 }; -Objid myipnm = { 10, 43, 6, 1, 4, 1, 353, 2, 1, 2, 0 }; -Objid layeridx = { 12, 43, 6, 1, 4, 1, 353, 2, 2, 1, 1, 1, 0 }; -Objid maxvcc = { 12, 43, 6, 1, 4, 1, 353, 2, 2, 1, 1, 3, 0 }; -Objid unitype = { 12, 43, 6, 1, 4, 1, 353, 2, 2, 1, 1, 8, 0 }; -Objid univer = { 12, 43, 6, 1, 4, 1, 353, 2, 2, 1, 1, 9, 0 }; -Objid devtype = { 12, 43, 6, 1, 4, 1, 353, 2, 2, 1, 1, 10, 0 }; -Objid netpfx_oid = { 9, 43, 6, 1, 4, 1, 353, 2, 7, 1 }; -Objid setprefix = { 12, 43, 6, 1, 4, 1, 353, 2, 7, 1, 1, 3, 0 }; -/* - * (Partialy) pre-encoded SNMP responses + * Define SNMP Version numbers */ +#define SNMP_VERSION_1 1 +#define SNMP_VERSION_2 2 /* - * sysObjId reply + * Max string length for Variable */ -u_char sysObjId_Resp[] = { - 54, /* <--- len */ - 0x30, /* Sequence of */ - 0x82, 0x00, 0x32, /* <--- len */ - 0x02, 0x01, 0x00, /* (Version - 1) */ - 0x04, 0x04, 0x49, 0x4c, 0x4d, 0x49, /* Community: ILMI */ - PDU_TYPE_GETRESP, /* GET Response */ - 0x27, /* <--- len */ - 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, /* <--- request id */ - 0x02, 0x01, 0x00, /* Error Status */ - 0x02, 0x01, 0x00, /* Error Index */ - 0x30, /* Sequence of */ - 0x82, 0x00, 0x17, /* <--- len */ - 0x82, 0x00, 0x14, /* <--- len */ - 0x06, 0x08, /* Objid: 1.3.6.1.4.1.1.2.0 */ - 0x2b, 0x06, 0x01, 0x04, 0x01, 0x01, 0x02, 0x00, - 0x06, 0x08, /* Objid: 1.3.6.1.4.1.9999.1 */ - 0x2b, 0x06, 0x01, 0x04, 0x01, 0xce, 0x0f, 0x01 -}; +#define STRLEN 128 /* - * sysUpTime: reply to a sysUpTime GET request + * Unknown variable */ -u_char sysUpTime_Resp[] = { - 45, /* <--- len */ - 0x30, /* Sequence of */ - 0x82, 0x00, 0x29, /* <--- len */ - 0x02, 0x01, 0x00, /* (Version - 1) */ - 0x04, 0x04, 0x49, 0x4c, 0x4d, 0x49, /* Community - ILMI */ - PDU_TYPE_GETRESP, /* GET Response */ - 0x1e, /* <--- len */ - 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, /* <--- request id */ - 0x02, 0x01, 0x00, /* Error Status */ - 0x02, 0x01, 0x00, /* Error Index */ - 0x30, /* Sequence of */ - 0x82, 0x00, 0x0E, /* <--- len */ - 0x30, /* Sequence of */ - 0x82, 0x00, 0x0A, /* <--- len */ - /* Objid: .1.3.6.1.2.1.1.3.0 */ - 0x06, 0x08, 0x2b, 0x06, 0x01, 0x02, 0x01, 0x01, 0x03, 0x00, - /* <--- uptime */ -}; +#define VAR_UNKNOWN -1 /* - * coldStart TRAP to start the ILMI protocol + * Define our internal representation of an OBJECT IDENTIFIER */ -u_char coldStart_Trap[] = { - 60, - 0x30, /* Sequence of */ - 0x82, 0x00, 0x38, /* <--- len */ - 0x02, 0x01, 0x00, /* (Version - 1) */ - 0x04, 0x04, 0x49, 0x4c, 0x4d, 0x49, /* Community: ILMI */ - PDU_TYPE_TRAP, /* TRAP */ - 0x2d, /* <--- len */ - 0x06, 0x08, /* Objid: .1.3.6.1.4.1.3.1.1 */ - 0x2b, 0x06, 0x01, 0x04, 0x01, 0x03, 0x01, 0x01, - 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, /* IP address - 0.0.0.0 */ - 0x02, 0x01, 0x00, /* generic trap */ - 0x02, 0x01, 0x00, /* specific trap */ - 0x43, 0x01, 0x00, /* Time ticks - 0 */ - 0x30, /* Sequence of */ - 0x82, 0x00, 0x10, /* <--- len */ - 0x30, /* Sequence of */ - 0x82, 0x00, 0x0c, /* <-- len */ - 0x06, 0x08, /* Objid: 1.3.6.1.2.1.1.3.0 */ - 0x2b, 0x06, 0x01, 0x02, 0x01, 0x01, 0x03, 0x00, - 0x05, 0x00 /* Null */ -}; - -u_char GetNext_Resp[] = { - 49, - 0x30, /* Sequence of */ - 0x82, 0x00, 0x2d, /* <--- len */ - 0x02, 0x01, 0x00, /* (Version - 1) */ - 0x04, 0x04, 0x49, 0x4c, 0x4d, 0x49, /* Community: ILMI */ - PDU_TYPE_GETRESP, /* PDU_TYPE_GETRESP */ - 0x22, /* <--- len */ - 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, /* Request ID */ - 0x02, 0x01, 0x02, /* Error Status */ - 0x02, 0x01, 0x01, /* Error Index */ - 0x30, /* Sequence of */ - 0x82, 0x00, 0x12, /* <--- len */ - 0x30, /* Seqence of */ - 0x82, 0x00, 0x0e, /* <--- len */ - 0x06, 0x0a, /* Objid: .1.3.6.4.1.353.2.7.1 */ - 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x61, 0x02, 0x07, 0x01, - 0x05, 0x00 /* Get response: NULL */ +struct objid { + int oid[128]; }; +typedef struct objid Objid; /* - * Reply to GET myIpNm + * Define a Veriable classso that we can handle multiple GET/SET's + * per PDU. */ -u_char MyIpNm_Resp[] = { - 54, - 0x30, /* Sequence of */ - 0x82, 0x00, 0x32, /* <--- len */ - 0x02, 0x01, 0x00, /* (Version - 1) */ - 0x04, 0x04, 0x49, 0x4c, 0x4d, 0x49, /* Community: ILMI */ - PDU_TYPE_GETRESP, /* PDU_TYPE_GETRESP */ - 0x27, /* <--- len */ - 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, /* Request ID */ - 0x02, 0x01, 0x00, /* Error Status */ - 0x02, 0x01, 0x00, /* Error Index */ - 0x30, /* Sequence of */ - 0x82, 0x00, 0x17, /* <--- len */ - 0x30, /* Sequence of */ - 0x82, 0x00, 0x13, /* <--- len */ - /* Objid: .1.3.6.1.4.1.353.2.1.2.1 */ - 0x06, 0x0B, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x61, 0x02, - 0x01, 0x02, 0x01, - 0x40, 0x04, 0x00, 0x00, 0x00, 0x00 /* IP address */ +typedef struct variable Variable; +struct variable { + Objid oid; + int type; + union { + int ival; /* INTEGER/TIMESTAMP */ + Objid oval; /* OBJID */ + long aval; /* IPADDR */ + char sval[STRLEN]; /* OCTET */ + } var; + Variable *next; }; /* - * Reply to GET portIndex - we're always 1 + unit number + * Every SNMP PDU has the first four fields of this header. The only type + * which doesn't have the last three fields is the TRAP type. */ -u_char PortIndex_Resp[] = { - 53, - 0x30, /* Sequence of */ - 0x82, 0x00, 0x31, /* <-- len */ - 0x02, 0x01, 0x00, /* (Version - 1) */ - 0x04, 0x04, 0x49, 0x4c, 0x4d, 0x49, /* Community: ILMI */ - PDU_TYPE_GETRESP, - 0x26, /* <-- len */ - 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, /* Request ID */ - 0x02, 0x01, 0x00, /* Error Status */ - 0x02, 0x01, 0x00, /* Error Index */ - 0x30, /* Sequence of */ - 0x82, 0x00, 0x16, /* <--- len */ - 0x30, /* Sequence of */ - 0x82, 0x00, 0x12, /* <--- len */ - /* Objid: .1.3.6.1.4.1.353.2.1.1.1.1.x */ - 0x06, 0x0d, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x61, 0x02, - 0x01, 0x01, 0x01, 0x01, 0x00, - 0x02, 0x01, 0x00, /* Value */ -}; +struct snmp_header { + int pdulen; + int version; + char community[64]; + int pdutype; -/* - * Reply to GET MaxVcc - */ -u_char maxVCC_Resp[] = { - 52, /* <--- len */ - 0x30, /* Sequence of */ - 0x82, 0x00, 0x30, /* <--- len */ - 0x02, 0x01, 0x01, /* (Version - 1) */ - 0x04, 0x04, 0x49, 0x4c, 0x4d, 0x49, /* Community: ILMI */ - PDU_TYPE_GETRESP, /* GET Response */ - 0x25, /* <--- len */ - 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, /* <--- request id */ - 0x02, 0x01, 0x00, /* Error Status */ - 0x02, 0x01, 0x00, /* Error Index */ - 0x30, /* Sequence of */ - 0x82, 0x16, /* <--- len */ - 0x30, /* Sequence of */ - 0x82, 0x13, /* <--- len */ - 0x06, 0x0d, /* Objid: 1.3.6.1.4.1.353.2.2.1.1.3.0 */ - 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x61, 0x02, - 0x02, 0x01, 0x01, 0x03, 0x00, - 0x02, 0x02, 0x04, 0x00 /* Value = 1024 */ + /* GET/GETNEXT/GETRESP/SET */ + int reqid; + int error; + int erridx; + + /* TRAP */ + Objid enterprise; + int ipaddr; + int generic_trap; + int specific_trap; + + int varlen; + Variable *head, + *tail; }; +typedef struct snmp_header Snmp_Header; + +Snmp_Header *ColdStart_Header; +Snmp_Header *PDU_Header; /* - * Reply to GET uniType - we only support PRIVATE + * Define some OBJET IDENTIFIERS that we'll try to reply to: + * + * sysUpTime: number of time ticks since this deamon came up + * netpfx_oid: network prefix table + * unitype: is this a PRIVATE or PUBLIC network link + * univer: which version of UNI are we running + * devtype: is this a USER or NODE ATM device + * setprefix: used when the switch wants to tell us its NSAP prefix + * foresiggrp: FORE specific Objid we see alot of (being connected to FORE + * switches...) */ -u_char UniType_Resp[] = { - 53, - 0x30, /* Sequence of */ - 0x82, 0x00, 0x31, /* <--- len */ - 0x02, 0x01, 0x00, /* (Version - 1) */ - 0x04, 0x04, 0x49, 0x4c, 0x4d, 0x49, /* Community: ILMI */ - PDU_TYPE_GETRESP, /* PDU_TYPE_GETRESP */ - 0x26, /* <--- len */ - 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, /* Request ID */ - 0x02, 0x01, 0x00, /* Error Status */ - 0x02, 0x01, 0x00, /* Error Index */ - 0x30, /* Sequence of */ - 0x82, 0x00, 0x16, /* <--- len */ - 0x30, /* Sequence of */ - 0x82, 0x00, 0x12, /* <--- len */ - /* Objid: .1.3.6.1.4.1.353.2.2.1.1.8.0 */ - 0x06, 0x0d, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x61, 0x02, 0x02, - 0x01, 0x01, 0x08, 0x00, - 0x02, 0x01, 0x02 /* Get response: Integer */ - /* = UNITYPE_PRIVATE (2) */ +Objid Objids[] = { +#define SYS_OBJID 0 + {{ 8, 43, 6, 1, 2, 1, 1, 2, 0 }}, +#define UPTIME_OBJID 1 + {{ 8, 43, 6, 1, 2, 1, 1, 3, 0 }}, +#define PORT_OBJID 2 + {{ 12, 43, 6, 1, 4, 1, 353, 2, 1, 1, 1, 1, 0 }}, +#define IPNM_OBJID 3 + {{ 10, 43, 6, 1, 4, 1, 353, 2, 1, 2, 0 }}, +#define LAYER_OBJID 4 + {{ 12, 43, 6, 1, 4, 1, 353, 2, 2, 1, 1, 1, 0 }}, +#define MAXVCC_OBJID 5 + {{ 12, 43, 6, 1, 4, 1, 353, 2, 2, 1, 1, 3, 0 }}, +#define UNITYPE_OBJID 6 + {{ 12, 43, 6, 1, 4, 1, 353, 2, 2, 1, 1, 8, 0 }}, +#define UNIVER_OBJID 7 + {{ 12, 43, 6, 1, 4, 1, 353, 2, 2, 1, 1, 9, 0 }}, +#define DEVTYPE_OBJID 8 + {{ 12, 43, 6, 1, 4, 1, 353, 2, 2, 1, 1, 10, 0 }}, +#define ADDRESS_OBJID 9 + {{ 8, 43, 6, 1, 4, 1, 353, 2, 6 }}, +#define NETPFX_OBJID 10 + {{ 9, 43, 6, 1, 4, 1, 353, 2, 7, 1 }}, +#define MY_OBJID 11 + {{ 7, 43, 6, 1, 4, 1, 9999, 1 }}, +#define SETPFX_OBJID 12 + {{ 12, 43, 6, 1, 4, 1, 353, 2, 7, 1, 1, 3, 0 }}, +#define ENTERPRISE_OBJID 13 + {{ 8, 43, 6, 1, 4, 1, 3, 1, 1 }}, +#define ATMF_PORTID 14 + {{ 10, 43, 6, 1, 4, 1, 353, 2, 1, 4, 0 }}, +#define ATMF_SYSID 15 + {{ 12, 43, 6, 1, 4, 1, 353, 2, 1, 1, 1, 8, 0 }}, }; +#define NUM_OIDS (sizeof(Objids)/sizeof(Objid)) + +#define UNIVER_UNI20 1 #define UNIVER_UNI30 2 #define UNIVER_UNI31 3 #define UNIVER_UNI40 4 +#define UNIVER_UNKNOWN 5 -/* - * Reply to GET uniVer - */ -u_char UniVer_Resp[] = { - 53, - 0x30, /* Sequence of */ - 0x82, 0x00, 0x31, /* <--- len */ - 0x02, 0x01, 0x00, /* (Version - 1) */ - 0x04, 0x04, 0x49, 0x4c, 0x4d, 0x49, /* Community: ILMI */ - PDU_TYPE_GETRESP, /* PDU_TYPE_GETRESP */ - 0x26, /* <--- len */ - 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, /* Request ID */ - 0x02, 0x01, 0x00, /* Error Status */ - 0x02, 0x01, 0x00, /* Error Index */ - 0x30, /* Sequence of */ - 0x82, 0x00, 0x16, /* <--- len */ - 0x30, /* Sequence of */ - 0x82, 0x00, 0x12, /* <--- len */ - /* Objid: .1.3.6.1.4.1.353.2.2.1.1.9.0 */ - 0x06, 0x0d, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x61, 0x02, 0x02, - 0x01, 0x01, 0x09, 0x00, - 0x02, 0x01, 0x02 /* Get response: Integer */ - /* = UNIVER_UNI30 (2) */ -}; +#define UNITYPE_PUBLIC 1 +#define UNITYPE_PRIVATE 2 -/* - * Reply to GET devType - we're a host therefore we're type USER - */ -u_char DevType_Resp[] = { - 53, - 0x30, /* Sequence of */ - 0x82, 0x00, 0x31, /* <--- len */ - 0x02, 0x01, 0x00, /* (Version -1) */ - 0x04, 0x04, 0x49, 0x4c, 0x4d, 0x49, /* Community: ILMI */ - PDU_TYPE_GETRESP, /* PDU_TYPE_GETRESP */ - 0x26, /* <--- len */ - 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, /* Request ID */ - 0x02, 0x01, 0x00, /* Error Status */ - 0x02, 0x01, 0x00, /* Error Index */ - 0x30, /* Sequence of */ - 0x82, 0x00, 0x16, /* <--- len */ - 0x30, /* Sequence of */ - 0x82, 0x00, 0x12, /* <--- len */ - /* Objid: .1.3.6.1.4.1.353.2.2.1.1.10.0 */ - 0x06, 0x0d, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x61, 0x02, 0x02, - 0x01, 0x01, 0x0a, 0x00, - 0x02, 0x01, 0x01 /* Get response: Integer */ - /* = DEVTYPE_USER (1) */ -}; +#define DEVTYPE_USER 1 +#define DEVTYPE_NODE 2 /* - * Reply to GET foreSigGroup.* with noSuchError + * ILMI protocol states */ -u_char NoSuchFore_Resp[] = { - 85, - 0x30, /* Sequence of */ - 0x82, 0x00, 0x51, /* <--- len */ - 0x02, 0x01, 0x00, /* (Version - 1) */ - 0x04, 0x04, 0x49, 0x4c, 0x4d, 0x49, /* Community: ILMI */ - PDU_TYPE_GETRESP, /* PDU_TYPE_GETRESP */ - 0x46, /* <--- len */ - 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, /* Request ID */ - 0x02, 0x01, 0x02, /* Error Status: noSuch (2) */ - 0x02, 0x01, 0x01, /* Error Index */ - 0x30, /* Sequence of */ - 0x82, 0x00, 0x36, /* <--- len */ - 0x30, /* Sequence of */ - 0x82, 0x00, 0x17, /* <--- len */ - /* Objid: .1.3.6.1.5.1.326.2.2.2.1.6.2.1.1.1.20.0.0 */ - 0x06, 0x13, - 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x46, - 0x02, 0x02, 0x02, 0x01, 0x06, 0x02, 0x01, 0x01, - 0x01, 0x14, 0x00, 0x00, - 0x05, 0x00, /* NULL */ - 0x30, /* Sequence of */ - 0x82, 0x00, 0x17, /* <--- len */ - /* Objid: .1.3.6.1.5.1.326.2.2.2.1.6.2.1.1.1.21.0.0 */ - 0x06, 0x13, - 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x46, - 0x02, 0x02, 0x02, 0x01, 0x06, 0x02, 0x01, 0x01, - 0x01, 0x15, 0x00, 0x00, - 0x05, 0x00 /* NULL */ -}; - -u_char NetPrefix_Resp[] = { - 50, - 0x30, /* Sequence of */ - 0x82, 0x00, 0x00, /* <--- len */ - 0x02, 0x01, 0x00, /* (Version - 1) */ - 0x04, 0x04, 0x49, 0x4c, 0x4d, 0x49, /* Community: ILMI */ - PDU_TYPE_SET, /* PDU_TYPE_SET */ - 0x00, /* <--- len */ - 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, /* Request ID */ - 0x02, 0x01, 0x00, - 0x02, 0x01, 0x00, - 0x30, /* Sequence of */ - 0x82, 0x00, 0x00, /* <--- len */ - 0x30, /* Sequence of */ - 0x82, 0x00, 0x00, /* <--- len */ - /* Objid: .1.3.6.1.4.1.353.2.6.1.1.3.0. */ - 0x06, 0x00, - 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x61, 0x02, - 0x06, 0x01, 0x01, 0x03, 0x00 - /* Remainder of Objid plus SET value INTEGER =1 */ +enum ilmi_states { + ILMI_UNKNOWN, /* Uninitialized */ + ILMI_COLDSTART, /* We need to send a COLD_START trap */ + ILMI_INIT, /* Ensure that switch has reset */ + ILMI_REG, /* Looking for SET message */ + ILMI_RUNNING /* Normal processing */ }; /* * Our (incrementing) Request ID */ -int Req_ID = 0; +int Req_ID; /* * Temporary buffer for building response packets. Should help ensure @@ -502,18 +287,15 @@ char *Traps[] = { "coldStart", "warmStart", "linkDown", "linkUp", int NUnits; + /* - * Time last coldStart trap was sent to this unit - */ -time_t last_trap[MAX_UNITS]; -/* - * fd for units still awiting coldStart TRAP from network side + * fd for units which have seen a coldStart TRAP and are now exchaning SNMP requests */ -int trap_fd[MAX_UNITS]; +int ilmi_fd[MAX_UNITS + 1]; /* - * fd for units which have seen a coldStart TRAP and are now exchaning SNMP requests + * enum ilmi_states for this unit */ -int ilmi_fd[MAX_UNITS]; +int ilmi_state[MAX_UNITS + 1]; /* * Local copy for HARP physical configuration information */ @@ -524,11 +306,17 @@ struct air_cfg_rsp Cfg[MAX_UNITS + 1]; struct air_int_rsp Intf[MAX_UNITS + 1]; /* + * addressEntry table + */ +Objid addressEntry[MAX_UNITS + 1]; + +/* * When this daemon started */ struct timeval starttime; int Debug_Level = 0; +int foregnd = 0; /* run in the foreground? */ char *progname; char hostname[80]; @@ -537,14 +325,6 @@ char hostname[80]; #define LOG_FILE "/var/log/ilmid" FILE *Log; /* File descriptor for log messages */ -extern int errno; - -#ifdef sun -extern char *optarg; -extern int optind, opterr; -extern int getopt __P((int, char **, char *)); -#endif /* sun */ - void set_reqid __P ( ( u_char *, int ) ); void Increment_DL __P ( ( int ) ); void Decrement_DL __P ( ( int ) ); @@ -574,10 +354,11 @@ write_timestamp() clock = time ( (time_t)NULL ); tm = localtime ( &clock ); - if ( Log ) - fprintf ( Log, "%.3s %2d %.2d:%.2d:%.2d %s: ", - Months[tm->tm_mon], tm->tm_mday, tm->tm_hour, tm->tm_min, - tm->tm_sec, hostname ); + if ( Log && Debug_Level > 1 ) + if ( Log != stderr ) + fprintf ( Log, "%.3s %2d %.2d:%.2d:%.2d %s: ", + Months[tm->tm_mon], tm->tm_mday, tm->tm_hour, tm->tm_min, + tm->tm_sec, hostname ); return; @@ -617,8 +398,10 @@ hexdump ( bp, len ) for ( ; j < 8 && j + i < len; j++ ) if ( Log ) fprintf ( Log, "%.2x ", *bp++ ); - if ( Log ) + if ( Log ) { fprintf ( Log, " " ); + fflush ( Log ); + } for ( ; j < 12 && j + i < len; j++ ) if ( Log ) fprintf ( Log, "%.2x ", *bp++ ); @@ -627,8 +410,10 @@ hexdump ( bp, len ) for ( ; j < 16 && j + i < len; j++ ) if ( Log ) fprintf ( Log, "%.2x ", *bp++ ); - if ( Log ) + if ( Log ) { fprintf ( Log, "\n" ); + fflush ( Log ); + } } return; @@ -646,24 +431,32 @@ hexdump ( bp, len ) * * Arguments: * bufp - pointer to buffer pointer + * plen - pointer to PDU length or NULL if not a concern * * Returns: * bufp - updated buffer pointer + * plen - (possibly) adjusted pdu length * <len> - decoded length * */ int -asn_get_pdu_len ( bufp ) - u_char **bufp; +asn_get_pdu_len ( bufp, plen ) + u_char **bufp; + int *plen; { u_char *bp = *bufp; int len = 0; int i, b; b = *bp++; + if ( plen ) + (*plen)--; if ( b & 0x80 ) { - for ( i = 0; i < (b & ~0x80); i++ ) + for ( i = 0; i < (b & ~0x80); i++ ) { len = len * 256 + *bp++; + if ( plen ) + (*plen)--; + } } else len = b; @@ -720,15 +513,18 @@ asn_get_encoded ( bufp, len ) * * Arguments: * bufp - pointer to the buffer pointer + * plen - pointer to PDU length or NULL if not a concern * * Returns: * bufp - updated buffer pointer + * plen - (possibly) updated PDU length * <val> - value of encoded integer * */ int -asn_get_int ( bufp ) - u_char **bufp; +asn_get_int ( bufp, plen ) + u_char **bufp; + int *plen; { int i; int len; @@ -736,14 +532,69 @@ asn_get_int ( bufp ) u_char *bp = *bufp; len = *bp++; + if ( plen ) + (*plen)--; for ( i = 0; i < len; i++ ) { v = (v * 256) + *bp++; + if ( plen ) + (*plen)--; } *bufp = bp; return ( v ); } /* + * Set a BER encoded integer + * + * Arguments: + * bufp - pointer to buffer pointer where we are to set int in + * val - integer value to set + * + * Returns: + * none + * <bufp> - updated buffer pointer + * + */ +void +asn_set_int ( bufp, val ) + u_char **bufp; + int val; +{ + union { + int i; + u_char c[4]; + } u; + int len = sizeof(int); + int i = 0; + u_char *bp = *bufp; + + /* Check for special case where val == 0 */ + if ( val == 0 ) { + *bp++ = 1; + *bp++ = 0; + *bufp = bp; + return; + } + + u.i = htonl ( val ); + + while ( u.c[i] == 0 && i++ < sizeof(int) ) + len--; + + if ( u.c[i] > 0x7f ) { + i--; + len++; + } + + *bp++ = len; + UM_COPY ( (caddr_t)&u.c[sizeof(int)-len], bp, len ); + bp += len; + *bufp = bp; + + return; +} + +/* * Utility to print a object identifier * * Arguments: @@ -782,16 +633,19 @@ print_objid ( objid ) * Arguments: * bufp - pointer to buffer pointer * objid - pointer to objid buffer + * plen - pointer to PDU length or NULL of not a concern * * Returns: * bufp - updated buffer pointer * objid - internal representation of encoded objid + * plen - (possibly) adjusted PDU length * */ void -asn_get_objid ( bufp, objid ) - u_char **bufp; - Objid *objid; +asn_get_objid ( bufp, objid, plen ) + u_char **bufp; + Objid *objid; + int *plen; { int len; u_char *bp = *bufp; @@ -799,20 +653,56 @@ asn_get_objid ( bufp, objid ) int oidlen = 0; len = *bp++; + if ( plen ) + (*plen)--; while ( len ) { *ip++ = asn_get_encoded ( &bp, &len ); + if ( plen ) + (*plen)--; oidlen++; } objid->oid[0] = oidlen; *bufp = bp; - if ( Debug_Level > 1 ) - print_objid ( objid ); - return; } /* + * Put OBJID - assumes elements <= 16383 for two byte coding + * + */ +int +asn_put_objid ( bufp, objid ) + u_char **bufp; + Objid *objid; +{ + int len = 0; + u_char *bp = *bufp; + u_char *cpp; + int i; + + cpp = bp; + *bp++ = objid->oid[0]; + len++; + for ( i = 1; i <= objid->oid[0]; i++ ) { + u_int c = objid->oid[i]; + + while ( c > 127 ) { + *bp++ = ( ( c >> 7 ) & 0x7f ) | 0x80; + len++; + c &= 0x7f; /* XXX - assumption of two bytes */ + (*cpp)++; + } + *bp++ = c; + len++; + } + + *bufp = bp; + return ( len ); + +} + +/* * Get OCTET STRING * * Octet strings are encoded as a 7-bit encoded length followed by <len> @@ -821,16 +711,19 @@ asn_get_objid ( bufp, objid ) * Arguments: * bufp - pointer to buffer pointer * octet - pointer to octet buffer + * plen - pointer to PDU length * * Returns: * bufp - updated buffer pointer * octet - encoded Octet String + * plen - (possibly) adjusted PDU length * */ void -asn_get_octet ( bufp, octet ) - u_char **bufp; - char *octet; +asn_get_octet ( bufp, octet, plen ) + u_char **bufp; + char *octet; + int *plen; { u_char *bp = *bufp; int i = 0; @@ -840,10 +733,13 @@ asn_get_octet ( bufp, octet ) * &i is really a dummy value here as we don't keep track * of the ongoing buffer length */ - len = asn_get_encoded ( &bp, &i ); + len = asn_get_encoded ( &bp, &i, plen ); - for ( i = 0; i < len; i++ ) + for ( i = 0; i < len; i++ ) { *octet++ = *bp++; + if ( plen ) + (*plen)--; + } *bufp = bp; @@ -865,22 +761,133 @@ void print_header ( Hdr ) Snmp_Header *Hdr; { + Variable *var; + if ( Log ) { write_timestamp(); fprintf ( Log, - "Pdu len: %d Version: %d Community: \"%s\" Pdu Type: 0x%x\n", + "Pdu len: %d Version: %d Community: \"%s\" Pdu Type: 0x%x %s\n", Hdr->pdulen, Hdr->version + 1, Hdr->community, - Hdr->pdutype ); + Hdr->pdutype, PDU_Types[Hdr->pdutype - PDU_TYPE_GET] ); + write_timestamp(); + if ( Hdr->pdutype != PDU_TYPE_TRAP && Log ) + fprintf ( Log, "\tReq Id: 0x%x Error: %d Error Index: %d\n", + Hdr->reqid, Hdr->error, Hdr->erridx ); + } + + var = Hdr->head; + while ( var ) { + if ( Log ) { + write_timestamp(); + fprintf ( Log, " Variable Type: %d", var->type ); + if ( Var_Types[var->type] ) + fprintf ( Log, " %s", Var_Types[var->type] ); + fprintf ( Log, "\n\tObject: " ); + print_objid ( &var->oid ); + fprintf ( Log, "\tValue: " ); + switch ( var->type ) { + case ASN_INTEGER: + fprintf ( Log, "%d (0x%x)\n", var->var.ival, var->var.ival ); + break; + case ASN_NULL: + fprintf ( Log, "NULL" ); + break; + default: + fprintf ( Log, "[0x%x]", var->type ); + break; + } + fprintf ( Log, "\n" ); + } + var = var->next; } - if ( Hdr->pdutype != PDU_TYPE_TRAP && Log ) - fprintf ( Log, "\tReq Id: 0x%x Error: %d Error Index: %d\n", - Hdr->reqid, Hdr->error, Hdr->erridx ); return; } /* + * Pull OID's from GET/SET message + * + * Arguments: + * h - pointer to Snmp_Header + * bp - pointer to input PDU + * + * Returns: + * none + * + */ +void +parse_oids ( h, bp ) + Snmp_Header *h; + caddr_t *bp; +{ + int len = h->varlen; + int sublen; + Variable *var; + caddr_t bufp = *bp; + + while ( len > 0 ) { + if ( *bufp++ == ASN_SEQUENCE ) { + len--; + + /* Create new Variable instance */ + if ( ( var = (Variable *)UM_ALLOC(sizeof(Variable)) ) == NULL ) + { + *bp = bufp; + return; + } + /* Link to tail */ + if ( h->tail ) + h->tail->next = var; + /* Set head iff NULL */ + if ( h->head == NULL ) { + h->head = var; + } + /* Adjust tail */ + h->tail = var; + + /* Get length of variable sequence */ + sublen = asn_get_pdu_len ( &bufp, &len ); + /* Should be OBJID type */ + if ( *bufp++ != ASN_OBJID ) { + *bp = bufp; + return; + } + asn_get_objid ( &bufp, &var->oid, &len ); + var->type = *bufp++; + len--; + switch ( var->type ) { + case ASN_INTEGER: + var->var.ival = asn_get_int ( &bufp, &len ); + break; + case ASN_NULL: + bufp++; + len--; + break; + case ASN_OBJID: + asn_get_objid ( &bufp, &var->var.oval, &len ); + break; + case ASN_OCTET: + asn_get_octet ( &bufp, var->var.sval, &len ); + break; + default: + if ( Log ) { + write_timestamp(); + fprintf ( Log, "Unknown variable type: %d\n", + var->type ); + } + break; + } + var->next = NULL; + } else + break; + } + + *bp = bufp; + return; +} + +/* * Crack the SNMP header * * Pull the PDU length, SNMP version, SNMP community and PDU type. @@ -901,6 +908,8 @@ asn_get_header ( bufp ) { Snmp_Header *h; u_char *bp = *bufp; + int len = 0; + int dummy = 0; /* * Allocate memory to hold the SNMP header @@ -909,6 +918,11 @@ asn_get_header ( bufp ) return ( (Snmp_Header *)NULL ); /* + * Ensure that we wipe the slate clean + */ + UM_ZERO ( h, sizeof ( Snmp_Header ) ); + + /* * PDU has to start as SEQUENCE OF */ if ( *bp++ != ASN_SEQUENCE ) /* Class == Universial, f == 1, tag == SEQUENCE */ @@ -917,7 +931,7 @@ asn_get_header ( bufp ) /* * Get the length of remaining PDU data */ - h->pdulen = asn_get_pdu_len ( &bp ); + h->pdulen = asn_get_pdu_len ( &bp, NULL ); /* * We expect to find an integer encoding Version-1 @@ -925,7 +939,7 @@ asn_get_header ( bufp ) if ( *bp++ != ASN_INTEGER ) { return ( (Snmp_Header *)NULL ); } - h->version = asn_get_int ( &bp ); + h->version = asn_get_int ( &bp, NULL ); /* * After the version, we need the community name @@ -933,8 +947,7 @@ asn_get_header ( bufp ) if ( *bp++ != ASN_OCTET ) { return ( (Snmp_Header *)NULL ); } - UM_ZERO ( h->community, sizeof ( h->community ) ); - asn_get_octet ( &bp, h->community ); + asn_get_octet ( &bp, h->community, NULL ); /* * Single byte PDU type @@ -946,31 +959,43 @@ asn_get_header ( bufp ) */ if ( h->pdutype != PDU_TYPE_TRAP ) { /* TRAP uses different format */ - bp++; /* Skip over data len */ + (void) asn_get_pdu_len ( &bp, &dummy ); /* Request ID */ if ( *bp++ != ASN_INTEGER ) { + UM_FREE ( h ); return ( (Snmp_Header *)NULL ); } - h->reqid = asn_get_int ( &bp ); + h->reqid = asn_get_int ( &bp, NULL ); /* Error Status */ if ( *bp++ != ASN_INTEGER ) { + UM_FREE ( h ); return ( (Snmp_Header *)NULL ); } - h->error = asn_get_int ( &bp ); + h->error = asn_get_int ( &bp, NULL ); /* Error Index */ if ( *bp++ != ASN_INTEGER ) { + UM_FREE ( h ); + return ( (Snmp_Header *)NULL ); + } + h->erridx = asn_get_int ( &bp, NULL ); + + /* Sequence of... */ + if ( *bp++ != ASN_SEQUENCE ) { + UM_FREE ( h ); return ( (Snmp_Header *)NULL ); } - h->erridx = asn_get_int ( &bp ); + h->varlen = ( asn_get_pdu_len ( &bp, &len ) - 1 ); + h->varlen += ( len - 1 ); + parse_oids ( h, &bp ); } *bufp = bp; - if ( Debug_Level > 2 ) + if ( Log && Debug_Level ) print_header ( h ); return ( h ); @@ -978,7 +1003,7 @@ asn_get_header ( bufp ) } /* - * Compare to internal OID representations + * Compare two internal OID representations * * Arguments: * oid1 - Internal Object Identifier @@ -994,18 +1019,21 @@ oid_cmp ( oid1, oid2 ) Objid *oid1, *oid2; { int i; + int len; /* * Compare lengths */ - if ( !(oid1->oid[0] == oid2->oid[0]) ) + if ( !(oid1->oid[0] == oid2->oid[0] ) ) /* Different lengths */ return ( 1 ); + len = oid1->oid[0]; + /* * value by value compare */ - for ( i = 1; i <= oid1->oid[0]; i++ ) { + for ( i = 1; i <= len; i++ ) { if ( !(oid1->oid[i] == oid2->oid[i]) ) /* values don't match */ return ( 1 ); @@ -1016,35 +1044,83 @@ oid_cmp ( oid1, oid2 ) } /* - * Encode a timeval as the number of time ticks + * Compare two internal OID representations + * + * Arguments: + * oid1 - Internal Object Identifier + * oid2 - Internal Object Identifier + * len - Length of OID to compare * - * Time ticks are the number of 100th's of a second since some event. - * For sysUpTime, this is the time ticks since the application started, - * not since the host came up. We only support encoding ticks since we - * started running (what we are calling 'starttime'). + * Returns: + * 0 - Objid's match + * 1 - Objid's don't match + * + */ +int +oid_ncmp ( oid1, oid2, len ) + Objid *oid1, *oid2; + int len; +{ + int i; + + /* + * value by value compare + */ + for ( i = 1; i <= len; i++ ) { + if ( !(oid1->oid[i] == oid2->oid[i]) ) + /* values don't match */ + return ( 1 ); + } + + /* Objid's are identical */ + return ( 0 ); +} + +/* + * Find the index of a OBJID which matches this Variable instance * * Arguments: - * bufp - pointer to buffer pointer + * var - pointer to Variable instance * * Returns: - * bufp - updated buffper pointer - * len - number of bytes to encode time ticks value - * - ticks since 'starttime' encoded in buffer + * idx - index of matched Variable instance + * -1 - no matching Variable found * */ int -asn_encode_ticks ( bufp, ret ) - u_char **bufp; - int *ret; +find_var ( var ) + Variable *var; { - struct timeval timenow; - struct timeval timediff; - u_char *bp = *bufp; - int len, ticks; + int i; + + for ( i = 0; i < NUM_OIDS; i++ ) + if ( oid_cmp ( &var->oid, &Objids[i] ) == 0 ) { + return ( i ); + } + + return ( -1 ); + +} + +/* + * Return the time process has been running as a number of ticks + * + * Arguments: + * none + * + * Returns: + * number of ticks + * + */ +int +get_ticks() +{ + struct timeval timenow; + struct timeval timediff; (void) gettimeofday ( &timenow, NULL ); /* - * Adjust for subtraction + * Adjust for subtraction */ timenow.tv_sec--; timenow.tv_usec += 1000000; @@ -1064,139 +1140,252 @@ asn_encode_ticks ( bufp, ret ) } /* - * Compute 100th's of second in diff time structure + * Compute number of ticks */ - *ret = ticks = (timediff.tv_sec * 100) + (timediff.tv_usec / 10000); - - /* - * The rest of this is just plain gross. I'm sure there - * are better ways to do this... - */ - - /* Compute time ticks length */ - if ( ticks < 0xFF ) - len = 1; - else if ( ticks < 0xFFFF ) - len = 2; - else if ( ticks < 0xFFFFFF ) - len = 3; - else - len = 4; - - /* - * Encode time ticks - */ - *bp++ = ASN_TIMESTAMP; /* Time Ticks */ - *bp++ = len; /* length of value */ - - /* there's always a better way but this is quick and dirty... */ - if ( ticks > 0xFFFFFF ) { - *bp++ = ( ticks & 0xFF000000 ) >> 24; - ticks &= 0xFFFFFF; - } - if ( ticks > 0xFFFF ) { - *bp++ = ( ticks & 0xFF0000 ) >> 16; - ticks &= 0xFFFF; - } - if ( ticks > 0xFF ) { - *bp++ = ( ticks & 0xFF00 ) >> 8; - ticks &= 0xFF; - } - *bp++ = ticks; + return ( ( timediff.tv_sec * 100 ) + ( timediff.tv_usec / 10000 ) ); - *bufp = bp; - return ( len + 2 ); } /* - * Send back up sysUpTime response + * Build a response PDU * * Arguments: - * sd - socket descriptor to send reply on - * reqid - original GET request id - * + * hdr - pointer to PDU Header with completed Variable list + * * Returns: - * none - response sent + * none * */ void -send_uptime_resp ( sd, reqid ) - int sd; - int reqid; +build_pdu ( hdr, type ) + Snmp_Header *hdr; + int type; { - int len; - short *sp; - u_long *ip; - u_char *bp; - short val; - int ticks; + u_char *bp = Resp_Buf; + u_char *vpp; + u_char *ppp; + int erridx = 0; + int varidx = 1; + int varlen = 0; + int pdulen = 0; + int traplen = 0; + Variable *var; + + /* + * Clear out the reply + */ + UM_ZERO ( Resp_Buf, sizeof(Resp_Buf) ); + + /* [0] is reserved for overall length */ + bp++; + + /* Start with SEQUENCE OF */ + *bp++ = ASN_SEQUENCE; + /* - assume we can code length in two octets */ + *bp++ = 0x82; + bp++; + bp++; + /* Version */ + *bp++ = ASN_INTEGER; + asn_set_int ( &bp, hdr->version ); + /* Community name */ + *bp++ = ASN_OCTET; + *bp++ = strlen ( hdr->community ); + UM_COPY ( hdr->community, bp, strlen ( hdr->community ) ); + bp += strlen ( hdr->community ); + /* PDU Type */ + *bp++ = type; + ppp = bp; + /* Length of OID data - assume it'll fit in one octet */ + bp++; + + if ( type != PDU_TYPE_TRAP ) { + /* Sequence ID */ + *bp++ = ASN_INTEGER; + asn_set_int ( &bp, hdr->reqid ); + /* + * Check to see if all the vaiables were resolved - we do this + * by looking for something which still has a ASN_NULL value. + */ + var = hdr->head; + if ( type == PDU_TYPE_GETRESP ) { + while ( var && erridx == 0 ) { + if ( var->type != ASN_NULL ) { + varidx++; + var = var->next; + } else + erridx = varidx; + } + } - COPY_RESP ( sysUpTime_Resp ); + /* Error status */ + *bp++ = ASN_INTEGER; + *bp++ = 0x01; /* length = 1 */ + if ( erridx ) + *bp++ = 0x02; /* NoSuch */ + else + *bp++ = 0x00; /* NoError */ + /* Error Index */ + *bp++ = ASN_INTEGER; + *bp++ = 0x01; /* length = 1 */ + *bp++ = erridx; /* index - 0 if no error */ + } else { + /* type == PDU_TYPE_TRAP */ + + /* Fill in ENTERPRISE OBJID */ + *bp++ = ASN_OBJID; + (void) asn_put_objid ( &bp, &hdr->enterprise ); + + /* Fill in IP address */ + *bp++ = ASN_IPADDR; + *bp++ = sizeof ( hdr->ipaddr ); + UM_COPY ( (caddr_t)&hdr->ipaddr, bp, sizeof(hdr->ipaddr) ); + bp += sizeof(hdr->ipaddr); + + /* Fill in generic and specific trap types */ + *bp++ = ASN_INTEGER; + asn_set_int ( &bp, hdr->generic_trap ); + *bp++ = ASN_INTEGER; + asn_set_int ( &bp, hdr->specific_trap ); + + /* Fill in time-stamp - assume 0 for now */ + *bp++ = ASN_TIMESTAMP; + asn_set_int ( &bp, 0 ); + + /* encoded length */ + traplen = ( bp - ppp - 1 ); - bp = (u_char *)&Resp_Buf[Resp_Buf[0]+1]; - len = asn_encode_ticks ( &bp, &ticks ); + /* Continue with variable processing */ + } - /* - * Adjust overall length - */ - bp = (u_char *)&Resp_Buf[0]; - *bp += len; + /* SEQUENCE OF */ + *bp++ = ASN_SEQUENCE; + *bp++ = 0x82; + /* - assume we can code length in two octets */ + vpp = bp; + varlen = 0; + bp++; + bp++; + + /* Install Variables */ + var = hdr->head; + varidx = 1; + while ( var ) { + u_char *bpp; + int len = 0; + + /* SEQUENCE OF */ + *bp++ = ASN_SEQUENCE; + *bp++ = 0x82; + /* - assume we can code length in two octets */ + bpp = bp; + bp++; + bp++; + /* OBJID */ + *bp++ = ASN_OBJID; + len++; + len += asn_put_objid ( &bp, &var->oid ); - /* - * Adjust sequence lengths - works because this is my - * PDU and I know all the variable lengths are fixed (ie. - * reqid is always 4 byte encoded). - */ -#ifndef sun - sp = (short *)&Resp_Buf[3]; - val = ntohs ( *sp ); - *sp = htons ( val + len ); - Resp_Buf[15] += len; - sp = (u_short *)&Resp_Buf[30]; - val = ntohs ( *sp ); - *sp = htons ( val + len ); - sp = (u_short *)&Resp_Buf[34]; - val = ntohs ( *sp ); - *sp = htons ( val + len ); -#else - /* Sun SPARCs have alignment requirements */ - Resp_Buf[4] += len; - Resp_Buf[15] += len; - Resp_Buf[31] += len; - Resp_Buf[35] += len; -#endif /* sun */ + if ( erridx && varidx >= erridx ) { + /* Code this variable as NULL */ + *bp++ = ASN_NULL; + len++; + bp++; + len++; + } else { + u_char *lpp; + /* Variable type */ + *bp++ = var->type; + len++; + lpp = bp; + switch ( var->type ) { + case ASN_INTEGER: + asn_set_int ( &bp, var->var.ival ); + len += ( *lpp + 1 ); + break; + case ASN_OCTET: + *bp++ = var->var.sval[0]; + len++; + UM_COPY ( (caddr_t)&var->var.sval[1], + bp, var->var.sval[0] ); + len += var->var.sval[0]; + bp += var->var.sval[0]; + break; + case ASN_NULL: + *bp++ = 0x00; + len++; + break; + case ASN_OBJID: + len += asn_put_objid ( &bp, &var->var.oval ); + break; + case ASN_SEQUENCE: + break; + case ASN_IPADDR: + *bp++ = 4; + len++; + UM_COPY ( (caddr_t)&var->var.aval, bp, 4 ); + len += 4; + bp += 4; + break; + case ASN_TIMESTAMP: + asn_set_int ( &bp, var->var.ival ); + len += ( *lpp + 1 ); + break; + default: + break; + } + } - /* - * Store the original request ID in the response - */ - set_reqid ( Resp_Buf, reqid ); -#ifdef notdef -#ifndef sun - ip = (u_long *)&Resp_Buf[18]; - *ip = htonl ( reqid ); -#else - /* Sun SPARCs have alignment requirements */ - UM_COPY ( (caddr_t)&reqid, (caddr_t)&Resp_Buf[18], sizeof(reqid) ); -#endif /* sun */ -#endif + /* Accumulate total Variable sequence length */ + varlen += (len + 4); - if ( Debug_Level > 1 && Log ) { - write_timestamp(); - fprintf ( Log, "\tSend sysUpTime: %d\n", ticks ); + /* Fill in length of this sequence */ + bpp[1] = len & 0xff; + bpp[0] = len >> 8; + + var = var->next; } - if ( Debug_Level > 4 && Log ) { - write_timestamp(); - fprintf ( Log, "\n===== Sent %d bytes =====\n", Resp_Buf[0] ); - hexdump ( (u_char *)&Resp_Buf[1], Resp_Buf[0] ); + + /* Fill in length of Variable sequence */ + vpp[1] = varlen & 0xff; + vpp[0] = varlen >> 8; + + if ( type != PDU_TYPE_TRAP ) { + /* Fill in length of data AFTER PDU type */ + *ppp = varlen + 12 + ppp[2]; /* + length of reqid */ + } else { + /* Fill in length of data AFTER PDU type */ + *ppp = varlen + traplen + 4; /* + length of initial sequence of */ } - /* - * Send response - */ - write ( sd, (caddr_t)&Resp_Buf[1], Resp_Buf[0] ); + + /* Fill in overall sequence length */ + pdulen = *ppp + 7 + strlen ( hdr->community ); + Resp_Buf[4] = pdulen & 0x7f; + Resp_Buf[3] = pdulen >> 8; + + pdulen = bp - Resp_Buf - 1; + + Resp_Buf[0] = pdulen; + + hdr->pdutype = type; return; +} +void +free_pdu ( hdr ) +Snmp_Header *hdr; +{ + Variable *var; + + while ( hdr->head ) { + var = hdr->head->next; /* Save next link */ + UM_FREE ( hdr->head ); /* Free current var */ + hdr->head = var; /* Set head to next link */ + } + + UM_FREE ( hdr ); /* Free fixed portion */ } /* @@ -1221,11 +1410,7 @@ set_reqid ( resp, reqid ) u_char c[4]; } u; -#ifndef sun u.i = htonl(reqid); -#else - u.i = reqid; -#endif /* !sun */ /* * Replace the current Request ID with the supplied value @@ -1233,7 +1418,6 @@ set_reqid ( resp, reqid ) UM_COPY ( (caddr_t)&u.c[4-resp[17]], bp, resp[17] ); return; - } /* @@ -1249,24 +1433,77 @@ set_reqid ( resp, reqid ) * */ void -send_resp ( sd, reqid, resp ) - int sd; - int reqid; +send_resp ( intf, Hdr, resp ) + int intf; + Snmp_Header *Hdr; u_char *resp; { + int n; - set_reqid ( resp, reqid ); - - if ( Debug_Level > 1 && Log ) { + if ( ilmi_fd[intf] > 0 ) { + n = write ( ilmi_fd[intf], (caddr_t)&resp[1], resp[0] ); + if ( Log && Debug_Level > 1 ) { write_timestamp(); - fprintf ( Log, "===== Sent %d bytes =====\n", resp[0] ); - hexdump ( (u_char *)&resp[1], resp[0] ); + fprintf ( Log, "===== Sent %d of %d bytes (%d) =====\n", n, resp[0], ilmi_fd[intf] ); + print_header ( Hdr ); + if ( Debug_Level > 2 ) + hexdump ( (u_char *)&resp[1], resp[0] ); + } } - write ( sd, (caddr_t)&resp[1], resp[0] ); + free_pdu ( Hdr ); return; } +/* + * Build a COLD_START TRAP PDU + * + */ +Snmp_Header * +build_cold_start() +{ + Snmp_Header *hdr; + Variable *var; + + hdr = (Snmp_Header *)UM_ALLOC (sizeof(Snmp_Header)); + + hdr->pdulen = 0; + hdr->version = SNMP_VERSION_1 - 1; + snprintf ( hdr->community, sizeof(hdr->community), "ILMI" ); + + hdr->ipaddr = 0x0; /* 0.0.0.0 */ + hdr->generic_trap = TRAP_COLDSTART; + hdr->specific_trap = 0; + UM_COPY ( (caddr_t)&Objids[ENTERPRISE_OBJID], (caddr_t)&hdr->enterprise, + sizeof(Objid) ); + + hdr->head = (Variable *)UM_ALLOC(sizeof(Variable)); + var = hdr->head; + UM_COPY ( (caddr_t)&Objids[UPTIME_OBJID], (caddr_t)&var->oid, + sizeof(Objid) ); + var->type = ASN_NULL; + + return ( hdr ); +} + +/* + * Build a Generic PDU Header + * + */ +Snmp_Header * +build_generic_header() +{ + Snmp_Header *hdr; + + hdr = (Snmp_Header *)UM_ALLOC(sizeof(Snmp_Header)); + + hdr->pdulen = 0; + hdr->version = SNMP_VERSION_1 - 1; + snprintf ( hdr->community, sizeof(hdr->community), "ILMI" ); + + return ( hdr ); +} + /* * Initialize information on what physical adapters HARP knows about * @@ -1285,7 +1522,7 @@ void init_ilmi() { struct air_cfg_rsp *cfg_info = NULL; - struct air_intf_rsp *intf_info = NULL; + struct air_int_rsp *intf_info = NULL; int buf_len; /* @@ -1299,10 +1536,6 @@ init_ilmi() UM_ZERO ( Cfg, sizeof(Cfg) ); UM_ZERO ( Intf, sizeof(Intf) ); NUnits = 0; - if ( Debug_Level > 1 && Log ) { - write_timestamp(); - fprintf ( Log, "NUnits: %d\n", NUnits ); - } return; } @@ -1314,12 +1547,8 @@ init_ilmi() * Compute how many units information was returned for */ NUnits = buf_len / sizeof(struct air_cfg_rsp); - if ( Debug_Level > 1 && Log ) { - write_timestamp(); - fprintf ( Log, "NUnits: %d\n", NUnits ); - } /* Housecleaning */ - free ( cfg_info ); + UM_FREE ( cfg_info ); cfg_info = NULL; /* * Get the per interface information @@ -1338,7 +1567,7 @@ init_ilmi() */ UM_COPY ( intf_info, (caddr_t)Intf, buf_len ); /* Housecleaning */ - free ( intf_info ); + UM_FREE ( intf_info ); intf_info = NULL; return; @@ -1370,28 +1599,15 @@ ilmi_open () struct t_atm_qos qos; struct t_atm_app_name appname; Atm_addr subaddr; - char buffer[MAX_LEN+1]; char nifname[IFNAMSIZ]; int optlen; int unit = 0; - struct timer_elem *open_timer, - *state_timer; u_char sig_proto; - if ( Debug_Level > 1 && Log ) { - write_timestamp(); - fprintf ( Log, "ilmi_open()\n" ); - } init_ilmi(); for ( unit = 0; unit < NUnits; unit++ ) { - if ( Debug_Level > 1 && Log ) { - write_timestamp(); - fprintf ( Log, "Unit: %d Sig: %d Trap: %d Ilmi: %d\n", - unit, Intf[unit].anp_sig_proto, trap_fd[unit], - ilmi_fd[unit] ); - } /* * ILMI only makes sense for UNI signalling protocols */ @@ -1400,16 +1616,11 @@ ilmi_open () sig_proto != ATM_SIG_UNI40 ) continue; - /* - * If we're waiting for a coldStart TRAP, we'll be in trap_fd[], - * If we're processing ILMI, we'll be in ilmi_fd[], otherwise, - * this unit hasn't been opened yet. - */ - if ( trap_fd[unit] == -1 && ilmi_fd[unit] == -1 ) { + if ( ilmi_fd[unit] == -1 ) { - trap_fd[unit] = socket ( AF_ATM, SOCK_SEQPACKET, ATM_PROTO_AAL5 ); + ilmi_fd[unit] = socket ( AF_ATM, SOCK_SEQPACKET, ATM_PROTO_AAL5 ); - if ( trap_fd[unit] < 0 ) { + if ( ilmi_fd[unit] < 0 ) { perror ( "open" ); continue; } @@ -1422,14 +1633,13 @@ ilmi_open () write_timestamp(); fprintf ( Log, "No nif on unit %d\n", unit ); } - close ( trap_fd[unit] ); - trap_fd[unit] = -1; + close ( ilmi_fd[unit] ); ilmi_fd[unit] = -1; continue; } - sprintf ( nifname, "%s0\0", Intf[unit].anp_nif_pref ); + sprintf ( nifname, "%s0", Intf[unit].anp_nif_pref ); optlen = sizeof ( nifname ); - if ( setsockopt ( trap_fd[unit], T_ATM_SIGNALING, + if ( setsockopt ( ilmi_fd[unit], T_ATM_SIGNALING, T_ATM_NET_INTF, (caddr_t)nifname, optlen ) < 0 ) { perror ( "setsockopt" ); if ( Log ) { @@ -1442,9 +1652,8 @@ ilmi_open () write_timestamp(); fprintf ( Log, "nifname: closing unit %d\n", unit ); } - close ( trap_fd[unit] ); - trap_fd[unit] = -1; - ilmi_fd[unit] = -1; + close ( ilmi_fd[unit] ); + ilmi_fd[unit] = -1; continue; } @@ -1453,9 +1662,9 @@ ilmi_open () */ UM_ZERO ( (caddr_t) &satm, sizeof(satm) ); satm.satm_family = AF_ATM; -#ifndef sun +#if (defined(BSD) && (BSD >= 199103)) satm.satm_len = sizeof(satm); -#endif /* sun */ +#endif satm.satm_addr.t_atm_sap_addr.SVE_tag_addr = T_ATM_PRESENT; satm.satm_addr.t_atm_sap_addr.SVE_tag_selector = T_ATM_ABSENT; @@ -1481,15 +1690,14 @@ ilmi_open () aal5.backward_max_SDU_size = MAX_LEN; aal5.SSCS_type = T_ATM_NULL; optlen = sizeof(aal5); - if ( setsockopt ( trap_fd[unit], T_ATM_SIGNALING, T_ATM_AAL5, + if ( setsockopt ( ilmi_fd[unit], T_ATM_SIGNALING, T_ATM_AAL5, (caddr_t) &aal5, optlen ) < 0 ) { perror ( "setsockopt(aal5)" ); if ( Debug_Level > 1 && Log ) { write_timestamp(); fprintf ( Log, "aal5: closing unit %d\n", unit ); } - close ( trap_fd[unit] ); - trap_fd[unit] = -1; + close ( ilmi_fd[unit] ); ilmi_fd[unit] = -1; continue; } @@ -1510,7 +1718,7 @@ ilmi_open () traffic.backward.tagging = T_NO; traffic.best_effort = T_YES; optlen = sizeof(traffic); - if (setsockopt(trap_fd[unit], T_ATM_SIGNALING, T_ATM_TRAFFIC, + if (setsockopt(ilmi_fd[unit], T_ATM_SIGNALING, T_ATM_TRAFFIC, (caddr_t)&traffic, optlen) < 0) { perror("setsockopt(traffic)"); } @@ -1520,7 +1728,7 @@ ilmi_open () bearer.clipping_susceptibility = T_NO; bearer.connection_configuration = T_ATM_1_TO_1; optlen = sizeof(bearer); - if (setsockopt(trap_fd[unit], T_ATM_SIGNALING, T_ATM_BEARER_CAP, + if (setsockopt(ilmi_fd[unit], T_ATM_SIGNALING, T_ATM_BEARER_CAP, (caddr_t)&bearer, optlen) < 0) { perror("setsockopt(bearer)"); } @@ -1529,7 +1737,7 @@ ilmi_open () qos.forward.qos_class = T_ATM_QOS_CLASS_0; qos.backward.qos_class = T_ATM_QOS_CLASS_0; optlen = sizeof(qos); - if (setsockopt(trap_fd[unit], T_ATM_SIGNALING, T_ATM_QOS, (caddr_t)&qos, + if (setsockopt(ilmi_fd[unit], T_ATM_SIGNALING, T_ATM_QOS, (caddr_t)&qos, optlen) < 0) { perror("setsockopt(qos)"); } @@ -1537,14 +1745,14 @@ ilmi_open () subaddr.address_format = T_ATM_ABSENT; subaddr.address_length = 0; optlen = sizeof(subaddr); - if (setsockopt(trap_fd[unit], T_ATM_SIGNALING, T_ATM_DEST_SUB, + if (setsockopt(ilmi_fd[unit], T_ATM_SIGNALING, T_ATM_DEST_SUB, (caddr_t)&subaddr, optlen) < 0) { perror("setsockopt(dest_sub)"); } strncpy(appname.app_name, "ILMI", T_ATM_APP_NAME_LEN); optlen = sizeof(appname); - if (setsockopt(trap_fd[unit], T_ATM_SIGNALING, T_ATM_APP_NAME, + if (setsockopt(ilmi_fd[unit], T_ATM_SIGNALING, T_ATM_APP_NAME, (caddr_t)&appname, optlen) < 0) { perror("setsockopt(appname)"); } @@ -1552,15 +1760,14 @@ ilmi_open () /* * Now try to connect to destination */ - if ( connect ( trap_fd[unit], (struct sockaddr *) &satm, + if ( connect ( ilmi_fd[unit], (struct sockaddr *) &satm, sizeof(satm)) < 0 ) { perror ( "connect" ); if ( Debug_Level > 1 && Log ) { write_timestamp(); fprintf ( Log, "connect: closing unit %d\n", unit ); } - close ( trap_fd[unit] ); - trap_fd[unit] = -1; + close ( ilmi_fd[unit] ); ilmi_fd[unit] = -1; continue; } @@ -1569,61 +1776,44 @@ ilmi_open () write_timestamp(); fprintf ( Log, "***** opened unit %d\n", unit ); } - /* - * Send coldStart TRAP - */ - if ( Debug_Level > 4 && Log ) { - write_timestamp(); - fprintf ( Log, "===== Sent %d bytes =====\n", - coldStart_Trap[0] ); - hexdump ( (u_char *)&coldStart_Trap[1], coldStart_Trap[0] ); - } - if ( Debug_Level && Log ) { - write_timestamp(); - fprintf ( Log, "\tSend coldStart TRAP to unit %d\n", unit ); - } - last_trap[unit] = time ( (time_t *)NULL ); - write ( trap_fd[unit], (caddr_t)&coldStart_Trap[1], - coldStart_Trap[0] ); + + ilmi_state[unit] = ILMI_COLDSTART; + } } - signal ( SIGALRM, ilmi_open ); - alarm ( SLEEP_TIME ); - return; } /* - * Send our local IP address for this interface + * Get our local IP address for this interface * * Arguments: - * s - socket to send message on - * hdr - pointer to internal SNMP header + * s - socket to find address for + * aval - pointer to variable to store address in * * Returns: * none * */ void -send_myipnm ( s, hdr ) - int s; - Snmp_Header *hdr; +get_local_ip ( s, aval ) + int s; + long *aval; { - char intf_name[IFNAMSIZ]; - int namelen = IFNAMSIZ; - struct air_netif_rsp *net_info = NULL; + char intf_name[IFNAMSIZ]; + int namelen = IFNAMSIZ; + struct air_netif_rsp *net_info = NULL; struct sockaddr_in *sin; - COPY_RESP ( MyIpNm_Resp ); - + /* + * Get physical interface name + */ if ( getsockopt ( s, T_ATM_SIGNALING, T_ATM_NET_INTF, - (caddr_t) intf_name, &namelen ) ) { - perror ( "Couldn't get socket name" ); - return; - } + (caddr_t) intf_name, &namelen ) ) + return; /* * Get network interface information for this physical interface @@ -1635,23 +1825,14 @@ send_myipnm ( s, hdr ) sin = (struct sockaddr_in *)&net_info->anp_proto_addr; /* - * Copy interface's IP address into reply packet + * Fill in answer */ - UM_COPY ( (caddr_t)&sin->sin_addr.s_addr, (caddr_t)&Resp_Buf[51], - 4 ); - - if ( Debug_Level > 1 && Log ) { - write_timestamp(); - fprintf ( Log, "\tSend NM IP address\n" ); - } + UM_COPY ( (caddr_t)&sin->sin_addr.s_addr, aval, 4 ); - send_resp ( s, hdr->reqid, Resp_Buf ); + UM_FREE ( net_info ); - /* - * Clean up - */ - free ( net_info ); return; + } /* @@ -1672,40 +1853,29 @@ send_myipnm ( s, hdr ) * */ void -set_prefix ( oid, hdr, buf, s ) +set_prefix ( oid, hdr, intf ) Objid *oid; Snmp_Header *hdr; - u_char *buf; - int s; + int intf; { - struct atmsetreq asr; - Atm_addr *aa; - int fd; - int i; - u_char *cpp; - int len; /* PDU length before completion */ - - /* - * If we don't reply to the SET then it keeps getting retransmitted. - */ - buf[14] = PDU_TYPE_GETRESP; - if ( Debug_Level > 1 && Log ) { - write_timestamp(); - fprintf ( Log, "\tSend SET_RESPONSE\n" ); - } - send_resp ( s, hdr->reqid, buf ); + struct atmsetreq asr; + Atm_addr *aa; + int fd; + int i; /* * Build IOCTL request to set prefix */ asr.asr_opcode = AIOCS_SET_PRF; - strncpy ( asr.asr_prf_intf, Intf[0].anp_intf, + strncpy ( asr.asr_prf_intf, Intf[intf].anp_intf, sizeof(asr.asr_prf_intf ) ); /* * Pull prefix out of received Objid + * save in set_prefix IOCTL and addressEntry table */ - for ( i = 0; i < oid->oid[13]; i++ ) + for ( i = 0; i < oid->oid[13]; i++ ) { asr.asr_prf_pref[i] = oid->oid[i + 14]; + } /* * Pass new prefix to the HARP kernel @@ -1718,9 +1888,10 @@ set_prefix ( oid, hdr, buf, s ) syslog ( LOG_ERR, "ilmid: error setting prefix: %m" ); if ( Log ) { write_timestamp(); - fprintf ( Log, "ilmid: errno %d setting prefix\n", + fprintf ( Log, "errno %d setting prefix\n", errno ); } + close ( fd ); return; } } @@ -1731,375 +1902,58 @@ set_prefix ( oid, hdr, buf, s ) */ init_ilmi(); - aa = &Intf[0].anp_addr; + aa = &Intf[intf].anp_addr; /* - * Finish building SET NSAP packet + * Copy our NSAP into addressEntry table */ - COPY_RESP ( NetPrefix_Resp ); - - len = Resp_Buf[0]; - cpp = &Resp_Buf[len + 1]; /* Set to end of response buffer */ - len++; - *cpp++ = aa->address_length; + addressEntry[intf].oid[0] = 0; for ( i = 0; i < aa->address_length; i++ ) { - u_char c = ((u_char *)(aa->address))[i]; + addressEntry[intf].oid[0]++; /* Increment length */ + addressEntry[intf].oid[i + 1] = (int)((u_char *)(aa->address))[i]; - if ( c > 127 ) { - *cpp++ = ( c >> 7 ) | 0x80; - len++; - c &= 0x7f; - } - *cpp++ = c; - len++; - } - /* - * Pack "set = 1" onto end - */ - *cpp++ = 0x02; - *cpp++ = 0x01; - *cpp++ = 0x01; - len += 3; - - /* - * Go back and patch up lengths... - */ - Resp_Buf[0] = len; - Resp_Buf[4] = (u_char)(len - 4); - Resp_Buf[15] = (u_char)(len - 15); - Resp_Buf[31] = (u_char)(len - 31); - Resp_Buf[35] = (u_char)(len - 35); - Resp_Buf[37] = (u_char)(len - 40); - - /* - * Set reqid - */ - set_reqid ( Resp_Buf, Req_ID++ ); - - /* - * Send SET - */ - if ( Debug_Level > 2 && Log ) { - write_timestamp(); - fprintf ( Log, "===== Send SET: %d bytes =====\n", - Resp_Buf[0] ); - hexdump ( (u_char *)&Resp_Buf[1], Resp_Buf[0] ); } - write ( s, (caddr_t)&Resp_Buf[1], Resp_Buf[0] ); return; } -Objid oid; - -/* - * Parse an ASN_TYPE_SET pdu - * - * Crack apart the various pieces of a SET message. The OBJID being set is - * left in oid which is compared and handled else where. - * - * Arguments: - * bp - pointer to current location in PDU buffer - * - * Returns: - * bp - updated buffer pointer - * 0 - no error - * -1 - error in PDU - * - */ -int -process_set ( bp ) - caddr_t *bp; -{ - caddr_t bufp = *bp; - int pdulen; - int b; - - if ( Debug_Level > 1 && Log ) { - write_timestamp(); - fprintf ( Log, "SET:: " ); - } - /* - * Should be SEQUENCE OF - */ - if ( *bufp++ != ASN_SEQUENCE ) { - *bp = bufp; - return ( -1 ); - } - pdulen = asn_get_pdu_len ( &bufp ); - /* - * Should be SEQUENCE OF - */ - if ( *bufp++ != ASN_SEQUENCE ) { - *bp = bufp; - return ( -1 ); - } - pdulen = asn_get_pdu_len ( &bufp ); - /* - * Should be OBJID - */ - if ( *bufp++ != ASN_OBJID ) { - *bp = bufp; - return ( -1 ); - } - asn_get_objid ( &bufp, &oid ); - /* - * Should be <= value> - */ - switch ( *bufp++ ) { - case ASN_INTEGER: - b = asn_get_int ( &bufp ); - if ( Debug_Level > 5 && Log ) { - write_timestamp(); - fprintf ( Log, "Value = %d\n", b ); - } - break; - case ASN_OBJID: - break; - } - - /* - * Return updated pointer - */ - *bp = bufp; - - return ( 0 ); -} - -int specific_trap; -int generic_trap; -int trap_time; -u_char trap_ip[5]; -Objid trap_oid; -Objid extra_trap_oid; - -/* - * Parse an ASN_TYPE_TRAP pdu - * - * Crack apart the various pieces of a TRAP message. The information elements are - * left in global space and used elsewhere if anyone cares (which they currently don't). - * - * Arguments: - * bp - pointer to current location in PDU buffer - * sd - socket descriptor pdu arrived on - * - * Returns: - * bp - updated buffer pointer - * 0 - no error - * -1 - error in PDU - * - */ -int -process_trap ( bp, sd ) - caddr_t *bp; - int sd; -{ - caddr_t bufp = *bp; - int pdulen; - int i; - - if ( Debug_Level > 1 && Log ) { - write_timestamp(); - fprintf ( Log, "TRAP:: " ); - } - /* - * Should be pdulen - */ - pdulen = *bufp++; - /* - * Should be OBJID - */ - if ( *bufp++ != ASN_OBJID ) { - if ( Log ) - fprintf ( Log, "\n" ); - *bp = bufp; - return ( -1 ); - } - asn_get_objid ( &bufp, &trap_oid ); - /* - * First oid coded as 40 * X + Y - */ - if ( Debug_Level > 5 && Log ) { - write_timestamp(); - fprintf ( Log, "%d.%d", trap_oid.oid[1] / 40, - trap_oid.oid[1] % 40 ); - for ( i = 2; i <= trap_oid.oid[0]; i++ ) - fprintf ( Log, ".%d", trap_oid.oid[i] ); - fprintf ( Log, "\n" ); - } - /* - * Should be OCTET STRING - */ - if ( *bufp++ != ASN_IPADDR ) { - if ( Debug_Level > 5 && Log ) { - write_timestamp(); - fprintf ( Log, "Expected IP ADDRESS\n" ); - } - *bp = bufp; - return ( -1 ); - } - asn_get_octet ( &bufp, trap_ip ); - if ( Debug_Level > 5 && Log) { - write_timestamp(); - fprintf ( Log, "\tIP: %d.%d.%d.%d", - trap_ip[0], trap_ip[1], trap_ip[2], trap_ip[3] ); - } - /* - * Should be Generic Trap followed by Specific Trap - */ - if ( *bufp++ != ASN_INTEGER ) { - if ( Log ) - fprintf ( Log, "\n" ); - *bp = bufp; - return ( -1 ); - } - generic_trap = asn_get_int ( &bufp ); - if ( Debug_Level > 5 && Log ) { - fprintf ( Log, " Generic Trap: %s (%d)", - Traps[generic_trap], generic_trap ); - } - if ( *bufp++ != ASN_INTEGER ) { - if ( Log ) - fprintf ( Log, "\n" ); - *bp = bufp; - return ( -1 ); - } - specific_trap = asn_get_int ( &bufp ); - if ( Debug_Level > 5 && Log ) { - fprintf ( Log, " Specific Trap: 0x%x\n", - specific_trap ); - } - /* - * Should be TIMESTAMP - */ - if ( *bufp++ != ASN_TIMESTAMP ) { - if ( Log ) - fprintf ( Log, "\n" ); - *bp = bufp; - return ( -1 ); - } - trap_time = asn_get_int ( &bufp ); - if ( Debug_Level > 5 && Log ) { - write_timestamp(); - fprintf ( Log, "\tTimestamp: %d seconds", trap_time ); - } - /* - * Should be SEQUENCE OF - */ - if ( *bufp++ != ASN_SEQUENCE ) { - *bp = bufp; - return ( -1 ); - } - pdulen = asn_get_pdu_len ( &bufp ); - /* - * Should be OBJID - */ - if ( *bufp++ != ASN_OBJID ) { - *bp = bufp; - return ( -1 ); - } - asn_get_objid ( &bufp, &extra_trap_oid ); - if ( Debug_Level > 5 && Log ) { - write_timestamp(); - fprintf ( Log, "\tExtra Objid: " ); - fprintf ( Log, "%d.%d", extra_trap_oid.oid[1] / 40, - extra_trap_oid.oid[1] % 40 ); - for ( i = 2; i <= extra_trap_oid.oid[0]; i++ ) - fprintf ( Log, ".%d", extra_trap_oid.oid[i] ); - fprintf ( Log, "\n" ); - } - /* - * Whole thing ended with a NULL - */ - bufp++; - bufp++; - - /* - * Return updated pointer - */ - *bp = bufp; - - if ( generic_trap == 0 ) { - write ( sd, (caddr_t)&coldStart_Trap[1], - coldStart_Trap[0] ); - } - - return ( 0 ); - -} - -u_char No_Such[] = { 37, - 0x30, 0x82, 0x00, 0x00, - 0x02, 0x01, 0x00, - 0x04, 0x04, 0x49, 0x4c, 0x4d, 0x49, - PDU_TYPE_GETRESP, - 0x00, - 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x01, 0x02, - 0x02, 0x01, 0x01, - 0x30, 0x82, 0x00, 0x00, - 0x30, 0x82, 0x00, 0x00, - 0x06, 0x00 - }; void -send_no_such ( s, Hdr, op ) - int s; - Snmp_Header *Hdr; - Objid *op; +set_address ( hdr, intf ) + Snmp_Header *hdr; + int intf; { - u_char *cp, *cpp; - int len; - int i; - - len = No_Such[0]; - - UM_COPY ( No_Such, Resp_Buf, len + 1 ); - - cp = cpp = (u_char *)&Resp_Buf[len]; - - /* - * Copy OID into response buffer - */ - *cp++ = op->oid[0]; - for ( i = 1; i <= op->oid[0]; i++ ) { - u_int c = op->oid[i]; - - if ( c > 127 ) { - *cp++ = ( c >> 7 ) | 0x80; - len++; - c &= 0x7f; - /* - * Increment OID length - */ - *cpp += 1; - } - *cp++ = c; - len++; - } - /* - * Finish off with a NULL - */ - *cp++ = 0x05; - *cp++ = 0x00; - len += 2; - - /* - * Patch up all the length locations - */ - Resp_Buf[0] = len; - Resp_Buf[4] = len - 4; - Resp_Buf[15] = len - 15; - Resp_Buf[31] = len - 31; - Resp_Buf[35] = len - 35; - - /* - * Send Response - */ - send_resp ( s, Hdr->reqid, Resp_Buf ); - - return; + Variable *var; + int i, j; + + PDU_Header = build_generic_header(); + PDU_Header->head = (Variable *)UM_ALLOC(sizeof(Variable)); + var = PDU_Header->head; + /* Copy generic addressEntry OBJID */ + UM_COPY ( (caddr_t)&Objids[ADDRESS_OBJID], (caddr_t)&var->oid, + sizeof(Objid) ); + /* Set specific instance */ + i = var->oid.oid[0] + 1; /* Get length */ + var->oid.oid[i++] = 1; + var->oid.oid[i++] = 1; + var->oid.oid[i++] = 3; + var->oid.oid[i++] = 0; + + /* Copy in address length */ + var->oid.oid[i++] = addressEntry[intf].oid[0]; + + /* Copy in address */ + for ( j = 0; j < addressEntry[intf].oid[0]; j++ ) + var->oid.oid[i++] = addressEntry[intf].oid[j + 1]; + var->oid.oid[0] = i - 1; /* Set new length */ + + /* Set == VALID */ + var->type = ASN_INTEGER; + var->var.ival = 1; + + build_pdu ( PDU_Header, PDU_TYPE_SET ); + send_resp ( intf, PDU_Header, Resp_Buf ); } /* @@ -2143,13 +1997,20 @@ Increment_DL ( sig ) int sig; { Debug_Level++; - if ( Debug_Level && Log == (FILE *)NULL ) - if ( ( Log = fopen ( LOG_FILE, "a" ) ) == NULL ) - Log = NULL; - else + if ( Debug_Level && Log == (FILE *)NULL ) { + if ( foregnd ) { + Log = stderr; + } else { + if ( ( Log = fopen ( LOG_FILE, "a" ) ) == NULL ) + Log = NULL; + } + if ( Log ) { setbuf ( Log, NULL ); + write_timestamp(); + fprintf ( Log, "Raised Debug_Level to %d\n", Debug_Level ); + } + } signal ( SIGUSR1, Increment_DL ); - alarm ( SLEEP_TIME ); return; } @@ -2173,37 +2034,388 @@ Decrement_DL ( sig ) if ( Debug_Level <= 0 ) { Debug_Level = 0; if ( Log ) { - fclose ( Log ); + write_timestamp(); + fprintf ( Log, "Lowered Debug_Level to %d\n", Debug_Level ); + if ( !foregnd ) + fclose ( Log ); Log = NULL; } } signal ( SIGUSR2, Decrement_DL ); - alarm ( SLEEP_TIME ); return; } +/* + * Loop through GET variable list looking for matches + * + */ +void +process_get ( hdr, intf ) + Snmp_Header *hdr; + int intf; +{ + Variable *var; + int idx; + + var = hdr->head; + while ( var ) { + idx = find_var ( var ); + switch ( idx ) { + case SYS_OBJID: + var->type = ASN_OBJID; + UM_COPY ( (caddr_t)&Objids[MY_OBJID], + (caddr_t)&var->var.oval, + sizeof(Objid) ); + break; + case UPTIME_OBJID: + var->type = ASN_TIMESTAMP; + var->var.ival = get_ticks(); + break; + case UNITYPE_OBJID: + var->type = ASN_INTEGER; + var->var.ival = UNITYPE_PRIVATE; + break; + case UNIVER_OBJID: + var->type = ASN_INTEGER; + switch ( Intf[intf].anp_sig_proto ) { + case ATM_SIG_UNI30: + var->var.ival = UNIVER_UNI30; + break; + case ATM_SIG_UNI31: + var->var.ival = UNIVER_UNI31; + break; + case ATM_SIG_UNI40: + var->var.ival = UNIVER_UNI40; + break; + default: + var->var.ival = UNIVER_UNKNOWN; + break; + } + break; + case DEVTYPE_OBJID: + var->type = ASN_INTEGER; + var->var.ival = DEVTYPE_USER; + break; + case MAXVCC_OBJID: + var->type = ASN_INTEGER; + var->var.ival = 1024; + break; + case PORT_OBJID: + var->type = ASN_INTEGER; + var->var.ival = intf + 1; + break; + case IPNM_OBJID: + var->type = ASN_IPADDR; + get_local_ip ( ilmi_fd[intf], + &var->var.ival ); + break; + case ADDRESS_OBJID: + break; + case ATMF_PORTID: + var->type = ASN_INTEGER; + var->var.ival = 0x30 + intf; + break; + case ATMF_SYSID: + var->type = ASN_OCTET; + var->var.sval[0] = 6; + UM_COPY ( (caddr_t)&Cfg[intf].acp_macaddr, + (caddr_t)&var->var.sval[1], 6 ); + break; + default: + /* NO_SUCH */ + break; + } + var = var->next; + } + build_pdu ( hdr, PDU_TYPE_GETRESP ); + send_resp ( intf, hdr, Resp_Buf ); + +} + +/* + * ILMI State Processing Loop + * + * + */ +void +ilmi_do_state () +{ + struct timeval tvp; + fd_set rfd; + u_char buf[1024]; + Variable *var; + int intf; + int maxfd = 0; + + /* + * Loop forever + */ + for ( ; ; ) { + int count; + int n; + caddr_t bpp; + Snmp_Header *Hdr; + + /* + * SunOS CC doesn't allow automatic aggregate initialization. + * Initialize to zero which effects a poll operation. + */ + tvp.tv_sec = 15; + tvp.tv_usec = 0; + + /* + * Clear fd_set and initialize to check this interface + */ + FD_ZERO ( &rfd ); + for ( intf = 0; intf < MAX_UNITS; intf++ ) + if ( ilmi_fd[intf] > 0 ) { + FD_SET ( ilmi_fd[intf], &rfd ); + maxfd = MAX ( maxfd, ilmi_fd[intf] ); + } + + /* + * Check for new interfaces + */ + ilmi_open(); + + for ( intf = 0; intf < MAX_UNITS; intf++ ) { + /* + * Do any pre-message state processing + */ + switch ( ilmi_state[intf] ) { + case ILMI_COLDSTART: + /* + * Clear addressTable + */ + UM_ZERO ( (caddr_t)&addressEntry[intf], sizeof(Objid) ); + + /* + * Start by sending a COLD_START trap. This should cause the + * remote end to clear the associated prefix/address table(s). + */ + /* Build ColdStart TRAP header */ + ColdStart_Header = build_cold_start(); + build_pdu ( ColdStart_Header, PDU_TYPE_TRAP ); + send_resp ( intf, ColdStart_Header, Resp_Buf ); + + /* + * Start a timeout so that if the next state fails, we re-enter + * ILMI_COLDSTART. + */ + /* atm_timeout() */ + + /* Enter new state */ + ilmi_state[intf] = ILMI_INIT; + /* fall into ILMI_INIT */ + + case ILMI_INIT: + /* + * After a COLD_START, we need to check that the remote end has + * cleared any tables. Send a GET_NEXT request to check for this. + * In the event that the table is not empty, or that no reply is + * received, return to COLD_START state. + */ + PDU_Header = build_generic_header(); + PDU_Header->head = (Variable *)UM_ALLOC(sizeof(Variable)); + var = PDU_Header->head; + UM_COPY ( (caddr_t)&Objids[ADDRESS_OBJID], (caddr_t)&var->oid, + sizeof(Objid) ); + var->type = ASN_NULL; + var->next = NULL; + + /* + * Send GETNEXT request looking for empty ATM Address Table + */ + PDU_Header->reqid = Req_ID++; + build_pdu ( PDU_Header, PDU_TYPE_GETNEXT ); + send_resp ( intf, PDU_Header, Resp_Buf ); + + /* + * Start a timeout while looking for SET message. If we don't receive + * a SET, then go back to COLD_START state. + */ + /* atm_timeout() */ + break; + + case ILMI_RUNNING: + /* Normal SNMP processing */ + break; + + default: + break; + } + } + + count = select ( maxfd + 1, &rfd, NULL, NULL, &tvp ); + + for ( intf = 0; intf < MAX_UNITS; intf++ ) { + /* + * Check for received messages + */ + if ( ilmi_fd[intf] > 0 && FD_ISSET ( ilmi_fd[intf], & rfd ) ) { + + n = read ( ilmi_fd[intf], (caddr_t)&buf[1], sizeof(buf) - 1 ); + if ( n == -1 && ( errno == ECONNRESET || errno == EBADF ) ) { + ilmi_state[intf] = ILMI_COLDSTART; + close ( ilmi_fd[intf] ); + ilmi_fd[intf] = -1; + } else { + if ( Log && Debug_Level > 1 ) fprintf ( Log, "***** state %d ***** read %d bytes from %d (%d) ***** %s *****\n", + ilmi_state[intf], n, intf, ilmi_fd[intf], PDU_Types[buf[14] - 0xA0] ); { + if ( Debug_Level > 2 ) + hexdump ( (caddr_t)&buf[1], n ); + } + bpp = (caddr_t)&buf[1]; + if ( ( Hdr = asn_get_header ( &bpp ) ) == NULL ) + continue; + + /* What we do with this messages depends upon the state we're in */ + switch ( ilmi_state[intf] ) { + case ILMI_COLDSTART: + /* We should never be in this state here */ + free_pdu ( Hdr ); + break; + case ILMI_INIT: + /* The only messages we care about are GETNEXTs, GETRESPs, and TRAPs */ + switch ( Hdr->pdutype ) { + case PDU_TYPE_GETNEXT: + /* + * Should be because the remote side is attempting + * to verify that our table is empty + */ + if ( oid_ncmp ( (caddr_t)&Hdr->head->oid, + (caddr_t)&Objids[ADDRESS_OBJID], + Objids[ADDRESS_OBJID].oid[0] ) == 0 ) { + if ( addressEntry[intf].oid[0] ) { + /* XXX - FIXME */ + /* Our table is not empty - return address */ + } + } + build_pdu ( Hdr, PDU_TYPE_GETRESP ); + send_resp ( intf, Hdr, Resp_Buf ); + break; + case PDU_TYPE_GETRESP: + /* + * This should be in response to our GETNEXT. + * Check the OIDs and go onto ILMI_RUNNING if + * the address table is empty. We can cheat and + * not check sequence numbers because we only send + * the one GETNEXT request and ILMI says we shouldn't + * have interleaved sessions. + */ + /* + * First look for empty table. If found, go to next state. + */ + if ( oid_ncmp ( &Objids[ADDRESS_OBJID], &Hdr->head->oid, + Objids[ADDRESS_OBJID].oid[0] ) == 1 ) { + ilmi_state[intf] = ILMI_RUNNING; /* ILMI_REG; */ + } else { + /* + * Check to see if this matches our address + * and if so, that it's a VALID entry. + */ + Atm_addr *aa; + int l; + int match = 1; + + aa = &Intf[intf].anp_addr; + if ( aa->address_length == Hdr->head->oid.oid[13] ) { + for ( l = 0; l < aa->address_length; l++ ) { + if ( (int)((u_char *)(aa->address))[l] != + Hdr->head->oid.oid[14 + l] ) { + match = 0; + } + } + } + if ( match ) { + if ( Hdr->head->var.ival == 1 ) { + ilmi_state[intf] = ILMI_RUNNING; + } + } + } + free_pdu ( Hdr ); + break; + case PDU_TYPE_SET: + /* Look for SET_PREFIX Objid */ + if ( oid_ncmp ( (caddr_t)&Hdr->head->oid, + (caddr_t)&Objids[SETPFX_OBJID], + Objids[SETPFX_OBJID].oid[0] ) == 0 ) { + set_prefix ( &Hdr->head->oid, Hdr, intf ); + /* Reply to SET before sending our ADDRESS */ + build_pdu(Hdr, PDU_TYPE_GETRESP); + send_resp( intf, Hdr, Resp_Buf ); + set_address ( Hdr, intf ); + } else { + build_pdu(Hdr, PDU_TYPE_GETRESP); + send_resp( intf, Hdr, Resp_Buf ); + } + break; + case PDU_TYPE_TRAP: + /* Remote side wants us to start fresh */ + free_pdu ( Hdr ); + break; + default: + /* Ignore */ + free_pdu ( Hdr ); + break; + } + break; + case ILMI_REG: + break; + case ILMI_RUNNING: + /* We'll take anything here */ + switch ( Hdr->pdutype ) { + case PDU_TYPE_GET: + process_get ( Hdr, intf ); + break; + case PDU_TYPE_GETRESP: + /* Ignore GETRESPs */ + free_pdu ( Hdr ); + break; + case PDU_TYPE_GETNEXT: + build_pdu ( Hdr, PDU_TYPE_GETRESP ); + send_resp ( intf, Hdr, Resp_Buf ); + break; + case PDU_TYPE_SET: + /* Look for SET_PREFIX Objid */ + if ( oid_ncmp ( (caddr_t)&Hdr->head->oid, + (caddr_t)&Objids[SETPFX_OBJID], + Objids[SETPFX_OBJID].oid[0] ) == 0 ) { + set_prefix ( &Hdr->head->oid, Hdr, intf ); + /* Reply to SET before sending our ADDRESS */ + build_pdu(Hdr, PDU_TYPE_GETRESP); + send_resp( intf, Hdr, Resp_Buf ); + set_address ( Hdr, intf ); + } else { + build_pdu(Hdr, PDU_TYPE_GETRESP); + send_resp( intf, Hdr, Resp_Buf ); + } + break; + case PDU_TYPE_TRAP: + free_pdu ( Hdr ); + break; + } + break; + default: + /* Unknown state */ + free_pdu ( Hdr ); + break; + } + } /* if n > 0 */ + } /* if received message */ + } /* for each interface */ + } /* for ever loop */ + +} + +int main ( argc, argv ) int argc; char *argv[]; { - u_char buf[256], set_buf[256]; - char community[1024]; - u_char *bufp; - int s; int c; - int foregnd = 0; /* run in the foreground? */ - int pdulen; - int version; - int pdutype; - int reqid; - int error_status; - int error_ptr; - int b; int i; - int lerr = 0; int Reset = 0; /* Should we send a coldStart and exit? */ - Snmp_Header *Hdr; - int n; /* * What are we running as? (argv[0]) @@ -2248,34 +2460,10 @@ main ( argc, argv ) * If we're not doing debugging, run in the background */ if ( foregnd == 0 ) { -#ifdef sun - int pid, fd; - - if ( ( pid = fork() ) < 0 ) { - fprintf ( stderr, "fork failed\n" ); - exit ( 1 ); - } else if (pid != 0) { - /* Parent process - exit and allow child to run */ - exit ( 0 ); - } - /* Child process */ - if ( ( lerr = setpgrp ( 0, getpid() ) ) < 0 ) { - fprintf ( stderr, "Can't set process group" ); - exit ( 1 ); - } - if ( ( fd = open ( "/dev/tty", O_RDWR ) ) >= 0 ) { - ioctl ( fd, TIOCNOTTY, (char *)NULL ); - close ( fd ); - } - /* close all open descriptors */ - for ( fd = 3; fd < getdtablesize(); fd++ ) - close ( fd ); -#else if ( daemon ( 0, 0 ) ) err ( 1, "Can't fork" ); -#endif } else - setbuf ( stdout, NULL ); + ; /* setbuf ( stdout, NULL ); */ signal ( SIGUSR1, Increment_DL ); signal ( SIGUSR2, Decrement_DL ); @@ -2283,11 +2471,16 @@ main ( argc, argv ) /* * Open log file */ - if ( Debug_Level ) - if ( ( Log = fopen ( LOG_FILE, "a" ) ) == NULL ) - Log = NULL; - else - setbuf ( Log, NULL ); + if ( Debug_Level ) { + if ( foregnd ) { + Log = stderr; + } else { + if ( ( Log = fopen ( LOG_FILE, "a" ) ) == NULL ) + Log = NULL; + } + } + if ( Log ) + setbuf ( Log, NULL ); /* * Get our startup time @@ -2296,12 +2489,13 @@ main ( argc, argv ) starttime.tv_sec--; starttime.tv_usec += 1000000; + /* Randomize starting request ID */ + Req_ID = starttime.tv_sec; + /* * Reset all the interface descriptors */ for ( i = 0; i < MAX_UNITS; i++ ) { - trap_fd[i] = -1; - last_trap[i] = (time_t)0; ilmi_fd[i] = -1; } /* @@ -2314,497 +2508,23 @@ main ( argc, argv ) */ if ( Reset ) { for ( i = 0; i < MAX_UNITS; i++ ) - if ( trap_fd[i] >= 0 ) { + if ( ilmi_fd[i] >= 0 ) { + /* Build ColdStart TRAP header */ + ColdStart_Header = build_cold_start(); + build_pdu ( ColdStart_Header, PDU_TYPE_TRAP ); + send_resp ( i, ColdStart_Header, Resp_Buf ); if ( Debug_Level > 1 && Log ) { write_timestamp(); - fprintf ( Log, "Close trap_fd[%d]: %d\n", - i, trap_fd[i] ); + fprintf ( Log, "Close ilmi_fd[%d]: %d\n", + i, ilmi_fd[i] ); } - close ( trap_fd[i] ); + close ( ilmi_fd[i] ); } exit ( 2 ); } - /* - * For ever... - */ - for ( ; ; ) { - int maxfd = 0; - int count; - struct timeval tvp; - fd_set rfd; - time_t curtime; - - ilmi_open(); - - /* - * SunOS CC doesn't allow automatic aggregate initialization. - * Make everybody happy and do it here... - */ - tvp.tv_sec = 15; - tvp.tv_usec = 0; - - curtime = time ( (time_t *)NULL ); - - /* - * Check for TRAP messages - */ - FD_ZERO ( &rfd ); - if ( Debug_Level > 1 && Log ) { - write_timestamp(); - fprintf ( Log, "Check Traps: " ); - } - for ( i = 0; i < MAX_UNITS; i++ ) { - if ( Debug_Level > 1 && Log ) - fprintf ( Log, "trap_fd[%d]: %d ", i, trap_fd[i] ); - if ( trap_fd[i] != -1 ) { - /* - * If we haven't sent a coldStart trap recently, - * send one now - */ - if ( last_trap[i] + TRAP_TIME < curtime ) { - last_trap[i] = curtime; - /* - * Send coldStart TRAP - */ - if ( Debug_Level > 4 && Log ) { - write_timestamp(); - fprintf ( Log, "===== Sent %d bytes =====\n", - coldStart_Trap[0] ); - hexdump ( (u_char *)&coldStart_Trap[1], - coldStart_Trap[0] ); - } - if ( Debug_Level && Log ) { - write_timestamp(); - fprintf ( Log, - "\tSend coldStart TRAP to unit %d\n", i ); - } - write ( trap_fd[i], (caddr_t)&coldStart_Trap[1], - coldStart_Trap[0] ); - } - if ( (trap_fd[i] >= 0) && - FD_SET ( trap_fd[i], &rfd )) { - maxfd = MAX ( maxfd, trap_fd[i] ); - } - } - } - if ( Debug_Level > 1 && Log ) - fprintf ( Log, "maxfd: %d\n", maxfd ); - - if ( maxfd ) { - count = select ( maxfd + 1, &rfd, NULL, NULL, &tvp ); - - if ( count > 0 ) { - for ( i = 0; i < MAX_UNITS; i++ ) { - if ( trap_fd[i] >= 0 && FD_ISSET ( trap_fd[i], &rfd ) ) { - s = trap_fd[i]; - - n = read ( s, (caddr_t)&buf[1], sizeof(buf) - 1 ); - if ( n == -1 && ( errno == ECONNRESET || - errno == EBADF ) ) { - if ( Debug_Level > 1 && Log ) { - write_timestamp(); - fprintf ( Log, - "Bad read: close trap_fd[%d]: %d\n", - i, trap_fd[i] ); - } - close ( trap_fd[i] ); - trap_fd[i] = -1; - ilmi_fd[i] = -1; - } - if ( n ) { - buf[0] = n; - if ( Debug_Level > 1 && Log ) { - write_timestamp(); - fprintf ( Log, "***** Read %d bytes *****\n", - n ); - hexdump ( (caddr_t)&buf[1], n ); - } - bufp = buf; - /* - * Skip length byte - */ - bufp++; - /* - * Crack the header - */ - if ( ( Hdr = asn_get_header ( &bufp ) ) == NULL ) - continue; - pdutype = Hdr->pdutype; - /* - * Only interested in TRAP messages - */ - switch ( pdutype ) { - /* - * FORE switches often go straight to SET prefix - * after receiving a coldStart TRAP from us - */ - case PDU_TYPE_SET: - /* - * Make a copy of this PDU so that a - * SET NSAP prefix can reply to it. - */ - UM_COPY ( buf, set_buf, sizeof(buf) ); - - lerr = process_set ( &bufp ); - /* - * Can't do a simple oid_cmp since we - * don't yet know what the prefix is. - * If it looks like a SET netPrefix.0, - * then compare the portion leading up - * to the NSAP prefix part. - */ - if ( oid.oid[0] == 26 ) { - oid.oid[0] = 12; - if ( oid_cmp ( &setprefix, &oid ) == 0 ) { - oid.oid[0] = 26; - set_prefix ( &oid, Hdr, set_buf, s ); - } - } - /* - * We now move from awaiting TRAP to processing ILMI - */ - ilmi_fd[i] = trap_fd[i]; - trap_fd[i] = -1; - break; - case PDU_TYPE_TRAP: - lerr = process_trap ( &bufp, trap_fd[i] ); - /* - * We now move from awaiting TRAP to processing ILMI - */ - ilmi_fd[i] = trap_fd[i]; - trap_fd[i] = -1; - break; - } - } /* if n */ - } /* if FD_ISSET */ - } /* for i */ - } /* if count */ - } - - /* - * Reset from TRAP checking - */ - maxfd = 0; - errno = 0; - /* - * Check for ILMI messages - */ - FD_ZERO ( &rfd ); - if ( Debug_Level > 1 && Log ) { - write_timestamp(); - fprintf ( Log, "Check Ilmis: " ); - } - for ( i = 0; i < MAX_UNITS; i++ ) { - if ( Debug_Level > 1 && Log ) - fprintf ( Log, "ilmi_fd[%d]: %d ", i, ilmi_fd[i] ); - if ( ilmi_fd[i] != -1 ) { - if ( (ilmi_fd[i] >= 0) && - FD_SET ( ilmi_fd[i], &rfd )) { - maxfd = MAX ( maxfd, ilmi_fd[i] ); - } - } - } - if ( Debug_Level > 1 && Log ) - fprintf ( Log, "maxfd: %d\n", maxfd ); - - if ( maxfd ) { - count = select ( maxfd + 1, &rfd, NULL, NULL, &tvp ); - - if ( count > 0 ) { - for ( i = 0; i < MAX_UNITS; i++ ) { - if ( ilmi_fd[i] >= 0 && FD_ISSET ( ilmi_fd[i], &rfd ) ) { - - s = ilmi_fd[i]; - - n = read ( s, (caddr_t)&buf[1], sizeof(buf) - 1 ); - if ( n == -1 && ( errno == ECONNRESET || - errno == EBADF ) ) { - if ( Debug_Level > 1 && Log ) { - write_timestamp(); - fprintf ( Log, - "Bad read: close ilmi_fd[%d]: %d\n", - i, ilmi_fd[i] ); - } - close ( ilmi_fd[i] ); - trap_fd[i] = -1; - ilmi_fd[i] = -1; - } - if ( n ) { - buf[0] = n; - if ( Debug_Level > 1 && Log ) { - write_timestamp(); - fprintf ( Log, - "***** Read %d bytes *****\n", - n ); - hexdump ( (caddr_t)&buf[1], n ); - } - bufp = buf; - /* - * Skip length byte - */ - bufp++; - /* - * Crack the header - */ - if ( ( Hdr = asn_get_header ( &bufp ) ) - == NULL ) - continue; - pdutype = Hdr->pdutype; - - /* - * Do the operation... - */ - switch ( pdutype ) { - - case PDU_TYPE_GET: - if ( Debug_Level > 1 && Log ) { - write_timestamp(); - fprintf ( Log, "GET:: " ); - } - /* - * Should be SEQUENCE OF - */ - if ( *bufp++ != ASN_SEQUENCE ) { - lerr = 1; - break; - } - pdulen = asn_get_pdu_len ( &bufp ); - /* - * Should be SEQUENCE OF - */ - if ( *bufp++ != ASN_SEQUENCE ) { - lerr = 1; - break; - } - pdulen = asn_get_pdu_len ( &bufp ); - /* - * Should be OBJID - */ - if ( *bufp++ != ASN_OBJID ) { - lerr = 1; - break; - } - asn_get_objid ( &bufp, &oid ); - /* - * Ended with a NULL - */ - bufp++; - bufp++; - /* - * If GET sysObjId.0 - */ - if (oid_cmp(&sysObjId, &oid) == 0 ) { - send_resp ( s, Hdr->reqid, - sysObjId_Resp ); - - } else - /* - * If GET sysUpTime.0 - */ - if (oid_cmp(&sysUpTime, &oid) == 0 ) { - send_uptime_resp ( s, - Hdr->reqid ); - } else - /* - * If GET myIpNm.0 - */ - if ( oid_cmp ( &myipnm, &oid ) == 0 ) { - send_myipnm ( s, Hdr ); - } else - /* - * If GET uniType.0 - */ - if ( oid_cmp ( &unitype, &oid ) == 0 ) { - if ( Debug_Level > 1 && Log ) { - write_timestamp(); - fprintf ( Log, - "\tSend uniType\n" ); - } - send_resp ( s, Hdr->reqid, - UniType_Resp ); - } else - /* - * If GET uniVer.0 - */ - if ( oid_cmp ( &univer, &oid ) == 0 ) { - int p = UniVer_Resp[0]; - if ( Debug_Level > 1 && Log ) { - write_timestamp(); - fprintf ( Log, - "\tSend uniVer\n" ); - } - switch (Intf[i].anp_sig_proto) { - case ATM_SIG_UNI30: - UniVer_Resp[p] = - UNIVER_UNI30; - break; - case ATM_SIG_UNI31: - UniVer_Resp[p] = - UNIVER_UNI31; - break; - case ATM_SIG_UNI40: - UniVer_Resp[p] = - UNIVER_UNI40; - break; - } - send_resp ( s, Hdr->reqid, - UniVer_Resp ); - } else - /* - * If GET devType.0 - */ - if ( oid_cmp ( &devtype, &oid ) == 0 ) { - if ( Debug_Level > 1 && Log ) { - write_timestamp(); - fprintf ( Log, - "\tSend devType\n" ); - } - send_resp ( s, Hdr->reqid, - DevType_Resp ); - } else - /* - * If GET foreSigGrp....0 - */ - if (oid_cmp(&foresiggrp, &oid) == 0) { - if ( Debug_Level > 1 && Log ) { - write_timestamp(); - fprintf ( Log, - "\tSend noSuchVar\n" ); - } - send_resp ( s, Hdr->reqid, - NoSuchFore_Resp ); - } else - if ( oid_cmp(&layeridx, &oid) == 0 ) { - if ( Debug_Level > 1 && Log ) { - write_timestamp(); - fprintf ( Log, - "\t*** LayerIndex\n" ); - } - } else - if ( oid_cmp(&maxvcc, &oid) == 0 ) { - send_resp ( s, Hdr->reqid, - maxVCC_Resp ); - } else - if ( oid_cmp ( &portidx, &oid ) == 0 ) { - int p = PortIndex_Resp[0]; - PortIndex_Resp[p] = i + 1; - send_resp ( s, Hdr->reqid, - PortIndex_Resp ); - } else - send_no_such ( s, Hdr, &oid ); - break; - - case PDU_TYPE_GETNEXT: - if ( Debug_Level > 1 && Log ) { - write_timestamp(); - fprintf ( Log, "GET_NEXT:: " ); - } - /* - * Should be SEQUENCE OF - */ - if ( *bufp++ != ASN_SEQUENCE ) { - lerr = 1; - break; - } - pdulen = asn_get_pdu_len ( &bufp ); - /* - * Should be SEQUENCE OF - */ - if ( *bufp++ != ASN_SEQUENCE ) { - lerr = 1; - break; - } - pdulen = asn_get_pdu_len ( &bufp ); - /* - * Should be OBJID - */ - if ( *bufp++ != ASN_OBJID ) { - lerr = 1; - break; - } - asn_get_objid ( &bufp, &oid ); - /* - * Ended with a NULL - */ - bufp++; - bufp++; - /* - * If this is a GET_NEXT netPrefix then - * the other side probably restarted - * and is looking for a table empty - * indication before restarting the - * ILMI protocol. - */ - if ( oid_cmp(&netpfx_oid, &oid) == 0 ) { - if ( Debug_Level > 1 && Log ) { - write_timestamp(); - fprintf ( Log, - "\tSend GET_RESP:\n" ); - } - send_resp ( s, Hdr->reqid, - GetNext_Resp ); - } - break; - - case PDU_TYPE_GETRESP: - if ( Debug_Level > 1 && Log ) { - write_timestamp(); - fprintf ( Log, - "GET_RESP:: \n" ); - } - /* - * Ignore any responses to our GETs. - * (We don't send any GETs.) - */ - break; - - case PDU_TYPE_SET: - /* - * Make a copy of this PDU so that a - * SET NSAP prefix can reply to it. - */ - UM_COPY ( buf, set_buf, sizeof(buf) ); - - if ( process_set ( &bufp ) < 0 ) - break; - - /* - * Can't do a simple oid_cmp since we - * don't know what the prefix is yet. - * If it looks like a SET netPrefix.0, - * then compare the portion leading up - * to the NSAP prefix part. - */ - if ( oid.oid[0] == 26 ) { - oid.oid[0] = 12; - if ( oid_cmp(&setprefix,&oid) - == 0 ) { - oid.oid[0] = 26; - set_prefix ( &oid, Hdr, - set_buf, s ); - } - } - break; - - case PDU_TYPE_TRAP: - lerr = process_trap ( &bufp, s ); - break; - } - /* - * Forget about this PDU - */ - free ( Hdr ); - Hdr = NULL; + ilmi_do_state(); - } /* end of read(s) */ - } /* end if FD_ISSET(s) */ - } /* end of for ( i... */ - } /* end of if ( count ) */ - } else { - sleep ( SLEEP_TIME ); - } - } /* end of for ever */ - + exit(0); } |