diff options
Diffstat (limited to 'sbin/atm/ilmid/ilmid.c')
-rw-r--r-- | sbin/atm/ilmid/ilmid.c | 2830 |
1 files changed, 1555 insertions, 1275 deletions
diff --git a/sbin/atm/ilmid/ilmid.c b/sbin/atm/ilmid/ilmid.c index 9da24241f726..e515a1088f99 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.1 1998/09/15 08:22:47 phk Exp $ + * @(#) $Id: ilmid.c,v 1.9 1998/08/13 20:15:28 jpt Exp $ * */ @@ -45,24 +45,40 @@ * */ -#include <sys/param.h> - #ifndef lint -__RCSID("@(#) $Id: ilmid.c,v 1.1 1998/09/15 08:22:47 phk Exp $"); +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> -#include <errno.h> +#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 <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> @@ -70,30 +86,36 @@ __RCSID("@(#) $Id: ilmid.c,v 1.1 1998/09/15 08:22:47 phk 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 <libatm.h> +#include <netatm/uni/unisig_var.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 */ @@ -103,167 +125,360 @@ static char *Var_Types[] = { "", "", "ASN_INTEGER", "", "ASN_OCTET", "ASN_NULL", #define PDU_TYPE_SET 0xA3 #define PDU_TYPE_TRAP 0xA4 -static char *PDU_Types[] = { "GET REQUEST", "GETNEXT REQUEST", "GET RESPONSE", "SET REQUEST", - "TRAP" }; - /* - * Define TRAP codes + * 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. */ -#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 +struct snmp_header { + int pdulen; + int version; + char community[64]; + int pdutype; + int reqid; + int error; + int erridx; +}; +typedef struct snmp_header Snmp_Header; /* - * Define SNMP Version numbers + * Define our internal representation of an OBJECT IDENTIFIER */ -#define SNMP_VERSION_1 1 -#define SNMP_VERSION_2 2 +struct objid { + int oid[128]; +}; +typedef struct objid Objid; /* - * Max string length for Variable + * 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...) */ -#define STRLEN 128 - +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 }; /* - * Unknown variable + * (Partialy) pre-encoded SNMP responses */ -#define VAR_UNKNOWN -1 /* - * Define our internal representation of an OBJECT IDENTIFIER + * sysObjId reply */ -struct objid { - int oid[128]; +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 }; -typedef struct objid Objid; /* - * Define a Veriable classso that we can handle multiple GET/SET's - * per PDU. + * sysUpTime: reply to a sysUpTime GET request */ -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; +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 */ }; /* - * 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. + * coldStart TRAP to start the ILMI protocol */ -struct snmp_header { - int pdulen; - int version; - char community[64]; - int pdutype; +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 */ +}; - /* 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; +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 */ }; -typedef struct snmp_header Snmp_Header; -Snmp_Header *ColdStart_Header; -Snmp_Header *PDU_Header; +/* + * Reply to GET myIpNm + */ +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 */ +}; /* - * 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...) + * Reply to GET portIndex - we're always 1 + unit number */ -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 }}, +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 */ }; -#define NUM_OIDS (sizeof(Objids)/sizeof(Objid)) +/* + * 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 */ +}; + +/* + * Reply to GET uniType - we only support PRIVATE + */ +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) */ +}; -#define UNIVER_UNI20 1 #define UNIVER_UNI30 2 #define UNIVER_UNI31 3 #define UNIVER_UNI40 4 -#define UNIVER_UNKNOWN 5 -#define UNITYPE_PUBLIC 1 -#define UNITYPE_PRIVATE 2 +/* + * 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 DEVTYPE_USER 1 -#define DEVTYPE_NODE 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) */ +}; /* - * ILMI protocol states + * Reply to GET foreSigGroup.* with noSuchError */ -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 */ +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 */ }; /* * Our (incrementing) Request ID */ -int Req_ID; +int Req_ID = 0; /* * Temporary buffer for building response packets. Should help ensure @@ -287,15 +502,18 @@ char *Traps[] = { "coldStart", "warmStart", "linkDown", "linkUp", int NUnits; - /* - * fd for units which have seen a coldStart TRAP and are now exchaning SNMP requests + * 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 */ -int ilmi_fd[MAX_UNITS + 1]; +int trap_fd[MAX_UNITS]; /* - * enum ilmi_states for this unit + * fd for units which have seen a coldStart TRAP and are now exchaning SNMP requests */ -int ilmi_state[MAX_UNITS + 1]; +int ilmi_fd[MAX_UNITS]; /* * Local copy for HARP physical configuration information */ @@ -306,17 +524,11 @@ 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]; @@ -325,6 +537,14 @@ 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 ) ); @@ -354,11 +574,10 @@ write_timestamp() clock = time ( (time_t)NULL ); tm = localtime ( &clock ); - 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 ); + 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 ); return; @@ -398,10 +617,8 @@ 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++ ); @@ -410,10 +627,8 @@ 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; @@ -431,32 +646,24 @@ 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, plen ) - u_char **bufp; - int *plen; +asn_get_pdu_len ( bufp ) + u_char **bufp; { 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; @@ -513,18 +720,15 @@ 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, plen ) - u_char **bufp; - int *plen; +asn_get_int ( bufp ) + u_char **bufp; { int i; int len; @@ -532,69 +736,14 @@ asn_get_int ( bufp, plen ) 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: @@ -633,19 +782,16 @@ 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, plen ) - u_char **bufp; - Objid *objid; - int *plen; +asn_get_objid ( bufp, objid ) + u_char **bufp; + Objid *objid; { int len; u_char *bp = *bufp; @@ -653,53 +799,17 @@ asn_get_objid ( bufp, objid, plen ) 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; - 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 ); + if ( Debug_Level > 1 ) + print_objid ( objid ); + return; } /* @@ -711,19 +821,16 @@ asn_put_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, plen ) - u_char **bufp; - char *octet; - int *plen; +asn_get_octet ( bufp, octet ) + u_char **bufp; + char *octet; { u_char *bp = *bufp; int i = 0; @@ -733,13 +840,10 @@ asn_get_octet ( bufp, octet, plen ) * &i is really a dummy value here as we don't keep track * of the ongoing buffer length */ - len = asn_get_encoded ( &bp, &i, plen ); + len = asn_get_encoded ( &bp, &i ); - for ( i = 0; i < len; i++ ) { + for ( i = 0; i < len; i++ ) *octet++ = *bp++; - if ( plen ) - (*plen)--; - } *bufp = bp; @@ -761,133 +865,22 @@ 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 %s\n", + "Pdu len: %d Version: %d Community: \"%s\" Pdu Type: 0x%x\n", Hdr->pdulen, Hdr->version + 1, Hdr->community, - 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; + Hdr->pdutype ); } + 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. @@ -908,8 +901,6 @@ asn_get_header ( bufp ) { Snmp_Header *h; u_char *bp = *bufp; - int len = 0; - int dummy = 0; /* * Allocate memory to hold the SNMP header @@ -918,11 +909,6 @@ 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 */ @@ -931,7 +917,7 @@ asn_get_header ( bufp ) /* * Get the length of remaining PDU data */ - h->pdulen = asn_get_pdu_len ( &bp, NULL ); + h->pdulen = asn_get_pdu_len ( &bp ); /* * We expect to find an integer encoding Version-1 @@ -939,7 +925,7 @@ asn_get_header ( bufp ) if ( *bp++ != ASN_INTEGER ) { return ( (Snmp_Header *)NULL ); } - h->version = asn_get_int ( &bp, NULL ); + h->version = asn_get_int ( &bp ); /* * After the version, we need the community name @@ -947,7 +933,8 @@ asn_get_header ( bufp ) if ( *bp++ != ASN_OCTET ) { return ( (Snmp_Header *)NULL ); } - asn_get_octet ( &bp, h->community, NULL ); + UM_ZERO ( h->community, sizeof ( h->community ) ); + asn_get_octet ( &bp, h->community ); /* * Single byte PDU type @@ -959,43 +946,31 @@ asn_get_header ( bufp ) */ if ( h->pdutype != PDU_TYPE_TRAP ) { /* TRAP uses different format */ - (void) asn_get_pdu_len ( &bp, &dummy ); + bp++; /* Skip over data len */ /* Request ID */ if ( *bp++ != ASN_INTEGER ) { - UM_FREE ( h ); return ( (Snmp_Header *)NULL ); } - h->reqid = asn_get_int ( &bp, NULL ); + h->reqid = asn_get_int ( &bp ); /* Error Status */ if ( *bp++ != ASN_INTEGER ) { - UM_FREE ( h ); return ( (Snmp_Header *)NULL ); } - h->error = asn_get_int ( &bp, NULL ); + h->error = asn_get_int ( &bp ); /* 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->varlen = ( asn_get_pdu_len ( &bp, &len ) - 1 ); - h->varlen += ( len - 1 ); + h->erridx = asn_get_int ( &bp ); - parse_oids ( h, &bp ); } *bufp = bp; - if ( Log && Debug_Level ) + if ( Debug_Level > 2 ) print_header ( h ); return ( h ); @@ -1003,7 +978,7 @@ asn_get_header ( bufp ) } /* - * Compare two internal OID representations + * Compare to internal OID representations * * Arguments: * oid1 - Internal Object Identifier @@ -1019,54 +994,18 @@ 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 <= len; i++ ) { - if ( !(oid1->oid[i] == oid2->oid[i]) ) - /* values don't match */ - return ( 1 ); - } - - /* Objid's are identical */ - return ( 0 ); -} - -/* - * Compare two internal OID representations - * - * Arguments: - * oid1 - Internal Object Identifier - * oid2 - Internal Object Identifier - * len - Length of OID to compare - * - * 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++ ) { + for ( i = 1; i <= oid1->oid[0]; i++ ) { if ( !(oid1->oid[i] == oid2->oid[i]) ) /* values don't match */ return ( 1 ); @@ -1077,50 +1016,35 @@ oid_ncmp ( oid1, oid2, len ) } /* - * Find the index of a OBJID which matches this Variable instance - * - * Arguments: - * var - pointer to Variable instance - * - * Returns: - * idx - index of matched Variable instance - * -1 - no matching Variable found + * Encode a timeval as the number of time ticks * - */ -int -find_var ( var ) - Variable *var; -{ - 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 + * 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'). * * Arguments: - * none + * bufp - pointer to buffer pointer * * Returns: - * number of ticks + * bufp - updated buffper pointer + * len - number of bytes to encode time ticks value + * - ticks since 'starttime' encoded in buffer * */ int -get_ticks() +asn_encode_ticks ( bufp, ret ) + u_char **bufp; + int *ret; { - struct timeval timenow; - struct timeval timediff; + struct timeval timenow; + struct timeval timediff; + u_char *bp = *bufp; + int len, ticks; (void) gettimeofday ( &timenow, NULL ); /* - * Adjust for subtraction + * Adjust for subtraction */ timenow.tv_sec--; timenow.tv_usec += 1000000; @@ -1140,252 +1064,139 @@ get_ticks() } /* - * Compute number of ticks + * Compute 100th's of second in diff time structure */ - return ( ( timediff.tv_sec * 100 ) + ( timediff.tv_usec / 10000 ) ); + *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; + *bufp = bp; + return ( len + 2 ); } /* - * Build a response PDU + * Send back up sysUpTime response * * Arguments: - * hdr - pointer to PDU Header with completed Variable list - * + * sd - socket descriptor to send reply on + * reqid - original GET request id + * * Returns: - * none + * none - response sent * */ void -build_pdu ( hdr, type ) - Snmp_Header *hdr; - int type; +send_uptime_resp ( sd, reqid ) + int sd; + int reqid; { - 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; - } - } - - /* 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 ); + int len; + short *sp; + u_long *ip; + u_char *bp; + short val; + int ticks; - /* Continue with variable processing */ - } + COPY_RESP ( sysUpTime_Resp ); - /* 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 ); + bp = (u_char *)&Resp_Buf[Resp_Buf[0]+1]; + len = asn_encode_ticks ( &bp, &ticks ); - 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; - } - } + /* + * Adjust overall length + */ + bp = (u_char *)&Resp_Buf[0]; + *bp += len; - /* Accumulate total Variable sequence length */ - varlen += (len + 4); + /* + * 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 */ - /* Fill in length of this sequence */ - bpp[1] = len & 0xff; - bpp[0] = len >> 8; + /* + * 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 - var = var->next; + if ( Debug_Level > 1 && Log ) { + write_timestamp(); + fprintf ( Log, "\tSend sysUpTime: %d\n", ticks ); } - - /* 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 */ + 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 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; + /* + * Send response + */ + write ( sd, (caddr_t)&Resp_Buf[1], Resp_Buf[0] ); 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 */ } /* @@ -1410,7 +1221,11 @@ 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 @@ -1418,6 +1233,7 @@ set_reqid ( resp, reqid ) UM_COPY ( (caddr_t)&u.c[4-resp[17]], bp, resp[17] ); return; + } /* @@ -1433,77 +1249,24 @@ set_reqid ( resp, reqid ) * */ void -send_resp ( intf, Hdr, resp ) - int intf; - Snmp_Header *Hdr; +send_resp ( sd, reqid, resp ) + int sd; + int reqid; u_char *resp; { - int n; - if ( ilmi_fd[intf] > 0 ) { - n = write ( ilmi_fd[intf], (caddr_t)&resp[1], resp[0] ); - if ( Log && Debug_Level > 1 ) { + set_reqid ( resp, reqid ); + + if ( Debug_Level > 1 && Log ) { write_timestamp(); - 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] ); - } + fprintf ( Log, "===== Sent %d bytes =====\n", resp[0] ); + 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 * @@ -1522,7 +1285,7 @@ void init_ilmi() { struct air_cfg_rsp *cfg_info = NULL; - struct air_int_rsp *intf_info = NULL; + struct air_intf_rsp *intf_info = NULL; int buf_len; /* @@ -1536,6 +1299,10 @@ 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; } @@ -1547,8 +1314,12 @@ 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 */ - UM_FREE ( cfg_info ); + free ( cfg_info ); cfg_info = NULL; /* * Get the per interface information @@ -1567,7 +1338,7 @@ init_ilmi() */ UM_COPY ( intf_info, (caddr_t)Intf, buf_len ); /* Housecleaning */ - UM_FREE ( intf_info ); + free ( intf_info ); intf_info = NULL; return; @@ -1599,15 +1370,28 @@ 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 */ @@ -1616,11 +1400,16 @@ ilmi_open () sig_proto != ATM_SIG_UNI40 ) continue; - if ( ilmi_fd[unit] == -1 ) { + /* + * 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 ) { - ilmi_fd[unit] = socket ( AF_ATM, SOCK_SEQPACKET, ATM_PROTO_AAL5 ); + trap_fd[unit] = socket ( AF_ATM, SOCK_SEQPACKET, ATM_PROTO_AAL5 ); - if ( ilmi_fd[unit] < 0 ) { + if ( trap_fd[unit] < 0 ) { perror ( "open" ); continue; } @@ -1633,13 +1422,14 @@ ilmi_open () write_timestamp(); fprintf ( Log, "No nif on unit %d\n", unit ); } - close ( ilmi_fd[unit] ); + close ( trap_fd[unit] ); + trap_fd[unit] = -1; ilmi_fd[unit] = -1; continue; } - sprintf ( nifname, "%s0", Intf[unit].anp_nif_pref ); + sprintf ( nifname, "%s0\0", Intf[unit].anp_nif_pref ); optlen = sizeof ( nifname ); - if ( setsockopt ( ilmi_fd[unit], T_ATM_SIGNALING, + if ( setsockopt ( trap_fd[unit], T_ATM_SIGNALING, T_ATM_NET_INTF, (caddr_t)nifname, optlen ) < 0 ) { perror ( "setsockopt" ); if ( Log ) { @@ -1652,8 +1442,9 @@ ilmi_open () write_timestamp(); fprintf ( Log, "nifname: closing unit %d\n", unit ); } - close ( ilmi_fd[unit] ); - ilmi_fd[unit] = -1; + close ( trap_fd[unit] ); + trap_fd[unit] = -1; + ilmi_fd[unit] = -1; continue; } @@ -1662,9 +1453,9 @@ ilmi_open () */ UM_ZERO ( (caddr_t) &satm, sizeof(satm) ); satm.satm_family = AF_ATM; -#if (defined(BSD) && (BSD >= 199103)) +#ifndef sun satm.satm_len = sizeof(satm); -#endif +#endif /* sun */ 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; @@ -1690,14 +1481,15 @@ ilmi_open () aal5.backward_max_SDU_size = MAX_LEN; aal5.SSCS_type = T_ATM_NULL; optlen = sizeof(aal5); - if ( setsockopt ( ilmi_fd[unit], T_ATM_SIGNALING, T_ATM_AAL5, + if ( setsockopt ( trap_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 ( ilmi_fd[unit] ); + close ( trap_fd[unit] ); + trap_fd[unit] = -1; ilmi_fd[unit] = -1; continue; } @@ -1718,7 +1510,7 @@ ilmi_open () traffic.backward.tagging = T_NO; traffic.best_effort = T_YES; optlen = sizeof(traffic); - if (setsockopt(ilmi_fd[unit], T_ATM_SIGNALING, T_ATM_TRAFFIC, + if (setsockopt(trap_fd[unit], T_ATM_SIGNALING, T_ATM_TRAFFIC, (caddr_t)&traffic, optlen) < 0) { perror("setsockopt(traffic)"); } @@ -1728,7 +1520,7 @@ ilmi_open () bearer.clipping_susceptibility = T_NO; bearer.connection_configuration = T_ATM_1_TO_1; optlen = sizeof(bearer); - if (setsockopt(ilmi_fd[unit], T_ATM_SIGNALING, T_ATM_BEARER_CAP, + if (setsockopt(trap_fd[unit], T_ATM_SIGNALING, T_ATM_BEARER_CAP, (caddr_t)&bearer, optlen) < 0) { perror("setsockopt(bearer)"); } @@ -1737,7 +1529,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(ilmi_fd[unit], T_ATM_SIGNALING, T_ATM_QOS, (caddr_t)&qos, + if (setsockopt(trap_fd[unit], T_ATM_SIGNALING, T_ATM_QOS, (caddr_t)&qos, optlen) < 0) { perror("setsockopt(qos)"); } @@ -1745,14 +1537,14 @@ ilmi_open () subaddr.address_format = T_ATM_ABSENT; subaddr.address_length = 0; optlen = sizeof(subaddr); - if (setsockopt(ilmi_fd[unit], T_ATM_SIGNALING, T_ATM_DEST_SUB, + if (setsockopt(trap_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(ilmi_fd[unit], T_ATM_SIGNALING, T_ATM_APP_NAME, + if (setsockopt(trap_fd[unit], T_ATM_SIGNALING, T_ATM_APP_NAME, (caddr_t)&appname, optlen) < 0) { perror("setsockopt(appname)"); } @@ -1760,14 +1552,15 @@ ilmi_open () /* * Now try to connect to destination */ - if ( connect ( ilmi_fd[unit], (struct sockaddr *) &satm, + if ( connect ( trap_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 ( ilmi_fd[unit] ); + close ( trap_fd[unit] ); + trap_fd[unit] = -1; ilmi_fd[unit] = -1; continue; } @@ -1776,44 +1569,61 @@ ilmi_open () write_timestamp(); fprintf ( Log, "***** opened unit %d\n", unit ); } - - ilmi_state[unit] = ILMI_COLDSTART; - + /* + * 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] ); } } + signal ( SIGALRM, ilmi_open ); + alarm ( SLEEP_TIME ); + return; } /* - * Get our local IP address for this interface + * Send our local IP address for this interface * * Arguments: - * s - socket to find address for - * aval - pointer to variable to store address in + * s - socket to send message on + * hdr - pointer to internal SNMP header * * Returns: * none * */ void -get_local_ip ( s, aval ) - int s; - long *aval; +send_myipnm ( s, hdr ) + int s; + Snmp_Header *hdr; { - 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; - /* - * Get physical interface name - */ + COPY_RESP ( MyIpNm_Resp ); + if ( getsockopt ( s, T_ATM_SIGNALING, T_ATM_NET_INTF, - (caddr_t) intf_name, &namelen ) ) - return; + (caddr_t) intf_name, &namelen ) ) { + perror ( "Couldn't get socket name" ); + return; + } /* * Get network interface information for this physical interface @@ -1825,14 +1635,23 @@ get_local_ip ( s, aval ) sin = (struct sockaddr_in *)&net_info->anp_proto_addr; /* - * Fill in answer + * Copy interface's IP address into reply packet */ - UM_COPY ( (caddr_t)&sin->sin_addr.s_addr, aval, 4 ); + 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_FREE ( net_info ); + send_resp ( s, hdr->reqid, Resp_Buf ); + /* + * Clean up + */ + free ( net_info ); return; - } /* @@ -1853,29 +1672,40 @@ get_local_ip ( s, aval ) * */ void -set_prefix ( oid, hdr, intf ) +set_prefix ( oid, hdr, buf, s ) Objid *oid; Snmp_Header *hdr; - int intf; + u_char *buf; + int s; { - struct atmsetreq asr; - Atm_addr *aa; - int fd; - int i; + 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 ); /* * Build IOCTL request to set prefix */ asr.asr_opcode = AIOCS_SET_PRF; - strncpy ( asr.asr_prf_intf, Intf[intf].anp_intf, + strncpy ( asr.asr_prf_intf, Intf[0].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 @@ -1888,10 +1718,9 @@ set_prefix ( oid, hdr, intf ) syslog ( LOG_ERR, "ilmid: error setting prefix: %m" ); if ( Log ) { write_timestamp(); - fprintf ( Log, "errno %d setting prefix\n", + fprintf ( Log, "ilmid: errno %d setting prefix\n", errno ); } - close ( fd ); return; } } @@ -1902,58 +1731,375 @@ set_prefix ( oid, hdr, intf ) */ init_ilmi(); - aa = &Intf[intf].anp_addr; + aa = &Intf[0].anp_addr; /* - * Copy our NSAP into addressEntry table + * Finish building SET NSAP packet */ - addressEntry[intf].oid[0] = 0; + COPY_RESP ( NetPrefix_Resp ); + + len = Resp_Buf[0]; + cpp = &Resp_Buf[len + 1]; /* Set to end of response buffer */ + len++; + *cpp++ = aa->address_length; for ( i = 0; i < aa->address_length; i++ ) { - addressEntry[intf].oid[0]++; /* Increment length */ - addressEntry[intf].oid[i + 1] = (int)((u_char *)(aa->address))[i]; + u_char c = ((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 -set_address ( hdr, intf ) - Snmp_Header *hdr; - int intf; +send_no_such ( s, Hdr, op ) + int s; + Snmp_Header *Hdr; + Objid *op; { - 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 ); + 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; } /* @@ -1997,20 +2143,13 @@ Increment_DL ( sig ) int sig; { Debug_Level++; - if ( Debug_Level && Log == (FILE *)NULL ) { - if ( foregnd ) { - Log = stderr; - } else { - if ( ( Log = fopen ( LOG_FILE, "a" ) ) == NULL ) - Log = NULL; - } - if ( Log ) { + if ( Debug_Level && Log == (FILE *)NULL ) + if ( ( Log = fopen ( LOG_FILE, "a" ) ) == NULL ) + Log = NULL; + else setbuf ( Log, NULL ); - write_timestamp(); - fprintf ( Log, "Raised Debug_Level to %d\n", Debug_Level ); - } - } signal ( SIGUSR1, Increment_DL ); + alarm ( SLEEP_TIME ); return; } @@ -2034,388 +2173,37 @@ Decrement_DL ( sig ) if ( Debug_Level <= 0 ) { Debug_Level = 0; if ( Log ) { - write_timestamp(); - fprintf ( Log, "Lowered Debug_Level to %d\n", Debug_Level ); - if ( !foregnd ) - fclose ( Log ); + 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]) @@ -2460,10 +2248,34 @@ 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 ); @@ -2471,16 +2283,11 @@ main ( argc, argv ) /* * Open log file */ - if ( Debug_Level ) { - if ( foregnd ) { - Log = stderr; - } else { - if ( ( Log = fopen ( LOG_FILE, "a" ) ) == NULL ) - Log = NULL; - } - } - if ( Log ) - setbuf ( Log, NULL ); + if ( Debug_Level ) + if ( ( Log = fopen ( LOG_FILE, "a" ) ) == NULL ) + Log = NULL; + else + setbuf ( Log, NULL ); /* * Get our startup time @@ -2489,13 +2296,12 @@ 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; } /* @@ -2508,23 +2314,497 @@ main ( argc, argv ) */ if ( Reset ) { for ( i = 0; i < MAX_UNITS; i++ ) - 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 ( trap_fd[i] >= 0 ) { if ( Debug_Level > 1 && Log ) { write_timestamp(); - fprintf ( Log, "Close ilmi_fd[%d]: %d\n", - i, ilmi_fd[i] ); + fprintf ( Log, "Close trap_fd[%d]: %d\n", + i, trap_fd[i] ); } - close ( ilmi_fd[i] ); + close ( trap_fd[i] ); } exit ( 2 ); } - ilmi_do_state(); + /* + * 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; - exit(0); + } /* 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 */ + } |