c3dd1fa899
Host ATM Research Platform (HARP), Network Computing Services, Inc. This software was developed with the support of the Defense Advanced Research Projects Agency (DARPA).
2811 lines
63 KiB
C
2811 lines
63 KiB
C
/*
|
|
*
|
|
* ===================================
|
|
* HARP | Host ATM Research Platform
|
|
* ===================================
|
|
*
|
|
*
|
|
* This Host ATM Research Platform ("HARP") file (the "Software") is
|
|
* made available by Network Computing Services, Inc. ("NetworkCS")
|
|
* "AS IS". NetworkCS does not provide maintenance, improvements or
|
|
* support of any kind.
|
|
*
|
|
* NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
|
|
* INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
* AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
|
|
* SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
|
|
* In no event shall NetworkCS be responsible for any damages, including
|
|
* but not limited to consequential damages, arising from or relating to
|
|
* any use of the Software or related support.
|
|
*
|
|
* Copyright 1994-1998 Network Computing Services, Inc.
|
|
*
|
|
* 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 $
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* User utilities
|
|
* --------------
|
|
*
|
|
* Implement very minimal ILMI address registration.
|
|
*
|
|
* Implement very crude and basic support for "cracking" and
|
|
* "encoding" SNMP PDU's to support ILMI prefix and NSAP address
|
|
* registration. Code is not robust nor is it meant to provide any
|
|
* "real" SNMP support. Much of the code expects predetermined values
|
|
* and will fail if anything else is found. Much of the "encoding" is
|
|
* done with pre-computed PDU's.
|
|
*
|
|
* See "The Simple Book", Marshall T. Rose, particularly chapter 5,
|
|
* for ASN and BER information.
|
|
*
|
|
*/
|
|
|
|
#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>
|
|
#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 <sys/socket.h>
|
|
#include <net/if.h>
|
|
#include <netinet/in.h>
|
|
|
|
#include <netatm/port.h>
|
|
#include <netatm/atm.h>
|
|
#include <netatm/atm_if.h>
|
|
#include <netatm/atm_sigmgr.h>
|
|
#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>
|
|
|
|
#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_OBJID 0x06
|
|
#define ASN_SEQUENCE 0x30
|
|
#define ASN_IPADDR 0x40
|
|
#define ASN_TIMESTAMP 0x43
|
|
|
|
/*
|
|
* Define SNMP PDU types
|
|
*/
|
|
#define PDU_TYPE_GET 0xA0
|
|
#define PDU_TYPE_GETNEXT 0xA1
|
|
#define PDU_TYPE_GETRESP 0xA2
|
|
#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;
|
|
|
|
/*
|
|
* Define our internal representation of an OBJECT IDENTIFIER
|
|
*/
|
|
struct objid {
|
|
int oid[128];
|
|
};
|
|
typedef struct objid Objid;
|
|
|
|
/*
|
|
* 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
|
|
*/
|
|
|
|
/*
|
|
* sysObjId reply
|
|
*/
|
|
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
|
|
};
|
|
|
|
/*
|
|
* sysUpTime: reply to a sysUpTime GET request
|
|
*/
|
|
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 */
|
|
};
|
|
|
|
/*
|
|
* coldStart TRAP to start the ILMI protocol
|
|
*/
|
|
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 */
|
|
};
|
|
|
|
/*
|
|
* 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 */
|
|
};
|
|
|
|
/*
|
|
* Reply to GET portIndex - we're always 1 + unit number
|
|
*/
|
|
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 */
|
|
};
|
|
|
|
/*
|
|
* 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_UNI30 2
|
|
#define UNIVER_UNI31 3
|
|
#define UNIVER_UNI40 4
|
|
|
|
/*
|
|
* 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) */
|
|
};
|
|
|
|
/*
|
|
* 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) */
|
|
};
|
|
|
|
/*
|
|
* Reply to GET foreSigGroup.* with noSuchError
|
|
*/
|
|
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 = 0;
|
|
|
|
/*
|
|
* Temporary buffer for building response packets. Should help ensure
|
|
* that we aren't accidently overwriting some other memory.
|
|
*/
|
|
u_char Resp_Buf[1024];
|
|
|
|
/*
|
|
* Copy the reponse into a buffer we can modify without
|
|
* changing the original...
|
|
*/
|
|
#define COPY_RESP(resp) \
|
|
UM_COPY ( (resp), Resp_Buf, (resp)[0] + 1 )
|
|
|
|
/*
|
|
* TRAP generic trap types
|
|
*/
|
|
char *Traps[] = { "coldStart", "warmStart", "linkDown", "linkUp",
|
|
"authenticationFailure", "egpNeighborLoss",
|
|
"enterpriseSpecific" };
|
|
|
|
|
|
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
|
|
*/
|
|
int trap_fd[MAX_UNITS];
|
|
/*
|
|
* fd for units which have seen a coldStart TRAP and are now exchaning SNMP requests
|
|
*/
|
|
int ilmi_fd[MAX_UNITS];
|
|
/*
|
|
* Local copy for HARP physical configuration information
|
|
*/
|
|
struct air_cfg_rsp Cfg[MAX_UNITS + 1];
|
|
/*
|
|
* Local copy for HARP interface configuration information
|
|
*/
|
|
struct air_int_rsp Intf[MAX_UNITS + 1];
|
|
|
|
/*
|
|
* When this daemon started
|
|
*/
|
|
struct timeval starttime;
|
|
|
|
int Debug_Level = 0;
|
|
|
|
char *progname;
|
|
char hostname[80];
|
|
|
|
/* File to write debug messages to */
|
|
#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 ) );
|
|
|
|
static char *Months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
|
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
|
|
|
/*
|
|
* Write a syslog() style timestamp
|
|
*
|
|
* Write a syslog() style timestamp with month, day, time and hostname
|
|
* to the log file.
|
|
*
|
|
* Arguments:
|
|
* none
|
|
*
|
|
* Returns:
|
|
* none
|
|
*
|
|
*/
|
|
void
|
|
write_timestamp()
|
|
{
|
|
time_t clock;
|
|
struct tm *tm;
|
|
|
|
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 );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/*
|
|
* Utility to pretty print buffer as hex dumps
|
|
*
|
|
* Arguments:
|
|
* bp - buffer pointer
|
|
* len - length to pretty print
|
|
*
|
|
* Returns:
|
|
* none
|
|
*
|
|
*/
|
|
void
|
|
hexdump ( bp, len )
|
|
u_char *bp;
|
|
int len;
|
|
{
|
|
int i, j;
|
|
|
|
/*
|
|
* Print as 4 groups of four bytes. Each byte seperated
|
|
* by space, each block of four seperated, and two blocks`
|
|
* of eight also seperated.
|
|
*/
|
|
for ( i = 0; i < len; i += 16 ) {
|
|
if ( Log )
|
|
write_timestamp();
|
|
for ( j = 0; j < 4 && j + i < len; j++ )
|
|
if ( Log )
|
|
fprintf ( Log, "%.2x ", *bp++ );
|
|
if ( Log )
|
|
fprintf ( Log, " " );
|
|
for ( ; j < 8 && j + i < len; j++ )
|
|
if ( Log )
|
|
fprintf ( Log, "%.2x ", *bp++ );
|
|
if ( Log )
|
|
fprintf ( Log, " " );
|
|
for ( ; j < 12 && j + i < len; j++ )
|
|
if ( Log )
|
|
fprintf ( Log, "%.2x ", *bp++ );
|
|
if ( Log )
|
|
fprintf ( Log, " " );
|
|
for ( ; j < 16 && j + i < len; j++ )
|
|
if ( Log )
|
|
fprintf ( Log, "%.2x ", *bp++ );
|
|
if ( Log )
|
|
fprintf ( Log, "\n" );
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/*
|
|
* Get lengths from PDU encodings
|
|
*
|
|
* Lengths are sometimes encoded as a single byte if the length
|
|
* is less the 127 but are more commonly encoded as one byte with
|
|
* the high bit set and the lower seven bits indicating the nuber
|
|
* of bytes which make up the length value. Trailing data is (to my
|
|
* knowledge) not 7-bit encoded.
|
|
*
|
|
* Arguments:
|
|
* bufp - pointer to buffer pointer
|
|
*
|
|
* Returns:
|
|
* bufp - updated buffer pointer
|
|
* <len> - decoded length
|
|
*
|
|
*/
|
|
int
|
|
asn_get_pdu_len ( bufp )
|
|
u_char **bufp;
|
|
{
|
|
u_char *bp = *bufp;
|
|
int len = 0;
|
|
int i, b;
|
|
|
|
b = *bp++;
|
|
if ( b & 0x80 ) {
|
|
for ( i = 0; i < (b & ~0x80); i++ )
|
|
len = len * 256 + *bp++;
|
|
} else
|
|
len = b;
|
|
|
|
*bufp = bp;
|
|
return ( len );
|
|
}
|
|
|
|
/*
|
|
* Get an 7-bit encoded value.
|
|
*
|
|
* Get a value which is represented using a 7-bit encoding. The last
|
|
* byte in the stream has the high-bit clear.
|
|
*
|
|
* Arguments:
|
|
* bufp - pointer to the buffer pointer
|
|
* len - pointer to the buffer length
|
|
*
|
|
* Returns:
|
|
* bufp - updated buffer pointer
|
|
* len - updated buffer length
|
|
* <val> - value encoding represented
|
|
*
|
|
*/
|
|
int
|
|
asn_get_encoded ( bufp, len )
|
|
u_char **bufp;
|
|
int *len;
|
|
{
|
|
u_char *bp = *bufp;
|
|
int val = 0;
|
|
int l = *len;
|
|
|
|
/*
|
|
* Keep going while high bit is set
|
|
*/
|
|
do {
|
|
/*
|
|
* Each byte can represent 7 bits
|
|
*/
|
|
val = ( val << 7 ) + ( *bp & ~0x80 );
|
|
l--;
|
|
} while ( *bp++ & 0x80 );
|
|
|
|
*bufp = bp; /* update buffer pointer */
|
|
*len = l; /* update buffer length */
|
|
|
|
return ( val );
|
|
}
|
|
|
|
/*
|
|
* Get a BER encoded integer
|
|
*
|
|
* Intergers are encoded as one byte length followed by <length> data bytes
|
|
*
|
|
* Arguments:
|
|
* bufp - pointer to the buffer pointer
|
|
*
|
|
* Returns:
|
|
* bufp - updated buffer pointer
|
|
* <val> - value of encoded integer
|
|
*
|
|
*/
|
|
int
|
|
asn_get_int ( bufp )
|
|
u_char **bufp;
|
|
{
|
|
int i;
|
|
int len;
|
|
int v = 0;
|
|
u_char *bp = *bufp;
|
|
|
|
len = *bp++;
|
|
for ( i = 0; i < len; i++ ) {
|
|
v = (v * 256) + *bp++;
|
|
}
|
|
*bufp = bp;
|
|
return ( v );
|
|
}
|
|
|
|
/*
|
|
* Utility to print a object identifier
|
|
*
|
|
* Arguments:
|
|
* objid - pointer to objid representation
|
|
*
|
|
* Returns:
|
|
* none
|
|
*
|
|
*/
|
|
void
|
|
print_objid ( objid )
|
|
Objid *objid;
|
|
{
|
|
int i;
|
|
|
|
/*
|
|
* First oid coded as 40 * X + Y
|
|
*/
|
|
if ( Log ) {
|
|
write_timestamp();
|
|
fprintf ( Log, ".%d.%d", objid->oid[1] / 40,
|
|
objid->oid[1] % 40 );
|
|
}
|
|
for ( i = 2; i <= objid->oid[0]; i++ )
|
|
if ( Log )
|
|
fprintf ( Log, ".%d", objid->oid[i] );
|
|
if ( Log )
|
|
fprintf ( Log, "\n" );
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Get Object Identifier
|
|
*
|
|
* Arguments:
|
|
* bufp - pointer to buffer pointer
|
|
* objid - pointer to objid buffer
|
|
*
|
|
* Returns:
|
|
* bufp - updated buffer pointer
|
|
* objid - internal representation of encoded objid
|
|
*
|
|
*/
|
|
void
|
|
asn_get_objid ( bufp, objid )
|
|
u_char **bufp;
|
|
Objid *objid;
|
|
{
|
|
int len;
|
|
u_char *bp = *bufp;
|
|
int *ip = (int *)objid + 1; /* First byte will contain length */
|
|
int oidlen = 0;
|
|
|
|
len = *bp++;
|
|
while ( len ) {
|
|
*ip++ = asn_get_encoded ( &bp, &len );
|
|
oidlen++;
|
|
}
|
|
objid->oid[0] = oidlen;
|
|
*bufp = bp;
|
|
|
|
if ( Debug_Level > 1 )
|
|
print_objid ( objid );
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Get OCTET STRING
|
|
*
|
|
* Octet strings are encoded as a 7-bit encoded length followed by <len>
|
|
* data bytes;
|
|
*
|
|
* Arguments:
|
|
* bufp - pointer to buffer pointer
|
|
* octet - pointer to octet buffer
|
|
*
|
|
* Returns:
|
|
* bufp - updated buffer pointer
|
|
* octet - encoded Octet String
|
|
*
|
|
*/
|
|
void
|
|
asn_get_octet ( bufp, octet )
|
|
u_char **bufp;
|
|
char *octet;
|
|
{
|
|
u_char *bp = *bufp;
|
|
int i = 0;
|
|
int len = 0;
|
|
|
|
/*
|
|
* &i is really a dummy value here as we don't keep track
|
|
* of the ongoing buffer length
|
|
*/
|
|
len = asn_get_encoded ( &bp, &i );
|
|
|
|
for ( i = 0; i < len; i++ )
|
|
*octet++ = *bp++;
|
|
|
|
*bufp = bp;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/*
|
|
* Utility to print SNMP PDU header information
|
|
*
|
|
* Arguments:
|
|
* Hdr - pointer to internal SNMP header structure
|
|
*
|
|
* Returns:
|
|
* none
|
|
*
|
|
*/
|
|
void
|
|
print_header ( Hdr )
|
|
Snmp_Header *Hdr;
|
|
{
|
|
if ( Log ) {
|
|
write_timestamp();
|
|
fprintf ( Log,
|
|
"Pdu len: %d Version: %d Community: \"%s\" Pdu Type: 0x%x\n",
|
|
Hdr->pdulen, Hdr->version + 1, Hdr->community,
|
|
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;
|
|
|
|
}
|
|
|
|
/*
|
|
* Crack the SNMP header
|
|
*
|
|
* Pull the PDU length, SNMP version, SNMP community and PDU type.
|
|
* If present, also pull out the Request ID, Error status, and Error
|
|
* index values.
|
|
*
|
|
* Arguments:
|
|
* bufp - pointer to buffer pointer
|
|
*
|
|
* Returns:
|
|
* bufp - updated buffer pointer
|
|
* - generated SNMP header
|
|
*
|
|
*/
|
|
Snmp_Header *
|
|
asn_get_header ( bufp )
|
|
u_char **bufp;
|
|
{
|
|
Snmp_Header *h;
|
|
u_char *bp = *bufp;
|
|
|
|
/*
|
|
* Allocate memory to hold the SNMP header
|
|
*/
|
|
if ( ( h = (Snmp_Header *)UM_ALLOC(sizeof(Snmp_Header)) ) == NULL )
|
|
return ( (Snmp_Header *)NULL );
|
|
|
|
/*
|
|
* PDU has to start as SEQUENCE OF
|
|
*/
|
|
if ( *bp++ != ASN_SEQUENCE ) /* Class == Universial, f == 1, tag == SEQUENCE */
|
|
return ( (Snmp_Header *)NULL );
|
|
|
|
/*
|
|
* Get the length of remaining PDU data
|
|
*/
|
|
h->pdulen = asn_get_pdu_len ( &bp );
|
|
|
|
/*
|
|
* We expect to find an integer encoding Version-1
|
|
*/
|
|
if ( *bp++ != ASN_INTEGER ) {
|
|
return ( (Snmp_Header *)NULL );
|
|
}
|
|
h->version = asn_get_int ( &bp );
|
|
|
|
/*
|
|
* After the version, we need the community name
|
|
*/
|
|
if ( *bp++ != ASN_OCTET ) {
|
|
return ( (Snmp_Header *)NULL );
|
|
}
|
|
UM_ZERO ( h->community, sizeof ( h->community ) );
|
|
asn_get_octet ( &bp, h->community );
|
|
|
|
/*
|
|
* Single byte PDU type
|
|
*/
|
|
h->pdutype = *bp++;
|
|
|
|
/*
|
|
* If this isn't a TRAP PDU, then look for the rest of the header
|
|
*/
|
|
if ( h->pdutype != PDU_TYPE_TRAP ) { /* TRAP uses different format */
|
|
|
|
bp++; /* Skip over data len */
|
|
|
|
/* Request ID */
|
|
if ( *bp++ != ASN_INTEGER ) {
|
|
return ( (Snmp_Header *)NULL );
|
|
}
|
|
h->reqid = asn_get_int ( &bp );
|
|
|
|
/* Error Status */
|
|
if ( *bp++ != ASN_INTEGER ) {
|
|
return ( (Snmp_Header *)NULL );
|
|
}
|
|
h->error = asn_get_int ( &bp );
|
|
|
|
/* Error Index */
|
|
if ( *bp++ != ASN_INTEGER ) {
|
|
return ( (Snmp_Header *)NULL );
|
|
}
|
|
h->erridx = asn_get_int ( &bp );
|
|
|
|
}
|
|
|
|
*bufp = bp;
|
|
|
|
if ( Debug_Level > 2 )
|
|
print_header ( h );
|
|
|
|
return ( h );
|
|
|
|
}
|
|
|
|
/*
|
|
* Compare to internal OID representations
|
|
*
|
|
* Arguments:
|
|
* oid1 - Internal Object Identifier
|
|
* oid2 - Internal Object Identifier
|
|
*
|
|
* Returns:
|
|
* 0 - Objid's match
|
|
* 1 - Objid's don't match
|
|
*
|
|
*/
|
|
int
|
|
oid_cmp ( oid1, oid2 )
|
|
Objid *oid1, *oid2;
|
|
{
|
|
int i;
|
|
|
|
/*
|
|
* Compare lengths
|
|
*/
|
|
if ( !(oid1->oid[0] == oid2->oid[0]) )
|
|
/* Different lengths */
|
|
return ( 1 );
|
|
|
|
/*
|
|
* value by value compare
|
|
*/
|
|
for ( i = 1; i <= oid1->oid[0]; i++ ) {
|
|
if ( !(oid1->oid[i] == oid2->oid[i]) )
|
|
/* values don't match */
|
|
return ( 1 );
|
|
}
|
|
|
|
/* Objid's are identical */
|
|
return ( 0 );
|
|
}
|
|
|
|
/*
|
|
* Encode a timeval as the number of time 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:
|
|
* bufp - pointer to buffer pointer
|
|
*
|
|
* Returns:
|
|
* bufp - updated buffper pointer
|
|
* len - number of bytes to encode time ticks value
|
|
* - ticks since 'starttime' encoded in buffer
|
|
*
|
|
*/
|
|
int
|
|
asn_encode_ticks ( bufp, ret )
|
|
u_char **bufp;
|
|
int *ret;
|
|
{
|
|
struct timeval timenow;
|
|
struct timeval timediff;
|
|
u_char *bp = *bufp;
|
|
int len, ticks;
|
|
|
|
(void) gettimeofday ( &timenow, NULL );
|
|
/*
|
|
* Adjust for subtraction
|
|
*/
|
|
timenow.tv_sec--;
|
|
timenow.tv_usec += 1000000;
|
|
|
|
/*
|
|
* Compute time since 'starttime'
|
|
*/
|
|
timediff.tv_sec = timenow.tv_sec - starttime.tv_sec;
|
|
timediff.tv_usec = timenow.tv_usec - starttime.tv_usec;
|
|
|
|
/*
|
|
* Adjust difference timeval
|
|
*/
|
|
if ( timediff.tv_usec > 1000000 ) {
|
|
timediff.tv_usec -= 1000000;
|
|
timediff.tv_sec++;
|
|
}
|
|
|
|
/*
|
|
* Compute 100th's of second in diff time structure
|
|
*/
|
|
*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 );
|
|
}
|
|
|
|
/*
|
|
* Send back up sysUpTime response
|
|
*
|
|
* Arguments:
|
|
* sd - socket descriptor to send reply on
|
|
* reqid - original GET request id
|
|
*
|
|
* Returns:
|
|
* none - response sent
|
|
*
|
|
*/
|
|
void
|
|
send_uptime_resp ( sd, reqid )
|
|
int sd;
|
|
int reqid;
|
|
{
|
|
int len;
|
|
short *sp;
|
|
u_long *ip;
|
|
u_char *bp;
|
|
short val;
|
|
int ticks;
|
|
|
|
COPY_RESP ( sysUpTime_Resp );
|
|
|
|
bp = (u_char *)&Resp_Buf[Resp_Buf[0]+1];
|
|
len = asn_encode_ticks ( &bp, &ticks );
|
|
|
|
/*
|
|
* Adjust overall length
|
|
*/
|
|
bp = (u_char *)&Resp_Buf[0];
|
|
*bp += len;
|
|
|
|
/*
|
|
* 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 */
|
|
|
|
/*
|
|
* 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
|
|
|
|
if ( Debug_Level > 1 && Log ) {
|
|
write_timestamp();
|
|
fprintf ( Log, "\tSend sysUpTime: %d\n", ticks );
|
|
}
|
|
|
|
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] );
|
|
}
|
|
/*
|
|
* Send response
|
|
*/
|
|
write ( sd, (caddr_t)&Resp_Buf[1], Resp_Buf[0] );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/*
|
|
* Set Request ID in PDU
|
|
*
|
|
* Arguments:
|
|
* resp - Response PDU buffer
|
|
* reqid - request id value
|
|
*
|
|
* Returns:
|
|
* none - request id may/may not be set
|
|
*
|
|
*/
|
|
void
|
|
set_reqid ( resp, reqid )
|
|
u_char *resp;
|
|
int reqid;
|
|
{
|
|
u_char *bp = (u_char *)&resp[18];
|
|
union {
|
|
int i;
|
|
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
|
|
*/
|
|
UM_COPY ( (caddr_t)&u.c[4-resp[17]], bp, resp[17] );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/*
|
|
* Send a generic response packet
|
|
*
|
|
* Arguments:
|
|
* sd - socket to send the reply on
|
|
* reqid - original request ID from GET PDU
|
|
* resp - pointer to the response to send
|
|
*
|
|
* Returns:
|
|
* none - response sent
|
|
*
|
|
*/
|
|
void
|
|
send_resp ( sd, reqid, resp )
|
|
int sd;
|
|
int reqid;
|
|
u_char *resp;
|
|
{
|
|
|
|
set_reqid ( resp, reqid );
|
|
|
|
if ( Debug_Level > 1 && Log ) {
|
|
write_timestamp();
|
|
fprintf ( Log, "===== Sent %d bytes =====\n", resp[0] );
|
|
hexdump ( (u_char *)&resp[1], resp[0] );
|
|
}
|
|
write ( sd, (caddr_t)&resp[1], resp[0] );
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Initialize information on what physical adapters HARP knows about
|
|
*
|
|
* Query the HARP subsystem about configuration and physical interface
|
|
* information for any currently registered ATM adapters. Store the information
|
|
* as arrays for easier indexing by SNMP port/index numbers.
|
|
*
|
|
* Arguments:
|
|
* none
|
|
*
|
|
* Returns:
|
|
* none Information from HARP available
|
|
*
|
|
*/
|
|
void
|
|
init_ilmi()
|
|
{
|
|
struct air_cfg_rsp *cfg_info = NULL;
|
|
struct air_intf_rsp *intf_info = NULL;
|
|
int buf_len;
|
|
|
|
/*
|
|
* Get configuration info - what's available with 'atm sh config'
|
|
*/
|
|
buf_len = get_cfg_info ( NULL, &cfg_info );
|
|
/*
|
|
* If error occurred, clear out everything
|
|
*/
|
|
if ( buf_len <= 0 ) {
|
|
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;
|
|
}
|
|
|
|
/*
|
|
* Move to local storage
|
|
*/
|
|
UM_COPY ( cfg_info, (caddr_t)Cfg, buf_len );
|
|
/*
|
|
* 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 );
|
|
cfg_info = NULL;
|
|
/*
|
|
* Get the per interface information
|
|
*/
|
|
buf_len = get_intf_info ( NULL, &intf_info );
|
|
/*
|
|
* If error occurred, clear out Intf info
|
|
*/
|
|
if ( buf_len <= 0 ) {
|
|
UM_ZERO ( Intf, sizeof(Intf) );
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Move to local storage
|
|
*/
|
|
UM_COPY ( intf_info, (caddr_t)Intf, buf_len );
|
|
/* Housecleaning */
|
|
free ( intf_info );
|
|
intf_info = NULL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/*
|
|
* Open a new SNMP session for ILMI
|
|
*
|
|
* Start by updating interface information, in particular, how many
|
|
* interfaces are in the system. While we'll try to open sessons on
|
|
* all interfaces, this deamon currently can only handle the first
|
|
* interface.
|
|
*
|
|
* Arguments:
|
|
* none
|
|
*
|
|
* Returns:
|
|
* none
|
|
*
|
|
*/
|
|
void
|
|
ilmi_open ()
|
|
{
|
|
struct sockaddr_atm satm;
|
|
struct t_atm_aal5 aal5;
|
|
struct t_atm_traffic traffic;
|
|
struct t_atm_bearer bearer;
|
|
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
|
|
*/
|
|
sig_proto = Intf[unit].anp_sig_proto;
|
|
if ( sig_proto != ATM_SIG_UNI30 && sig_proto != ATM_SIG_UNI31 &&
|
|
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 ) {
|
|
|
|
trap_fd[unit] = socket ( AF_ATM, SOCK_SEQPACKET, ATM_PROTO_AAL5 );
|
|
|
|
if ( trap_fd[unit] < 0 ) {
|
|
perror ( "open" );
|
|
continue;
|
|
}
|
|
|
|
/*
|
|
* Set interface name. For now, we must have a netif to go on...
|
|
*/
|
|
if ( Intf[unit].anp_nif_cnt == 0 ) {
|
|
if ( Debug_Level > 1 && Log ) {
|
|
write_timestamp();
|
|
fprintf ( Log, "No nif on unit %d\n", unit );
|
|
}
|
|
close ( trap_fd[unit] );
|
|
trap_fd[unit] = -1;
|
|
ilmi_fd[unit] = -1;
|
|
continue;
|
|
}
|
|
sprintf ( nifname, "%s0\0", Intf[unit].anp_nif_pref );
|
|
optlen = sizeof ( nifname );
|
|
if ( setsockopt ( trap_fd[unit], T_ATM_SIGNALING,
|
|
T_ATM_NET_INTF, (caddr_t)nifname, optlen ) < 0 ) {
|
|
perror ( "setsockopt" );
|
|
if ( Log ) {
|
|
write_timestamp();
|
|
fprintf ( Log,
|
|
"Couldn't set interface name \"%s\"\n",
|
|
nifname );
|
|
}
|
|
if ( Debug_Level > 1 && Log ) {
|
|
write_timestamp();
|
|
fprintf ( Log, "nifname: closing unit %d\n", unit );
|
|
}
|
|
close ( trap_fd[unit] );
|
|
trap_fd[unit] = -1;
|
|
ilmi_fd[unit] = -1;
|
|
continue;
|
|
}
|
|
|
|
/*
|
|
* Set up destination SAP
|
|
*/
|
|
UM_ZERO ( (caddr_t) &satm, sizeof(satm) );
|
|
satm.satm_family = AF_ATM;
|
|
#ifndef sun
|
|
satm.satm_len = sizeof(satm);
|
|
#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;
|
|
satm.satm_addr.t_atm_sap_addr.address_format = T_ATM_PVC_ADDR;
|
|
satm.satm_addr.t_atm_sap_addr.address_length = sizeof(Atm_addr_pvc);
|
|
ATM_PVC_SET_VPI((Atm_addr_pvc *)satm.satm_addr.t_atm_sap_addr.address,
|
|
0 );
|
|
ATM_PVC_SET_VCI((Atm_addr_pvc *)satm.satm_addr.t_atm_sap_addr.address,
|
|
16 );
|
|
|
|
satm.satm_addr.t_atm_sap_layer2.SVE_tag = T_ATM_PRESENT;
|
|
satm.satm_addr.t_atm_sap_layer2.ID_type = T_ATM_SIMPLE_ID;
|
|
satm.satm_addr.t_atm_sap_layer2.ID.simple_ID = T_ATM_BLLI2_I8802;
|
|
|
|
satm.satm_addr.t_atm_sap_layer3.SVE_tag = T_ATM_ABSENT;
|
|
|
|
satm.satm_addr.t_atm_sap_appl.SVE_tag = T_ATM_ABSENT;
|
|
|
|
/*
|
|
* Set up connection parameters
|
|
*/
|
|
aal5.forward_max_SDU_size = MAX_LEN;
|
|
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,
|
|
(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;
|
|
ilmi_fd[unit] = -1;
|
|
continue;
|
|
}
|
|
|
|
traffic.forward.PCR_high_priority = T_ATM_ABSENT;
|
|
traffic.forward.PCR_all_traffic = 100000;
|
|
traffic.forward.SCR_high_priority = T_ATM_ABSENT;
|
|
traffic.forward.SCR_all_traffic = T_ATM_ABSENT;
|
|
traffic.forward.MBS_high_priority = T_ATM_ABSENT;
|
|
traffic.forward.MBS_all_traffic = T_ATM_ABSENT;
|
|
traffic.forward.tagging = T_NO;
|
|
traffic.backward.PCR_high_priority = T_ATM_ABSENT;
|
|
traffic.backward.PCR_all_traffic = 100000;
|
|
traffic.backward.SCR_high_priority = T_ATM_ABSENT;
|
|
traffic.backward.SCR_all_traffic = T_ATM_ABSENT;
|
|
traffic.backward.MBS_high_priority = T_ATM_ABSENT;
|
|
traffic.backward.MBS_all_traffic = T_ATM_ABSENT;
|
|
traffic.backward.tagging = T_NO;
|
|
traffic.best_effort = T_YES;
|
|
optlen = sizeof(traffic);
|
|
if (setsockopt(trap_fd[unit], T_ATM_SIGNALING, T_ATM_TRAFFIC,
|
|
(caddr_t)&traffic, optlen) < 0) {
|
|
perror("setsockopt(traffic)");
|
|
}
|
|
bearer.bearer_class = T_ATM_CLASS_X;
|
|
bearer.traffic_type = T_ATM_NULL;
|
|
bearer.timing_requirements = T_ATM_NULL;
|
|
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,
|
|
(caddr_t)&bearer, optlen) < 0) {
|
|
perror("setsockopt(bearer)");
|
|
}
|
|
|
|
qos.coding_standard = T_ATM_NETWORK_CODING;
|
|
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,
|
|
optlen) < 0) {
|
|
perror("setsockopt(qos)");
|
|
}
|
|
|
|
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,
|
|
(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,
|
|
(caddr_t)&appname, optlen) < 0) {
|
|
perror("setsockopt(appname)");
|
|
}
|
|
|
|
/*
|
|
* Now try to connect to destination
|
|
*/
|
|
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 ( trap_fd[unit] );
|
|
trap_fd[unit] = -1;
|
|
ilmi_fd[unit] = -1;
|
|
continue;
|
|
}
|
|
|
|
if ( Debug_Level && Log ) {
|
|
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] );
|
|
}
|
|
|
|
}
|
|
|
|
signal ( SIGALRM, ilmi_open );
|
|
alarm ( SLEEP_TIME );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/*
|
|
* Send our local IP address for this interface
|
|
*
|
|
* Arguments:
|
|
* s - socket to send message on
|
|
* hdr - pointer to internal SNMP header
|
|
*
|
|
* Returns:
|
|
* none
|
|
*
|
|
*/
|
|
void
|
|
send_myipnm ( s, hdr )
|
|
int s;
|
|
Snmp_Header *hdr;
|
|
{
|
|
char intf_name[IFNAMSIZ];
|
|
int namelen = IFNAMSIZ;
|
|
struct air_netif_rsp *net_info = NULL;
|
|
struct sockaddr_in *sin;
|
|
|
|
COPY_RESP ( MyIpNm_Resp );
|
|
|
|
if ( getsockopt ( s, T_ATM_SIGNALING, T_ATM_NET_INTF,
|
|
(caddr_t) intf_name, &namelen ) ) {
|
|
perror ( "Couldn't get socket name" );
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Get network interface information for this physical interface
|
|
*/
|
|
get_netif_info ( intf_name, &net_info );
|
|
if ( net_info == NULL )
|
|
return;
|
|
|
|
sin = (struct sockaddr_in *)&net_info->anp_proto_addr;
|
|
|
|
/*
|
|
* Copy interface's IP address into reply packet
|
|
*/
|
|
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" );
|
|
}
|
|
|
|
send_resp ( s, hdr->reqid, Resp_Buf );
|
|
|
|
/*
|
|
* Clean up
|
|
*/
|
|
free ( net_info );
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Set local NSAP prefix and then reply with our full NSAP address.
|
|
*
|
|
* Switch will send a SET message with the NSAP prefix after a coldStart.
|
|
* We'll set that prefix into HARP and then send a SET message of our own
|
|
* with our full interface NSAP address.
|
|
*
|
|
* Arguments:
|
|
* oid - objid from SET message
|
|
* hdr - pointer to internal SNMP header
|
|
* buf - pointer to SET buffer
|
|
* s - socket to send messages on
|
|
*
|
|
* Returns:
|
|
* none
|
|
*
|
|
*/
|
|
void
|
|
set_prefix ( oid, hdr, buf, s )
|
|
Objid *oid;
|
|
Snmp_Header *hdr;
|
|
u_char *buf;
|
|
int s;
|
|
{
|
|
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[0].anp_intf,
|
|
sizeof(asr.asr_prf_intf ) );
|
|
/*
|
|
* Pull prefix out of received Objid
|
|
*/
|
|
for ( i = 0; i < oid->oid[13]; i++ )
|
|
asr.asr_prf_pref[i] = oid->oid[i + 14];
|
|
|
|
/*
|
|
* Pass new prefix to the HARP kernel
|
|
*/
|
|
fd = socket ( AF_ATM, SOCK_DGRAM, 0 );
|
|
if ( fd < 0 )
|
|
return;
|
|
if ( ioctl ( fd, AIOCSET, (caddr_t)&asr ) < 0 ) {
|
|
if ( errno != EALREADY ) {
|
|
syslog ( LOG_ERR, "ilmid: error setting prefix: %m" );
|
|
if ( Log ) {
|
|
write_timestamp();
|
|
fprintf ( Log, "ilmid: errno %d setting prefix\n",
|
|
errno );
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
close ( fd );
|
|
|
|
/*
|
|
* Reload the cfg/intf info with newly set prefix
|
|
*/
|
|
init_ilmi();
|
|
|
|
aa = &Intf[0].anp_addr;
|
|
|
|
/*
|
|
* Finish building SET NSAP packet
|
|
*/
|
|
|
|
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++ ) {
|
|
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
|
|
send_no_such ( s, Hdr, op )
|
|
int s;
|
|
Snmp_Header *Hdr;
|
|
Objid *op;
|
|
{
|
|
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;
|
|
}
|
|
|
|
/*
|
|
* Utility to strip off any leading path information from a filename
|
|
*
|
|
* Arguments:
|
|
* path pathname to strip
|
|
*
|
|
* Returns:
|
|
* fname striped filename
|
|
*
|
|
*/
|
|
char *
|
|
basename ( path )
|
|
char *path;
|
|
{
|
|
char *fname;
|
|
|
|
if ( ( fname = (char *)strrchr ( path, '/' ) ) != NULL )
|
|
fname++;
|
|
else
|
|
fname = path;
|
|
|
|
return ( fname );
|
|
}
|
|
|
|
/*
|
|
* Increment Debug Level
|
|
*
|
|
* Catches SIGUSR1 signal and increments value of Debug_Level
|
|
*
|
|
* Arguments:
|
|
* sig - signal number
|
|
*
|
|
* Returns:
|
|
* none - Debug_Level incremented
|
|
*
|
|
*/
|
|
void
|
|
Increment_DL ( sig )
|
|
int sig;
|
|
{
|
|
Debug_Level++;
|
|
if ( Debug_Level && Log == (FILE *)NULL )
|
|
if ( ( Log = fopen ( LOG_FILE, "a" ) ) == NULL )
|
|
Log = NULL;
|
|
else
|
|
setbuf ( Log, NULL );
|
|
signal ( SIGUSR1, Increment_DL );
|
|
alarm ( SLEEP_TIME );
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Decrement Debug Level
|
|
*
|
|
* Catches SIGUSR2 signal and decrements value of Debug_Level
|
|
*
|
|
* Arguments:
|
|
* sig - signal number
|
|
*
|
|
* Returns:
|
|
* none - Debug_Level decremented
|
|
*
|
|
*/
|
|
void
|
|
Decrement_DL ( sig )
|
|
int sig;
|
|
{
|
|
Debug_Level--;
|
|
if ( Debug_Level <= 0 ) {
|
|
Debug_Level = 0;
|
|
if ( Log ) {
|
|
fclose ( Log );
|
|
Log = NULL;
|
|
}
|
|
}
|
|
signal ( SIGUSR2, Decrement_DL );
|
|
alarm ( SLEEP_TIME );
|
|
return;
|
|
}
|
|
|
|
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])
|
|
*/
|
|
progname = strdup ( (char *)basename ( argv[0] ) );
|
|
/*
|
|
* What host are we
|
|
*/
|
|
gethostname ( hostname, sizeof ( hostname ) );
|
|
|
|
/*
|
|
* Ilmid needs to run as root to set prefix
|
|
*/
|
|
if ( getuid() != 0 ) {
|
|
fprintf ( stderr, "%s: needs to run as root.\n", progname );
|
|
exit ( -1 );
|
|
}
|
|
|
|
/*
|
|
* Parse arguments
|
|
*/
|
|
while ( ( c = getopt ( argc, argv, "d:fr" ) ) != EOF )
|
|
switch ( c ) {
|
|
case 'd':
|
|
Debug_Level = atoi ( optarg );
|
|
break;
|
|
case 'f':
|
|
foregnd++;
|
|
break;
|
|
case 'r':
|
|
Reset++;
|
|
break;
|
|
case '?':
|
|
fprintf ( stderr, "usage: %s [-d level] [-f] [-r]\n",
|
|
progname );
|
|
exit ( -1 );
|
|
/* NOTREACHED */
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* 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 );
|
|
|
|
signal ( SIGUSR1, Increment_DL );
|
|
signal ( SIGUSR2, Decrement_DL );
|
|
|
|
/*
|
|
* Open log file
|
|
*/
|
|
if ( Debug_Level )
|
|
if ( ( Log = fopen ( LOG_FILE, "a" ) ) == NULL )
|
|
Log = NULL;
|
|
else
|
|
setbuf ( Log, NULL );
|
|
|
|
/*
|
|
* Get our startup time
|
|
*/
|
|
(void) gettimeofday ( &starttime, NULL );
|
|
starttime.tv_sec--;
|
|
starttime.tv_usec += 1000000;
|
|
|
|
/*
|
|
* 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;
|
|
}
|
|
/*
|
|
* Try to open all the interfaces
|
|
*/
|
|
ilmi_open ();
|
|
|
|
/*
|
|
* If we're just sending a coldStart end exiting...
|
|
*/
|
|
if ( Reset ) {
|
|
for ( i = 0; i < MAX_UNITS; i++ )
|
|
if ( trap_fd[i] >= 0 ) {
|
|
if ( Debug_Level > 1 && Log ) {
|
|
write_timestamp();
|
|
fprintf ( Log, "Close trap_fd[%d]: %d\n",
|
|
i, trap_fd[i] );
|
|
}
|
|
close ( trap_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;
|
|
|
|
} /* 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 */
|
|
|
|
}
|
|
|