summaryrefslogtreecommitdiffstats
path: root/sbin/atm/ilmid
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>1998-09-15 08:23:17 +0000
committerphk <phk@FreeBSD.org>1998-09-15 08:23:17 +0000
commitc3dd1fa899d435ea4bf79897f646a93cb80c94ac (patch)
tree98dfbc96e3c6aa7ff1f322855f6484c4e609819d /sbin/atm/ilmid
parent9ed6892f4808d56de443849229e151f8f7ad43b0 (diff)
downloadFreeBSD-src-c3dd1fa899d435ea4bf79897f646a93cb80c94ac.zip
FreeBSD-src-c3dd1fa899d435ea4bf79897f646a93cb80c94ac.tar.gz
Add new files for HARP3
Host ATM Research Platform (HARP), Network Computing Services, Inc. This software was developed with the support of the Defense Advanced Research Projects Agency (DARPA).
Diffstat (limited to 'sbin/atm/ilmid')
-rw-r--r--sbin/atm/ilmid/Makefile36
-rw-r--r--sbin/atm/ilmid/ilmid.8118
-rw-r--r--sbin/atm/ilmid/ilmid.c2810
3 files changed, 2964 insertions, 0 deletions
diff --git a/sbin/atm/ilmid/Makefile b/sbin/atm/ilmid/Makefile
new file mode 100644
index 0000000..b7ed852
--- /dev/null
+++ b/sbin/atm/ilmid/Makefile
@@ -0,0 +1,36 @@
+#
+#
+# ===================================
+# 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: Makefile,v 1.5 1998/07/10 16:01:58 jpt Exp $
+#
+#
+
+PROG= ilmid
+MAN8= ilmid.8
+
+CFLAGS+= -I ${.CURDIR}/../../../sys
+LDADD+= -latm
+
+.include <bsd.prog.mk>
diff --git a/sbin/atm/ilmid/ilmid.8 b/sbin/atm/ilmid/ilmid.8
new file mode 100644
index 0000000..e837adb
--- /dev/null
+++ b/sbin/atm/ilmid/ilmid.8
@@ -0,0 +1,118 @@
+.\"
+.\" ===================================
+.\" 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:$
+.\"
+.\"
+.de EX \"Begin example
+.ne 5
+.if n .sp 1
+.if t .sp .5
+.nf
+.in +.5i
+..
+.de EE
+.fi
+.in -.5i
+.if n .sp 1
+.if t .sp .5
+..
+.TH ILMID 8 "1998-09-14" "HARP"
+.SH NAME
+ilmid \- Simple ILMI ATM address registration daemon
+.SH SYNOPSIS
+.B ilmid
+[-d level]
+[-f]
+[-r]
+.sp
+.fi
+.SH DESCRIPTION
+.B ilmid
+is a HARP ATM daemon that performs the ILMI ATM address registration
+procedures with an ATM network switch. It is normally invoked at boot time
+from the ATM startup script.
+.fi
+.PP
+For each ATM interface with a UNI signalling manager attached,
+.B ilmid
+will open an ILMI PVC (VPI = 0, VCI = 16) and register the interface's
+ATM address with the switch. As part of the address registration procedure,
+the ATM switch will notify the endsystem (local host) of the
+"network prefix" portion of the endsystem's ATM address and
+.B ilmid
+will notify the switch of the endsystem's "user part" of its address
+(typically the interface card MAC address).
+.fi
+.SH OPTIONS
+.TP
+.B \-d level
+Specify the debug level for optional protocol tracing. Messages are
+written to /var/log/ilmid.
+.TP
+.B \-f
+Causes
+.B ilmid
+to run in the foregroud.
+.TP
+.B \-r
+Causes
+.B ilmid
+to issue a coldStart TRAP on all ATM interfaces it's able to open and exit.
+.fi
+.SH NOTES
+.PP
+This daemon does not fully conform to the ATM Forum ILMI specifications.
+In particular, it
+does not make any queries of the network side to ensure
+that the ATM Address table is empty.
+It also does not implement any
+of the ATM Forum MIB that is specified as part of ILMI.
+.fi
+.PP
+.B ilmid
+will increment the debug level when it receives a SIGUSR1 signal and will
+decrement the debug level when it receives a SIGUSR2 signal.
+.SH "SEE ALSO"
+.PP
+The ATM Forum, \fIATM User-Network Interface, Version 3.1 (UNI 3.1)
+Specification\fP for details on the ILMI protocols and address registration
+procedures.
+.fi
+.SH BUGS
+Please report any bugs to harp-bugs@magic.net.
+.fi
+.SH COPYRIGHT
+Copyright (c) 1994-1998, Network Computing Services, Inc.
+.fi
+.SH AUTHORS
+John Cavanaugh, Network Computing Services, Inc.
+.br
+Mike Spengler, Network Computing Services, Inc.
+.br
+Joseph Thomas, Network Computing Services, Inc.
+.fi
+.SH ACKNOWLEDGMENTS
+This software was developed with the support of the
+Defense Advanced Research Projects Agency (DARPA).
diff --git a/sbin/atm/ilmid/ilmid.c b/sbin/atm/ilmid/ilmid.c
new file mode 100644
index 0000000..e515a10
--- /dev/null
+++ b/sbin/atm/ilmid/ilmid.c
@@ -0,0 +1,2810 @@
+/*
+ *
+ * ===================================
+ * 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 */
+
+}
+
OpenPOWER on IntegriCloud