summaryrefslogtreecommitdiffstats
path: root/sbin/atm
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
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')
-rw-r--r--sbin/atm/Makefile33
-rw-r--r--sbin/atm/Makefile.inc30
-rw-r--r--sbin/atm/atm/Makefile38
-rw-r--r--sbin/atm/atm/atm.8984
-rw-r--r--sbin/atm/atm/atm.c1072
-rw-r--r--sbin/atm/atm/atm.h212
-rw-r--r--sbin/atm/atm/atm_eni.c437
-rw-r--r--sbin/atm/atm/atm_fore200.c603
-rw-r--r--sbin/atm/atm/atm_inet.c164
-rw-r--r--sbin/atm/atm/atm_print.c904
-rw-r--r--sbin/atm/atm/atm_set.c540
-rw-r--r--sbin/atm/atm/atm_show.c1187
-rw-r--r--sbin/atm/atm/atm_subr.c620
-rw-r--r--sbin/atm/fore_dnld/Makefile36
-rw-r--r--sbin/atm/fore_dnld/fore_dnld.8108
-rw-r--r--sbin/atm/fore_dnld/fore_dnld.c1245
-rw-r--r--sbin/atm/ilmid/Makefile36
-rw-r--r--sbin/atm/ilmid/ilmid.8118
-rw-r--r--sbin/atm/ilmid/ilmid.c2810
19 files changed, 11177 insertions, 0 deletions
diff --git a/sbin/atm/Makefile b/sbin/atm/Makefile
new file mode 100644
index 0000000..481f216
--- /dev/null
+++ b/sbin/atm/Makefile
@@ -0,0 +1,33 @@
+#
+#
+# ===================================
+# 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 $
+#
+
+SUBDIR= atm \
+ fore_dnld \
+ ilmid
+
+.include <bsd.subdir.mk>
diff --git a/sbin/atm/Makefile.inc b/sbin/atm/Makefile.inc
new file mode 100644
index 0000000..2bf6722
--- /dev/null
+++ b/sbin/atm/Makefile.inc
@@ -0,0 +1,30 @@
+#
+#
+# ===================================
+# 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.inc,v 1.5 1998/07/10 16:01:58 jpt Exp $
+#
+#
+
+.include "${.CURDIR}/../../Makefile.inc"
diff --git a/sbin/atm/atm/Makefile b/sbin/atm/atm/Makefile
new file mode 100644
index 0000000..18c02db
--- /dev/null
+++ b/sbin/atm/atm/Makefile
@@ -0,0 +1,38 @@
+#
+#
+# ===================================
+# 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= atm
+SRCS= atm.c atm_fore200.c atm_eni.c atm_inet.c atm_print.c \
+ atm_set.c atm_show.c atm_subr.c
+MAN8= atm.8
+
+CFLAGS+= -I ${.CURDIR}/../../../sys
+LDADD+= -latm
+
+.include <bsd.prog.mk>
diff --git a/sbin/atm/atm/atm.8 b/sbin/atm/atm/atm.8
new file mode 100644
index 0000000..51b39f9
--- /dev/null
+++ b/sbin/atm/atm/atm.8
@@ -0,0 +1,984 @@
+.\"
+.\" ===================================
+.\" 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: atm.1,v 1.4 1998/08/26 21:38:28 johnc Exp $
+.\"
+.\"
+.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 ATM 8 "1998-08-20" "HARP"
+.SH NAME
+atm \- user configuration and display command for HARP ATM interface
+.SH SYNOPSIS
+Interface management subcommands:
+.in +10
+.ti -5
+.B atm attach
+<interface> <sigmgr>
+.ti -5
+.B atm detach
+<interface>
+.ti -5
+.B atm set MAC
+<interface> <MAC/ESI address>
+.ti -5
+.B atm set netif
+<interface> <prefix> <count>
+.ti -5
+.B atm set prefix
+<interface> <NSAP prefix>
+.ti -5
+.B atm show config
+[<interface>]
+.ti -5
+.B atm show interface
+[<interface>]
+.ti -5
+.B atm show netif
+[<netif>]
+.ti -5
+.B atm show stats interface
+[<interface> [phy | dev | atm | aal0 | aal4 | aal5 | driver]]
+.sp
+.ti -10
+VCC management subcommands:
+.ti -5
+.B atm add PVC
+<interface> <vpi> <vci> <aal> <encaps> <owner> ...
+.ti -5
+.B atm delete PVC
+<interface> <vpi> <vci>
+.ti -5
+.B atm delete SVC
+<interface> <vpi> <vci>
+.ti -5
+.B atm show stats VCC
+[<interface> [<vpi> [<vci>]]]
+.ti -5
+.B atm show VCC
+[<interface> [<vpi> [<vci>] | SVC | PVC]]
+.sp
+.ti -10
+IP management subcommands:
+.ti -5
+.B atm add ARP
+[<netif>] <host> <ATM address>
+.ti -5
+.B atm add PVC
+<interface> <vpi> <vci> <aal> <encaps> IP <netif> <host> | dynamic
+.ti -5
+.B atm delete ARP
+[<netif>] <host>
+.ti -5
+.B atm set arpserver
+<netif> <ATM address> | local [<IP prefix> ...]
+.ti -5
+.B atm show ARP
+[<host>]
+.ti -5
+.B atm show arpserver
+[<netif>]
+.ti -5
+.B atm show IPVCC
+[<host> | <netif>]
+.ti -5
+.sp
+.ti -10
+Miscellaneous subcommands:
+.ti -5
+.B atm help
+.ti -5
+.B atm show version
+.in -10
+.fi
+.SH DESCRIPTION
+.I atm
+configures and displays the status of the Host ATM Research Platform
+(HARP) networking software.
+The subcommands fall into several categories:
+.PP
+\fIInterface management\fP subcommands allow manipulation of the
+ATM interface.
+Functions include assigning a signalling manager to an interface,
+setting the ATM address, associating network interfaces with
+an interface, and displaying information about interfaces.
+.PP
+\fIVCC management\fP subcommands allow for managing ATM virtual
+channel connections (VCCs).
+Functions include opening and closing VCCs and displaying information
+about them.
+.PP
+\fIIP management\fP subcommands allow for managing the interface
+between IP and the ATM software.
+Functions include displaying and manipulating the ATMARP cache,
+opening a PVC connected to IP,
+assigning an ATMARP server to a network interface,
+and displaying information about IP VCCs.
+.PP
+\fIMiscellaneous\fP subcommands allow for displaying the version
+of the ATM software and for getting help with the \fIatm\fP command.
+.SS "Signalling Managers"
+The signalling manager is responsible for the opening and closing of
+VCCs.
+Four signalling managers are supported:
+.PP
+.in +10
+.ti -5
+PVC - for PVCs only,
+.ti -5
+SPANS - supports SPANS, FORE's proprietary signalling protocol,
+.ti -5
+UNI 3.0 - supports the signalling protocol from The ATM Forum's
+\fIATM User-Network Interface Specification, Version 3.0\fP.
+.ti -5
+UNI 3.1 - supports the signalling protocol from The ATM Forum's
+\fIATM User-Network Interface Specification, Version 3.1\fP.
+.in -10
+.PP
+All four signalling managers support the opening and closing of PVCs
+(see the \fIadd\fP and \fIdelete\fP subcommands).
+.PP
+A signalling manager must be attached to a physical interface
+(see the \fIattach\fP subcommand)
+before any VCCs can be created on the interface.
+.SS "Physical and Network Interfaces"
+Two types of interfaces are supported:
+physical interfaces and network interfaces.
+A physical interface represents a physical point of attachment to an
+ATM network.
+A physical interface has an ATM address associated with it.
+.PP
+A network interface is a logical interface.
+One or more network interfaces are associated with a physical
+interface; each network interface has an IP address associated with it.
+For interfaces controlled by the SPANS or PVC signalling managers,
+there must be one and
+only one network interface associated with each physical interface.
+For UNI-controlled interfaces, there can be up to 256 network
+interfaces associated with a physical interface.
+In this case, the correspondence between the network interface and
+the ATM address is determined by the selector field (the last
+byte) of the physical interface's ATM address.
+.SS "Keyword and Documentation Conventions"
+Command and subcommand keywords can be abbreviated by simply giving
+enough of the first part of the keyword to make it unique.
+Thus, \fIatm sh v\fB gives the same result as \fIatm show vcc\fB.
+.PP
+All keywords are case-insensitive.
+.PP
+Where a host address needs to be given to the \fIatm\fP command,
+either a DNS name or an IP address in dotted decimal format can
+be used.
+.PP
+ATM addresses are specified as strings of hex digits, with an
+optional leading "0x".
+Fields within the address may be separated by periods, but periods
+are for readability only and are ignored.
+SPANS addresses are 8 bytes long, while NSAP-format addresses
+are 20 bytes long.
+The full address, including any leading zeroes, must be given.
+For example:
+.in +5
+0x47.0005.80.ffe100.0000.f21a.0170.0020481a0170.00 (NSAP format)
+.br
+0x00000010.f2050aa9 (SPANS format)
+.in -5
+.fi
+.SH SUBCOMMANDS
+.SS Interface Management Subcommands:
+.in +5
+.ti -5
+\fIatm add PVC <interface> <vpi> <vci> <aal> <encaps> <owner> ...\fP
+.in -5
+.PP
+the format of the \fIadd PVC\fP subcommand varies depending on the
+owner of the PVC.
+See the description under "IP Management Subcommands."
+.PP
+\fIatm attach <interface> <sigmgr>\fP
+.PP
+where:
+.in +10
+.ti -5
+\fI<interface>\fP specifies the physical interface to which the
+signalling manager is to be attached,
+.ti -5
+\fI<sigmgr>\fP specifies which signalling manager is to be attached.
+Valid choices are "SIGPVC", "SPANS", "UNI30", and "UNI31".
+.in -10
+.PP
+This command attaches a signalling manager to an interface.
+Until this is done, VCCs cannot be opened or closed.
+Only one signalling manager at a time can be attached to an interface.
+.PP
+\fIatm detach <interface>\fP
+.PP
+where:
+.in +10
+.ti -5
+\fI<interface>\fP specifies the physical interface whose signalling
+manager is to be detached.
+.in -10
+.PP
+This command detaches a signalling manager from an interface.
+All VCCs that the signalling manager has created will be closed,
+and no new VCCs can be created until a signalling manager (either
+the same or a different one) is attached again.
+.PP
+\fIatm set MAC <interface> <MAC/ESI address>\fP
+.PP
+where:
+.in +10
+.ti -5
+\fI<interface>\fP specifies the physical interface whose
+MAC address is to be set,
+.ti -5
+\fI<MAC/ESI address>\fP specifies the 6-byte MAC part of the NSAP
+address for the interface.
+The MAC address is specified as a string of 12 hexadecimal
+digits with an optional leading "0x".
+Fields in the address may be separated by periods.
+.in -10
+.PP
+This command sets the MAC address for a UNI-controlled interface.
+The first 13 bytes (the prefix) of the 20-byte NSAP-format address
+are set by the \fIatm set prefix\fP command or the ILMI daemon
+(\fIilmid\fP (8)),
+the next 6 bytes (the End System Identifier (ESI)) are set by
+this command,
+and the last byte (the selector) will be determined by which
+network interface is to be associated with the address.
+.PP
+The \fIatm set MAC\fP command can be used to override the MAC
+address in the interface hardware.
+.PP
+\fIatm set netif <interface> <prefix> <count>\fP
+.PP
+where:
+.in +10
+.ti -5
+\fI<interface>\fP specifies the physical interface that the network
+interface(s) are to be associated with,
+.ti -5
+\fI<prefix>\fP specifies the invariant part of the network
+interface name,
+.ti -5
+\fI<count>\fP specifies the number of network interface to be
+created.
+.in -10
+.PP
+This command creates one or more network interfaces and associates them
+with the specified physical interface.
+The network interface names are determined by the prefix and the count.
+The names will be of the form <prefix><nn>, where <prefix> is the
+prefix specified in the \fIset\fP subcommand and <nn> is a number
+in the range 0 - <count>-1. For example, the command:
+.PP
+.ti +5
+atm set netif hfa0 ni 2
+.PP
+would create two network interfaces, named ni0 and ni1, and associate
+them with physical interface hfa0.
+.PP
+\fIatm set prefix <interface> <NSAP prefix>\fP
+.PP
+where:
+.in +10
+.ti -5
+\fI<interface>\fP specifies the physical interface whose NSAP
+prefix is to be set,
+.ti -5
+\fI<NSAP prefix>\fP specifies the first 13 bytes of the NSAP address
+for the interface.
+The prefix is specified as a string of hexadecimal digits with an
+optional leading "0x".
+Fields in the prefix may be separated by periods.
+.in -10
+.PP
+This command sets the address for a UNI-controlled interface.
+The first 13 bytes (the prefix) of the 20-byte NSAP-format address
+are set by this command,
+the next 6 bytes (the End System Identifier (ESI)) will be the
+MAC address taken from the physical interface or set by the
+\fIset MAC\fP subcommand,
+and the last byte (the selector) will be determined by which
+network interface is to be associated with the address.
+.PP
+The NSAP prefix must be set before a UNI-controlled
+interface can become active.
+This can be accomplished either by the ILMI daemon (\fIilmid\fP (8))
+or the \fIset prefix\fP subcommand.
+.PP
+.I atm show config [<interface>]
+.PP
+displays the following information:
+.PP
+.B Interface
+\- the name of the physical interface.
+.PP
+.B Vendor
+\- the name of the adapter vendor.
+.PP
+.B Model
+\- the model of the adapter.
+.PP
+.B Media
+\- the communications medium used by the adapter.
+.PP
+.B Bus
+\- the type of bus the adapter is attached to.
+.PP
+.B Serial No.
+\- the adapter's serial number.
+.PP
+.B MAC address
+\- the MAC address of the interface.
+Note that this is the MAC address encoded in the hardware of
+the adapter, even if the \fIatm set MAC\fP command has been used
+to change the effective MAC address of the interface.
+.PP
+.B Hardware version
+\- the hardware revision level reported by the interface.
+.PP
+.B Firmware version
+\- the firmware revision level reported by the interface.
+.PP
+If no parameters are specified on the \fIshow config\fP subcommand,
+the configurations of all physical interfaces will be displayed.
+If an interface name is specified, only the configuration of the given
+interface is displayed.
+.PP
+.I atm show interface [<interface>]
+.PP
+displays the following information:
+.PP
+.B Interface
+\- the name of the physical interface.
+.PP
+.B Sigmgr
+\- the name of the signalling manager which has been attached to the
+interface.
+A dash (-) is shown if no signalling manager has been attached.
+.PP
+.B State
+\- the state of the signalling manager for the interface.
+Each signalling manager has its own set of states.
+They are:
+.in +21
+.ti -16
+PVC:
+.ti -11
+ACTIVE\ ---\ The signalling manager is active.
+.ti -11
+DETACH\ ---\ The signalling manager is being detached.
+.ti -16
+SPANS:
+.ti -11
+ACTIVE\ ---\ The signalling manager is active.
+.ti -11
+DETACH\ ---\ The signalling manager is being detached.
+.ti -11
+INIT\ -----\ The signalling manager's initial state.
+.ti -11
+PROBE\ ----\ The signalling manager is attempting to make
+contact with the ATM switch.
+.ti -16
+UNI 3.0 or UNI 3.1:
+.ti -11
+NULL\ -----\ The signalling manager's initial state.
+.ti -11
+ADR_WAIT\ -\ The signalling manager is waiting for the NSAP
+prefix to be set.
+.ti -11
+INIT\ -----\ The signalling manager is attempting to establish
+contact with the switch.
+.ti -11
+ACTIVE\ ---\ The signalling manager is active.
+.ti -11
+DETACH\ ---\ The signalling manager is being detached.
+.ti -21
+.PP
+.B ATM address
+\- the ATM address of the interface.
+.PP
+.B Network interfaces
+\- the names of network interfaces, if any, associated with the
+physical interface.
+.PP
+If no parameters are specified on the \fIshow interface\fP subcommand,
+information about all physical interfaces will be displayed.
+If an interface name is specified, only information about the given
+interface is displayed.
+.PP
+.I atm show netif [<netif>]
+.PP
+displays the following information:
+.PP
+.B Net Intf
+\- the name of the network interface.
+.PP
+.B IP Address
+\- the IP address of the network interface.
+.PP
+If no parameters are specified on the \fIshow netif\fP subcommand,
+information about all network interfaces will be displayed.
+If an interface name is specified, only information about the given
+network interface is displayed.
+.PP
+\fIatm show stats interface [<interface> [phy | dev | atm | aal0 |
+aal4 | aal5 | driver]]\fP
+.PP
+displays statistics associated with one or more interfaces.
+Subject-area keywords
+(\fIphy\fP, \fIdev\fP, \fIatm\fP, \fIaal0\fP,
+\fIaal4\fP, \fIaal5\fP, or \fIdriver\fP)
+can be specified to change the scope of the statistics displayed.
+.PP
+If no subject area keyword is specified, the following information is
+displayed:
+.PP
+.B Interface
+\- the name of the physical ATM interface.
+.PP
+.B Input PDUs
+\- the number of Protocol Data Units (PDUs) which have been received
+by the interface.
+.PP
+.B Input Bytes
+\- the number of bytes which have been received by the interface.
+.PP
+.B Input Errs
+\- the number of input errors which the interface has experienced.
+.PP
+.B Output PDUs
+\- the number of Protocol Data Units (PDUs) which have been transmitted
+by the interface.
+.PP
+.B Output Bytes
+\- the number of bytes which have been transmitted by the interface.
+.PP
+.B Output Errs
+\- the number of output errors which the interface has experienced.
+.PP
+.B Cmd Errs
+\- the number of command errors which the interface has experienced.
+.PP
+If a subject-area keyword is specified, then statistics for
+that subject are displayed.
+The statistics displayed depend on the adapter.
+If requested statistics are not available for an adaptor,
+an error will be noted.
+.PP
+If no parameters are specified on the \fIshow stats interface\fP
+subcommand, statistics for all ATM interfaces are displayed.
+If an interface name is specified, only statistics for the given
+interface are displayed.
+.PP
+.SS VCC Management Subcommands:
+.PP
+\fIatm delete PVC <interface> <vpi> <vci>\fP
+.br
+\fIatm delete SVC <interface> <vpi> <vci>\fP
+.PP
+where:
+.in +10
+.ti -5
+\fIPVC\fP specifies that the VCC to be closed is a PVC,
+.ti -5
+\fISVC\fP specifies that the VCC to be closed is an SVC,
+.ti -5
+\fI<interface>\fP specifies the physical interface at which the
+VCC to be closed terminates,
+.ti -5
+\fI<vpi>\fP specifies the Virtual Path Identifier (VPI) of the VCC,
+.ti -5
+\fI<vci>\fP specifies the Virtual Channel Identifier (VCI) of the VCC.
+.in -10
+.PP
+This command closes a VCC.
+The two forms differ only in that the first specifies that the
+VCC is a PVC (that was created by the \fIadd PVC\fP subcommand) and
+the second specifies that the VCC is an SVC.
+Reserved VCCs (with VCI values less than 32) cannot be closed
+with this command.
+.PP
+\fIatm show stats VCC [<interface> [<vpi> [<vci>]]]\fP
+.PP
+displays the following information:
+.PP
+.B Interface
+\- the physical interface on which the VCC terminates.
+.PP
+.B VPI
+\- the Virtual Path Identifier (VPI) for the VCC.
+.PP
+.B VCI
+\- the Virtual Channel Identifier (VCI) for the VCC.
+.PP
+.B Input PDUs
+\- the number of Protocol Data Units (PDUs) which have been received
+on the VCC.
+.PP
+.B Input Bytes
+\- the number of bytes which have been received on the VCC.
+.PP
+.B Input Errs
+\- the number of input errors which the VCC has experienced.
+.PP
+.B Output PDUs
+\- the number of Protocol Data Units (PDUs) which have been transmitted
+on the VCC.
+.PP
+.B Output Bytes
+\- the number of bytes which have been transmitted on the VCC.
+.PP
+.B Output Errs
+\- the number of output errors which the VCC has experienced.
+.PP
+If no parameters are specified on the \fIshow VCC\fP subcommand, all
+active VCCs are displayed.
+If an interface name is specified, all active VCCs for the given
+interface are displayed.
+If an interface and VPI are specified, all active VCCs for the VPI
+on the given interface are displayed.
+If an interface, VPI, and VCI are specified, only the specified VCC on
+the given interface is displayed (note that this could actually be
+two VCCs, since SPANS considers SVCs to be unidirectional).
+.PP
+\fIatm show VCC [<interface> [<vpi> [<vci>] | SVC | PVC]]\fP
+.PP
+displays the following information:
+.PP
+.B Interface
+\- the physical interface on which the VCC terminates.
+.PP
+.B VPI
+\- the Virtual Path Identifier (VPI) for the VCC.
+.PP
+.B VCI
+\- the Virtual Channel Identifier (VCI) for the VCC.
+.PP
+.B AAL
+\- the ATM Adaptation Layer (AAL) in use on the VCC.
+Possible values are null and AAL 1-5.
+.PP
+.B Type
+\- specifies whether the VCC is an SVC or a PVC.
+.PP
+.B Dir
+\- the direction of information flow on the VCC.
+VCCs can be inbound, outbound, or both.
+.PP
+.B State
+\- the state of the VCC, as reported by the signalling manager.
+Each signalling manager has its own set of states.
+They are:
+.in +21
+.ti -16
+PVC:
+.ti -11
+NULL\ -----\ No state.
+.ti -11
+ACTIVE\ ---\ The VCC is active.
+.ti -11
+FREE\ -----\ The VCC is closed and the signalling manager is waiting for
+its resources to be freed.
+.ti -16
+SPANS:
+.ti -11
+NULL\ -----\ No state.
+.ti -11
+ACTIVE\ ---\ The VCC is a PVC and is active.
+.ti -11
+ACT_DOWN\ -\ The VCC is a PVC and the interface is down.
+.ti -11
+POPEN\ ----\ The VCC is being opened.
+.ti -11
+R_POPEN\ --\ The VCC is being opened by a remote host.
+.ti -11
+OPEN\ -----\ The VCC is active.
+.ti -11
+CLOSE\ ----\ The VCC is being closed.
+.ti -11
+ABORT\ ----\ The VCC is being aborted.
+.ti -11
+FREE\ -----\ The VCC is closed and the signalling manager is waiting for
+its resources to be freed.
+.ti -16
+UNI 3.0 or UNI 3.1:
+.ti -11
+NULL\ -----\ No state.
+.ti -11
+C_INIT\ ---\ A VCC is being initiated.
+.ti -11
+C_OUT_PR\ -\ An outgoing VCC request is proceeding.
+.ti -11
+C_PRES\ ---\ A VCC is being initiated by the network.
+.ti -11
+CONN_REQ\ -\ A VCC request has been accepted by a HARP user.
+.ti -11
+C_IN_PR\ --\ An incoming VCC request is proceeding.
+.ti -11
+ACTIVE\ ---\ The VCC is active.
+.ti -11
+REL_REQ\ --\ The VCC is being closed.
+.ti -11
+REL_IND\ --\ The network is clearing a VCC.
+.ti -11
+SSCF_REC\ -\ The SSCF session on the signalling channel is in
+recovery from an error.
+.ti -11
+FREE\ -----\ The VCC is closed and the signalling manager is waiting
+for its resources to be freed.
+.ti -11
+ACT_DOWN\ -\ The VCC is a PVC and the interface is down.
+.ti -21
+.PP
+.B Encaps
+\- the encapsulation in effect on the VCC.
+Possible encapsulations are null and LLC/SNAP.
+.PP
+.B Owner
+\- the owner or owners of the VCC.
+Shows the name(s) of the function(s) using the VCC.
+.PP
+.B Destination
+\- the ATM address of the host at the remote end of the VCC.
+.PP
+If no parameters are specified on the \fIshow VCC\fP subcommand, all
+active VCCs are displayed.
+If an interface name is specified, all active VCCs for the given
+interface are displayed.
+If an interface and VPI are specified, all active VCCs for the VPI
+on the given interface are displayed.
+If an interface, VPI, and VCI are specified, only the specified VCC on
+the given interface is displayed (note that this could actually be
+two VCCs, since SPANS considers SVCs to be unidirectional).
+.PP
+.SS IP Management Subcommands:
+\fIatm add ARP [<netif>] <host> <ATM address>\fP
+.PP
+where:
+.in +10
+.ti -5
+\fI<netif>\fP is the optional name of the network interface the
+ATMARP entry is to be associated with.
+If no name is specified, a network interface is chosen depending
+on the IP address of the host being added.
+.ti -5
+\fI<host>\fP is the host name or IP address of the host to
+be added to the ATMARP table,
+.ti -5
+\fI<ATM address>\fP is the ATM address of the host.
+.in -10
+.PP
+This command adds an entry to the ATMARP table for ATM.
+The given host's IP address is associated with the given ATM address.
+When IP needs to transmit data to the host, the specified ATM
+address will be used to open an SVC.
+.PP
+The entry will be marked as permanent in the ATMARP table and will not
+be subject to aging.
+.PP
+.in +5
+.ti -5
+\fIatm add PVC <interface> <vpi> <vci> <aal> <encaps> IP <netif> <host> | dynamic\fP
+.in -5
+.PP
+where:
+.in +10
+.ti -5
+\fI<interface>\fP specifies the physical interface where the PVC
+is to terminate,
+.ti -5
+\fI<vpi>\fP specifies the Virtual Path Identifier (VPI) of the PVC,
+.ti -5
+\fI<vci>\fP specifies the Virtual Channel Identifier (VCI) of the PVC,
+.ti -5
+\fI<aal>\fP specifies the ATM Adaptation Layer (AAL) for the PVC.
+Valid choices are "null" or "AAL0" for the null AAL; "AAL1" for
+AAL 1; "AAL2" for AAL 2; "AAL3", "AAL4", or "AAL3/4" for AAL 3/4;
+and "AAL5" for AAL 5,
+.ti -5
+\fI<encaps>\fP specifies the encapsulation for the PVC.
+Valid choices are "null" or "none" for null encapsulation, and
+"LLC/SNAP", "LLC", or "SNAP" for LLC/SNAP encapsulation,
+.ti -5
+\fIIP\fP specifies that the owner of the PVC is IP.
+.ti -5
+\fI<netif>\fP specifies the network interface which the PVC is
+to be associated with.
+The network interface must exist and be associated with the
+specified physical interface,
+.ti -5
+\fI<host> | dynamic\fP gives the address of the host at
+the far end of the PVC, or the word "dynamic" if its address
+is to be determined with Inverse ARP.
+If "dynamic" is specified, LLC/SNAP encapsulation must also
+be specified.
+.PP
+This command creates a PVC with the specified attributes and attaches
+it to IP.
+.PP
+\fIatm delete ARP [<netif>] <host>\fP
+.PP
+where:
+.in +10
+.ti -5
+\fI<netif>\fP is the optional name of the network interface the
+ATMARP entry is associated with.
+If no name is specified, the specified host is deleted from the
+cache regardless of what network interface it is associated with.
+.ti -5
+\fI<host>\fP is the host name or IP address of the host to
+be deleted from the ATMARP table.
+.PP
+This command deletes the specified host's entry from the ATMARP table.
+.PP
+\fIatm set arpserver <netif> <ATM address> | local [<IP prefix> ...]\fP
+.PP
+where:
+.in +10
+.ti -5
+\fI<netif>\fP specifies the network interface for which the
+ATMARP server address is to be set.
+.ti -5
+\fI<ATM address>\fP specifies the ATM address of the host which is to
+provide ATMARP service.
+If "local" is specified instead of an ATM address, the host on
+which the command is issued will become the ATMARP server.
+.ti -5
+\fI<IP prefix> ...\fP is an optional list of IP prefixes
+that the ATMARP server will provide information about.
+An IP prefix is specified as a dotted decimal IP address, followed by
+a slash, followed a number specifying how many bits of the IP address
+are significant.
+For example, 10.0.0.0/8 indicates that the ATMARP server will provide
+services for all addresses on IP network 10.
+The IP subnetwork which the network interface belongs to is
+automatically included.
+.in -10
+.PP
+This command sets the address of the ATMARP server for a network
+interface.
+.PP
+.I atm show ARP [<host>]
+.PP
+displays the following information:
+.PP
+.B Net Intf
+\- the network interface which traffic for the entry will use.
+.PP
+.B Flags
+\- flags showing whether the entry is valid and whether it is
+permanent.
+\- flags giving further information about the ATMARP entry.
+The meanings of the characters in the flags are:
+.PP
+.in +5
+P - the entry is permanent
+.br
+R - the entry has been refreshed
+.br
+V - the entry is valid
+.in -5
+.PP
+.B Age
+\- the number of minutes for which the entry will remain valid.
+.PP
+.B Origin
+\- the source of the ATMARP entry.
+Possible values are:
+.in +16
+.ti -11
+LOCAL\ ----\ The entry is for an interface on the host.
+.ti -11
+PERM\ -----\ The entry is permanent.
+This is used for entries that are created with the
+\fIadd ARP\fP command.
+.ti -11
+REG\ ------\ The entry was created as the result of a host
+registering with the ATMARP server.
+.ti -11
+SCSP\ -----\ The entry was learned via SCSP.
+.ti -11
+LOOKUP\ ---\ The entry was created as the result of a host
+performing an ATMARP lookup.
+.ti -11
+PEER_RSP\ -\ The entry was created as the result of a host
+answering an InARP Request.
+.ti -11
+PEER_REQ\ -\ The entry was created as the result of a host
+sending an InARP Request.
+.in -5
+.PP
+.B ATM address
+\- the ATM address of the host the entry refers to.
+.PP
+.B IP address
+\- the IP address or domain name of the host the entry refers to.
+.PP
+If no parameters are specified on the \fIshow ARP\fP subcommand,
+the whole ATMARP table will be displayed.
+If a host name or IP address is specified, only information about the
+given host is displayed.
+.PP
+This command dislays both information that has been learned dynamically
+(through one form or another of ATMARP and via SCSP) and information
+which has been configured by the user (through the \fIadd ARP\fP
+subcommand).
+.PP
+.I atm show arpserver [<netif>]
+.PP
+displays the following information:
+.PP
+.B Net Intf
+\- the network interface for which information is being displayed.
+.PP
+.B State
+\- the state of the connection to the ATMARP server.
+Possible values are:
+.in +16
+.ti -11
+NOT_CONF\ -\ No ATMARP server has been configured for the interface.
+.ti -11
+SERVER\ ---\ The host is the ATMARP server.
+.ti -11
+PEND_ADR\ -\ No ATM address has been set for the interface.
+.ti -11
+POPEN\ ----\ The host is attempting to open a VCC to the ATMARP server.
+.ti -11
+REGISTER\ -\ The host has a VCC open to the ATMARP server and is in
+the process of registering with the server.
+.ti -11
+ACTIVE\ ---\ The ATMARP server connection is active.
+.in -16
+.PP
+.B ATM Address
+\- the ATM address of the ATMARP server.
+.PP
+If no parameters are specified on the \fIshow arpserver\fP subcommand,
+the ATMARP servers for all network interfaces will be displayed.
+If an interface name is specified, only information about the given
+network interface is displayed.
+.PP
+.I atm show IPVCC [<host> | <netif>]
+.PP
+displays the following information:
+.PP
+.B Net Intf
+\- the name of the network interface at which the VCC terminates.
+.PP
+.B VPI
+\- the Virtual Path Identifier (VPI) for the VCC.
+.PP
+.B VCI
+\- the Virtual Channel Identifier (VCI) for the VCC.
+.PP
+.B State
+\- the state of the VCC.
+Possible values are:
+.in +15
+.ti -10
+PMAP\ ----\ The host has an IP packet to send and is waiting for
+an ATMARP mapping.
+.ti -10
+POPEN\ ---\ The VCC is being opened.
+.ti -10
+PACCEPT\ -\ A VCC from a remote host is being accepted.
+.ti -10
+ACTPENT\ -\ A PVC is open, but no ATMARP information is
+available for it yet.
+.ti -10
+ACTIVE\ --\ The VCC is active.
+.in -15
+.PP
+.B Flags
+\- flags giving further information about the VCC.
+The meanings of the characters in the flags are:
+.PP
+.in +5
+S - the VCC is an SVC
+.br
+P - the VCC is a PVC
+.br
+L - the VCC uses LLC/SNAP encapsulation
+.br
+M - the IP-to-ATM address mapping for the VCC is valid
+.br
+N - there is no idle timeout for the VCC
+.in -5
+.PP
+.B IP Address
+\- the name and IP address of the host at the remote end of the VCC.
+.PP
+If no parameters are specified on the \fIshow IPVCC\fP subcommand, all
+active VCCs are displayed.
+If a host name is specified, the active VCC(s) for the given
+host are displayed.
+If a network interface name is specified, the active VCC(s) for the
+given network interface are displayed.
+.PP
+.SS Miscellaneous Subcommands:
+.I atm help
+.PP
+displays a synopsis of the atm command with its subcommands
+and their parameters.
+.PP
+.I atm show version
+displays the version of the running HARP software.
+.fi
+.SH "SEE ALSO"
+\fIilmid\fP (8); \fIscspd\fP (8); \fIatmarpd\fP (8).
+.fi
+.SH BUGS
+Care must be taken to avoid confusing physical interfaces and
+network interfaces.
+.PP
+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
+Joe 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/atm/atm.c b/sbin/atm/atm/atm.c
new file mode 100644
index 0000000..a668b74
--- /dev/null
+++ b/sbin/atm/atm/atm.c
@@ -0,0 +1,1072 @@
+/*
+ *
+ * ===================================
+ * 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: atm.c,v 1.17 1998/08/06 16:57:47 johnc Exp $
+ *
+ */
+
+/*
+ * User configuration and display program
+ * --------------------------------------
+ *
+ * Main routine
+ *
+ */
+
+#ifndef lint
+static char *RCSid = "@(#) $Id: atm.c,v 1.17 1998/08/06 16:57:47 johnc Exp $";
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netatm/port.h>
+#include <netatm/atm.h>
+#include <netatm/atm_if.h>
+#include <netatm/atm_sap.h>
+#include <netatm/atm_sys.h>
+#include <netatm/atm_cm.h>
+#include <netatm/atm_sigmgr.h>
+#include <netatm/atm_ioctl.h>
+
+#include <libatm.h>
+#include "atm.h"
+
+
+/*
+ * Usage string
+ */
+#define USAGE_STR "Interface management subcommands:\n\
+ attach <intf> <protocol>\n\
+ detach <intf>\n\
+ set mac <intf> <MAC/ESI address>\n\
+ set netif <intf> <prefix> <n>\n\
+ set prefix <intf> <NSAP prefix>\n\
+ show config [<intf>]\n\
+ show interface [<intf>]\n\
+ show netif [<netif>]\n\
+ show stats interface [<intf> phy | dev | atm | aal0 | aal4 |\n\
+ aal5 | driver]\n\
+\n\
+VC management subcommands:\n\
+ add pvc <intf> <vpi> <vci> <aal> <encaps> <owner> ...\n\
+ delete pvc <intf> <vpi> <vci>\n\
+ delete svc <intf> <vpi> <vci>\n\
+ show stats vcc [<intf> [vpi [vci]]]\n\
+ show vcc [<intf> [<vpi> [<vci>] | SVC | PVC]]\n\
+\n\
+IP management subcommands:\n\
+ add arp [<netif>] <IP addr> <ATM addr>\n\
+ add pvc <intf> <vpi> <vci> <aal> <encaps> IP <netif> <IP addr> |\n\
+ dynamic\n\
+ delete arp [<netif>] <IP addr>\n\
+ set arpserver <netif> <server> <IP prefix> ...\n\
+ show arp [<host>]\n\
+ show arpserver [<netif>]\n\
+ show ipvcc [<IP addr> | <netif>]\n\
+\n\
+Miscellaneous subcommands:\n\
+ help\n\
+ show version\n"
+
+
+/*
+ * Local definitions
+ */
+
+struct cmd add_subcmd[];
+struct cmd dlt_subcmd[];
+struct cmd set_subcmd[];
+struct cmd show_subcmd[];
+struct cmd stats_subcmd[];
+
+struct cmd cmds[] = {
+ { "add", 0, 0, NULL, (char *) add_subcmd },
+ { "attach", 2, 2, attach, "<intf> <protocol>" },
+ { "delete", 0, 0, NULL, (char *) dlt_subcmd },
+ { "detach", 1, 1, detach, "<intf>" },
+ { "set", 0, 0, NULL, (char *) set_subcmd },
+ { "show", 0, 0, NULL, (char *) show_subcmd },
+ { "help", 0, 99, help, "" },
+ { 0, 0, 0, NULL, "" }
+};
+
+struct cmd add_subcmd[] = {
+ { "arp", 2, 3, arp_add, "[<netif>] <IP addr> <ATM addr>" },
+ { "pvc", 6, 12, pvc_add, "<intf> <vpi> <vci> <aal> <encaps> <owner> ..." },
+ { 0, 0, 0, NULL, "" }
+};
+
+struct cmd dlt_subcmd[] = {
+ { "arp", 1, 2, arp_dlt, "[<netif>] <IP addr>" },
+ { "pvc", 3, 3, pvc_dlt, "<intf> <vpi> <vci>" },
+ { "svc", 3, 3, svc_dlt, "<intf> <vpi> <vci>" },
+ { 0, 0, 0, NULL, "" }
+};
+
+struct cmd set_subcmd[] = {
+ { "arpserver", 2, 18, set_arpserver, "<netif> <server>" },
+ { "mac", 2, 2, set_macaddr, "<intf> <MAC/ESI address>" },
+ { "netif", 3, 3, set_netif, "<intf> <prefix> <n>" },
+ { "prefix", 2, 2, set_prefix, "<intf> <NSAP prefix>" },
+ { 0, 0, 0, NULL, ""}
+};
+
+struct cmd show_subcmd[] = {
+ { "arp", 0, 1, show_arp, "[<host>]" },
+ { "arpserver", 0, 1, show_arpserv, "[<netif>]" },
+ { "config", 0, 1, show_config, "[<intf>]" },
+ { "interface", 0, 1, show_intf, "[<intf>]" },
+ { "ipvcc", 0, 3, show_ip_vcc, "[<IP addr> | <netif>]" },
+ { "netif", 0, 1, show_netif, "[<netif>]" },
+ { "stats", 0, 3, NULL, (char *) stats_subcmd },
+ { "vcc", 0, 3, show_vcc, "[<intf>] [<vpi> [<vci>] | SVC | PVC]" },
+ { "version", 0, 0, show_version, "" },
+ { 0, 0, 0, NULL, "" }
+};
+
+struct cmd stats_subcmd[] = {
+ { "interface", 0, 2, show_intf_stats, "[<intf> [cfg | phy | dev | atm | aal0 | aal4 | aal5 | driver]]" },
+ { "vcc", 0, 3, show_vcc_stats, "[<intf> [vpi [vci]]]" },
+ { 0, 0, 0, NULL, "" }
+};
+
+
+/*
+ * Supported signalling protocols
+ */
+struct proto protos[] = {
+ { "SIGPVC", ATM_SIG_PVC },
+ { "SPANS", ATM_SIG_SPANS },
+ { "UNI30", ATM_SIG_UNI30 },
+ { "UNI31", ATM_SIG_UNI31 },
+ { "UNI40", ATM_SIG_UNI40 },
+ { 0, 0 }
+};
+
+/*
+ * Supported VCC owners
+ */
+struct owner owners[] = {
+ { "IP", ENDPT_IP, ip_pvcadd },
+ { "SPANS", ENDPT_SPANS_SIG,0 },
+ { "SPANS CLS", ENDPT_SPANS_CLS,0 },
+ { "UNI SIG", ENDPT_UNI_SIG, 0 },
+ { 0, 0, 0 }
+};
+
+/*
+ * Supported AAL parameters
+ */
+struct aal aals[] = {
+ { "Null", ATM_AAL0 },
+ { "AAL0", ATM_AAL0 },
+ { "AAL1", ATM_AAL1 },
+ { "AAL2", ATM_AAL2 },
+ { "AAL4", ATM_AAL3_4 },
+ { "AAL3", ATM_AAL3_4 },
+ { "AAL3/4", ATM_AAL3_4 },
+ { "AAL5", ATM_AAL5 },
+ { 0, 0 },
+};
+
+/*
+ * Supported VCC encapsulations
+ */
+struct encaps encaps[] = {
+ { "Null", ATM_ENC_NULL },
+ { "None", ATM_ENC_NULL },
+ { "LLC/SNAP", ATM_ENC_LLC },
+ { "LLC", ATM_ENC_LLC },
+ { "SNAP", ATM_ENC_LLC },
+ { 0, 0 },
+};
+
+
+char *prog;
+char prefix[128] = "";
+
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int error;
+
+ /*
+ * Save program name, ignoring any path components
+ */
+ if (prog = (char *)strrchr(argv[0], '/'))
+ prog++;
+ else
+ prog = argv[0];
+
+ if (argc < 2) {
+ usage(cmds, "");
+ exit(1);
+ }
+ argc--; argv++;
+
+ /*
+ * Validate and process command
+ */
+ if (error = do_cmd(cmds, argc, argv))
+ usage(cmds, "");
+
+ exit(error);
+}
+
+
+/*
+ * Validate and process user command
+ *
+ * Arguments:
+ * descp pointer to command description array
+ * argc number of arguments left in command
+ * argv pointer to argument strings
+ *
+ * Returns:
+ * none
+ *
+ */
+int
+do_cmd(descp, argc, argv)
+ struct cmd *descp;
+ int argc;
+ char **argv;
+{
+ struct cmd *cmdp = 0;
+
+ /*
+ * Make sure we have paramaters to process
+ */
+ if (!argc) {
+ usage(cmds, "");
+ exit(1);
+ }
+
+ /*
+ * Figure out what command user wants
+ */
+ for (; descp->name; descp++) {
+ /*
+ * Use an exact match if there is one
+ */
+ if (!strcasecmp(descp->name, argv[0])) {
+ cmdp = descp;
+ break;
+ }
+ /*
+ * Look for a match on the first part of keyword
+ */
+ if (!strncasecmp(descp->name, argv[0], strlen(argv[0]))) {
+ if (cmdp) {
+ fprintf(stderr, "%s: Ambiguous parameter \"%s\"\n",
+ prog, argv[0]);
+ exit(1);
+ }
+ cmdp = descp;
+ }
+ }
+ if (!cmdp)
+ return(1);
+ argc--; argv++;
+
+ /*
+ * See if this command has subcommands
+ */
+ if (cmdp->func == NULL) {
+ strcat(prefix, cmdp->name);
+ strcat(prefix, " ");
+ return(do_cmd((struct cmd *)cmdp->help, argc, argv));
+ }
+
+ /*
+ * Minimal validation
+ */
+ if ((argc < cmdp->minp) || (argc > cmdp->maxp)) {
+ fprintf(stderr, "%s: Invalid number of arguments\n",
+ prog);
+ fprintf(stderr, "\tformat is: %s%s %s\n",
+ prefix, cmdp->name, cmdp->help);
+ exit(1);
+ }
+
+ /*
+ * Process command
+ */
+ (*cmdp->func)(argc, argv, cmdp);
+ return(0);
+}
+
+
+/*
+ * Print command usage information
+ *
+ * Arguments:
+ * cmdp pointer to command description
+ * pref pointer current command prefix
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+usage(cmdp, pref)
+ struct cmd *cmdp;
+ char *pref;
+{
+ fprintf(stderr, "usage: %s command [arg] [arg]...\n", prog);
+ fprintf(stderr, USAGE_STR);
+}
+
+
+/*
+ * Process interface attach command
+ *
+ * Command format:
+ * atm attach <interface_name> <protocol_name>
+ *
+ * Arguments:
+ * argc number of arguments to command
+ * argv pointer to argument strings
+ * cmdp pointer to command description
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+attach(argc, argv, cmdp)
+ int argc;
+ char **argv;
+ struct cmd *cmdp;
+{
+ struct atmcfgreq aar;
+ struct proto *prp;
+ int s;
+
+ /*
+ * Validate interface name
+ */
+ if (strlen(argv[0]) > sizeof(aar.acr_att_intf) - 1) {
+ fprintf(stderr, "%s: Illegal interface name\n", prog);
+ exit(1);
+ }
+
+ /*
+ * Find/validate requested signalling protocol
+ */
+ for (prp = protos; prp->p_name; prp++) {
+ if (strcasecmp(prp->p_name, argv[1]) == 0)
+ break;
+ }
+ if (prp->p_name == NULL) {
+ fprintf(stderr, "%s: Unknown signalling protocol\n", prog);
+ exit(1);
+ }
+
+
+ /*
+ * Build ioctl request
+ */
+ aar.acr_opcode = AIOCS_CFG_ATT;
+ strncpy(aar.acr_att_intf, argv[0], sizeof(aar.acr_att_intf));
+ aar.acr_att_proto = prp->p_id;
+
+ /*
+ * Tell the kernel to do the attach
+ */
+ s = socket(AF_ATM, SOCK_DGRAM, 0);
+ if (s < 0) {
+ sock_error(errno);
+ }
+ if (ioctl(s, AIOCCFG, (caddr_t)&aar) < 0) {
+ fprintf(stderr, "%s: ", prog);
+ switch (errno) {
+ case EINVAL:
+ case EOPNOTSUPP:
+ case EPROTONOSUPPORT:
+ perror("Internal error");
+ break;
+ case ENOMEM:
+ fprintf(stderr, "Kernel memory exhausted\n");
+ break;
+ case EEXIST:
+ fprintf(stderr, "Signalling manager already attached to %s\n",
+ argv[0]);
+ break;
+ case ENETDOWN:
+ fprintf(stderr, "ATM network is inoperable\n");
+ break;
+ case EPERM:
+ fprintf(stderr, "Must be super user to use attach subcommand\n");
+ break;
+ case ENXIO:
+ fprintf(stderr, "%s is not an ATM device\n",
+ argv[0]);
+ break;
+ case ETOOMANYREFS:
+ fprintf(stderr, "%s has too few or too many network interfaces\n",
+ argv[0]);
+ break;
+ default:
+ perror("Ioctl (AIOCCFG) attach");
+ break;
+ }
+ exit(1);
+ }
+ (void)close(s);
+}
+
+
+/*
+ * Process interface detach command
+ *
+ * Command format:
+ * atm detach <interface_name>
+ *
+ * Arguments:
+ * argc number of arguments to command
+ * argv pointer to argument strings
+ * cmdp pointer to command description
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+detach(argc, argv, cmdp)
+ int argc;
+ char **argv;
+ struct cmd *cmdp;
+{
+ struct atmcfgreq adr;
+ int s;
+
+ /*
+ * Validate interface name
+ */
+ if (strlen(argv[0]) > sizeof(adr.acr_det_intf) - 1) {
+ fprintf(stderr, "%s: Illegal interface name\n", prog);
+ exit(1);
+ }
+
+ /*
+ * Build ioctl request
+ */
+ adr.acr_opcode = AIOCS_CFG_DET;
+ strncpy(adr.acr_det_intf, argv[0], sizeof(adr.acr_det_intf));
+
+ /*
+ * Tell the kernel to do the detach
+ */
+ s = socket(AF_ATM, SOCK_DGRAM, 0);
+ if (s < 0) {
+ sock_error(errno);
+ }
+ if (ioctl(s, AIOCCFG, (caddr_t)&adr) < 0) {
+ fprintf(stderr, "%s: ", prog);
+ switch (errno) {
+ case EALREADY:
+ fprintf(stderr, "Signalling manager already detaching from %s\n",
+ argv[0]);
+ break;
+ case EINVAL:
+ perror("Internal error");
+ break;
+ case EPERM:
+ fprintf(stderr, "Must be super user to use detach subcommand\n");
+ break;
+ default:
+ perror("ioctl (AIOCCFG) detach");
+ break;
+ }
+ exit(1);
+ }
+ (void)close(s);
+}
+
+
+/*
+ * Process PVC add command
+ *
+ * Command format:
+ * atm add PVC <interface_name> <vpi> <vci> <aal> <encaps>
+ * <owner_name>
+ *
+ * Arguments:
+ * argc number of arguments to command
+ * argv pointer to argument strings
+ * cmdp pointer to command description
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+pvc_add(argc, argv, cmdp)
+ int argc;
+ char **argv;
+ struct cmd *cmdp;
+{
+ struct atmaddreq apr;
+ struct atminfreq air;
+ struct air_int_rsp *int_info;
+ struct owner *owp;
+ struct aal *alp;
+ struct encaps *enp;
+ char *cp;
+ long v;
+ int buf_len, s;
+
+ /*
+ * Initialize opcode and flags
+ */
+ apr.aar_opcode = AIOCS_ADD_PVC;
+ apr.aar_pvc_flags = 0;
+
+ /*
+ * Validate interface name and issue an information
+ * request IOCTL for the interface
+ */
+ if (strlen(argv[0]) > sizeof(apr.aar_pvc_intf) - 1) {
+ fprintf(stderr, "%s: Illegal interface name\n", prog);
+ exit(1);
+ }
+ UM_ZERO(air.air_int_intf, sizeof(air.air_int_intf));
+ strcpy(air.air_int_intf, argv[0]);
+ buf_len = sizeof(struct air_int_rsp);
+ air.air_opcode = AIOCS_INF_INT;
+ buf_len = do_info_ioctl(&air, buf_len);
+ if (buf_len < 0) {
+ fprintf(stderr, "%s: ", prog);
+ switch (errno) {
+ case ENOPROTOOPT:
+ case EOPNOTSUPP:
+ perror("Internal error");
+ break;
+ case ENXIO:
+ fprintf(stderr, "%s is not an ATM device\n",
+ argv[0]);
+ break;
+ default:
+ perror("ioctl (AIOCINFO)");
+ break;
+ }
+ exit(1);
+ }
+ int_info = (struct air_int_rsp *) air.air_buf_addr;
+ strcpy(apr.aar_pvc_intf, argv[0]);
+ argc--; argv++;
+
+ /*
+ * Validate vpi/vci values
+ */
+ v = strtol(argv[0], &cp, 0);
+ if ((*cp != '\0') || (v < 0) || (v >= 1 << 8)) {
+ fprintf(stderr, "%s: Invalid VPI value\n", prog);
+ exit(1);
+ }
+ apr.aar_pvc_vpi = (u_short) v;
+ argc--; argv++;
+
+ v = strtol(argv[0], &cp, 0);
+ if ((*cp != '\0') || (v < MIN_VCI) || (v >= 1 << 16)) {
+ fprintf(stderr, "%s: Invalid VCI value\n", prog);
+ exit(1);
+ }
+ apr.aar_pvc_vci = (u_short) v;
+ argc--; argv++;
+
+ /*
+ * Validate requested PVC AAL
+ */
+ for (alp = aals; alp->a_name; alp++) {
+ if (strcasecmp(alp->a_name, argv[0]) == 0)
+ break;
+ }
+ if (alp->a_name == NULL) {
+ fprintf(stderr, "%s: Invalid PVC AAL\n", prog);
+ exit(1);
+ }
+ apr.aar_pvc_aal = alp->a_id;
+ argc--; argv++;
+
+ /*
+ * Validate requested PVC encapsulation
+ */
+ for (enp = encaps; enp->e_name; enp++) {
+ if (strcasecmp(enp->e_name, argv[0]) == 0)
+ break;
+ }
+ if (enp->e_name == NULL) {
+ fprintf(stderr, "%s: Invalid PVC encapsulation\n", prog);
+ exit(1);
+ }
+ apr.aar_pvc_encaps = enp->e_id;
+ argc--; argv++;
+
+ /*
+ * Validate requested PVC owner
+ */
+ for (owp = owners; owp->o_name; owp++) {
+ if (strcasecmp(owp->o_name, argv[0]) == 0)
+ break;
+ }
+ if (owp->o_name == NULL) {
+ fprintf(stderr, "%s: Unknown PVC owner\n", prog);
+ exit(1);
+ }
+ apr.aar_pvc_sap = owp->o_sap;
+ argc--; argv++;
+
+ /*
+ * Perform service user processing
+ */
+ if (owp->o_pvcadd) {
+ (*owp->o_pvcadd)(argc, argv, cmdp, &apr, int_info);
+ } else {
+ fprintf(stderr, "%s: Unsupported PVC owner\n", prog);
+ exit(1);
+ }
+
+ /*
+ * Tell the kernel to add the PVC
+ */
+ s = socket(AF_ATM, SOCK_DGRAM, 0);
+ if (s < 0) {
+ sock_error(errno);
+ }
+ if (ioctl(s, AIOCADD, (caddr_t)&apr) < 0) {
+ fprintf(stderr, "%s: ", prog);
+ switch (errno) {
+ case EPROTONOSUPPORT:
+ case ENOPROTOOPT:
+ perror("Internal error");
+ break;
+ case EINVAL:
+ fprintf(stderr, "Invalid parameter\n");
+ break;
+ case EEXIST:
+ fprintf(stderr, "PVC already exists\n");
+ break;
+ case ENETDOWN:
+ fprintf(stderr, "ATM network is inoperable\n");
+ break;
+ case ENOMEM:
+ fprintf(stderr, "Kernel memory exhausted\n");
+ break;
+ case EPERM:
+ fprintf(stderr, "Must be super user to use add subcommand\n");
+ break;
+ case ERANGE:
+ fprintf(stderr, "Invalid VPI or VCI value\n");
+ break;
+ default:
+ perror("ioctl (AIOCADD) add PVC");
+ break;
+ }
+ exit(1);
+ }
+ (void)close(s);
+}
+
+
+/*
+ * Process ARP add command
+ *
+ * Command formats:
+ * atm add arp [<netif>] <IP addr> <ATM addr>
+ *
+ * Arguments:
+ * argc number of arguments to command
+ * argv pointer to argument strings
+ * cmdp pointer to command description
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+arp_add(argc, argv, cmdp)
+ int argc;
+ char **argv;
+ struct cmd *cmdp;
+{
+ int len, rc, s;
+ struct atmaddreq apr;
+ Atm_addr host_atm;
+ struct sockaddr_in *sin;
+ union {
+ struct sockaddr_in sin;
+ struct sockaddr sa;
+ } host_ip;
+
+ /*
+ * Initialize add request structure
+ */
+ UM_ZERO(&apr, sizeof(apr));
+
+ /*
+ * Get network interface name if one is present
+ */
+ if (argc == 3) {
+ check_netif_name(argv[0]);
+ strcpy(apr.aar_arp_intf, argv[0]);
+ argc--; argv++;
+ }
+
+ /*
+ * Get IP address of specified host name
+ */
+ UM_ZERO(&host_ip, sizeof(host_ip));
+ host_ip.sa.sa_family = AF_INET;
+ sin = get_ip_addr(argv[0]);
+ host_ip.sin.sin_addr.s_addr = sin->sin_addr.s_addr;
+ argc--; argv++;
+
+ /*
+ * Get specified ATM address
+ */
+ len = get_hex_atm_addr(argv[0], (u_char *)host_atm.address,
+ sizeof(Atm_addr_nsap));
+ switch(len) {
+ case sizeof(Atm_addr_nsap):
+ host_atm.address_format = T_ATM_ENDSYS_ADDR;
+ host_atm.address_length = sizeof(Atm_addr_nsap);
+ break;
+ case sizeof(Atm_addr_spans):
+ host_atm.address_format = T_ATM_SPANS_ADDR;
+ host_atm.address_length = sizeof(Atm_addr_spans);
+ break;
+ default:
+ fprintf(stderr, "%s: Invalid ATM address\n", prog);
+ exit(1);
+ }
+
+ /*
+ * Build IOCTL request
+ */
+ apr.aar_opcode = AIOCS_ADD_ARP;
+ apr.aar_arp_dst = host_ip.sa;
+ ATM_ADDR_COPY(&host_atm, &apr.aar_arp_addr);
+ apr.aar_arp_origin = ARP_ORIG_PERM;
+
+ /*
+ * Tell the kernel to add the ARP table entry
+ */
+ s = socket(AF_ATM, SOCK_DGRAM, 0);
+ if (s < 0) {
+ sock_error(errno);
+ }
+ if (ioctl(s, AIOCADD, (caddr_t)&apr) < 0) {
+ fprintf(stderr, "%s: ", prog);
+ switch (errno) {
+ case EINVAL:
+ fprintf(stderr, "Invalid parameter\n");
+ break;
+ case EPERM:
+ fprintf(stderr, "Must be super user to use add subcommand\n");
+ break;
+ case EADDRNOTAVAIL:
+ fprintf(stderr, "IP address not valid for interface\n");
+ break;
+ default:
+ perror("ioctl (AIOCADD) add");
+ break;
+ }
+ exit(1);
+ }
+ (void)close(s);
+}
+
+
+/*
+ * Process PVC delete command
+ *
+ * Command formats:
+ * atm delete pvc <interface_name> <vpi> <vci>
+ *
+ * Arguments:
+ * argc number of arguments to command
+ * argv pointer to argument strings
+ * cmdp pointer to command description
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+pvc_dlt(argc, argv, cmdp)
+ int argc;
+ char **argv;
+ struct cmd *cmdp;
+{
+ struct atmdelreq apr;
+
+ /*
+ * Set opcode
+ */
+ apr.adr_opcode = AIOCS_DEL_PVC;
+
+ /*
+ * Complete request by calling subroutine
+ */
+ vcc_dlt(argc, argv, cmdp, &apr);
+}
+
+
+/*
+ * Process SVC delete command
+ *
+ * Command formats:
+ * atm delete svc <interface_name> <vpi> <vci>
+ *
+ * Arguments:
+ * argc number of arguments to command
+ * argv pointer to argument strings
+ * cmdp pointer to command description
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+svc_dlt(argc, argv, cmdp)
+ int argc;
+ char **argv;
+ struct cmd *cmdp;
+{
+ struct atmdelreq apr;
+
+ /*
+ * Set opcode
+ */
+ apr.adr_opcode = AIOCS_DEL_SVC;
+
+ /*
+ * Complete request by calling subroutine
+ */
+ vcc_dlt(argc, argv, cmdp, &apr);
+}
+
+
+/*
+ * Complete an SVC or PVC delete command
+ *
+ * Arguments:
+ * argc number of arguments to command
+ * argv pointer to argument strings
+ * cmdp pointer to command description
+ * apr pointer to ATM delete IOCTL structure
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+vcc_dlt(argc, argv, cmdp, apr)
+ int argc;
+ char **argv;
+ struct cmd *cmdp;
+ struct atmdelreq *apr;
+{
+ char *cp;
+ long v;
+ int s;
+
+ /*
+ * Validate interface name
+ */
+ if (strlen(argv[0]) > sizeof(apr->adr_pvc_intf) - 1) {
+ fprintf(stderr, "%s: Illegal interface name\n", prog);
+ exit(1);
+ }
+ strcpy(apr->adr_pvc_intf, argv[0]);
+ argc--; argv++;
+
+ /*
+ * Validate vpi/vci values
+ */
+ v = strtol(argv[0], &cp, 0);
+ if ((*cp != '\0') || (v < 0) || (v >= 1 << 8)) {
+ fprintf(stderr, "%s: Invalid VPI value\n", prog);
+ exit(1);
+ }
+ apr->adr_pvc_vpi = (u_short) v;
+ argc--; argv++;
+
+ v = strtol(argv[0], &cp, 0);
+ if ((*cp != '\0') || (v < MIN_VCI) || (v >= 1 << 16)) {
+ fprintf(stderr, "%s: Invalid VCI value\n", prog);
+ exit(1);
+ }
+ apr->adr_pvc_vci = (u_short) v;
+ argc--; argv++;
+
+ /*
+ * Tell the kernel to delete the VCC
+ */
+ s = socket(AF_ATM, SOCK_DGRAM, 0);
+ if (s < 0) {
+ sock_error(errno);
+ }
+ if (ioctl(s, AIOCDEL, (caddr_t)apr) < 0) {
+ fprintf(stderr, "%s: ", prog);
+ switch (errno) {
+ case EINVAL:
+ fprintf(stderr, "Invalid parameter\n");
+ break;
+ case ENOENT:
+ fprintf(stderr, "VCC not found\n");
+ break;
+ case EALREADY:
+ fprintf(stderr, "VCC already being closed\n");
+ break;
+ case ENXIO:
+ fprintf(stderr, "%s is not an ATM device\n",
+ apr->adr_pvc_intf);
+ break;
+ case EPERM:
+ fprintf(stderr, "Must be super user to use delete subcommand\n");
+ break;
+ default:
+ perror("ioctl (AIOCDEL) delete");
+ break;
+ }
+ exit(1);
+ }
+ (void)close(s);
+}
+
+
+/*
+ * Process ARP delete command
+ *
+ * Command formats:
+ * atm delete arp <IP addr>
+ *
+ * Arguments:
+ * argc number of arguments to command
+ * argv pointer to argument strings
+ * cmdp pointer to command description
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+arp_dlt(argc, argv, cmdp)
+ int argc;
+ char **argv;
+ struct cmd *cmdp;
+{
+ int s;
+ struct atmdelreq apr;
+ struct sockaddr_in *sin;
+ union {
+ struct sockaddr_in sin;
+ struct sockaddr sa;
+ } host_addr;
+
+ /*
+ * Set opcode
+ */
+ UM_ZERO(&apr, sizeof(apr));
+ apr.adr_opcode = AIOCS_DEL_ARP;
+
+ /*
+ * Get network interface name if one is present
+ */
+ if (argc == 2) {
+ check_netif_name(argv[0]);
+ strcpy(apr.adr_arp_intf, argv[0]);
+ argc--; argv++;
+ }
+
+ /*
+ * Get IP address of specified host name
+ */
+ UM_ZERO(&host_addr, sizeof(host_addr));
+ host_addr.sa.sa_family = AF_INET;
+ sin = get_ip_addr(argv[0]);
+ host_addr.sin.sin_addr.s_addr = sin->sin_addr.s_addr;
+ apr.adr_arp_dst = host_addr.sa;
+
+ /*
+ * Tell the kernel to delete the ARP table entry
+ */
+ s = socket(AF_ATM, SOCK_DGRAM, 0);
+ if (s < 0) {
+ sock_error(errno);
+ }
+ if (ioctl(s, AIOCDEL, (caddr_t)&apr) < 0) {
+ fprintf(stderr, "%s: ", prog);
+ switch (errno) {
+ case EINVAL:
+ fprintf(stderr, "Invalid parameter\n");
+ break;
+ case EPERM:
+ fprintf(stderr, "Must be super user to use delete subcommand\n");
+ break;
+ default:
+ perror("ioctl (AIOCDEL) delete");
+ break;
+ }
+ exit(1);
+ }
+ (void)close(s);
+}
+
+
+/*
+ * Process help command
+ *
+ * Arguments:
+ * argc number of arguments to command
+ * argv pointer to argument strings
+ * cmdp pointer to command description
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+help(argc, argv, cmdp)
+ int argc;
+ char **argv;
+ struct cmd *cmdp;
+{
+ usage(cmds, "");
+}
diff --git a/sbin/atm/atm/atm.h b/sbin/atm/atm/atm.h
new file mode 100644
index 0000000..efb8d1e
--- /dev/null
+++ b/sbin/atm/atm/atm.h
@@ -0,0 +1,212 @@
+/*
+ *
+ * ===================================
+ * 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: atm.h,v 1.9 1998/07/09 21:23:53 johnc Exp $
+ *
+ */
+
+/*
+ * User configuration and display program
+ * --------------------------------------
+ *
+ * Control blocks
+ *
+ */
+
+#define MAX_NIFS 32 /* Max network interfaces */
+#define MIN_VCI 32 /* Smallest non-reserved VCI */
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+
+/*
+ * User commands
+ */
+struct cmd {
+ char *name; /* Command name */
+ int minp; /* Minimum number of parameters */
+ int maxp; /* Maximum number of parameters */
+ void (*func) /* Processing function */
+ __P((int, char **, struct cmd *));
+ char *help; /* User help string */
+};
+
+
+/*
+ * Supported signalling protocols
+ */
+struct proto {
+ char *p_name; /* Protocol name */
+ u_char p_id; /* Protocol id */
+};
+
+
+/*
+ * Table of state names
+ */
+struct state {
+ char *s_name; /* State name */
+ u_char s_id; /* State id */
+};
+
+
+/*
+ * Supported signalling protocol states
+ */
+struct proto_state {
+ char *p_name; /* Signalling manager name */
+ struct state *p_state; /* Protocol state table */
+ struct state *v_state; /* Protocol VCC state table */
+ u_char p_id; /* Protocol ID */
+};
+
+
+/*
+ * Supported VCC owners
+ */
+struct owner {
+ char *o_name; /* Owner name */
+ u_int o_sap; /* Owner's SAP */
+ void (*o_pvcadd) /* PVC ADD processing function */
+ __P((int, char **, struct cmd *, struct atmaddreq *,
+ struct air_int_rsp *));
+};
+
+
+/*
+ * Supported AALs
+ */
+struct aal {
+ char *a_name; /* AAL name */
+ u_char a_id; /* AAL code */
+};
+
+
+/*
+ * Supported encapsulations
+ */
+struct encaps {
+ char *e_name; /* Encapsulation name */
+ u_char e_id; /* Encapsulation code */
+};
+
+
+/*
+ * External variables
+ */
+extern char *prog; /* Program invocation */
+extern char prefix[]; /* Current command prefix */
+
+/*
+ * Global function declarations
+ */
+ /* atm.c */
+int do_cmd __P((struct cmd *, int, char **));
+void usage __P((struct cmd *, char *));
+void attach __P((int, char **, struct cmd *));
+void detach __P((int, char **, struct cmd *));
+void pvc_add __P((int, char **, struct cmd *));
+void arp_add __P((int, char **, struct cmd *));
+void pvc_dlt __P((int, char **, struct cmd *));
+void svc_dlt __P((int, char **, struct cmd *));
+void vcc_dlt __P((int, char **, struct cmd *, struct atmdelreq *));
+void arp_dlt __P((int, char **, struct cmd *));
+void help __P((int, char **, struct cmd *));
+
+ /* atm_eni.c */
+void show_eni_stats __P((char *, int, char **));
+void print_eni_oc3 __P((struct air_vinfo_rsp *));
+void print_eni_atm __P((struct air_vinfo_rsp *));
+void print_eni_aal0 __P((struct air_vinfo_rsp *));
+void print_eni_aal5 __P((struct air_vinfo_rsp *));
+void print_eni_driver __P((struct air_vinfo_rsp *));
+
+ /* atm_fore200.c */
+void show_fore200_stats __P((char *, int, char **));
+void print_fore200_taxi __P((struct air_vinfo_rsp *));
+void print_fore200_oc3 __P((struct air_vinfo_rsp *));
+void print_fore200_dev __P((struct air_vinfo_rsp *));
+void print_fore200_atm __P((struct air_vinfo_rsp *));
+void print_fore200_aal0 __P((struct air_vinfo_rsp *));
+void print_fore200_aal4 __P((struct air_vinfo_rsp *));
+void print_fore200_aal5 __P((struct air_vinfo_rsp *));
+void print_fore200_driver __P((struct air_vinfo_rsp *));
+
+ /* atm_inet.c */
+void ip_pvcadd __P((int, char **, struct cmd *, struct atmaddreq *,
+ struct air_int_rsp *));
+
+ /* atm_print.c */
+void print_arp_info __P((struct air_arp_rsp *));
+void print_asrv_info __P((struct air_asrv_rsp *));
+void print_intf_info __P((struct air_int_rsp *));
+void print_ip_vcc_info __P((struct air_ip_vcc_rsp *));
+void print_netif_info __P((struct air_netif_rsp *));
+void print_intf_stats __P((struct air_phy_stat_rsp *));
+void print_vcc_stats __P((struct air_vcc_rsp *));
+void print_vcc_info __P((struct air_vcc_rsp *));
+void print_version_info __P((struct air_version_rsp *));
+
+ /* atm_set.c */
+void set_arpserver __P((int, char **, struct cmd *));
+void set_macaddr __P((int, char **, struct cmd *));
+void set_netif __P((int, char **, struct cmd *));
+void set_prefix __P((int, char **, struct cmd *));
+
+ /* atm_show.c */
+void show_arp __P((int, char **, struct cmd *));
+void show_arpserv __P((int, char **, struct cmd *));
+void show_config __P((int, char **, struct cmd *));
+void show_intf __P((int, char **, struct cmd *));
+void show_ip_vcc __P((int, char **, struct cmd *));
+void show_netif __P((int, char **, struct cmd *));
+void show_intf_stats __P((int, char **, struct cmd *));
+void show_vcc_stats __P((int, char **, struct cmd *));
+void show_vcc __P((int, char **, struct cmd *));
+void show_version __P((int, char **, struct cmd *));
+
+ /* atm_subr.c */
+char * get_vendor __P((int));
+char * get_adapter __P((int));
+char * get_media_type __P((int));
+char * get_bus_type __P((int));
+char * get_bus_slot_info __P((int, u_long));
+char * get_adapter_name __P((char *));
+int do_info_ioctl __P((struct atminfreq *, int));
+int get_vcc_info __P((char *, struct air_vcc_rsp **));
+int verify_nif_name __P((char *));
+struct sockaddr_in *
+ get_ip_addr __P((char *));
+int get_hex_addr __P((char *, u_char *, int));
+char * format_mac_addr __P((Mac_addr *));
+int parse_ip_prefix __P((char *, struct in_addr *));
+int compress_prefix_list __P((struct in_addr *, int));
+void check_netif_name __P((char *));
+void sock_error __P((int));
diff --git a/sbin/atm/atm/atm_eni.c b/sbin/atm/atm/atm_eni.c
new file mode 100644
index 0000000..272e48f
--- /dev/null
+++ b/sbin/atm/atm/atm_eni.c
@@ -0,0 +1,437 @@
+/*
+ *
+ * ===================================
+ * 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: atm_eni.c,v 1.8 1998/08/26 23:29:31 mks Exp $
+ *
+ */
+
+/*
+ * User configuration and display program
+ * --------------------------------------
+ *
+ * Routines for Efficient-specific subcommands
+ *
+ */
+
+#ifndef lint
+static char *RCSid = "@(#) $Id: atm_eni.c,v 1.8 1998/08/26 23:29:31 mks Exp $";
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.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_sap.h>
+#include <netatm/atm_sys.h>
+#include <netatm/atm_ioctl.h>
+
+#include <libatm.h>
+#include "atm.h"
+#include <dev/hea/eni_stats.h>
+
+
+/*
+ * Local constants
+ */
+#define SHOW_PHY 1
+#define SHOW_ATM 2
+#define SHOW_AAL0 4
+#define SHOW_AAL5 8
+#define SHOW_DRIVER 64
+
+
+/*
+ * Headers for statistics
+ */
+#define ATM_STATS_HDR \
+"%s ATM Layer Statistics\n\
+ Cells In Cells Out\n"
+
+#define AAL0_STATS_HDR \
+"%s AAL 0 Statistics\n\
+ Cells In Cells Out Cell Drops\n"
+
+#define AAL5_STATS_HDR \
+"%s AAL 5 Statistics\n\
+ CRC/Len CRC Proto PDU\n\
+ Cells In Cells Out Errs Drops PDUs In PDUs Out Errs Errs Drops\n"
+
+#define DRIVER_STATS_HDR_1 \
+"%s Device Driver Statistics\n\
+ Buf Buf Buf Buf Can't VCC VCC No No No RX RX\n\
+ Req No No Alrdy Find PDU Range Resrc RX DMA Queue\n\
+ Size Descr Mem Free Descr Size Error In Bufs Room Full\n"
+
+#define DRIVER_STATS_HDR_2 \
+"%s Device Driver Statistics\n\
+ No ATM No RX No TX Seg Max No No No TX\n\
+ RX IntrQ DMA DMA Not Seg Seg TX Resrc DMA\n\
+ VCC Full Room Addr Align Pad Out Buf Out Room\n"
+
+#define OC3_STATS_HDR \
+"%s OC-3c Statistics\n\
+Section Path Line Line Path Corr Uncorr\n\
+BIP8 BIP8 BIP24 FEBE FEBE HCS HCS\n\
+Errs Errs Errs Errs Errs Errs Errs\n"
+
+
+/*
+ * Process show ENI statistics command
+ *
+ * The statistics printed are vendor-specific, depending on the brand of
+ * the interface card.
+ *
+ * Command format:
+ * atm show stats interface [<interface-name> [phy | dev | atm |
+ aal0 | aal5 | driver ]]
+ *
+ * Arguments:
+ * intf interface to print statistics for
+ * argc number of remaining arguments to command
+ * argv pointer to remaining argument strings
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+show_eni_stats(intf, argc, argv)
+ char *intf;
+ int argc;
+ char **argv;
+{
+ int buf_len, stats_type;
+ struct atminfreq air;
+ struct air_vinfo_rsp *stats;
+
+ /*
+ * Get statistics type qualifier
+ */
+ if (!strcasecmp("phy", argv[0])) {
+ stats_type = SHOW_PHY;
+ } else if (!strcasecmp("atm", argv[0])) {
+ stats_type = SHOW_ATM;
+ } else if (!strcasecmp("aal0", argv[0])) {
+ stats_type = SHOW_AAL0;
+ } else if (!strcasecmp("aal5", argv[0])) {
+ stats_type = SHOW_AAL5;
+ } else if (!strcasecmp("driver", argv[0])) {
+ stats_type = SHOW_DRIVER;
+ } else {
+ fprintf(stderr, "%s: Illegal or unsupported statistics type\n", prog);
+ exit(1);
+ }
+ argc--; argv++;
+
+ /*
+ * Get vendor-specific statistics from the kernel
+ */
+ UM_ZERO(&air, sizeof(air));
+ air.air_opcode = AIOCS_INF_VST;
+ strcpy(air.air_vinfo_intf, intf);
+ buf_len = do_info_ioctl(&air, sizeof(struct air_vinfo_rsp) + 1024);
+ if (buf_len < 0) {
+ fprintf(stderr, "%s: ", prog);
+ switch (errno) {
+ case ENOPROTOOPT:
+ case EOPNOTSUPP:
+ perror("Internal error");
+ break;
+ case ENXIO:
+ fprintf(stderr, "%s is not an ATM device\n",
+ intf);
+ break;
+ default:
+ perror("ioctl (AIOCINFO)");
+ break;
+ }
+ exit(1);
+ }
+ stats = (struct air_vinfo_rsp *) air.air_buf_addr;
+
+ /*
+ * Print the statistics
+ */
+ if (buf_len < sizeof(struct air_vinfo_rsp) +
+ sizeof(Eni_stats)) {
+ UM_FREE(stats);
+ return;
+ }
+
+ switch (stats_type) {
+ case SHOW_PHY:
+ print_eni_oc3(stats);
+ break;
+ case SHOW_ATM:
+ print_eni_atm(stats);
+ break;
+ case SHOW_AAL0:
+ print_eni_aal0(stats);
+ break;
+ case SHOW_AAL5:
+ print_eni_aal5(stats);
+ break;
+ case SHOW_DRIVER:
+ print_eni_driver(stats);
+ break;
+ }
+
+ UM_FREE(stats);
+}
+
+
+/*
+ * Print ENI OC-3c statistics
+ *
+ * Arguments:
+ * vi pointer to vendor-specific statistics to print
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+print_eni_oc3(vi)
+ struct air_vinfo_rsp *vi;
+{
+ Eni_stats *stats;
+
+ /*
+ * Bump stats pointer past header info
+ */
+ stats = (Eni_stats *)
+ ((u_long) vi + sizeof(struct air_vinfo_rsp));
+
+ /*
+ * Print a header
+ */
+ printf(OC3_STATS_HDR, get_adapter_name(vi->avsp_intf));
+
+ /*
+ * Print the OC-3c info
+ */
+ printf("%7d %7d %7d %7d %7d %7d %7d\n",
+ stats->eni_st_oc3.oc3_sect_bip8,
+ stats->eni_st_oc3.oc3_path_bip8,
+ stats->eni_st_oc3.oc3_line_bip24,
+ stats->eni_st_oc3.oc3_line_febe,
+ stats->eni_st_oc3.oc3_path_febe,
+ stats->eni_st_oc3.oc3_hec_corr,
+ stats->eni_st_oc3.oc3_hec_uncorr);
+}
+
+
+/*
+ * Print ENI ATM statistics
+ *
+ * Arguments:
+ * vi pointer to vendor-specific statistics to print
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+print_eni_atm(vi)
+ struct air_vinfo_rsp *vi;
+{
+ Eni_stats *stats;
+
+ /*
+ * Bump stats pointer past header info
+ */
+ stats = (Eni_stats *)
+ ((u_long) vi + sizeof(struct air_vinfo_rsp));
+
+ /*
+ * Print a header
+ */
+ printf(ATM_STATS_HDR, get_adapter_name(vi->avsp_intf));
+
+ /*
+ * Print the ATM layer info
+ */
+ printf("%10d %10d\n",
+ stats->eni_st_atm.atm_rcvd,
+ stats->eni_st_atm.atm_xmit);
+}
+
+
+/*
+ * Print ENI AAL 0 statistics
+ *
+ * Arguments:
+ * vi pointer to vendor-specific statistics to print
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+print_eni_aal0(vi)
+ struct air_vinfo_rsp *vi;
+{
+ Eni_stats *stats;
+
+ /*
+ * Bump stats pointer past header info
+ */
+ stats = (Eni_stats *)
+ ((u_long) vi + sizeof(struct air_vinfo_rsp));
+
+ /*
+ * Print a header
+ */
+ printf(AAL0_STATS_HDR, get_adapter_name(vi->avsp_intf));
+
+ /*
+ * Print the AAL 0 info
+ */
+ printf("%10d %10d %10d\n",
+ stats->eni_st_aal0.aal0_rcvd,
+ stats->eni_st_aal0.aal0_xmit,
+ stats->eni_st_aal0.aal0_drops);
+}
+
+
+/*
+ * Print ENI AAL 5 statistics
+ *
+ * Arguments:
+ * vi pointer to vendor-specific statistics to print
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+print_eni_aal5(vi)
+ struct air_vinfo_rsp *vi;
+{
+ Eni_stats *stats;
+
+ /*
+ * Bump stats pointer past header info
+ */
+ stats = (Eni_stats *)
+ ((u_long) vi + sizeof(struct air_vinfo_rsp));
+
+ /*
+ * Print a header
+ */
+ printf(AAL5_STATS_HDR, get_adapter_name(vi->avsp_intf));
+
+ /*
+ * Print the AAL 5 info
+ */
+ printf("%10d %10d %5d %5d %9d %9d %5d %5d %5d\n",
+ stats->eni_st_aal5.aal5_rcvd,
+ stats->eni_st_aal5.aal5_xmit,
+ stats->eni_st_aal5.aal5_crc_len,
+ stats->eni_st_aal5.aal5_drops,
+ stats->eni_st_aal5.aal5_pdu_rcvd,
+ stats->eni_st_aal5.aal5_pdu_xmit,
+ stats->eni_st_aal5.aal5_pdu_crc,
+ stats->eni_st_aal5.aal5_pdu_errs,
+ stats->eni_st_aal5.aal5_pdu_drops);
+}
+
+/*
+ * Print Efficient device driver statistics
+ *
+ * Arguments:
+ * vi pointer to vendor-specific statistics to print
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+print_eni_driver(vi)
+ struct air_vinfo_rsp *vi;
+{
+ Eni_stats *stats;
+
+ /*
+ * Bump stats pointer past header info
+ */
+ stats = (Eni_stats *)
+ ((u_long) vi + sizeof(struct air_vinfo_rsp));
+
+ /*
+ * Print 1st header
+ */
+ printf(DRIVER_STATS_HDR_1, get_adapter_name(vi->avsp_intf));
+
+ /*
+ * Print the driver info
+ */
+ printf ( "%5d %5d %5d %5d %5d %5d %5d %5d %5d %5d %5d\n",
+ stats->eni_st_drv.drv_mm_toobig,
+ stats->eni_st_drv.drv_mm_nodesc,
+ stats->eni_st_drv.drv_mm_nobuf,
+ stats->eni_st_drv.drv_mm_notuse,
+ stats->eni_st_drv.drv_mm_notfnd,
+ stats->eni_st_drv.drv_vc_maxpdu,
+ stats->eni_st_drv.drv_vc_badrng,
+ stats->eni_st_drv.drv_rv_norsc,
+ stats->eni_st_drv.drv_rv_nobufs,
+ stats->eni_st_drv.drv_rv_nodma,
+ stats->eni_st_drv.drv_rv_rxq
+ );
+
+ /*
+ * Print 2nd header
+ */
+ printf(DRIVER_STATS_HDR_2, get_adapter_name(vi->avsp_intf));
+
+ /*
+ * Print the driver info
+ */
+ printf ( "%5d %5d %5d %5d %5d %5d %5d %7d %5d %7d\n",
+ stats->eni_st_drv.drv_rv_novcc,
+ stats->eni_st_drv.drv_rv_intrq,
+ stats->eni_st_drv.drv_rv_segdma,
+ stats->eni_st_drv.drv_xm_segdma,
+ stats->eni_st_drv.drv_xm_segnoal,
+ stats->eni_st_drv.drv_xm_seglen,
+ stats->eni_st_drv.drv_xm_maxpdu,
+ stats->eni_st_drv.drv_xm_nobuf,
+ stats->eni_st_drv.drv_xm_norsc,
+ stats->eni_st_drv.drv_xm_nodma
+ );
+
+
+}
+
diff --git a/sbin/atm/atm/atm_fore200.c b/sbin/atm/atm/atm_fore200.c
new file mode 100644
index 0000000..9dd64b4
--- /dev/null
+++ b/sbin/atm/atm/atm_fore200.c
@@ -0,0 +1,603 @@
+/*
+ *
+ * ===================================
+ * 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: atm_fore200.c,v 1.10 1998/08/26 23:29:31 mks Exp $
+ *
+ */
+
+/*
+ * User configuration and display program
+ * --------------------------------------
+ *
+ * Routines for Fore SBA-200-specific subcommands
+ *
+ */
+
+#ifndef lint
+static char *RCSid = "@(#) $Id: atm_fore200.c,v 1.10 1998/08/26 23:29:31 mks Exp $";
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.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_sap.h>
+#include <netatm/atm_sys.h>
+#include <netatm/atm_ioctl.h>
+
+#include <libatm.h>
+#include "atm.h"
+#include <dev/hfa/fore_aali.h>
+#include <dev/hfa/fore_slave.h>
+#include <dev/hfa/fore_stats.h>
+
+
+/*
+ * Local constants
+ */
+#define SHOW_PHY 1
+#define SHOW_DEV 2
+#define SHOW_ATM 4
+#define SHOW_AAL0 8
+#define SHOW_AAL4 16
+#define SHOW_AAL5 32
+#define SHOW_DRIVER 64
+
+
+/*
+ * Headers for statistics
+ */
+#define TAXI_STATS_HDR \
+"%s TAXI Statistics\n\
+ CRC Errs Framing Errs\n"
+
+#define DEV_STATS_HDR \
+"%s Device Statistics\n\
+Type 1 Type 1 Type 2 Type 2\n\
+Small Buff Large Buff Small Buff Large Buff Receive Receive\n\
+Alloc Fail Alloc Fail Alloc Fail Alloc Fail Queue Full Carrier\n"
+
+#define ATM_STATS_HDR \
+"%s ATM Layer Statistics\n\
+ Cells In Cells Out VPI Range VPI NoConn VCI Range VCI NoConn\n"
+
+#define AAL0_STATS_HDR \
+"%s AAL 0 Statistics\n\
+ Cells In Cells Out Cell Drops\n"
+
+#define AAL4_STATS_HDR \
+"%s AAL 4 Statistics\n\
+ CRC Proto Cell PDU PDU\n\
+ Cells In Cells Out Errs Errs Drops PDUs In PDUs Out Errs Drops\n"
+
+#define AAL5_STATS_HDR \
+"%s AAL 5 Statistics\n\
+ CRC/Len CRC Proto PDU\n\
+ Cells In Cells Out Errs Drops PDUs In PDUs Out Errs Errs Drops\n"
+
+#define DRIVER_STATS_HDR \
+"%s Device Driver Statistics\n\
+ No Xmit Max Seg No No No IQ No Cmd No\n\
+ VCC Queue Seg Not Seg DMA VCC No Mbuf Full DMA Queue DMA\n\
+ Out Full Size Align Pad Out In Buff In In Sup Full Cmd\n"
+
+#define OC3_STATS_HDR \
+"%s OC-3c Statistics\n\
+Section Path Line Line Path Corr Uncorr\n\
+BIP8 BIP8 BIP24 FEBE FEBE HCS HCS\n\
+Errs Errs Errs Errs Errs Errs Errs\n"
+
+
+/*
+ * Process show Fore SBA-200 statistics command
+ *
+ * The statistics printed are vendor-specific, depending on the brand of
+ * the interface card.
+ *
+ * Command format:
+ * atm show stats interface [<interface-name> [phy | dev | atm |
+ * aal0 | aal4 | aal5 | driver]]
+ *
+ * Arguments:
+ * intf interface statistics are for
+ * argc number of remaining arguments to command
+ * argv pointer to remaining argument strings
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+show_fore200_stats(intf, argc, argv)
+ char *intf;
+ int argc;
+ char **argv;
+{
+ int buf_len, stats_type;
+ struct air_cfg_rsp *cfg;
+ struct air_vinfo_rsp *stats;
+ struct atminfreq air;
+
+ /*
+ * Get statistics type qualifier
+ */
+ if (!strcasecmp("phy", argv[0])) {
+ stats_type = SHOW_PHY;
+ } else if (!strcasecmp("dev", argv[0])) {
+ stats_type = SHOW_DEV;
+ } else if (!strcasecmp("atm", argv[0])) {
+ stats_type = SHOW_ATM;
+ } else if (!strcasecmp("aal0", argv[0])) {
+ stats_type = SHOW_AAL0;
+ } else if (!strcasecmp("aal4", argv[0])) {
+ stats_type = SHOW_AAL4;
+ } else if (!strcasecmp("aal5", argv[0])) {
+ stats_type = SHOW_AAL5;
+ } else if (!strcasecmp("driver", argv[0])) {
+ stats_type = SHOW_DRIVER;
+ } else {
+ fprintf(stderr, "%s: Illegal statistics type\n", prog);
+ exit(1);
+ }
+ argc--; argv++;
+
+ /*
+ * Get adapter configuration from the kernel
+ */
+ UM_ZERO(&air, sizeof(air));
+ air.air_opcode = AIOCS_INF_CFG;
+ strcpy(air.air_cfg_intf, intf);
+ buf_len = do_info_ioctl(&air, sizeof(struct air_cfg_rsp));
+ if (buf_len < 0) {
+ fprintf(stderr, "%s: ", prog);
+ switch (errno) {
+ case ENOPROTOOPT:
+ case EOPNOTSUPP:
+ perror("Internal error");
+ break;
+ case ENXIO:
+ fprintf(stderr, "%s is not an ATM device\n",
+ intf);
+ break;
+ default:
+ perror("ioctl (AIOCINFO)");
+ break;
+ }
+ exit(1);
+ }
+ cfg = (struct air_cfg_rsp *) air.air_buf_addr;
+
+ /*
+ * Get vendor-specific statistics from the kernel
+ */
+ UM_ZERO(&air, sizeof(air));
+ air.air_opcode = AIOCS_INF_VST;
+ strcpy(air.air_vinfo_intf, intf);
+ buf_len = do_info_ioctl(&air, sizeof(struct air_vinfo_rsp) + 1024);
+ if (buf_len < 0) {
+ fprintf(stderr, "%s: ", prog);
+ switch (errno) {
+ case ENOPROTOOPT:
+ case EOPNOTSUPP:
+ perror("Internal error");
+ break;
+ case ENXIO:
+ fprintf(stderr, "%s is not an ATM device\n",
+ intf);
+ break;
+ default:
+ perror("ioctl (AIOCINFO)");
+ break;
+ }
+ exit(1);
+ }
+ stats = (struct air_vinfo_rsp *) air.air_buf_addr;
+
+ /*
+ * Print the statistics
+ */
+ if (buf_len < sizeof(struct air_vinfo_rsp) +
+ sizeof(Fore_stats)) {
+ UM_FREE(stats);
+ UM_FREE(cfg);
+ return;
+ }
+
+ switch (stats_type) {
+ case SHOW_PHY:
+ switch (cfg->acp_media) {
+ case MEDIA_TAXI_100:
+ case MEDIA_TAXI_140:
+ print_fore200_taxi(stats);
+ break;
+ case MEDIA_OC3C:
+ print_fore200_oc3(stats);
+ break;
+ case MEDIA_OC12C:
+ break;
+ default:
+ break;
+ }
+ break;
+ case SHOW_DEV:
+ print_fore200_dev(stats);
+ break;
+ case SHOW_ATM:
+ print_fore200_atm(stats);
+ break;
+ case SHOW_AAL0:
+ print_fore200_aal0(stats);
+ break;
+ case SHOW_AAL4:
+ print_fore200_aal4(stats);
+ break;
+ case SHOW_AAL5:
+ print_fore200_aal5(stats);
+ break;
+ case SHOW_DRIVER:
+ print_fore200_driver(stats);
+ break;
+ }
+
+ UM_FREE(stats);
+ UM_FREE(cfg);
+}
+
+
+/*
+ * Print Fore ASX-200 TAXI statistics
+ *
+ * Arguments:
+ * vi pointer to vendor-specific statistics to print
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+print_fore200_taxi(vi)
+ struct air_vinfo_rsp *vi;
+{
+ Fore_stats *stats;
+
+ /*
+ * Bump stats pointer past header info
+ */
+ stats = (Fore_stats *)
+ ((u_long) vi + sizeof(struct air_vinfo_rsp));
+
+ /*
+ * Print a header
+ */
+ printf(TAXI_STATS_HDR, get_adapter_name(vi->avsp_intf));
+
+ /*
+ * Print the physical layer info
+ */
+ printf("%10d %12d\n",
+ stats->st_taxi.taxi_bad_crc,
+ stats->st_taxi.taxi_framing);
+}
+
+
+/*
+ * Print Fore ASX-200 OC-3c statistics
+ *
+ * Arguments:
+ * vi pointer to vendor-specific statistics to print
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+print_fore200_oc3(vi)
+ struct air_vinfo_rsp *vi;
+{
+ Fore_stats *stats;
+
+ /*
+ * Bump stats pointer past header info
+ */
+ stats = (Fore_stats *)
+ ((u_long) vi + sizeof(struct air_vinfo_rsp));
+
+ /*
+ * Print a header
+ */
+ printf(OC3_STATS_HDR, get_adapter_name(vi->avsp_intf));
+
+ /*
+ * Print the OC-3c info
+ */
+ printf("%7d %7d %7d %7d %7d %7d %7d\n",
+ stats->st_oc3.oc3_sect_bip8,
+ stats->st_oc3.oc3_path_bip8,
+ stats->st_oc3.oc3_line_bip24,
+ stats->st_oc3.oc3_line_febe,
+ stats->st_oc3.oc3_path_febe,
+ stats->st_oc3.oc3_hec_corr,
+ stats->st_oc3.oc3_hec_uncorr);
+}
+
+
+/*
+ * Print Fore ASX-200 device statistics
+ *
+ * Arguments:
+ * vi pointer to vendor-specific statistics to print
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+print_fore200_dev(vi)
+ struct air_vinfo_rsp *vi;
+{
+ Fore_stats *stats;
+
+ /*
+ * Bump stats pointer past header info
+ */
+ stats = (Fore_stats *)
+ ((u_long) vi + sizeof(struct air_vinfo_rsp));
+
+ /*
+ * Print a header
+ */
+ printf(DEV_STATS_HDR, get_adapter_name(vi->avsp_intf));
+
+ /*
+ * Print the device info
+ */
+ printf("%10d %10d %10d %10d %10d %s\n",
+ stats->st_misc.buf1_sm_fail,
+ stats->st_misc.buf1_lg_fail,
+ stats->st_misc.buf2_sm_fail,
+ stats->st_misc.buf2_lg_fail,
+ stats->st_misc.rcvd_pdu_fail,
+ (stats->st_misc.carrier_status ? "On" : "Off"));
+}
+
+
+/*
+ * Print Fore ASX-200 ATM statistics
+ *
+ * Arguments:
+ * vi pointer to vendor-specific statistics to print
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+print_fore200_atm(vi)
+ struct air_vinfo_rsp *vi;
+{
+ Fore_stats *stats;
+
+ /*
+ * Bump stats pointer past header info
+ */
+ stats = (Fore_stats *)
+ ((u_long) vi + sizeof(struct air_vinfo_rsp));
+
+ /*
+ * Print a header
+ */
+ printf(ATM_STATS_HDR, get_adapter_name(vi->avsp_intf));
+
+ /*
+ * Print the ATM layer info
+ */
+ printf("%10d %10d %10d %10d %10d %10d\n",
+ stats->st_atm.atm_rcvd,
+ stats->st_atm.atm_xmit,
+ stats->st_atm.atm_vpi_range,
+ stats->st_atm.atm_vpi_noconn,
+ stats->st_atm.atm_vci_range,
+ stats->st_atm.atm_vci_noconn);
+}
+
+
+/*
+ * Print Fore ASX-200 AAL 0 statistics
+ *
+ * Arguments:
+ * vi pointer to vendor-specific statistics to print
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+print_fore200_aal0(vi)
+ struct air_vinfo_rsp *vi;
+{
+ Fore_stats *stats;
+
+ /*
+ * Bump stats pointer past header info
+ */
+ stats = (Fore_stats *)
+ ((u_long) vi + sizeof(struct air_vinfo_rsp));
+
+ /*
+ * Print a header
+ */
+ printf(AAL0_STATS_HDR, get_adapter_name(vi->avsp_intf));
+
+ /*
+ * Print the AAL 0 info
+ */
+ printf("%10d %10d %10d\n",
+ stats->st_aal0.aal0_rcvd,
+ stats->st_aal0.aal0_xmit,
+ stats->st_aal0.aal0_drops);
+}
+
+
+/*
+ * Print Fore ASX-200 AAL 4 statistics
+ *
+ * Arguments:
+ * vi pointer to vendor-specific statistics to print
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+print_fore200_aal4(vi)
+ struct air_vinfo_rsp *vi;
+{
+ Fore_stats *stats;
+
+ /*
+ * Bump stats pointer past header info
+ */
+ stats = (Fore_stats *)
+ ((u_long) vi + sizeof(struct air_vinfo_rsp));
+
+ /*
+ * Print a header
+ */
+ printf(AAL4_STATS_HDR, get_adapter_name(vi->avsp_intf));
+
+ /*
+ * Print the AAL 4 info
+ */
+ printf("%10d %10d %5d %5d %5d %9d %9d %5d %5d\n",
+ stats->st_aal4.aal4_rcvd,
+ stats->st_aal4.aal4_xmit,
+ stats->st_aal4.aal4_crc,
+ stats->st_aal4.aal4_sar_cs,
+ stats->st_aal4.aal4_drops,
+ stats->st_aal4.aal4_pdu_rcvd,
+ stats->st_aal4.aal4_pdu_xmit,
+ stats->st_aal4.aal4_pdu_errs,
+ stats->st_aal4.aal4_pdu_drops);
+}
+
+
+/*
+ * Print Fore ASX-200 AAL 5 statistics
+ *
+ * Arguments:
+ * vi pointer to vendor-specific statistics to print
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+print_fore200_aal5(vi)
+ struct air_vinfo_rsp *vi;
+{
+ Fore_stats *stats;
+
+ /*
+ * Bump stats pointer past header info
+ */
+ stats = (Fore_stats *)
+ ((u_long) vi + sizeof(struct air_vinfo_rsp));
+
+ /*
+ * Print a header
+ */
+ printf(AAL5_STATS_HDR, get_adapter_name(vi->avsp_intf));
+
+ /*
+ * Print the AAL 5 info
+ */
+ printf("%10d %10d %5d %5d %9d %9d %5d %5d %5d\n",
+ stats->st_aal5.aal5_rcvd,
+ stats->st_aal5.aal5_xmit,
+ stats->st_aal5.aal5_crc_len,
+ stats->st_aal5.aal5_drops,
+ stats->st_aal5.aal5_pdu_rcvd,
+ stats->st_aal5.aal5_pdu_xmit,
+ stats->st_aal5.aal5_pdu_crc,
+ stats->st_aal5.aal5_pdu_errs,
+ stats->st_aal5.aal5_pdu_drops);
+}
+
+
+/*
+ * Print Fore ASX-200 device driver statistics
+ *
+ * Arguments:
+ * vi pointer to vendor-specific statistics to print
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+print_fore200_driver(vi)
+ struct air_vinfo_rsp *vi;
+{
+ Fore_stats *stats;
+
+ /*
+ * Bump stats pointer past header info
+ */
+ stats = (Fore_stats *)
+ ((u_long) vi + sizeof(struct air_vinfo_rsp));
+
+ /*
+ * Print a header
+ */
+ printf(DRIVER_STATS_HDR, get_adapter_name(vi->avsp_intf));
+
+ /*
+ * Print the driver info
+ */
+ printf("%4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d\n",
+ stats->st_drv.drv_xm_notact,
+ stats->st_drv.drv_xm_full,
+ stats->st_drv.drv_xm_maxpdu,
+ stats->st_drv.drv_xm_segnoal,
+ stats->st_drv.drv_xm_seglen,
+ stats->st_drv.drv_xm_segdma,
+ stats->st_drv.drv_rv_novcc,
+ stats->st_drv.drv_rv_nosbf,
+ stats->st_drv.drv_rv_nomb,
+ stats->st_drv.drv_rv_ifull,
+ stats->st_drv.drv_bf_segdma,
+ stats->st_drv.drv_cm_full,
+ stats->st_drv.drv_cm_nodma);
+
+}
diff --git a/sbin/atm/atm/atm_inet.c b/sbin/atm/atm/atm_inet.c
new file mode 100644
index 0000000..91b62dc
--- /dev/null
+++ b/sbin/atm/atm/atm_inet.c
@@ -0,0 +1,164 @@
+/*
+ *
+ * ===================================
+ * 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: atm_inet.c,v 1.9 1998/08/26 23:29:31 mks Exp $
+ *
+ */
+
+/*
+ * User configuration and display program
+ * --------------------------------------
+ *
+ * IP support
+ *
+ */
+
+#ifndef lint
+static char *RCSid = "@(#) $Id: atm_inet.c,v 1.9 1998/08/26 23:29:31 mks Exp $";
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <string.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_sap.h>
+#include <netatm/atm_sys.h>
+#include <netatm/atm_ioctl.h>
+
+#include <libatm.h>
+#include "atm.h"
+
+
+/*
+ * Process add command for a TCP/IP PVC
+ *
+ * Command format:
+ * atm add pvc <intf> <vpi> <vci> <aal> <encaps> IP <netif>
+ * <IP addr> | dynamic
+ *
+ * Arguments:
+ * argc number of remaining arguments to command
+ * argv pointer to remaining argument strings
+ * cmdp pointer to command description
+ * app pointer to AIOCAPVC structure
+ * intp pointer to air_int_rsp structure with information
+ * about the physical interface that is the PVC is for.
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+ip_pvcadd(argc, argv, cmdp, app, intp)
+ int argc;
+ char **argv;
+ struct cmd *cmdp;
+ struct atmaddreq *app;
+ struct air_int_rsp *intp;
+{
+ char *cp;
+ char nhelp[128];
+ int i, netif_pref_len, netif_no;
+
+ /*
+ * Yet more validation
+ */
+ if (argc != 2) {
+ strcpy(nhelp, cmdp->help);
+ cp = strstr(nhelp, "<netif>");
+ if (cp)
+ strcpy(cp, "ip {dyn|<dst>}");
+ fprintf(stderr, "%s: Invalid number of arguments:\n",
+ prog);
+ fprintf(stderr, "\tformat is: %s%s %s\n",
+ prefix, cmdp->name, nhelp);
+ exit(1);
+ }
+
+ /*
+ * Validate and set network interface
+ */
+ UM_ZERO(app->aar_pvc_intf, sizeof(app->aar_pvc_intf));
+ netif_pref_len = strlen(intp->anp_nif_pref);
+ cp = &argv[0][netif_pref_len];
+ netif_no = atoi(cp);
+ for (i=0; i<strlen(cp); i++) {
+ if (cp[i] < '0' || cp[i] > '9') {
+ netif_no = -1;
+ break;
+ }
+ }
+ if ((strlen(argv[0]) > sizeof(app->aar_pvc_intf) - 1) ||
+ (netif_no < 0)) {
+ fprintf(stderr, "%s: Illegal network interface name\n",
+ prog);
+ exit(1);
+ }
+ if (strncasecmp(intp->anp_nif_pref, argv[0], netif_pref_len) ||
+ strlen (argv[0]) <= netif_pref_len ||
+ netif_no > intp->anp_nif_cnt - 1) {
+ fprintf(stderr, "%s: network interface %s is not associated with interface %s\n",
+ prog,
+ argv[0],
+ intp->anp_intf);
+ exit(1);
+ }
+ strcpy(app->aar_pvc_intf, argv[0]);
+ argc--; argv++;
+
+ /*
+ * Set PVC destination address
+ */
+ UM_ZERO(&app->aar_pvc_dst, sizeof(struct sockaddr));
+ if (strcasecmp(argv[0], "dynamic") == 0 ||
+ strcasecmp(argv[0], "dyn") == 0) {
+
+ /*
+ * Destination is dynamically determined
+ */
+ app->aar_pvc_flags |= PVC_DYN;
+ } else {
+
+ /*
+ * Get destination IP address
+ */
+ struct sockaddr_in *sin;
+
+ sin = (struct sockaddr_in *) &app->aar_pvc_dst;
+ sin->sin_addr.s_addr =
+ get_ip_addr(argv[0])->sin_addr.s_addr;
+ }
+ argc--; argv++;
+}
+
diff --git a/sbin/atm/atm/atm_print.c b/sbin/atm/atm/atm_print.c
new file mode 100644
index 0000000..93aaef8
--- /dev/null
+++ b/sbin/atm/atm/atm_print.c
@@ -0,0 +1,904 @@
+/*
+ *
+ * ===================================
+ * 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: atm_print.c,v 1.12 1998/07/30 22:38:56 mks Exp $
+ *
+ */
+
+/*
+ * User configuration and display program
+ * --------------------------------------
+ *
+ * Print routines for "show" subcommand
+ *
+ */
+
+#ifndef lint
+static char *RCSid = "@(#) $Id: atm_print.c,v 1.12 1998/07/30 22:38:56 mks Exp $";
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.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_sap.h>
+#include <netatm/atm_sigmgr.h>
+#include <netatm/atm_sys.h>
+#include <netatm/atm_vc.h>
+#include <netatm/atm_ioctl.h>
+
+#include <libatm.h>
+#include <netatm/ipatm/ipatm_var.h>
+#include <netatm/sigpvc/sigpvc_var.h>
+#include <netatm/spans/spans_var.h>
+#include <netatm/uni/uniip_var.h>
+#include <netatm/uni/unisig_var.h>
+#include "atm.h"
+
+
+
+#define ARP_HDR \
+"Net Intf Flags Age Origin\n"
+
+#define ASRV_HDR \
+"Net Intf State ATM Address\n"
+
+#define CFG_HDR \
+"Intf Vendor Model Media Bus Serial No\n"
+
+#define IP_VCC_HDR \
+"Net Intf VPI VCI State Flags IP Address\n"
+
+#define INTF_HDR \
+"Interface Sigmgr State\n"
+
+#define NETIF_HDR \
+"Net Intf Phy Intf IP Address\n"
+
+#define VCC_HDR \
+"Interface VPI VCI AAL Type Dir State Encaps Owner\n"
+
+#define VCC_STATS_HDR \
+" Input Input Input Output Output Output\n\
+Interface VPI VCI PDUs Bytes Errs PDUs Bytes Errs\n"
+
+#define VERSION_HDR \
+"Version\n"
+
+#define PHY_STATS_HDR \
+" Input Input Input Output Output Output Cmd\n\
+Interface PDUs Bytes Errs PDUs Bytes Errs Errs\n"
+
+/*
+ * External references
+ */
+extern struct proto protos[];
+extern struct aal aals[];
+extern struct encaps encaps[];
+
+/*
+ * Local variables
+ */
+static int arp_hdr = 0;
+static int asrv_hdr = 0;
+static int cfg_hdr = 0;
+static int ip_vcc_hdr = 0;
+static int netif_hdr = 0;
+static int vcc_hdr = 0;
+static int vcc_stats_hdr = 0;
+static int phy_stats_hdr = 0;
+static int version_hdr = 0;
+
+/*
+ * SIGPVC state definitions
+ */
+struct state sigpvc_states[] = {
+ { "ACTIVE", SIGPVC_ACTIVE },
+ { "DETACH", SIGPVC_DETACH },
+ { 0, 0 }
+};
+
+/*
+ * SPANS state definitions
+ */
+struct state spans_states[] = {
+ { "ACTIVE", SPANS_ACTIVE },
+ { "DETACH", SPANS_DETACH },
+ { "INIT", SPANS_INIT },
+ { "PROBE", SPANS_PROBE },
+ { 0, 0 }
+};
+
+/*
+ * UNISIG state definitions
+ */
+struct state unisig_states[] = {
+ { "NULL", UNISIG_NULL },
+ { "ADR_WAIT", UNISIG_ADDR_WAIT },
+ { "INIT", UNISIG_INIT },
+ { "ACTIVE", UNISIG_ACTIVE },
+ { "DETACH", UNISIG_DETACH },
+ { 0, 0 }
+};
+
+/*
+ * SIGPVC VCC state definitions
+ */
+struct state sigpvc_vcc_states[] = {
+ { "NULL", VCCS_NULL },
+ { "ACTIVE", VCCS_ACTIVE },
+ { "FREE", VCCS_FREE },
+ { 0, 0 }
+};
+
+/*
+ * SPANS VCC state definitions
+ */
+struct state spans_vcc_states[] = {
+ { "NULL", SPANS_VC_NULL },
+ { "ACTIVE", SPANS_VC_ACTIVE },
+ { "ACT_DOWN", SPANS_VC_ACT_DOWN },
+ { "POPEN", SPANS_VC_POPEN },
+ { "R_POPEN", SPANS_VC_R_POPEN },
+ { "OPEN", SPANS_VC_OPEN },
+ { "CLOSE", SPANS_VC_CLOSE },
+ { "ABORT", SPANS_VC_ABORT },
+ { "FREE", SPANS_VC_FREE },
+ {0, 0 }
+};
+
+/*
+ * UNISIG VCC state definitions
+ */
+struct state unisig_vcc_states[] = {
+ { "NULL", UNI_NULL },
+ { "C_INIT", UNI_CALL_INITIATED },
+ { "C_OUT_PR", UNI_CALL_OUT_PROC },
+ { "C_DELIV", UNI_CALL_DELIVERED },
+ { "C_PRES", UNI_CALL_PRESENT },
+ { "C_REC", UNI_CALL_RECEIVED },
+ { "CONN_REQ", UNI_CONNECT_REQUEST },
+ { "C_IN_PR", UNI_CALL_IN_PROC },
+ { "ACTIVE", UNI_ACTIVE },
+ { "REL_REQ", UNI_RELEASE_REQUEST },
+ { "REL_IND", UNI_RELEASE_IND },
+ { "SSCF_REC", UNI_SSCF_RECOV },
+ { "FREE", UNI_FREE },
+ { "ACTIVE", UNI_PVC_ACTIVE },
+ { "ACT_DOWN", UNI_PVC_ACT_DOWN },
+ {0, 0 }
+};
+
+/*
+ * IP VCC state definitions
+ */
+struct state ip_vcc_states[] = {
+ { "FREE", IPVCC_FREE },
+ { "PMAP", IPVCC_PMAP },
+ { "POPEN", IPVCC_POPEN },
+ { "PACCEPT", IPVCC_PACCEPT },
+ { "ACTPENT", IPVCC_ACTPENT },
+ { "ACTIVE", IPVCC_ACTIVE },
+ { "CLOSED", IPVCC_CLOSED },
+ { 0, 0 }
+};
+
+/*
+ * ARP server state definitions
+ */
+struct state arpserver_states[] = {
+ { "NOT_CONF", UIAS_NOTCONF },
+ { "SERVER", UIAS_SERVER_ACTIVE },
+ { "PEND_ADR", UIAS_CLIENT_PADDR },
+ { "POPEN", UIAS_CLIENT_POPEN },
+ { "REGISTER", UIAS_CLIENT_REGISTER },
+ { "ACTIVE", UIAS_CLIENT_ACTIVE },
+ { 0, 0 }
+};
+
+/*
+ * Supported signalling managers
+ */
+struct proto_state proto_states[] = {
+ { "SIGPVC", sigpvc_states, sigpvc_vcc_states, ATM_SIG_PVC },
+ { "SPANS", spans_states, spans_vcc_states, ATM_SIG_SPANS },
+ { "UNI 3.0", unisig_states, unisig_vcc_states, ATM_SIG_UNI30 },
+ { "UNI 3.1", unisig_states, unisig_vcc_states, ATM_SIG_UNI31 },
+ { "UNI 4.0", unisig_states, unisig_vcc_states, ATM_SIG_UNI40 },
+ { 0, 0, 0, 0 }
+};
+
+/*
+ * ATMARP origin values
+ */
+struct state arp_origins[] = {
+ { "LOCAL", UAO_LOCAL },
+ { "PERM", UAO_PERM },
+ { "REG", UAO_REGISTER },
+ { "SCSP", UAO_SCSP },
+ { "LOOKUP", UAO_LOOKUP },
+ { "PEER_RSP", UAO_PEER_RSP },
+ { "PEER_REQ", UAO_PEER_REQ },
+ { 0, 0 }
+};
+
+
+/*
+ * Print ARP table information
+ *
+ * Arguments:
+ * ai pointer to a struct air_arp_rsp
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+print_arp_info(ai)
+ struct air_arp_rsp *ai;
+{
+ int i;
+ char *atm_addr, *ip_addr, *origin;
+ char age[8], flags[32];
+ struct sockaddr_in *sin;
+
+ /*
+ * Print a header if it hasn't been done yet.
+ */
+ if (!arp_hdr) {
+ printf(ARP_HDR);
+ arp_hdr = 1;
+ }
+
+ /*
+ * Format the addresses
+ */
+ atm_addr = format_atm_addr(&ai->aap_addr);
+ sin = (struct sockaddr_in *)&ai->aap_arp_addr;
+ ip_addr = format_ip_addr(&sin->sin_addr);
+
+ /*
+ * Decode the flags
+ */
+ UM_ZERO(flags, sizeof(flags));
+ if (ai->aap_flags & ARPF_VALID) {
+ strcat(flags, "V");
+ }
+ if (ai->aap_flags & ARPF_REFRESH) {
+ strcat(flags, "R");
+ }
+
+ /*
+ * Format the origin
+ */
+ for (i=0; arp_origins[i].s_name != NULL &&
+ ai->aap_origin != arp_origins[i].s_id;
+ i++);
+ if (arp_origins[i].s_name) {
+ origin = arp_origins[i].s_name;
+ } else {
+ origin = "-";
+ }
+
+ /*
+ * Format the age
+ */
+ UM_ZERO(age, sizeof(age));
+ if (!(ai->aap_flags & ARPF_VALID)) {
+ strcpy(age, "-");
+ } else {
+ sprintf(age, "%d", ai->aap_age);
+ }
+
+ /*
+ * Print the ARP information
+ */
+ printf("%-8s %-5s %3s %s\n ATM address = %s\n IP address = %s\n",
+ ai->aap_intf,
+ flags,
+ age,
+ origin,
+ atm_addr,
+ ip_addr);
+}
+
+
+/*
+ * Print ARP server information
+ *
+ * Arguments:
+ * si pointer to a struct air_asrv_rsp
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+print_asrv_info(si)
+ struct air_asrv_rsp *si;
+{
+ int i;
+ char *atm_addr, *state;
+ char print_lis[32];
+ struct in_addr *addr;
+
+ /*
+ * Print a header if it hasn't been done yet.
+ */
+ if (!asrv_hdr) {
+ printf(ASRV_HDR);
+ asrv_hdr = 1;
+ }
+
+ /*
+ * Format the ATM address of the ARP server
+ */
+ atm_addr = format_atm_addr(&si->asp_addr);
+
+ /*
+ * Format the server state
+ */
+ for (i=0; arpserver_states[i].s_name != NULL &&
+ si->asp_state != arpserver_states[i].s_id;
+ i++);
+ if (arpserver_states[i].s_name) {
+ state = arpserver_states[i].s_name;
+ } else {
+ state = "-";
+ }
+
+ /*
+ * Print the ARP server information
+ */
+ printf("%-8s %-8s %s\n",
+ si->asp_intf,
+ state,
+ atm_addr);
+
+ /*
+ * Format and print the LIS prefixes
+ */
+ if (si->asp_nprefix) {
+ addr = (struct in_addr *)((u_long)si +
+ sizeof(struct air_asrv_rsp));
+ printf(" LIS = ");
+ for (i = 0; i < si->asp_nprefix; i++) {
+ printf("%s", inet_ntoa(*addr));
+ addr++;
+ printf("/0x%0x", ntohl(addr->s_addr));
+ addr++;
+ if (i < si->asp_nprefix -1)
+ printf(", ");
+ }
+ printf("\n");
+ }
+}
+
+
+/*
+ * Print adapter configuration information
+ *
+ * Arguments:
+ * si pointer to a struct air_cfg_rsp
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+print_cfg_info(si)
+ struct air_cfg_rsp *si;
+{
+ char *adapter, *bus, *media, *vendor;
+
+ /*
+ * Print a header if it hasn't been done yet.
+ */
+ if (!cfg_hdr) {
+ printf(CFG_HDR);
+ cfg_hdr = 1;
+ }
+
+ /*
+ * Format the vendor name and adapter type
+ */
+ vendor = get_vendor(si->acp_vendor);
+ adapter = get_adapter(si->acp_device);
+
+ /*
+ * Format the communications medium
+ */
+ media = get_media_type(si->acp_media);
+ bus = get_bus_type(si->acp_bustype);
+
+ /*
+ * Print the ARP server information
+ */
+ printf("%-8s %-8s %-8s %-14s %-4s %d\n",
+ si->acp_intf,
+ vendor,
+ adapter,
+ media,
+ bus,
+ si->acp_serial);
+ printf(" MAC address = %s\n",
+ format_mac_addr(&si->acp_macaddr));
+ printf(" Hardware version = %s\n", si->acp_hard_vers);
+ printf(" Firmware version = %s\n", si->acp_firm_vers);
+}
+
+
+/*
+ * Print interface information
+ *
+ * Arguments:
+ * ni pointer to a struct air_int_rsp
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+print_intf_info(ni)
+ struct air_int_rsp *ni;
+{
+ int i;
+ char nif_names[(IFNAMSIZ *2)+4];
+ char *atm_addr, *ip_addr;
+ char *sigmgr = "-", *state_name = "-";
+ struct sockaddr_in *sin;
+ struct state *s_t;
+
+ /*
+ * Print a header
+ */
+ printf(INTF_HDR);
+
+ /*
+ * Translate signalling manager name
+ */
+ for (i=0; proto_states[i].p_state != NULL; i++)
+ if (ni->anp_sig_proto == proto_states[i].p_id)
+ break;
+ if (proto_states[i].p_state != NULL)
+ sigmgr = proto_states[i].p_name;
+
+ /*
+ * Get the signalling manager state
+ */
+ if (proto_states[i].p_state != NULL) {
+ s_t = proto_states[i].p_state;
+ for (i=0; s_t[i].s_name != NULL; i++)
+ if (ni->anp_sig_state == s_t[i].s_id)
+ break;
+ if (s_t[i].s_name != NULL)
+ state_name = s_t[i].s_name;
+ }
+
+ /*
+ * Format the ATM address
+ */
+ atm_addr = format_atm_addr(&ni->anp_addr);
+
+ /*
+ * Get the range of NIFs on the physical interface
+ */
+ UM_ZERO(nif_names, sizeof(nif_names));
+ if (strlen(ni->anp_nif_pref) == 0) {
+ strcpy(nif_names, "-");
+ } else {
+ strcpy(nif_names, ni->anp_nif_pref);
+ strcat(nif_names, "0");
+ if (ni->anp_nif_cnt > 1) {
+ strcat(nif_names, " - ");
+ strcat(nif_names, ni->anp_nif_pref);
+ sprintf(&nif_names[strlen(nif_names)], "%d",
+ ni->anp_nif_cnt-1);
+ }
+ }
+
+
+ /*
+ * Print the interface information
+ */
+ printf("%-9s %-7s %s\n",
+ ni->anp_intf,
+ sigmgr,
+ state_name);
+ printf(" ATM address = %s\n", atm_addr);
+ printf(" Network interfaces: %s\n", nif_names);
+}
+
+
+/*
+ * Print IP address map information
+ *
+ * Arguments:
+ * ai pointer to a struct air_arp_rsp
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+print_ip_vcc_info(ai)
+ struct air_ip_vcc_rsp *ai;
+{
+ int i;
+ char *ip_addr, *state;
+ char flags[32], vpi_vci[16];
+ struct sockaddr_in *sin;
+
+ /*
+ * Print a header if it hasn't been done yet.
+ */
+ if (!ip_vcc_hdr) {
+ printf(IP_VCC_HDR);
+ ip_vcc_hdr = 1;
+ }
+
+ /*
+ * Format the IP address
+ */
+ sin = (struct sockaddr_in *)&ai->aip_dst_addr;
+ ip_addr = format_ip_addr(&sin->sin_addr);
+
+ /*
+ * Format the VPI/VCI
+ */
+ if (ai->aip_vpi == 0 && ai->aip_vci == 0) {
+ strcpy(vpi_vci, " - -");
+ } else {
+ sprintf(vpi_vci, "%3d %5d", ai->aip_vpi, ai->aip_vci);
+ }
+
+ /*
+ * Decode VCC flags
+ */
+ UM_ZERO(flags, sizeof(flags));
+ if (ai->aip_flags & IVF_PVC) {
+ strcat(flags, "P");
+ }
+ if (ai->aip_flags & IVF_SVC) {
+ strcat(flags, "S");
+ }
+ if (ai->aip_flags & IVF_LLC) {
+ strcat(flags, "L");
+ }
+ if (ai->aip_flags & IVF_MAPOK) {
+ strcat(flags, "M");
+ }
+ if (ai->aip_flags & IVF_NOIDLE) {
+ strcat(flags, "N");
+ }
+
+ /*
+ * Get the state of the VCC
+ */
+ for (i=0; ip_vcc_states[i].s_name != NULL &&
+ ai->aip_state != ip_vcc_states[i].s_id;
+ i++);
+ if (ip_vcc_states[i].s_name) {
+ state = ip_vcc_states[i].s_name;
+ } else {
+ state = "-";
+ }
+
+ /*
+ * Print the IP VCC information
+ */
+ printf("%-8s %9s %-7s %-5s %s\n",
+ ai->aip_intf,
+ vpi_vci,
+ state,
+ flags,
+ ip_addr);
+}
+
+
+/*
+ * Print network interface information
+ *
+ * Arguments:
+ * ni pointer to a struct air_int_rsp
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+print_netif_info(ni)
+ struct air_netif_rsp *ni;
+{
+ char *ip_addr;
+ struct sockaddr_in *sin;
+
+ /*
+ * Print a header
+ */
+ if (!netif_hdr) {
+ netif_hdr++;
+ printf(NETIF_HDR);
+ }
+
+ /*
+ * Format the protocol address
+ */
+ sin = (struct sockaddr_in *)&ni->anp_proto_addr;
+ ip_addr = format_ip_addr(&sin->sin_addr);
+
+ /*
+ * Print the network interface information
+ */
+ printf("%-8s %-8s %s\n",
+ ni->anp_intf,
+ ni->anp_phy_intf,
+ ip_addr);
+}
+
+
+/*
+ * Print physical interface statistics
+ *
+ * Arguments:
+ * pi pointer to a struct air_phy_stat_rsp
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+print_intf_stats(pi)
+ struct air_phy_stat_rsp *pi;
+{
+ int i;
+
+ /*
+ * Print a header if it hasn't already been done
+ */
+ if (!phy_stats_hdr) {
+ printf(PHY_STATS_HDR);
+ phy_stats_hdr = 1;
+ }
+
+ /*
+ * Print the interface statistics
+ */
+ printf("%-9s %7d %8d %5d %7d %8d %5d %5d\n",
+ pi->app_intf,
+ pi->app_ipdus,
+ pi->app_ibytes,
+ pi->app_ierrors,
+ pi->app_opdus,
+ pi->app_obytes,
+ pi->app_oerrors,
+ pi->app_cmderrors);
+}
+
+
+/*
+ * Print VCC statistics
+ *
+ * Arguments:
+ * vi pointer to VCC statistics to print
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+print_vcc_stats(vi)
+ struct air_vcc_rsp *vi;
+{
+
+ /*
+ * Print a header if it hasn't already been done
+ */
+ if (!vcc_stats_hdr) {
+ printf(VCC_STATS_HDR);
+ vcc_stats_hdr = 1;
+ }
+
+ /*
+ * Print the VCC statistics
+ */
+ printf("%-9s %3d %4d",
+ vi->avp_intf,
+ vi->avp_vpi,
+ vi->avp_vci);
+ if ( vi->avp_type & VCC_IN )
+ printf ( " %7d %8d %5d",
+ vi->avp_ipdus,
+ vi->avp_ibytes,
+ vi->avp_ierrors);
+ else
+ printf ( " - - -" );
+
+ if ( vi->avp_type & VCC_OUT )
+ printf ( " %7d %8d %5d\n",
+ vi->avp_opdus,
+ vi->avp_obytes,
+ vi->avp_oerrors);
+ else
+ printf ( " - - -\n" );
+}
+
+
+/*
+ * Print VCC information
+ *
+ * Arguments:
+ * vi pointer to a struct air_vcc_rsp
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+print_vcc_info(vi)
+ struct air_vcc_rsp *vi;
+{
+ int i;
+ char *aal_name = "-" , *encaps_name = "-", *owner_name = "-";
+ char *proto_name = "-", *state_name = "-", *type_name = "-";
+ char dir_name[10];
+ struct state *s_t;
+
+ /*
+ * Print a header if it hasn't already been done
+ */
+ if (!vcc_hdr) {
+ printf(VCC_HDR);
+ vcc_hdr = 1;
+ }
+
+ /*
+ * Translate AAL
+ */
+ for (i=0; aals[i].a_name != NULL; i++)
+ if (vi->avp_aal == aals[i].a_id)
+ break;
+ if (aals[i].a_name)
+ aal_name = aals[i].a_name;
+
+ /*
+ * Translate VCC type
+ */
+ if (vi->avp_type & VCC_PVC)
+ type_name = "PVC";
+ else if (vi->avp_type & VCC_SVC)
+ type_name = "SVC";
+ /*
+ * Translate VCC direction
+ */
+ UM_ZERO(dir_name, sizeof(dir_name));
+ if (vi->avp_type & VCC_IN)
+ strcat(dir_name, "In");
+ if (vi->avp_type & VCC_OUT)
+ strcat(dir_name, "Out");
+ if (strlen(dir_name) == 0)
+ strcpy(dir_name, "-");
+
+ /*
+ * Translate state
+ */
+ for (i=0; proto_states[i].p_state != NULL; i++)
+ if (vi->avp_sig_proto == proto_states[i].p_id)
+ break;
+ if (proto_states[i].p_state) {
+ s_t = proto_states[i].v_state;
+ for (i=0; s_t[i].s_name != NULL; i++)
+ if (vi->avp_state == s_t[i].s_id)
+ break;
+ if (s_t[i].s_name)
+ state_name = s_t[i].s_name;
+ }
+
+ /*
+ * Translate encapsulation
+ */
+ for (i=0; encaps[i].e_name != NULL; i++)
+ if (vi->avp_encaps == encaps[i].e_id)
+ break;
+ if (encaps[i].e_name)
+ encaps_name = encaps[i].e_name;
+
+ /*
+ * Print the VCC information
+ */
+ printf("%-9s %3d %5d %-4s %-4s %-5s %-8s %-8s ",
+ vi->avp_intf,
+ vi->avp_vpi,
+ vi->avp_vci,
+ aal_name,
+ type_name,
+ dir_name,
+ state_name,
+ encaps_name);
+
+ /*
+ * Print VCC owners' names
+ */
+ for (i = 0, owner_name = vi->avp_owners;
+ i < O_CNT - 1 && strlen(owner_name);
+ i++, owner_name += (T_ATM_APP_NAME_LEN + 1)) {
+ if (i > 0)
+ printf(", ");
+ printf("%s", owner_name);
+ }
+ if (i == 0)
+ printf("-");
+ printf("\n");
+
+ /*
+ * Print destination address if it's an SVC
+ */
+ if (vi->avp_type & VCC_SVC) {
+ printf(" Dest = %s\n",
+ format_atm_addr(&vi->avp_daddr));
+ }
+}
+
+
+/*
+ * Print network interface information
+ *
+ * Arguments:
+ * ni pointer to a struct air_int_rsp
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+print_version_info(vi)
+ struct air_version_rsp *vi;
+{
+ char version_str[80];
+
+ /*
+ * Print a header
+ */
+ if (!version_hdr) {
+ version_hdr++;
+ printf(VERSION_HDR);
+ }
+
+ /*
+ * Print the interface information
+ */
+ sprintf(version_str, "%d.%d",
+ ATM_VERS_MAJ(vi->avp_version),
+ ATM_VERS_MIN(vi->avp_version));
+ printf("%7s\n", version_str);
+}
diff --git a/sbin/atm/atm/atm_set.c b/sbin/atm/atm/atm_set.c
new file mode 100644
index 0000000..199c37f
--- /dev/null
+++ b/sbin/atm/atm/atm_set.c
@@ -0,0 +1,540 @@
+/*
+ *
+ * ===================================
+ * 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: atm_set.c,v 1.12 1998/08/26 23:29:32 mks Exp $
+ *
+ */
+
+/*
+ * User configuration and display program
+ * --------------------------------------
+ *
+ * Routines for "set" subcommand
+ *
+ */
+
+#ifndef lint
+static char *RCSid = "@(#) $Id: atm_set.c,v 1.12 1998/08/26 23:29:32 mks Exp $";
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netatm/port.h>
+#include <netatm/atm.h>
+#include <netatm/atm_if.h>
+#include <netatm/atm_sap.h>
+#include <netatm/atm_sys.h>
+#include <netatm/atm_ioctl.h>
+
+#include <libatm.h>
+#include "atm.h"
+
+
+/*
+ * Process ATM ARP server set command
+ *
+ * Command format:
+ * atm set arpserver <interface_name> <atm-address> <IP prefix> ...
+ *
+ * Arguments:
+ * argc number of arguments to command
+ * argv pointer to argument strings
+ * cmdp pointer to command description
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+set_arpserver(argc, argv, cmdp)
+ int argc;
+ char **argv;
+ struct cmd *cmdp;
+{
+ int i, len, prefix_len = 0, rc, s;
+ char *cp, *intf;
+ Atm_addr server;
+ struct sockaddr_in *lis;
+ struct sockaddr_in if_mask;
+ struct atmsetreq asr;
+ struct atminfreq air;
+ struct air_netif_rsp *int_info;
+ struct {
+ struct in_addr ip_addr;
+ struct in_addr ip_mask;
+ } prefix_buf[64];;
+
+ /*
+ * Validate interface name
+ */
+ check_netif_name(argv[0]);
+ intf = argv[0];
+ argc--; argv++;
+
+ /*
+ * Get the ARP server's ATM address
+ */
+ UM_ZERO(&server, sizeof(server));
+ if (strcasecmp(argv[0], "local")) {
+ /*
+ * ARP server NSAP address is provided
+ */
+ server.address_format = T_ATM_ENDSYS_ADDR;
+ server.address_length = sizeof(Atm_addr_nsap);
+ if (get_hex_atm_addr(argv[0],
+ (u_char *)server.address,
+ sizeof(Atm_addr_nsap)) !=
+ sizeof(Atm_addr_nsap)) {
+ fprintf(stderr, "%s: Invalid ARP server address\n",
+ prog);
+ exit(1);
+ }
+ if (argc > 1) {
+ fprintf(stderr, "%s: Invalid number of arguments\n",
+ prog);
+ exit(1);
+ }
+ prefix_len = 0;
+ } else {
+ argc--; argv++;
+
+ /*
+ * This host is the ARP server
+ */
+ server.address_format = T_ATM_ABSENT;
+ server.address_length = 0;
+
+ /*
+ * Get interface information from the kernel. We need
+ * to get the IP address and the subnet mask associated
+ * with the network interface and insert them into the
+ * list of permitted LIS prefixes.
+ */
+ len = sizeof(struct air_netif_rsp);
+ UM_ZERO(&air, sizeof(air));
+ air.air_opcode = AIOCS_INF_NIF;
+ strcpy(air.air_int_intf, intf);
+ len = do_info_ioctl(&air, len);
+ if (len < 0) {
+ fprintf(stderr, "%s: ", prog);
+ switch (errno) {
+ case ENOPROTOOPT:
+ case EOPNOTSUPP:
+ perror("Internal error");
+ break;
+ case ENXIO:
+ fprintf(stderr, "%s is not an ATM device\n",
+ intf);
+ break;
+ default:
+ perror("ioctl (AIOCINFO)");
+ break;
+ }
+ exit(1);
+ }
+ int_info = (struct air_netif_rsp *) air.air_buf_addr;
+ lis = (struct sockaddr_in *)&int_info->anp_proto_addr;
+ prefix_buf[0].ip_addr = lis->sin_addr;
+ UM_FREE(int_info);
+
+ rc = get_subnet_mask(intf, &if_mask);
+ if (rc) {
+ fprintf(stderr, "%s: Can't get subnet mask for %s\n",
+ prog, intf);
+ }
+ prefix_buf[0].ip_mask = if_mask.sin_addr;
+ prefix_buf[0].ip_addr.s_addr &=
+ prefix_buf[0].ip_mask.s_addr;
+
+ /*
+ * Get the prefixes of the LISs that we'll support
+ */
+ for (i = 1; argc; i++, argc--, argv++) {
+ rc = parse_ip_prefix(argv[0],
+ (struct in_addr *)&prefix_buf[i]);
+ if (rc != 0) {
+ fprintf(stderr, "%s: Invalid IP prefix value \'%s\'\n",
+ prog, argv[0]);
+ exit(1);
+ }
+ }
+
+ /*
+ * Compress the prefix list
+ */
+ prefix_len = compress_prefix_list((struct in_addr *)prefix_buf,
+ i * sizeof(struct in_addr) * 2);
+ }
+
+ /*
+ * Build ioctl request
+ */
+ UM_ZERO(&asr, sizeof(asr));
+ asr.asr_opcode = AIOCS_SET_ASV;
+ strncpy(asr.asr_arp_intf, intf, sizeof(asr.asr_arp_intf));
+ asr.asr_arp_addr = server;
+ asr.asr_arp_subaddr.address_format = T_ATM_ABSENT;
+ asr.asr_arp_subaddr.address_length = 0;
+ if (prefix_len)
+ asr.asr_arp_pbuf = (caddr_t)prefix_buf;
+ else
+ asr.asr_arp_pbuf = (caddr_t)0;
+ asr.asr_arp_plen = prefix_len;
+
+ /*
+ * Pass the new ARP server address to the kernel
+ */
+ s = socket(AF_ATM, SOCK_DGRAM, 0);
+ if (s < 0) {
+ sock_error(errno);
+ }
+ if (ioctl(s, AIOCSET, (caddr_t)&asr) < 0) {
+ fprintf(stderr, "%s: ", prog);
+ switch (errno) {
+ case EOPNOTSUPP:
+ case EPROTONOSUPPORT:
+ perror("Internal error");
+ break;
+ case EINVAL:
+ fprintf(stderr, "Invalid parameter\n");
+ break;
+ case ENOMEM:
+ fprintf(stderr, "Kernel memory exhausted\n");
+ break;
+ case ENETDOWN:
+ fprintf(stderr, "ATM network is inoperable\n");
+ break;
+ case EPERM:
+ fprintf(stderr, "Must be super user to use set subcommand\n");
+ break;
+ case ENXIO:
+ fprintf(stderr, "%s is not an ATM interface\n", intf);
+ break;
+ case ENOENT:
+ fprintf(stderr, "Signalling manager not attached\n");
+ break;
+ case ENOPROTOOPT:
+ fprintf(stderr,
+ "%s does not have an IP address configured\n",
+ intf);
+ break;
+ default:
+ perror("Ioctl (AIOCSET) ARPSERVER address");
+ break;
+ }
+ exit(1);
+ }
+
+ (void)close(s);
+}
+
+
+/*
+ * Process set MAC address command
+ *
+ * Command format:
+ * atm set mac <interface_name> <MAC address>
+ *
+ * Arguments:
+ * argc number of remaining arguments to command
+ * argv pointer to remaining argument strings
+ * cmdp pointer to command description
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+set_macaddr(argc, argv, cmdp)
+ int argc;
+ char **argv;
+ struct cmd *cmdp;
+{
+ int s;
+ char *intf;
+ struct mac_addr mac;
+ struct atmsetreq asr;
+
+ /*
+ * Validate interface name
+ */
+ if (strlen(argv[0]) > sizeof(asr.asr_mac_intf) - 1) {
+ fprintf(stderr, "%s: Illegal interface name\n", prog);
+ exit(1);
+ }
+ intf = argv[0];
+ argc--; argv++;
+
+ /*
+ * Get the MAC address provided by the user
+ */
+ if (get_hex_atm_addr(argv[0], (u_char *)&mac, sizeof(mac)) !=
+ sizeof(mac)) {
+ fprintf(stderr, "%s: Invalid MAC address\n", prog);
+ exit(1);
+ }
+
+ /*
+ * Build ioctl request
+ */
+ asr.asr_opcode = AIOCS_SET_MAC;
+ strncpy(asr.asr_mac_intf, intf, sizeof(asr.asr_mac_intf));
+ UM_COPY(&mac, &asr.asr_mac_addr, sizeof(asr.asr_mac_addr));
+
+ /*
+ * Pass the new address to the kernel
+ */
+ s = socket(AF_ATM, SOCK_DGRAM, 0);
+ if (s < 0) {
+ sock_error(errno);
+ }
+ if (ioctl(s, AIOCSET, (caddr_t)&asr) < 0) {
+ fprintf(stderr, "%s: ", prog);
+ switch (errno) {
+ case EOPNOTSUPP:
+ case EPROTONOSUPPORT:
+ perror("Internal error");
+ break;
+ case EADDRINUSE:
+ fprintf(stderr, "Interface must be detached to set MAC addres\n");
+ break;
+ case EINVAL:
+ fprintf(stderr, "Invalid parameter\n");
+ break;
+ case ENOMEM:
+ fprintf(stderr, "Kernel memory exhausted\n");
+ break;
+ case ENETDOWN:
+ fprintf(stderr, "ATM network is inoperable\n");
+ break;
+ case EPERM:
+ fprintf(stderr, "Must be super user to use set subcommand\n");
+ break;
+ case ENXIO:
+ fprintf(stderr, "%s is not an ATM device\n",
+ argv[0]);
+ break;
+ default:
+ perror("Ioctl (AIOCSET) MAC address");
+ break;
+ }
+ exit(1);
+ }
+
+ (void)close(s);
+}
+
+
+/*
+ * Process network interface set command
+ *
+ * Command format:
+ * atm set netif <interface_name> <prefix_name> <count>
+ *
+ * Arguments:
+ * argc number of arguments to command
+ * argv pointer to argument strings
+ * cmdp pointer to command description
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+set_netif(argc, argv, cmdp)
+ int argc;
+ char **argv;
+ struct cmd *cmdp;
+{
+ struct atmsetreq anr;
+ char str[16];
+ char *cp;
+ int nifs, s;
+
+ /*
+ * Set IOCTL opcode
+ */
+ anr.asr_opcode = AIOCS_SET_NIF;
+
+ /*
+ * Validate interface name
+ */
+ if (strlen(argv[0]) > sizeof(anr.asr_nif_intf) - 1) {
+ fprintf(stderr, "%s: Illegal interface name\n", prog);
+ exit(1);
+ }
+ strcpy(anr.asr_nif_intf, argv[0]);
+ argc--; argv++;
+
+ /*
+ * Validate network interface name prefix
+ */
+ if ((strlen(argv[0]) > sizeof(anr.asr_nif_pref) - 1) ||
+ (strpbrk(argv[0], "0123456789"))) {
+ fprintf(stderr, "%s: Illegal network interface prefix\n", prog);
+ exit(1);
+ }
+ strcpy(anr.asr_nif_pref, argv[0]);
+ argc--; argv++;
+
+ /*
+ * Validate interface count
+ */
+ nifs = (int) strtol(argv[0], &cp, 0);
+ if ((*cp != '\0') || (nifs < 0) || (nifs > MAX_NIFS)) {
+ fprintf(stderr, "%s: Invalid interface count\n", prog);
+ exit(1);
+ }
+ anr.asr_nif_cnt = nifs;
+
+ /*
+ * Make sure the resulting name won't be too long
+ */
+ sprintf(str, "%d", nifs - 1);
+ if ((strlen(str) + strlen(anr.asr_nif_pref)) >
+ sizeof(anr.asr_nif_intf) - 1) {
+ fprintf(stderr, "%s: Network interface prefix too long\n", prog);
+ exit(1);
+ }
+
+ /*
+ * Tell the kernel to do it
+ */
+ s = socket(AF_ATM, SOCK_DGRAM, 0);
+ if (s < 0) {
+ sock_error(errno);
+ }
+ if (ioctl(s, AIOCSET, (caddr_t)&anr) < 0) {
+ fprintf(stderr, "%s: ", prog);
+ perror("ioctl (AIOCSET) set NIF");
+ exit(1);
+ }
+ (void)close(s);
+}
+
+
+/*
+ * Process set NSAP prefix command
+ *
+ * Command format:
+ * atm set nsap <interface_name> <NSAP prefix>
+ *
+ * Arguments:
+ * argc number of remaining arguments to command
+ * argv pointer to remaining argument strings
+ * cmdp pointer to command description
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+set_prefix(argc, argv, cmdp)
+ int argc;
+ char **argv;
+ struct cmd *cmdp;
+{
+ int s;
+ char *intf;
+ u_char prefix[13];
+ struct atmsetreq asr;
+
+ /*
+ * Validate interface name
+ */
+ if (strlen(argv[0]) > sizeof(asr.asr_prf_intf) - 1) {
+ fprintf(stderr, "%s: Illegal interface name\n", prog);
+ exit(1);
+ }
+ intf = argv[0];
+ argc--; argv++;
+
+ /*
+ * Get the prefix provided by the user
+ */
+ if (get_hex_atm_addr(argv[0], prefix, sizeof(prefix)) !=
+ sizeof(prefix)) {
+ fprintf(stderr, "%s: Invalid NSAP prefix\n", prog);
+ exit(1);
+ }
+
+ /*
+ * Build ioctl request
+ */
+ asr.asr_opcode = AIOCS_SET_PRF;
+ strncpy(asr.asr_prf_intf, intf, sizeof(asr.asr_prf_intf));
+ UM_COPY(prefix, asr.asr_prf_pref, sizeof(asr.asr_prf_pref));
+
+ /*
+ * Pass the new prefix to the kernel
+ */
+ s = socket(AF_ATM, SOCK_DGRAM, 0);
+ if (s < 0) {
+ sock_error(errno);
+ }
+ if (ioctl(s, AIOCSET, (caddr_t)&asr) < 0) {
+ fprintf(stderr, "%s: ", prog);
+ switch (errno) {
+ case EOPNOTSUPP:
+ case EPROTONOSUPPORT:
+ perror("Internal error");
+ break;
+ case EALREADY:
+ fprintf(stderr, "NSAP prefix is already set\n");
+ break;
+ case EINVAL:
+ fprintf(stderr, "Invalid parameter\n");
+ break;
+ case ENOMEM:
+ fprintf(stderr, "Kernel memory exhausted\n");
+ break;
+ case ENETDOWN:
+ fprintf(stderr, "ATM network is inoperable\n");
+ break;
+ case EPERM:
+ fprintf(stderr, "Must be super user to use set subcommand\n");
+ break;
+ case ENXIO:
+ fprintf(stderr, "%s is not an ATM device\n",
+ argv[0]);
+ break;
+ default:
+ perror("Ioctl (AIOCSET) NSAP prefix");
+ break;
+ }
+ exit(1);
+ }
+
+ (void)close(s);
+}
diff --git a/sbin/atm/atm/atm_show.c b/sbin/atm/atm/atm_show.c
new file mode 100644
index 0000000..8c32dfc
--- /dev/null
+++ b/sbin/atm/atm/atm_show.c
@@ -0,0 +1,1187 @@
+/*
+ *
+ * ===================================
+ * 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: atm_show.c,v 1.12 1998/07/24 16:20:34 johnc Exp $
+ *
+ */
+
+/*
+ * User configuration and display program
+ * --------------------------------------
+ *
+ * Routines for "show" subcommand
+ *
+ */
+
+#ifndef lint
+static char *RCSid = "@(#) $Id: atm_show.c,v 1.12 1998/07/24 16:20:34 johnc Exp $";
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.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_sap.h>
+#include <netatm/atm_sys.h>
+#include <netatm/atm_vc.h>
+#include <netatm/atm_ioctl.h>
+
+#include <libatm.h>
+#include "atm.h"
+
+
+/*
+ * Local functions
+ */
+static int vcc_compare __P((const void *, const void *));
+static int ip_vcc_compare __P((const void *, const void *));
+static int arp_compare __P((const void *, const void *));
+
+
+/*
+ * Process show ARP command
+ *
+ * Command format:
+ * atm show ARP [<ip-addr>]
+ *
+ * Arguments:
+ * argc number of remaining arguments to command
+ * argv pointer to remaining argument strings
+ * cmdp pointer to command description
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+show_arp(argc, argv, cmdp)
+ int argc;
+ char **argv;
+ struct cmd *cmdp;
+{
+ int buf_len, arp_info_len, ip_info_len, sel;
+ struct atminfreq air;
+ struct air_arp_rsp *arp_info, *arp_info_base;
+ struct sockaddr_in *sin;
+ union {
+ struct sockaddr_in sin;
+ struct sockaddr sa;
+ } host_addr;
+
+ /*
+ * Get IP address of specified host name
+ */
+ UM_ZERO(&host_addr, sizeof(host_addr));
+ host_addr.sa.sa_family = AF_INET;
+ if (argc) {
+ sin = get_ip_addr(argv[0]);
+ if (!sin) {
+ fprintf(stderr, "%s: host \'%s\' not found\n",
+ prog, argv[0]);
+ exit(1);
+ }
+ host_addr.sin.sin_addr.s_addr = sin->sin_addr.s_addr;
+ } else {
+ host_addr.sin.sin_addr.s_addr = INADDR_ANY;
+ }
+
+ /*
+ * Get ARP information from the kernel
+ */
+ UM_ZERO(&air, sizeof(air));
+ buf_len = sizeof(struct air_arp_rsp) * 10;
+ air.air_opcode = AIOCS_INF_ARP;
+ air.air_arp_addr = host_addr.sa;
+ arp_info_len = do_info_ioctl(&air, buf_len);
+ if (arp_info_len < 0) {
+ fprintf(stderr, "%s: ", prog);
+ switch (errno) {
+ case ENOPROTOOPT:
+ case EOPNOTSUPP:
+ perror("Internal error");
+ break;
+ case ENXIO:
+ fprintf(stderr, "not an ATM device\n");
+ break;
+ default:
+ perror("ioctl (AIOCINFO)");
+ break;
+ }
+ exit(1);
+ }
+ arp_info_base = arp_info =
+ (struct air_arp_rsp *) air.air_buf_addr;
+
+ /*
+ * Sort the ARP table
+ */
+ qsort((void *) arp_info,
+ arp_info_len / sizeof(struct air_arp_rsp),
+ sizeof(struct air_arp_rsp),
+ arp_compare);
+
+ /*
+ * Print the relevant information
+ */
+ while (arp_info_len > 0) {
+ print_arp_info(arp_info);
+ arp_info++;
+ arp_info_len -= sizeof(struct air_arp_rsp);
+ }
+
+ /*
+ * Release the information from the kernel
+ */
+ UM_FREE(arp_info_base);
+}
+
+
+/*
+ * Process show ATM ARP server command
+ *
+ * Command format:
+ * atm show arpserver [<interface-name>]
+ *
+ * Arguments:
+ * argc number of remaining arguments to command
+ * argv pointer to remaining argument strings
+ * cmdp pointer to command description
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+show_arpserv(argc, argv, cmdp)
+ int argc;
+ char **argv;
+ struct cmd *cmdp;
+{
+ int asrv_info_len, buf_len = sizeof(struct air_asrv_rsp) * 3;
+ struct atminfreq air;
+ struct air_asrv_rsp *asrv_info, *asrv_info_base;
+
+ /*
+ * Validate interface name
+ */
+ UM_ZERO(air.air_int_intf, sizeof(air.air_int_intf));
+ if (argc) {
+ if (strlen(argv[0]) > IFNAMSIZ - 1) {
+ fprintf(stderr, "%s: Illegal interface name\n",
+ prog);
+ exit(1);
+ }
+ strcpy(air.air_int_intf, argv[0]);
+ argc--; argv++;
+ }
+
+ /*
+ * Get interface information from the kernel
+ */
+ air.air_opcode = AIOCS_INF_ASV;
+ buf_len = do_info_ioctl(&air, buf_len);
+ if (buf_len < 0) {
+ fprintf(stderr, "%s: ", prog);
+ switch (errno) {
+ case ENOPROTOOPT:
+ case EOPNOTSUPP:
+ perror("Internal error");
+ break;
+ case ENXIO:
+ fprintf(stderr, "%s is not an ATM device\n",
+ argv[0]);
+ break;
+ default:
+ perror("ioctl (AIOCINFO)");
+ break;
+ }
+ exit(1);
+ }
+
+ /*
+ * Print the interface information
+ */
+ asrv_info_base = asrv_info =
+ (struct air_asrv_rsp *) air.air_buf_addr;
+ for (; buf_len >= sizeof(struct air_asrv_rsp);
+ asrv_info = (struct air_asrv_rsp *)
+ ((u_long)asrv_info + asrv_info_len),
+ buf_len -= asrv_info_len) {
+ print_asrv_info(asrv_info);
+ asrv_info_len = sizeof(struct air_asrv_rsp) +
+ asrv_info->asp_nprefix *
+ sizeof(struct in_addr) * 2;
+ }
+ UM_FREE(asrv_info_base);
+}
+
+
+/*
+ * Process show ATM adapter configuration command
+ *
+ * Command format:
+ * atm show config [<interface-name>]
+ *
+ * Arguments:
+ * argc number of remaining arguments to command
+ * argv pointer to remaining argument strings
+ * cmdp pointer to command description
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+show_config(argc, argv, cmdp)
+ int argc;
+ char **argv;
+ struct cmd *cmdp;
+{
+ int buf_len = sizeof(struct air_asrv_rsp) * 3;
+ struct atminfreq air;
+ struct air_cfg_rsp *cfg_info, *cfg_info_base;
+
+ /*
+ * Validate interface name
+ */
+ UM_ZERO(air.air_cfg_intf, sizeof(air.air_cfg_intf));
+ if (argc) {
+ if (strlen(argv[0]) > IFNAMSIZ - 1) {
+ fprintf(stderr, "%s: Illegal interface name\n",
+ prog);
+ exit(1);
+ }
+ strcpy(air.air_cfg_intf, argv[0]);
+ argc--; argv++;
+ }
+
+ /*
+ * Get configuration information from the kernel
+ */
+ air.air_opcode = AIOCS_INF_CFG;
+ buf_len = do_info_ioctl(&air, buf_len);
+ if (buf_len < 0) {
+ fprintf(stderr, "%s: ", prog);
+ switch (errno) {
+ case ENOPROTOOPT:
+ case EOPNOTSUPP:
+ perror("Internal error");
+ break;
+ case ENXIO:
+ fprintf(stderr, "%s is not an ATM device\n",
+ argv[0]);
+ break;
+ default:
+ perror("ioctl (AIOCINFO)");
+ break;
+ }
+ exit(1);
+ }
+
+ /*
+ * Print the interface information
+ */
+ cfg_info_base = cfg_info =
+ (struct air_cfg_rsp *) air.air_buf_addr;
+ for (; buf_len >= sizeof(struct air_cfg_rsp); cfg_info++,
+ buf_len -= sizeof(struct air_cfg_rsp)) {
+ print_cfg_info(cfg_info);
+ }
+ UM_FREE(cfg_info_base);
+}
+
+
+/*
+ * Process show interface command
+ *
+ * Command format:
+ * atm show interface [<interface-name>]
+ *
+ * Arguments:
+ * argc number of remaining arguments to command
+ * argv pointer to remaining argument strings
+ * cmdp pointer to command description
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+show_intf(argc, argv, cmdp)
+ int argc;
+ char **argv;
+ struct cmd *cmdp;
+{
+ int buf_len = sizeof(struct air_int_rsp) * 3;
+ struct atminfreq air;
+ struct air_int_rsp *int_info, *int_info_base;
+
+ /*
+ * Validate interface name
+ */
+ UM_ZERO(&air, sizeof(air));
+ if (argc) {
+ if (strlen(argv[0]) > IFNAMSIZ - 1) {
+ fprintf(stderr, "%s: Illegal interface name\n",
+ prog);
+ exit(1);
+ }
+ strcpy(air.air_int_intf, argv[0]);
+ argc--; argv++;
+ }
+
+ /*
+ * Get interface information from the kernel
+ */
+ air.air_opcode = AIOCS_INF_INT;
+ buf_len = do_info_ioctl(&air, buf_len);
+ if (buf_len < 0) {
+ fprintf(stderr, "%s: ", prog);
+ switch (errno) {
+ case ENOPROTOOPT:
+ case EOPNOTSUPP:
+ perror("Internal error");
+ break;
+ case ENXIO:
+ fprintf(stderr, "%s is not an ATM device\n",
+ argv[0]);
+ break;
+ default:
+ perror("ioctl (AIOCINFO)");
+ break;
+ }
+ exit(1);
+ }
+
+ /*
+ * Print the interface information
+ */
+ int_info_base = int_info =
+ (struct air_int_rsp *) air.air_buf_addr;
+ for (; buf_len >= sizeof(struct air_int_rsp); int_info++,
+ buf_len -= sizeof(struct air_int_rsp)) {
+ print_intf_info(int_info);
+ }
+ UM_FREE(int_info_base);
+}
+
+
+/*
+ * Process show IP VCCs command
+ *
+ * Command format:
+ * atm show ipvcc [<ip-addr>]
+ *
+ * Arguments:
+ * argc number of remaining arguments to command
+ * argv pointer to remaining argument strings
+ * cmdp pointer to command description
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+show_ip_vcc(argc, argv, cmdp)
+ int argc;
+ char **argv;
+ struct cmd *cmdp;
+{
+ int buf_len, ip_info_len, rc, sel;
+ char *if_name = (char *)0;
+ struct atminfreq air;
+ struct air_ip_vcc_rsp *ip_info, *ip_info_base;
+ struct sockaddr_in *sin;
+ union {
+ struct sockaddr_in sin;
+ struct sockaddr sa;
+ } host_addr;
+
+ /*
+ * First parameter can be a netif name, an IP host name, or
+ * an IP address. Figure out which it is.
+ */
+ UM_ZERO(&host_addr, sizeof(host_addr));
+ host_addr.sa.sa_family = AF_INET;
+ if (argc) {
+ rc = verify_nif_name(argv[0]);
+ if (rc < 0) {
+ /*
+ * Error occured
+ */
+ fprintf(stderr, "%s: ", prog);
+ switch (errno) {
+ case ENOPROTOOPT:
+ case EOPNOTSUPP:
+ perror("Internal error");
+ break;
+ case ENXIO:
+ fprintf(stderr, "%s is not an ATM device\n",
+ argv[0]);
+ break;
+ default:
+ perror("ioctl (AIOCINFO)");
+ break;
+ }
+ exit(1);
+ } else if (rc > 0) {
+ /*
+ * Parameter is a valid netif name
+ */
+ if_name = argv[0];
+ } else {
+ /*
+ * Get IP address of specified host name
+ */
+ sin = get_ip_addr(argv[0]);
+ host_addr.sin.sin_addr.s_addr =
+ sin->sin_addr.s_addr;
+ }
+ } else {
+ host_addr.sin.sin_addr.s_addr = INADDR_ANY;
+ }
+
+ /*
+ * Get IP map information from the kernel
+ */
+ buf_len = sizeof(struct air_ip_vcc_rsp) * 10;
+ air.air_opcode = AIOCS_INF_IPM;
+ air.air_ip_addr = host_addr.sa;
+ ip_info_len = do_info_ioctl(&air, buf_len);
+ if (ip_info_len < 0) {
+ fprintf(stderr, "%s: ", prog);
+ switch (errno) {
+ case ENOPROTOOPT:
+ case EOPNOTSUPP:
+ perror("Internal error");
+ break;
+ case ENXIO:
+ fprintf(stderr, "not an ATM device\n");
+ break;
+ default:
+ perror("ioctl (AIOCINFO)");
+ break;
+ }
+ exit(1);
+ }
+ ip_info_base = ip_info =
+ (struct air_ip_vcc_rsp *) air.air_buf_addr;
+
+ /*
+ * Sort the information
+ */
+ qsort((void *) ip_info,
+ ip_info_len / sizeof(struct air_ip_vcc_rsp),
+ sizeof(struct air_ip_vcc_rsp),
+ ip_vcc_compare);
+
+ /*
+ * Print the relevant information
+ */
+ while (ip_info_len>0) {
+ if (!if_name || !strcmp(if_name, ip_info->aip_intf)) {
+ print_ip_vcc_info(ip_info);
+ }
+ ip_info++;
+ ip_info_len -= sizeof(struct air_ip_vcc_rsp);
+ }
+
+ /*
+ * Release the information from the kernel
+ */
+ UM_FREE(ip_info_base);
+
+}
+
+
+/*
+ * Process show network interface command
+ *
+ * Command format:
+ * atm show netif [<netif>]
+ *
+ * Arguments:
+ * argc number of remaining arguments to command
+ * argv pointer to remaining argument strings
+ * cmdp pointer to command description
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+show_netif(argc, argv, cmdp)
+ int argc;
+ char **argv;
+ struct cmd *cmdp;
+{
+ int buf_len = sizeof(struct air_netif_rsp) * 3;
+ struct atminfreq air;
+ struct air_netif_rsp *int_info, *int_info_base;
+
+ /*
+ * Validate network interface name
+ */
+ UM_ZERO(air.air_int_intf, sizeof(air.air_int_intf));
+ if (argc) {
+ if (strlen(argv[0]) > IFNAMSIZ - 1) {
+ fprintf(stderr, "%s: Illegal interface name\n", prog);
+ exit(1);
+ }
+ strcpy(air.air_int_intf, argv[0]);
+ argc--; argv++;
+ }
+
+ /*
+ * Get network interface information from the kernel
+ */
+ air.air_opcode = AIOCS_INF_NIF;
+ buf_len = do_info_ioctl(&air, buf_len);
+ if (buf_len < 0) {
+ fprintf(stderr, "%s: ", prog);
+ switch (errno) {
+ case ENOPROTOOPT:
+ case EOPNOTSUPP:
+ perror("Internal error");
+ break;
+ case ENXIO:
+ fprintf(stderr, "%s is not an ATM device\n",
+ argv[0]);
+ break;
+ default:
+ perror("ioctl (AIOCINFO)");
+ break;
+ }
+ exit(1);
+ }
+
+ /*
+ * Print the network interface information
+ */
+ int_info_base = int_info =
+ (struct air_netif_rsp *) air.air_buf_addr;
+ for (; buf_len >= sizeof(struct air_netif_rsp); int_info++,
+ buf_len -= sizeof(struct air_netif_rsp)) {
+ print_netif_info(int_info);
+ }
+ UM_FREE(int_info_base);
+}
+
+
+/*
+ * Process interface statistics command
+ *
+ * Command format:
+ * atm show stats interface [<interface-name>]
+ *
+ * Arguments:
+ * argc number of remaining arguments to command
+ * argv pointer to remaining argument strings
+ * cmdp pointer to command description
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+show_intf_stats(argc, argv, cmdp)
+ int argc;
+ char **argv;
+ struct cmd *cmdp;
+{
+ int buf_len;
+ char intf[IFNAMSIZ];
+ struct atminfreq air;
+ struct air_phy_stat_rsp *pstat_info, *pstat_info_base;
+ struct air_cfg_rsp *cfg_info;
+
+ /*
+ * Validate interface name
+ */
+ UM_ZERO(intf, sizeof(intf));
+ if (argc) {
+ if (strlen(argv[0]) > IFNAMSIZ - 1) {
+ fprintf(stderr, "%s: Illegal interface name\n",
+ prog);
+ exit(1);
+ }
+ strcpy(intf, argv[0]);
+ argc--; argv++;
+ }
+
+ /*
+ * If there are parameters remaining, the request is for
+ * vendor-specific adaptor statistics
+ */
+ if (argc) {
+ /*
+ * Get adapter configuration information
+ */
+ buf_len = sizeof(struct air_cfg_rsp);
+ air.air_opcode = AIOCS_INF_CFG;
+ strcpy(air.air_cfg_intf, intf);
+ buf_len = do_info_ioctl(&air, buf_len);
+ if (buf_len < 0) {
+ fprintf(stderr, "%s: ", prog);
+ switch (errno) {
+ case ENOPROTOOPT:
+ case EOPNOTSUPP:
+ perror("Internal error");
+ break;
+ case ENXIO:
+ fprintf(stderr, "%s is not an ATM device\n",
+ intf);
+ break;
+ default:
+ perror("ioctl (AIOCINFO)");
+ break;
+ }
+ exit(1);
+ }
+ cfg_info = (struct air_cfg_rsp *)air.air_buf_addr;
+
+ /*
+ * Call the appropriate vendor-specific routine
+ */
+ switch(cfg_info->acp_vendor) {
+ case VENDOR_FORE:
+ show_fore200_stats(intf, argc, argv);
+ break;
+ case VENDOR_ENI:
+ show_eni_stats(intf, argc, argv);
+ break;
+ default:
+ fprintf(stderr, "%s: Unknown adapter vendor\n",
+ prog);
+ break;
+ }
+
+ UM_FREE(cfg_info);
+ } else {
+ /*
+ * Get generic interface statistics
+ */
+ buf_len = sizeof(struct air_phy_stat_rsp) * 3;
+ air.air_opcode = AIOCS_INF_PIS;
+ strcpy(air.air_physt_intf, intf);
+ buf_len = do_info_ioctl(&air, buf_len);
+ if (buf_len < 0) {
+ fprintf(stderr, "%s: ", prog);
+ switch (errno) {
+ case ENOPROTOOPT:
+ case EOPNOTSUPP:
+ perror("Internal error");
+ break;
+ case ENXIO:
+ fprintf(stderr, "%s is not an ATM device\n",
+ intf);
+ break;
+ default:
+ perror("ioctl (AIOCINFO)");
+ break;
+ }
+ exit(1);
+ }
+
+ /*
+ * Display the interface statistics
+ */
+ pstat_info_base = pstat_info =
+ (struct air_phy_stat_rsp *)air.air_buf_addr;
+ for (; buf_len >= sizeof(struct air_phy_stat_rsp);
+ pstat_info++,
+ buf_len-=sizeof(struct air_phy_stat_rsp)) {
+ print_intf_stats(pstat_info);
+ }
+ UM_FREE((caddr_t)pstat_info_base);
+ }
+}
+
+
+/*
+ * Process VCC statistics command
+ *
+ * Command format:
+ * atm show stats VCC [<interface-name> [<vpi> [<vci>]]]
+ *
+ * Arguments:
+ * argc number of remaining arguments to command
+ * argv pointer to remaining argument strings
+ * cmdp pointer to command description
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+show_vcc_stats(argc, argv, cmdp)
+ int argc;
+ char **argv;
+ struct cmd *cmdp;
+{
+ int vcc_info_len;
+ int vpi = -1, vci = -1;
+ char *cp, *intf = NULL;
+ struct air_vcc_rsp *vcc_info, *vcc_info_base;
+
+ /*
+ * Validate interface name
+ */
+ if (argc) {
+ if (strlen(argv[0]) > IFNAMSIZ - 1) {
+ fprintf(stderr, "%s: Illegal interface name\n",
+ prog);
+ exit(1);
+ }
+ intf = argv[0];
+ argc--; argv++;
+ }
+
+ /*
+ * Validate VPI value
+ */
+ if (argc) {
+ vpi = strtol(argv[0], &cp, 0);
+ if ((*cp != '\0') || (vpi < 0) || (vpi >= 1 << 8)) {
+ fprintf(stderr, "%s: Invalid VPI value\n", prog);
+ exit(1);
+ }
+ argc--; argv++;
+ }
+
+ /*
+ * Validate VCI value
+ */
+ if (argc) {
+ vci = strtol(argv[0], &cp, 0);
+ if ((*cp != '\0') || (vci <= 0) || (vci >= 1 << 16)) {
+ fprintf(stderr, "%s: Invalid VCI value\n",
+ prog);
+ exit(1);
+ }
+ argc--; argv++;
+ }
+
+ /*
+ * Get VCC information
+ */
+ vcc_info_len = get_vcc_info(intf, &vcc_info);
+ if (vcc_info_len == 0)
+ exit(1);
+ else if (vcc_info_len < 0) {
+ fprintf(stderr, "%s: ", prog);
+ switch (errno) {
+ case ENOPROTOOPT:
+ case EOPNOTSUPP:
+ perror("Internal error");
+ break;
+ case ENXIO:
+ fprintf(stderr, "Not an ATM device\n");
+ break;
+ default:
+ perror("ioctl (AIOCINFO)");
+ break;
+ }
+ exit(1);
+ }
+
+ /*
+ * Sort the VCC information
+ */
+ qsort((void *) vcc_info,
+ vcc_info_len / sizeof(struct air_vcc_rsp),
+ sizeof(struct air_vcc_rsp),
+ vcc_compare);
+
+ /*
+ * Display the VCC statistics
+ */
+ vcc_info_base = vcc_info;
+ for (; vcc_info_len >= sizeof(struct air_vcc_rsp);
+ vcc_info_len-=sizeof(struct air_vcc_rsp),
+ vcc_info++) {
+ if (vpi != -1 && vcc_info->avp_vpi != vpi)
+ continue;
+ if (vci != -1 && vcc_info->avp_vci != vci)
+ continue;
+ print_vcc_stats(vcc_info);
+ }
+ UM_FREE(vcc_info_base);
+}
+
+
+/*
+ * Process VCC information command
+ *
+ * Command format:
+ * atm show VCC [<interface-name> [<vpi> [<vci>] | PVC | SVC]]
+ *
+ * Arguments:
+ * argc number of remaining arguments to command
+ * argv pointer to remaining argument strings
+ * cmdp pointer to command description
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+show_vcc(argc, argv, cmdp)
+ int argc;
+ char **argv;
+ struct cmd *cmdp;
+{
+ int vcc_info_len;
+ int vpi = -1, vci = -1, show_pvc = 0, show_svc = 0;
+ char *cp, *intf = NULL;
+ struct air_vcc_rsp *vcc_info, *vcc_info_base;
+
+ /*
+ * Validate interface name
+ */
+ if (argc) {
+ if (strlen(argv[0]) > IFNAMSIZ - 1) {
+ fprintf(stderr, "%s: Illegal interface name\n",
+ prog);
+ exit(1);
+ }
+ intf = argv[0];
+ argc--; argv++;
+ }
+
+ /*
+ * Validate VPI value
+ */
+ if (argc) {
+ if (strcasecmp(argv[0], "pvc"))
+ show_pvc = 1;
+ else if (strcasecmp(argv[0], "svc"))
+ show_svc = 1;
+ else {
+ vpi = strtol(argv[0], &cp, 0);
+ if ((*cp != '\0') || (vpi < 0) ||
+ (vpi >= 1 << 8)) {
+ fprintf(stderr, "%s: Invalid VPI value\n", prog);
+ exit(1);
+ }
+ }
+ argc--; argv++;
+ }
+
+ /*
+ * Validate VCI value
+ */
+ if (argc) {
+ vci = strtol(argv[0], &cp, 0);
+ if ((*cp != '\0') || (vci <= 0) || (vci >= 1 << 16)) {
+ fprintf(stderr, "%s: Invalid VCI value\n",
+ prog);
+ exit(1);
+ }
+ argc--; argv++;
+ }
+
+ /*
+ * Get VCC information
+ */
+ vcc_info_len = get_vcc_info(intf, &vcc_info);
+ if (vcc_info_len == 0)
+ exit(1);
+ else if (vcc_info_len < 0) {
+ fprintf(stderr, "%s: ", prog);
+ switch (errno) {
+ case ENOPROTOOPT:
+ case EOPNOTSUPP:
+ perror("Internal error");
+ break;
+ case ENXIO:
+ fprintf(stderr, "Not an ATM device\n");
+ break;
+ default:
+ perror("ioctl (AIOCINFO)");
+ break;
+ }
+ exit(1);
+ }
+
+ /*
+ * Sort the VCC information
+ */
+ qsort((void *) vcc_info,
+ vcc_info_len/sizeof(struct air_vcc_rsp),
+ sizeof(struct air_vcc_rsp),
+ vcc_compare);
+
+ /*
+ * Display the VCC information
+ */
+ vcc_info_base = vcc_info;
+ for (; vcc_info_len >= sizeof(struct air_vcc_rsp);
+ vcc_info_len-=sizeof(struct air_vcc_rsp),
+ vcc_info++) {
+ if (vpi != -1 && vcc_info->avp_vpi != vpi)
+ continue;
+ if (vci != -1 && vcc_info->avp_vci != vci)
+ continue;
+ if (show_pvc && vcc_info->avp_type & VCC_PVC)
+ continue;
+ if (show_svc && vcc_info->avp_type & VCC_SVC)
+ continue;
+ print_vcc_info(vcc_info);
+ }
+ UM_FREE(vcc_info_base);
+}
+
+
+/*
+ * Process version command
+ *
+ * Command format:
+ * atm show version
+ *
+ * Arguments:
+ * argc number of remaining arguments to command
+ * argv pointer to remaining argument strings
+ * cmdp pointer to command description
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+show_version(argc, argv, cmdp)
+ int argc;
+ char **argv;
+ struct cmd *cmdp;
+{
+ int buf_len = sizeof(struct air_version_rsp);
+ struct atminfreq air;
+ struct air_version_rsp *ver_info, *ver_info_base;
+
+ /*
+ * Get network interface information from the kernel
+ */
+ air.air_opcode = AIOCS_INF_VER;
+ buf_len = do_info_ioctl(&air, buf_len);
+ if (buf_len < 0) {
+ fprintf(stderr, "%s: ", prog);
+ switch (errno) {
+ case ENOPROTOOPT:
+ case EOPNOTSUPP:
+ perror("Internal error");
+ break;
+ case ENXIO:
+ fprintf(stderr, "Not an ATM device\n");
+ break;
+ default:
+ perror("ioctl (AIOCINFO)");
+ break;
+ }
+ exit(1);
+ }
+
+ /*
+ * Print the network interface information
+ */
+ ver_info_base = ver_info =
+ (struct air_version_rsp *) air.air_buf_addr;
+ for (; buf_len >= sizeof(struct air_version_rsp); ver_info++,
+ buf_len -= sizeof(struct air_version_rsp)) {
+ print_version_info(ver_info);
+ }
+ UM_FREE(ver_info_base);
+}
+
+
+/*
+ * Comparison function for qsort
+ *
+ * Arguments:
+ * p1 pointer to the first VCC response
+ * p2 pointer to the second VCC response
+ *
+ * Returns:
+ * int a number less than, greater than, or equal to zero,
+ * depending on whether *p1 is less than, greater than, or
+ * equal to *p2
+ *
+ */
+static int
+vcc_compare(p1, p2)
+ const void *p1, *p2;
+{
+ int rc;
+ struct air_vcc_rsp *c1, *c2;
+
+ c1 = (struct air_vcc_rsp *) p1;
+ c2 = (struct air_vcc_rsp *) p2;
+
+ /*
+ * Compare the interface names
+ */
+ rc = strcmp(c1->avp_intf, c2->avp_intf);
+ if (rc)
+ return(rc);
+
+ /*
+ * Compare the VPI values
+ */
+ rc = c1->avp_vpi - c2->avp_vpi;
+ if (rc)
+ return(rc);
+
+ /*
+ * Compare the VCI values
+ */
+ rc = c1->avp_vci - c2->avp_vci;
+ if (rc)
+ return(rc);
+
+ /*
+ * Compare the types
+ */
+ rc = c1->avp_type - c2->avp_type;
+ return(rc);
+}
+
+
+/*
+ * Comparison function for qsort
+ *
+ * Arguments:
+ * p1 pointer to the first VCC response
+ * p2 pointer to the second VCC response
+ *
+ * Returns:
+ * int a number less than, greater than, or equal to zero,
+ * depending on whether *p1 is less than, greater than, or
+ * equal to *p2
+ *
+ */
+static int
+ip_vcc_compare(p1, p2)
+ const void *p1, *p2;
+{
+ int rc;
+ struct air_ip_vcc_rsp *c1, *c2;
+
+ c1 = (struct air_ip_vcc_rsp *) p1;
+ c2 = (struct air_ip_vcc_rsp *) p2;
+
+ /*
+ * Compare the interface names
+ */
+ rc = strcmp(c1->aip_intf, c2->aip_intf);
+ if (rc)
+ return(rc);
+
+ /*
+ * Compare the VPI values
+ */
+ rc = c1->aip_vpi - c2->aip_vpi;
+ if (rc)
+ return(rc);
+
+ /*
+ * Compare the VCI values
+ */
+ rc = c1->aip_vci - c2->aip_vci;
+ return(rc);
+}
+
+
+/*
+ * Comparison function for qsort
+ *
+ * Arguments:
+ * p1 pointer to the first ARP or IP map entry
+ * p2 pointer to the second ARP or IP map entry
+ *
+ * Returns:
+ * int a number less than, greater than, or equal to zero,
+ * depending on whether *p1 is less than, greater than, or
+ * equal to *p2
+ *
+ */
+static int
+arp_compare(p1, p2)
+ const void *p1, *p2;
+{
+ int rc;
+ struct air_arp_rsp *c1, *c2;
+ struct sockaddr_in *sin1, *sin2;
+
+ c1 = (struct air_arp_rsp *) p1;
+ c2 = (struct air_arp_rsp *) p2;
+ sin1 = (struct sockaddr_in *) &c1->aap_arp_addr;
+ sin2 = (struct sockaddr_in *) &c2->aap_arp_addr;
+
+ /*
+ * Compare the IP addresses
+ */
+ if (rc = sin1->sin_family - sin2->sin_family)
+ return(rc);
+ if (rc = sin1->sin_addr.s_addr - sin2->sin_addr.s_addr)
+ return(rc);
+
+ /*
+ * Compare the ATM addresses
+ */
+ if (rc = c1->aap_addr.address_format - c2->aap_addr.address_format)
+ return(rc);
+ if (rc = c1->aap_addr.address_length - c2->aap_addr.address_length)
+ return(rc);
+ switch(c1->aap_addr.address_format) {
+ case T_ATM_ABSENT:
+ rc = 0;
+ break;
+ case T_ATM_ENDSYS_ADDR:
+ rc = bcmp((caddr_t)c1->aap_addr.address,
+ (caddr_t)c2->aap_addr.address,
+ sizeof(Atm_addr_nsap));
+ break;
+ case T_ATM_E164_ADDR:
+ rc = bcmp((caddr_t)c1->aap_addr.address,
+ (caddr_t)c2->aap_addr.address,
+ sizeof(Atm_addr_e164));
+ break;
+ case T_ATM_SPANS_ADDR:
+ rc = bcmp((caddr_t)c1->aap_addr.address,
+ (caddr_t)c2->aap_addr.address,
+ sizeof(Atm_addr_spans));
+ break;
+ }
+
+ return(rc);
+}
diff --git a/sbin/atm/atm/atm_subr.c b/sbin/atm/atm/atm_subr.c
new file mode 100644
index 0000000..4571173
--- /dev/null
+++ b/sbin/atm/atm/atm_subr.c
@@ -0,0 +1,620 @@
+/*
+ *
+ * ===================================
+ * 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: atm_subr.c,v 1.11 1998/07/09 22:24:03 johnc Exp $
+ *
+ */
+
+/*
+ * User configuration and display program
+ * --------------------------------------
+ *
+ * General subroutines
+ *
+ */
+
+#ifndef lint
+static char *RCSid = "@(#) $Id: atm_subr.c,v 1.11 1998/07/09 22:24:03 johnc Exp $";
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.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_sap.h>
+#include <netatm/atm_sys.h>
+#include <netatm/atm_ioctl.h>
+
+#include <libatm.h>
+#include "atm.h"
+
+
+/*
+ * Table entry definition
+ */
+typedef struct {
+ int type;
+ char *name;
+} tbl_ent;
+
+
+/*
+ * Table to translate vendor codes to ASCII
+ */
+tbl_ent vendors[] = {
+ { VENDAPI_UNKNOWN, "Unknown" },
+ { VENDAPI_FORE_1, "Fore" },
+ { VENDAPI_ENI_1, "ENI" },
+ { 0, 0 },
+};
+
+
+/*
+ * Table to translate adapter codes to ASCII
+ */
+tbl_ent adapter_types[] = {
+ { DEV_UNKNOWN, "Unknown" },
+ { DEV_FORE_SBA200E, "SBA-200E" },
+ { DEV_FORE_SBA200, "SBA-200" },
+ { DEV_FORE_PCA200E, "PCA-200E" },
+ { DEV_ENI_155P, "ENI-155p" },
+ { 0, 0 },
+};
+
+/*
+ * Table to translate medium types to ASCII
+ */
+tbl_ent media_types[] = {
+ { MEDIA_UNKNOWN, "Unknown" },
+ { MEDIA_TAXI_100, "100 Mbps 4B/5B" },
+ { MEDIA_TAXI_140, "140 Mbps 4B/5B" },
+ { MEDIA_OC3C, "OC-3c" },
+ { MEDIA_OC12C, "OC-12c" },
+ { MEDIA_UTP155, "155 Mbps UTP" },
+ { 0, 0 },
+};
+
+/*
+ * Table to translate bus types to ASCII
+ */
+tbl_ent bus_types[] = {
+ { BUS_UNKNOWN, "Unknown" },
+ { BUS_SBUS_B16, "SBus" },
+ { BUS_SBUS_B32, "SBus" },
+ { BUS_PCI, "PCI" },
+ { 0, 0 },
+};
+
+
+/*
+ * Get interface vendor name
+ *
+ * Return a character string with a vendor name, given a vendor code.
+ *
+ * Arguments:
+ * vendor vendor ID
+ *
+ * Returns:
+ * char * pointer to a string with the vendor name
+ *
+ */
+char *
+get_vendor(vendor)
+ int vendor;
+{
+ int i;
+
+ for(i=0; vendors[i].name; i++) {
+ if (vendors[i].type == vendor)
+ return(vendors[i].name);
+ }
+
+ return("-");
+}
+
+
+/*
+ * Get adapter type
+ *
+ * Arguments:
+ * dev adapter code
+ *
+ * Returns:
+ * char * pointer to a string with the adapter type
+ *
+ */
+char *
+get_adapter(dev)
+ int dev;
+{
+ int i;
+
+ for(i=0; adapter_types[i].name; i++) {
+ if (adapter_types[i].type == dev)
+ return(adapter_types[i].name);
+ }
+
+ return("-");
+}
+
+
+/*
+ * Get communication medium type
+ *
+ * Arguments:
+ * media medium code
+ *
+ * Returns:
+ * char * pointer to a string with the name of the medium
+ *
+ */
+char *
+get_media_type(media)
+ int media;
+{
+ int i;
+
+ for(i=0; media_types[i].name; i++) {
+ if (media_types[i].type == media)
+ return(media_types[i].name);
+ }
+
+ return("-");
+}
+
+
+/*
+ * Get bus type
+ *
+ * Arguments:
+ * bus bus type code
+ *
+ * Returns:
+ * char * pointer to a string with the bus type
+ *
+ */
+char *
+get_bus_type(bus)
+ int bus;
+{
+ int i;
+
+ for(i=0; bus_types[i].name; i++) {
+ if (bus_types[i].type == bus)
+ return(bus_types[i].name);
+ }
+
+ return("-");
+}
+
+
+/*
+ * Get adapter ID
+ *
+ * Get a string giving the adapter's vendor and type.
+ *
+ * Arguments:
+ * intf interface name
+ *
+ * Returns:
+ * char * pointer to a string identifying the adapter
+ *
+ */
+char *
+get_adapter_name(intf)
+ char *intf;
+{
+ int buf_len;
+ struct atminfreq air;
+ struct air_cfg_rsp *cfg;
+ static char name[256];
+
+ /*
+ * Initialize
+ */
+ UM_ZERO(&air, sizeof(air));
+ UM_ZERO(name, sizeof(name));
+
+ /*
+ * Get configuration information from the kernel
+ */
+ air.air_opcode = AIOCS_INF_CFG;
+ strcpy(air.air_cfg_intf, intf);
+ buf_len = do_info_ioctl(&air, sizeof(struct air_cfg_rsp));
+ if (buf_len < sizeof(struct air_cfg_rsp))
+ return("-");
+ cfg = (struct air_cfg_rsp *) air.air_buf_addr;
+
+ /*
+ * Build a string describing the adapter
+ */
+ strcpy(name, get_vendor(cfg->acp_vendor));
+ strcat(name, " ");
+ strcat(name, get_adapter(cfg->acp_device));
+
+ UM_FREE(cfg);
+
+ return(name);
+}
+
+
+/*
+ * Format a MAC address into a string
+ *
+ * Arguments:
+ * addr pointer to a MAC address
+ *
+ * Returns:
+ * the address of a string representing the MAC address
+ *
+ */
+char *
+format_mac_addr(addr)
+ Mac_addr *addr;
+{
+ static char str[256];
+
+ /*
+ * Check for null pointer
+ */
+ if (!addr)
+ return("-");
+
+ /*
+ * Clear the returned string
+ */
+ UM_ZERO(str, sizeof(str));
+
+ /*
+ * Format the address
+ */
+ sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
+ addr->ma_data[0],
+ addr->ma_data[1],
+ addr->ma_data[2],
+ addr->ma_data[3],
+ addr->ma_data[4],
+ addr->ma_data[5]);
+
+ return(str);
+}
+
+
+/*
+ * Parse an IP prefix designation in the form nnn.nnn.nnn.nnn/mm
+ *
+ * Arguments:
+ * cp pointer to prefix designation string
+ * op pointer to a pair of in_addrs for the result
+ *
+ * Returns:
+ * 0 success
+ * -1 prefix was invalid
+ *
+ */
+int
+parse_ip_prefix(cp, op)
+ char *cp;
+ struct in_addr *op;
+{
+ int i, len;
+ char *mp;
+ struct in_addr ip_addr;
+
+ static u_long masks[33] = {
+ 0x0,
+ 0x80000000,
+ 0xc0000000,
+ 0xe0000000,
+ 0xf0000000,
+ 0xf8000000,
+ 0xfc000000,
+ 0xfe000000,
+ 0xff000000,
+ 0xff800000,
+ 0xffc00000,
+ 0xffe00000,
+ 0xfff00000,
+ 0xfff80000,
+ 0xfffc0000,
+ 0xfffe0000,
+ 0xffff0000,
+ 0xffff8000,
+ 0xffffc000,
+ 0xffffe000,
+ 0xfffff000,
+ 0xfffff800,
+ 0xfffffc00,
+ 0xfffffe00,
+ 0xffffff00,
+ 0xffffff80,
+ 0xffffffc0,
+ 0xffffffe0,
+ 0xfffffff0,
+ 0xfffffff8,
+ 0xfffffffc,
+ 0xfffffffe,
+ 0xffffffff
+ };
+
+ /*
+ * Find the slash that marks the start of the mask
+ */
+ mp = strchr(cp, '/');
+ if (mp) {
+ *mp = '\0';
+ mp++;
+ }
+
+ /*
+ * Convert the IP-address part of the prefix
+ */
+ ip_addr.s_addr = inet_addr(cp);
+ if (ip_addr.s_addr == -1)
+ return(-1);
+
+ /*
+ * Set the default mask length
+ */
+ if (IN_CLASSA(ntohl(ip_addr.s_addr)))
+ len = 8;
+ else if (IN_CLASSB(ntohl(ip_addr.s_addr)))
+ len = 16;
+ else if (IN_CLASSC(ntohl(ip_addr.s_addr)))
+ len = 24;
+ else
+ return(-1);
+
+ /*
+ * Get the mask length
+ */
+ if (mp) {
+ len = atoi(mp);
+ if (len < 1 || len > 32)
+ return(-1);
+ }
+
+ /*
+ * Select the mask and copy the IP address into the
+ * result buffer, ANDing it with the mask
+ */
+ op[1].s_addr = htonl(masks[len]);
+ op[0].s_addr = ip_addr.s_addr & op[1].s_addr;
+
+ return(0);
+}
+
+
+/*
+ * Compress a list of IP network prefixes
+ *
+ * Arguments:
+ * ipp pointer to list of IP address/mask pairs
+ * ipc length of list
+ *
+ * Returns:
+ * length of compressed list
+ *
+ */
+int
+compress_prefix_list(ipp, ilen)
+ struct in_addr *ipp;
+ int ilen;
+{
+ int i, j, n;
+ struct in_addr *ip1, *ip2, *m1, *m2;
+
+ /*
+ * Figure out how many pairs there are
+ */
+ n = ilen / (sizeof(struct in_addr) * 2);
+
+ /*
+ * Check each pair of address/mask pairs to make sure
+ * none contains the other
+ */
+ for (i = 0; i < n; i++) {
+ ip1 = &ipp[i*2];
+ m1 = &ipp[i*2+1];
+
+ /*
+ * If we've already eliminated this address,
+ * skip the checks
+ */
+ if (ip1->s_addr == 0)
+ continue;
+
+ /*
+ * Try all possible second members of the pair
+ */
+ for (j = i + 1; j < n; j++) {
+ ip2 = &ipp[j*2];
+ m2 = &ipp[j*2+1];
+
+ /*
+ * If we've already eliminated the second
+ * address, just skip the checks
+ */
+ if (ip2->s_addr == 0)
+ continue;
+
+ /*
+ * Compare the address/mask pairs
+ */
+ if (m1->s_addr == m2->s_addr) {
+ /*
+ * Masks are equal
+ */
+ if (ip1->s_addr == ip2->s_addr) {
+ ip2->s_addr = 0;
+ m2->s_addr = 0;
+ }
+ } else if (ntohl(m1->s_addr) <
+ ntohl(m2->s_addr)) {
+ /*
+ * m1 is shorter
+ */
+ if ((ip2->s_addr & m1->s_addr) ==
+ ip1->s_addr) {
+ ip2->s_addr = 0;
+ m2->s_addr = 0;
+ }
+ } else {
+ /*
+ * m1 is longer
+ */
+ if (ip1->s_addr & m2->s_addr ==
+ ip2->s_addr) {
+ ip1->s_addr = 0;
+ m1->s_addr = 0;
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ * Now pull up the list, eliminating zeroed entries
+ */
+ for (i = 0, j = 0; i < n; i++) {
+ ip1 = &ipp[i*2];
+ m1 = &ipp[i*2+1];
+ ip2 = &ipp[j*2];
+ m2 = &ipp[j*2+1];
+ if (ip1->s_addr != 0) {
+ if (i != j) {
+ *ip2 = *ip1;
+ *m2 = *m1;
+ }
+ j++;
+ }
+ }
+
+ return(j * sizeof(struct in_addr) * 2);
+}
+
+
+/*
+ * Make sure a user-supplied parameter is a valid network interface
+ * name
+ *
+ * When a socket call fails, print an error message and exit
+ *
+ * Arguments:
+ * nif pointer to network interface name
+ *
+ * Returns:
+ * none exits if name is not valid
+ *
+ */
+void
+check_netif_name(nif)
+ char *nif;
+{
+ int rc;
+
+ /*
+ * Look up the name in the kernel
+ */
+ rc = verify_nif_name(nif);
+
+ /*
+ * Check the result
+ */
+ if (rc > 0) {
+ /*
+ * Name is OK
+ */
+ return;
+ } else if (rc == 0) {
+ /*
+ * Name is not valid
+ */
+ fprintf(stderr, "%s: Invalid network interface name %s\n",
+ prog, nif);
+ } else {
+ /*
+ * Error performing IOCTL
+ */
+ fprintf(stderr, "%s: ", prog);
+ switch(errno) {
+ case ENOPROTOOPT:
+ case EOPNOTSUPP:
+ perror("Internal error");
+ break;
+ case ENXIO:
+ fprintf(stderr, "%s is not an ATM device\n",
+ nif);
+ break;
+ default:
+ perror("ioctl (AIOCINFO)");
+ break;
+ }
+ }
+
+ exit(1);
+}
+
+
+/*
+ * Socket error handler
+ *
+ * When a socket call fails, print an error message and exit
+ *
+ * Arguments:
+ * err an errno describing the error
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+sock_error(err)
+ int err;
+{
+ fprintf(stderr, "%s: ", prog);
+
+ switch (err) {
+
+ case EPROTONOSUPPORT:
+ fprintf(stderr, "ATM protocol support not loaded\n");
+ break;
+
+ default:
+ perror("socket");
+ break;
+ }
+
+ exit(1);
+}
diff --git a/sbin/atm/fore_dnld/Makefile b/sbin/atm/fore_dnld/Makefile
new file mode 100644
index 0000000..ac7c3a2
--- /dev/null
+++ b/sbin/atm/fore_dnld/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= fore_dnld
+MAN8= fore_dnld.8
+
+CFLAGS+= -I ${.CURDIR}/../../../sys
+LDADD+= -latm
+
+.include <bsd.prog.mk>
diff --git a/sbin/atm/fore_dnld/fore_dnld.8 b/sbin/atm/fore_dnld/fore_dnld.8
new file mode 100644
index 0000000..770f85d
--- /dev/null
+++ b/sbin/atm/fore_dnld/fore_dnld.8
@@ -0,0 +1,108 @@
+.\"
+.\" ===================================
+.\" 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: fore_dnld.1,v 1.4 1997/05/09 17:29:37 mks Exp $
+.\"
+.\"
+.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 FORE_DNLD 8 "1996-12-03" "HARP"
+.SH NAME
+fore_dnld \- Download FORE Systems' microcode into host ATM adapter
+.SH SYNOPSIS
+.B fore_dnld
+[-i intf]
+[-d path]
+[-f objfile]
+.sp
+.fi
+.SH DESCRIPTION
+.I fore_dnld
+downloads FORE Systems' microcode into the host ATM adapter(s).
+.fi
+.SH OPTIONS
+.TP
+.B \-i intf
+Specify which ATM interface to download microcode to.
+Default is to load microcode into all FORE Systems host adapters.
+.TP
+.B -d path
+Specify the path to prepend to the "objfile" name.
+Default is to use current directory.
+.TP
+.B -f objfile
+Specify the microcode binary file. Defaults are:
+"sba200.obj" for SBA-200 adapters,
+"sba200e.obj" for SBA-200E adapters, and
+"pca200e.bin" for PCA-200E adapters.
+.fi
+.SH NOTES
+.PP
+Microcode as distributed by FORE Systems is not ready for downloading
+directly into SBA host ATM adapters. Instead, the supplied microcode needs
+to be processed with the "objcopy" command to create an image suitable
+for downloading. Arguments to "objcopy" are "-S -l -Fcoff". Microcode as
+distibuted by FORE Systems for the PCA host ATM adapter does not need
+to be processed.
+.SH "SEE ALSO"
+.PP
+~fore/etc/objcopy - command to process FORE Systems supplied microcode.
+.PP
+~fore/etc/sba200*.ucode* - microcode as supplied by FORE Systems for SBA
+adapters.
+.PP
+~fore/i386/pca200e.bin - microcode as supplied by FORE Systems for PCA
+adapters.
+.PP
+~harp/doc/Install - HARP installation instructions.
+.fi
+.SH BUGS
+.PP
+None known.
+.fi
+.SH COPYRIGHT
+Copyright (c) 1994-1998, Network Computing Services, Inc.
+.fi
+.SH AUTHORS
+John Cavanaugh, Minnesota Supercomputer Center, Inc.
+.br
+Mike Spengler, Minnesota Supercomputer Center, Inc.
+.br
+Joe Thomas, Minnesota Supercomputer Center, Inc.
+.fi
+.SH ACKNOWLEDGMENTS
+This software was developed under the sponsorship of the
+Defense Advanced Research Projects Agency (DARPA) under
+contract numbers F19628-92-C-0072 and F19628-95-C-0215.
diff --git a/sbin/atm/fore_dnld/fore_dnld.c b/sbin/atm/fore_dnld/fore_dnld.c
new file mode 100644
index 0000000..6ecafa5
--- /dev/null
+++ b/sbin/atm/fore_dnld/fore_dnld.c
@@ -0,0 +1,1245 @@
+/*
+ *
+ * ===================================
+ * 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: fore_dnld.c,v 1.15 1998/08/26 23:29:32 mks Exp $
+ *
+ */
+
+/*
+ * User utilities
+ * --------------
+ *
+ * Download (pre)processed microcode into Fore Series-200 host adapter
+ * Interact with i960 uart on Fore Series-200 host adapter
+ *
+ */
+
+#ifndef lint
+static char *RCSid = "@(#) $Id: fore_dnld.c,v 1.15 1998/08/26 23:29:32 mks Exp $";
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <sys/stat.h>
+#include <netatm/atm.h>
+#include <netatm/atm_if.h>
+#include <netatm/atm_sap.h>
+#include <netatm/atm_sys.h>
+#include <netatm/atm_ioctl.h>
+
+#include <dev/hfa/fore.h>
+#include <dev/hfa/fore_aali.h>
+#include <dev/hfa/fore_slave.h>
+
+#if (defined(BSD) && (BSD >= 199103))
+#include <termios.h>
+#else
+#include <termio.h>
+#endif /* !BSD */
+
+#ifdef sun
+#define DEV_NAME "/dev/sbus%d"
+#endif /* sun */
+#if (defined(BSD) && (BSD >= 199103))
+#define DEV_NAME "/dev/kmem"
+#endif /* BSD */
+
+#define MAX_CHECK 60
+
+int comm_mode = 0;
+char *progname;
+
+int tty;
+cc_t vmin, vtime;
+#if (defined(BSD) && (BSD >= 199103))
+struct termios sgtty;
+#define TCSETA TIOCSETA
+#define TCGETA TIOCGETA
+#else
+struct termio sgtty;
+#endif /* !BSD */
+
+int endian = 0;
+int verbose = 0;
+int reset = 0;
+
+char line[132];
+int lineptr = 0;
+
+Mon960 *Uart;
+
+delay(cnt)
+ int cnt;
+{
+ usleep(cnt);
+}
+
+unsigned long
+CP_READ ( val )
+unsigned long val;
+{
+ if ( endian )
+ return ( ntohl ( val ) );
+ else
+ return ( val );
+}
+
+unsigned long
+CP_WRITE ( val )
+unsigned long val;
+{
+ if ( endian )
+ return ( htonl ( val ) );
+ else
+ return ( val );
+}
+
+/*
+ * Print an error message and exit.
+ *
+ * Arguments:
+ * none
+ *
+ * Returns:
+ * none
+ */
+void
+error ( msg )
+char *msg;
+{
+ printf ( "%s\n", msg );
+ exit (1);
+}
+
+/*
+ * Get a byte for the uart and if printing, display it.
+ *
+ * Arguments:
+ * prn Are we displaying characters
+ *
+ * Returns:
+ * c Character from uart
+ */
+char
+getbyte ( prn )
+int prn;
+{
+ int c;
+
+ while ( ! ( CP_READ(Uart->mon_xmithost) & UART_VALID ) )
+ delay(10);
+
+ c = ( CP_READ(Uart->mon_xmithost) & UART_DATAMASK );
+ Uart->mon_xmithost = CP_WRITE(UART_READY);
+
+ /*
+ * We need to introduce a delay in here or things tend to hang...
+ */
+ delay(10);
+
+ if ( lineptr >= sizeof(line) )
+ lineptr = 0;
+
+ /*
+ * Save character into line
+ */
+ line[lineptr++] = c;
+
+ if (verbose) {
+ if (isprint(c) || (c == '\n') || (c == '\r'))
+ putc(c, stdout);
+ }
+ return ( c & 0xff );
+}
+
+/*
+ * Loop getting characters from uart into static string until eol. If printing,
+ * display the line retrieved.
+ *
+ * Arguments:
+ * prn Are we displaying characters
+ *
+ * Returns:
+ * none Line in global string 'line[]'
+ */
+void
+getline ( prn )
+int prn;
+{
+ char c = '\0';
+ int i = 0;
+
+ while ( c != '>' && c != '\n' && c != '\r' )
+ {
+ c = getbyte(0);
+ if ( ++i >= sizeof(line) )
+ {
+ if ( prn )
+ printf ( "%s", line );
+ i = 0;
+ }
+ }
+
+ /*
+ * Terminate line
+ */
+ line[lineptr] = 0;
+ lineptr = 0;
+
+}
+
+/*
+ * Send a byte to the i960
+ *
+ * Arguments:
+ * c Character to send
+ *
+ * Returns:
+ * none
+ */
+void
+xmit_byte ( c, dn )
+unsigned char c;
+int dn;
+{
+ int val;
+
+ while ( CP_READ(Uart->mon_xmitmon) != UART_READY )
+ {
+ if ( CP_READ(Uart->mon_xmithost) & UART_VALID )
+ getbyte ( 0 );
+ if ( !dn ) delay ( 1000 );
+ }
+ val = ( c | UART_VALID );
+ Uart->mon_xmitmon = CP_WRITE( val );
+
+}
+
+/*
+ * Transmit a line to the i960. Eol must be included as part of text to transmit.
+ *
+ * Arguments:
+ * line Character string to transmit
+ * len len of string. This allows us to include NULL's
+ * in the string/block to be transmitted.
+ *
+ * Returns:
+ * none
+ */
+xmit_to_i960 ( line, len, dn )
+char *line;
+int len;
+int dn;
+{
+ int i;
+
+ for ( i = 0; i < len; i++ )
+ xmit_byte ( line[i], dn );
+}
+
+/*
+ * Send autobaud sequence to i960 monitor
+ *
+ * Arguments:
+ * none
+ *
+ * Returns:
+ * none
+ */
+void
+autobaud()
+{
+ if ( strncmp ( line, "Mon960", 6 ) == 0 )
+ xmit_to_i960 ( "\r\n\r\n\r\n\r\n", 8, 0 );
+}
+
+/*
+ * Reset tty to initial state
+ *
+ * Arguments:
+ * ret error code for exit()
+ *
+ * Returns:
+ * none
+ *
+ */
+void
+finish ( ret )
+{
+ sgtty.c_lflag |= ( ICANON | ECHO );
+ sgtty.c_cc[VMIN] = vmin;
+ sgtty.c_cc[VTIME] = vtime;
+ ioctl ( tty, TCSETA, &sgtty );
+ exit ( ret );
+}
+
+/*
+ * 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 = strrchr ( path, '/' ) ) != NULL )
+ fname++;
+ else
+ fname = path;
+
+ return ( fname );
+}
+
+/*
+ * ASCII constants
+ */
+#define SOH 001
+#define STX 002
+#define ETX 003
+#define EOT 004
+#define ENQ 005
+#define ACK 006
+#define LF 012
+#define CR 015
+#define NAK 025
+#define SYN 026
+#define CAN 030
+#define ESC 033
+
+#define NAKMAX 2
+#define ERRORMAX 10
+#define RETRYMAX 5
+
+#define CRCCHR 'C'
+#define CTRLZ 032
+
+#define BUFSIZE 128
+
+#define W 16
+#define B 8
+
+/*
+ * crctab - CRC-16 constant array...
+ * from Usenet contribution by Mark G. Mendel, Network Systems Corp.
+ * (ihnp4!umn-cs!hyper!mark)
+ */
+unsigned short crctab[1<<B] = {
+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
+ 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
+ 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
+ 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
+ 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
+ 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
+ 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
+ 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
+ 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
+ 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
+ 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
+ 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
+ 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
+ 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
+ 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
+ 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
+ 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
+ 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
+ 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+ 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
+ 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
+ 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
+ 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
+ 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
+ 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
+ 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
+ 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
+ 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
+ };
+
+/*
+ * Hacked up xmodem protocol. Transmits the file 'filename' down to the i960
+ * using the xmodem protocol.
+ *
+ * Arguments:
+ * filename name of file to transmit
+ *
+ * Returns:
+ * 0 file transmitted
+ * -1 unable to send file
+ */
+int
+sendfile ( filename )
+char *filename;
+{
+ int fd;
+ int numsect;
+ int sectnum;
+ struct stat stb;
+ char c;
+ char sendresp;
+ int crcmode = 0;
+ int attempts = 0;
+ int errors;
+ int sendfin;
+ int extrachr;
+ char buf[BUFSIZE + 6];
+ char blockbuf[BUFSIZE + 6];
+ int bufcntr;
+ int bbufcntr;
+ int bufsize = BUFSIZE;
+ int checksum;
+
+ /*
+ * Try opening file
+ */
+ if ( ( fd = open ( filename, O_RDONLY ) ) < 0 )
+ {
+ return -1;
+ }
+ stat ( filename, &stb );
+
+ /*
+ * Determine number of 128 bytes sectors to transmit
+ */
+ numsect = ( stb.st_size / 128 ) + 1;
+
+ if ( verbose )
+ fprintf ( stderr, "Downloading %d sectors from %s\n",
+ numsect, filename );
+
+ /*
+ * Send DO'wnload' command to i960
+ */
+ xmit_to_i960 ( "do\r\n", 4, 0 );
+ /*
+ * Wait for response from i960 indicating download in progress
+ */
+ while ( strncmp ( line, "Downloading", 11 ) != 0 )
+ getline ( verbose );
+
+
+ /*
+ * Get startup character from i960
+ */
+ do {
+ while ( ( c = getbyte(0) ) != NAK && c != CRCCHR )
+ if ( ++attempts > NAKMAX )
+ error ( "Remote system not responding" );
+
+ if ( c == CRCCHR )
+ crcmode = 1;
+
+ } while ( c != NAK && c != CRCCHR );
+
+ sectnum = 1;
+ attempts = errors = sendfin = extrachr = 0;
+
+ /*
+ * Loop over each sector to be sent
+ */
+ do {
+ if ( extrachr >= 128 )
+ {
+ extrachr = 0;
+ numsect++;
+ }
+
+ if ( sectnum > 0 )
+ {
+ /*
+ * Read a sectors worth of data from the file into
+ * an internal buffer.
+ */
+ for ( bufcntr = 0; bufcntr < bufsize; )
+ {
+ int n;
+ /*
+ * Check for EOF
+ */
+ if ( ( n = read ( fd, &c, 1 ) ) == 0 )
+ {
+ sendfin = 1;
+ if ( !bufcntr )
+ break;
+ buf[bufcntr++] = CTRLZ;
+ continue;
+ }
+ buf[bufcntr++] = c;
+ }
+ if ( !bufcntr )
+ break;
+ }
+
+ /*
+ * Fill in xmodem protocol values. Block size and sector number
+ */
+ bbufcntr = 0;
+ blockbuf[bbufcntr++] = (bufsize == 1024) ? STX : SOH;
+ blockbuf[bbufcntr++] = sectnum;
+ blockbuf[bbufcntr++] = ~sectnum;
+
+ checksum = 0;
+
+ /*
+ * Loop over the internal buffer computing the checksum of the
+ * sector
+ */
+ for ( bufcntr = 0; bufcntr < bufsize; bufcntr++ )
+ {
+ blockbuf[bbufcntr++] = buf[bufcntr];
+
+ if ( crcmode )
+ checksum = (checksum<<B) ^ crctab[(checksum>>(W-B)) ^ buf[bufcntr]];
+ else
+ checksum = ((checksum + buf[bufcntr]) & 0xff);
+
+ }
+
+ /*
+ * Place the checksum at the end of the transmit buffer
+ */
+ if ( crcmode )
+ {
+ checksum &= 0xffff;
+ blockbuf[bbufcntr++] = ((checksum >> 8) & 0xff);
+ blockbuf[bbufcntr++] = (checksum & 0xff);
+ } else
+ blockbuf[bbufcntr++] = checksum;
+
+ attempts = 0;
+
+ /*
+ * Make several attempts to send the data to the i960
+ */
+ do
+ {
+ /*
+ * Transmit the sector + protocol to the i960
+ */
+ xmit_to_i960 ( blockbuf, bbufcntr, 1 );
+
+ /*
+ * Inform user where we're at
+ */
+ if ( verbose )
+ printf ( "Sector %3d %3dk\r",
+ sectnum, (sectnum * bufsize) / 1024 );
+
+ attempts++;
+ /*
+ * Get response from i960
+ */
+ sendresp = getbyte(0);
+
+ /*
+ * If i960 didn't like the sector
+ */
+ if ( sendresp != ACK )
+ {
+ errors++;
+
+ /*
+ * Are we supposed to cancel the transfer?
+ */
+ if ( ( sendresp & 0x7f ) == CAN )
+ if ( getbyte(0) == CAN )
+ error ( "Send canceled at user's request" );
+ }
+
+ } while ( ( sendresp != ACK ) && ( attempts < RETRYMAX ) && ( errors < ERRORMAX ) );
+
+ /*
+ * Next sector
+ */
+ sectnum++;
+
+ } while ( !sendfin && ( attempts < RETRYMAX ) && ( errors < ERRORMAX ) );
+
+ /*
+ * Did we expire all our allows attempts?
+ */
+ if ( attempts >= RETRYMAX )
+ {
+ xmit_byte ( CAN, 1 ), xmit_byte ( CAN, 1 ), xmit_byte ( CAN, 1 );
+ error ( "Remote system not responding" );
+ }
+
+ /*
+ * Check for too many transmission errors
+ */
+ if ( errors >= ERRORMAX )
+ {
+ xmit_byte ( CAN, 1 ), xmit_byte ( CAN, 1 ), xmit_byte ( CAN, 1 );
+ error ( "Too many errors in transmission" );
+ }
+
+ attempts = 0;
+
+ /*
+ * Indicate the transfer is complete
+ */
+ xmit_byte ( EOT, 1 );
+
+ /*
+ * Wait until i960 acknowledges us
+ */
+ while ( ( c = getbyte(0) ) != ACK && ( ++attempts < RETRYMAX ) )
+ xmit_byte ( EOT, 1 );
+
+ if ( attempts >= RETRYMAX )
+ error ( "Remote system not responding on completion" );
+
+ /*
+ * After download, we'll see a few more command
+ * prompts as the CP does its stuff. Ignore them.
+ */
+ while ( strncmp ( line, "=>", 2 ) != 0 )
+ getline ( verbose );
+
+ while ( strncmp ( line, "=>", 2 ) != 0 )
+ getline ( verbose );
+
+ while ( strncmp ( line, "=>", 2 ) != 0 )
+ getline ( verbose );
+
+ /*
+ * Tell the i960 to start executing the downloaded code
+ */
+ xmit_to_i960 ( "go\r\n", 4, 0 );
+
+ /*
+ * Get the messages the CP will spit out
+ * after the GO command.
+ */
+ getline ( verbose );
+ getline ( verbose );
+
+ close ( fd );
+
+ return ( 0 );
+}
+
+
+int
+sendbinfile ( fname, ram )
+char *fname;
+u_char *ram;
+{
+ struct {
+ u_long Id;
+ u_long fver;
+ u_long start;
+ u_long entry;
+ } binhdr;
+ union {
+ u_long w;
+ char c[4];
+ } w1, w2;
+ int fd;
+ int n;
+ int cnt = 0;
+ u_char *bufp;
+ long buffer[1024];
+
+ /*
+ * Try opening file
+ */
+ if ( ( fd = open ( fname, O_RDONLY ) ) < 0 )
+ return ( -1 );
+
+ /*
+ * Read the .bin header from the file
+ */
+ if ( ( read ( fd, &binhdr, sizeof(binhdr) ) ) != sizeof(binhdr) )
+ {
+ close ( fd );
+ return ( -1 );
+ }
+
+ /*
+ * Check that we understand this header
+ */
+ if ( strncmp ( (caddr_t)&binhdr.Id, "fore", 4 ) != 0 ) {
+ fprintf ( stderr, "Unrecognized format in micorcode file." );
+ close ( fd );
+ return ( -1 );
+ }
+
+#ifdef sun
+ /*
+ * We always swap the SunOS microcode file...
+ */
+ endian = 1;
+
+ /*
+ * We need to swap the header start/entry words...
+ */
+ w1.w = binhdr.start;
+ for ( n = 0; n < sizeof(u_long); n++ )
+ w2.c[3-n] = w1.c[n];
+ binhdr.start = w2.w;
+ w1.w = binhdr.entry;
+ for ( n = 0; n < sizeof(u_long); n++ )
+ w2.c[3-n] = w1.c[n];
+ binhdr.entry = w2.w;
+#endif /* sun */
+
+ /*
+ * Rewind the file
+ */
+ lseek ( fd, 0, 0 );
+
+ /*
+ * Set pointer to RAM load location
+ */
+ bufp = (ram + binhdr.start);
+
+ /*
+ * Load file
+ */
+ if ( endian ) {
+ /*
+ * Need to swap longs - copy file into temp buffer
+ */
+ while ( ( n = read ( fd, (char *)buffer, sizeof(buffer))) > 0 )
+ {
+ int i;
+
+ /* Swap buffer */
+ for ( i = 0; i < sizeof(buffer) / sizeof(long); i++ )
+#ifndef sun
+ buffer[i] = CP_WRITE(buffer[i]);
+#else
+ {
+ int j;
+
+ w1.w = buffer[i];
+ for ( j = 0; j < 4; j++ )
+ w2.c[3-j] = w1.c[j];
+ buffer[i] = w2.w;
+ }
+#endif
+
+ /*
+ * Copy swapped buffer into CP RAM
+ */
+ cnt++;
+ bcopy ( (caddr_t)buffer, bufp, n );
+ if ( verbose )
+ printf ( "%d\r", cnt );
+ bufp += n;
+ }
+ } else {
+ while ( ( n = read ( fd, bufp, 128 ) ) > 0 )
+ {
+ cnt++;
+ if ( verbose )
+ printf ( "%d\r", cnt );
+ bufp += n;
+ }
+ }
+
+ /*
+ * With .bin extension, we need to specify start address on 'go'
+ * command.
+ */
+ {
+ char cmd[80];
+ char c;
+
+ sprintf ( cmd, "go %x\r\n", binhdr.entry );
+
+ xmit_to_i960 ( cmd, strlen ( cmd ), 0 );
+
+ while ( strncmp ( line, cmd, strlen(cmd) - 3 ) != 0 )
+ getline ( verbose );
+
+ if ( verbose )
+ printf("\n");
+ }
+
+ close ( fd );
+ return ( 0 );
+}
+
+
+/*
+ * Program to download previously processed microcode to series-200 host adapter
+ */
+main( argc, argv )
+int argc;
+char *argv[];
+{
+ int fd; /* mmap for Uart */
+ u_char *ram; /* pointer to RAM */
+ Mon960 *Mon; /* Uart */
+ Aali *aap;
+ char c;
+ int i, err;
+ int binary = 0; /* Send binary file */
+ caddr_t buf; /* Ioctl buffer */
+ Atm_config *adp; /* Adapter config */
+ char bus_dev[80]; /* Bus device to mmap on */
+ struct atminfreq req;
+ struct air_cfg_rsp *air; /* Config info response structure */
+ int buf_len; /* Size of ioctl buffer */
+ char *devname = "\0"; /* Device to download */
+ char *dirname = NULL; /* Directory path to objd files */
+ char *objfile = NULL; /* Command line object filename */
+ char *sndfile; /* Object filename to download */
+ char filename[64]; /* Constructed object filename */
+ char base[64]; /* sba200/sba200e/pca200e basename */
+ int ext = 0; /* 0 == bin 1 == objd */
+ struct stat sbuf; /* Used to find if .bin or .objd */
+ extern char *optarg;
+
+ progname = (char *)basename(argv[0]);
+ comm_mode = strcmp ( progname, "fore_comm" ) == 0;
+
+ while ( ( c = getopt ( argc, argv, "i:d:f:berv" ) ) != EOF )
+ switch ( c ) {
+ case 'b':
+ binary++;
+ break;
+ case 'd':
+ dirname = (char *)strdup ( optarg );
+ break;
+ case 'e':
+ endian++;
+ break;
+ case 'i':
+ devname = (char *)strdup ( optarg );
+ break;
+ case 'f':
+ objfile = (char *)strdup ( optarg );
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case 'r':
+ reset++;
+ break;
+ case '?':
+ printf ( "usage: %s [-v] [-i intf] [-d dirname] [-f objfile]\n", argv[0] );
+ exit ( 2 );
+ }
+
+ /*
+ * Unbuffer stdout
+ */
+ setbuf ( stdout, NULL );
+
+ if ( ( fd = socket ( AF_ATM, SOCK_DGRAM, 0 ) ) < 0 )
+ {
+ perror ( "Cannot create ATM socket" );
+ exit ( 1 );
+ }
+ /*
+ * Over allocate memory for returned data. This allows
+ * space for IOCTL reply info as well as config info.
+ */
+ buf_len = 4 * sizeof(struct air_cfg_rsp);
+ if ( ( buf = (caddr_t)malloc(buf_len) ) == NULL )
+ {
+ perror ( "Cannot allocate memory for reply" );
+ exit ( 1 );
+ }
+ /*
+ * Fill in request paramaters
+ */
+ req.air_opcode = AIOCS_INF_CFG;
+ req.air_buf_addr = buf;
+ req.air_buf_len = buf_len;
+
+ /*
+ * Copy interface name into ioctl request
+ */
+ strcpy ( req.air_cfg_intf, devname );
+
+ /*
+ * Issue ioctl
+ */
+ if ( ( ioctl ( fd, AIOCINFO, (caddr_t)&req ) ) ) {
+ perror ( "ioctl (AIOCSINFO)" );
+ exit ( 1 );
+ }
+ /*
+ * Reset buffer pointer
+ */
+ req.air_buf_addr = buf;
+
+ /*
+ * Close socket
+ */
+ close ( fd );
+
+ /*
+ * Loop through all attached adapters
+ */
+ for (; req.air_buf_len >= sizeof(struct air_cfg_rsp);
+ buf += sizeof(struct air_cfg_rsp),
+ req.air_buf_len -= sizeof(struct air_cfg_rsp)) {
+
+ /*
+ * Point to vendor info
+ */
+ air = (struct air_cfg_rsp *)buf;
+
+ if (air->acp_vendor == VENDOR_FORE )
+ {
+ /*
+ * Create /dev name
+ */
+ sprintf ( bus_dev, DEV_NAME, air->acp_busslot );
+
+ /*
+ * Setup signal handlers
+ */
+ signal ( SIGINT, SIG_IGN );
+ signal ( SIGQUIT, SIG_IGN );
+
+ /*
+ * If comm_mode, setup terminal for single char I/O
+ */
+ if ( comm_mode ) {
+ tty = open ( "/dev/tty", O_RDWR );
+ ioctl ( tty, TCGETA, &sgtty );
+ sgtty.c_lflag &= ~( ICANON | ECHO );
+ vmin = sgtty.c_cc[VMIN];
+ vtime = sgtty.c_cc[VTIME];
+ sgtty.c_cc[VMIN] = 0;
+ sgtty.c_cc[VTIME] = 0;
+ ioctl ( tty, TCSETA, &sgtty );
+ }
+
+ /*
+ * Open bus for memory access
+ */
+ if ( ( fd = open ( bus_dev, O_RDWR ) ) < 0 )
+ {
+ perror ( "open bus_dev" );
+ fprintf(stderr, "%s download failed (%s)\n",
+ air->acp_intf, bus_dev);
+ continue;
+ }
+
+ /*
+ * Map in the RAM memory to get access to the Uart
+ */
+#ifdef __FreeBSD__ /*XXX*/
+ ram = (u_char *) mmap(0, PCA200E_MMAP_SIZE,
+#else
+ ram = (u_char *) mmap(0, air->acp_ramsize,
+#endif
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ fd, air->acp_ram);
+ if (ram == (u_char *)-1) {
+ perror ( "mmap ram" );
+ fprintf(stderr, "%s download failed\n",
+ air->acp_intf);
+ (void) close(fd);
+ continue;
+ }
+ Mon = (Mon960 *)(ram + MON960_BASE);
+ Uart = (Mon960 *)&(Mon->mon_xmitmon);
+
+ /*
+ * Determine endianess
+ */
+ switch ( Mon->mon_bstat ) {
+ case BOOT_COLDSTART:
+ case BOOT_MONREADY:
+ case BOOT_FAILTEST:
+ case BOOT_RUNNING:
+ break;
+
+ default:
+ switch (ntohl(Mon->mon_bstat)) {
+ case BOOT_COLDSTART:
+ case BOOT_MONREADY:
+ case BOOT_FAILTEST:
+ case BOOT_RUNNING:
+ endian++;
+ break;
+
+ default:
+ fprintf(stderr, "%s unknown status\n",
+ air->acp_intf);
+ (void) close(fd);
+ continue;
+ }
+ break;
+ }
+
+#ifdef __FreeBSD__
+ if (reset) {
+ u_int *hcr = (u_int *)(ram + PCA200E_HCR_OFFSET);
+ PCA200E_HCR_INIT(*hcr, PCA200E_RESET_BD);
+ delay(10000);
+ PCA200E_HCR_CLR(*hcr, PCA200E_RESET_BD);
+ delay(10000);
+ }
+#endif
+
+ if ( comm_mode ) {
+ static struct timeval timeout = { 0, 0 };
+ int esc_seen = 0;
+
+ /*
+ * We want to talk with the i960 monitor
+ */
+
+ /*
+ * Loop forever accepting characters
+ */
+ for ( ; ; ) {
+ fd_set fdr;
+ int ns;
+
+ /*
+ * Check for data from the terminal
+ */
+ FD_ZERO ( &fdr );
+ FD_SET ( fileno(stdin), &fdr );
+
+ if ( ( ns = select ( FD_SETSIZE, &fdr, NULL, NULL,
+ &timeout ) ) < 0 ) {
+ perror ( "select" );
+ finish( -1 );
+ }
+
+ if ( ns ) {
+ int c;
+ int nr;
+
+ nr = read ( fileno(stdin), &c, 1 );
+ c &= 0xff;
+ if ( !esc_seen ) {
+ if ( c == 27 )
+ esc_seen++;
+ else
+ xmit_byte ( c, 0 );
+ } else {
+ if ( c == 27 )
+ finish( -1 );
+ else {
+ xmit_byte ( 27, 0 );
+ esc_seen = 0;
+ }
+ xmit_byte ( c, 0 );
+ }
+ }
+
+ /*
+ * Check for data from the i960
+ */
+ if ( CP_READ(Uart->mon_xmithost) & UART_VALID ) {
+ c = getbyte(0);
+ putchar ( c );
+ }
+ if ( strcmp ( line, "Mon960" ) == 0 )
+ autobaud();
+
+ }
+ } else {
+ /*
+ * Make sure the driver is loaded and that the CP
+ * is ready for commands
+ */
+ if ( CP_READ(Mon->mon_bstat) == BOOT_RUNNING )
+ {
+ fprintf ( stderr,
+ "%s is up and running - no download allowed.\n",
+ air->acp_intf );
+ (void) close(fd);
+ continue;
+ }
+
+ if ( CP_READ(Mon->mon_bstat) != BOOT_MONREADY )
+ {
+ fprintf ( stderr,
+ "%s is not ready for downloading.\n",
+ air->acp_intf );
+ (void) close(fd);
+ continue;
+ }
+
+ /*
+ * Indicate who we're downloading
+ */
+ if ( verbose )
+ printf ( "Downloading code for %s\n",
+ air->acp_intf );
+
+ /*
+ * Look for the i960 monitor message.
+ * We should see this after a board reset.
+ */
+ while ( strncmp ( line, "Mon960", 6 ) != 0 &&
+ strncmp ( line, "=>", 2 ) != 0 )
+ getline( verbose ); /* Verbose */
+
+ /*
+ * Autobaud fakery
+ */
+ if ( strncmp ( line, "Mon960", 6 ) == 0 ) {
+ xmit_to_i960 ( "\r\n\r\n\r\n\r\n", 8, 0 );
+ delay ( 10000 );
+ }
+
+ /*
+ * Keep reading until we get a command prompt
+ */
+ while ( strncmp ( line, "=>", 2 ) != 0 )
+ getline( verbose ); /* Verbose */
+
+ /*
+ * Choose the correct microcode file based on the
+ * adapter type the card claims to be.
+ */
+ switch ( air->acp_device )
+ {
+ case DEV_FORE_SBA200:
+ sprintf ( base, "sba200" );
+ break;
+
+ case DEV_FORE_SBA200E:
+ sprintf ( base, "sba200e" );
+ break;
+
+ case DEV_FORE_PCA200E:
+ sprintf ( base, "pca200e" );
+ break;
+
+ default:
+ err = 1;
+ fprintf(stderr, "Unknown adapter type: %d\n",
+ air->acp_device );
+ }
+
+ sndfile = NULL;
+
+ if ( objfile == NULL ) {
+ switch ( air->acp_device ) {
+ case DEV_FORE_SBA200:
+ case DEV_FORE_SBA200E:
+ sprintf ( filename, "%s.bin%d", base,
+ air->acp_bustype );
+ if ( stat ( filename, &sbuf ) == -1 ) {
+ sprintf ( filename, "%s/%s.bin%d",
+ dirname, base,
+ air->acp_bustype );
+ if ( stat ( filename, &sbuf ) == -1 ) {
+ ext = 1;
+ sprintf ( filename, "%s.objd%d",
+ base, air->acp_bustype );
+ if ( stat(filename, &sbuf) == -1 ) {
+ sprintf ( filename,
+ "%s/%s.objd%d", dirname,
+ base,
+ air->acp_bustype );
+ if ( stat ( filename, &sbuf ) != -1 )
+ sndfile = filename;
+ } else
+ sndfile = filename;
+ } else
+ sndfile = filename;
+ } else
+ sndfile = filename;
+ break;
+ case DEV_FORE_PCA200E:
+ sprintf ( filename, "%s.bin", base );
+ if ( stat ( filename, &sbuf ) == -1 ) {
+ sprintf ( filename, "%s/%s.bin",
+ dirname, base );
+ if ( stat ( filename, &sbuf ) != -1 ) {
+ sndfile = filename;
+ }
+ } else
+ sndfile = filename;
+ break;
+ }
+ } else
+ sndfile = objfile;
+
+ if ( ext && !binary )
+ err = sendfile ( sndfile );
+ else
+ err = sendbinfile ( sndfile, ram );
+
+ if ( err ) {
+ fprintf(stderr, "%s download failed\n",
+ air->acp_intf);
+ (void) close(fd);
+ continue;
+ }
+
+ /*
+ * Download completed - wait around a while for
+ * the driver to initialize the adapter
+ */
+ aap = (Aali *)(ram + CP_READ(Mon->mon_appl));
+ for (i = 0; i < MAX_CHECK; i++, sleep(1)) {
+ u_long hb1, hb2;
+
+ if (CP_READ(Mon->mon_bstat) != BOOT_RUNNING)
+ continue;
+
+ hb1 = CP_READ(aap->aali_heartbeat);
+ delay(1);
+ hb2 = CP_READ(aap->aali_heartbeat);
+ if (hb1 < hb2)
+ break;
+ }
+ }
+
+ close ( fd );
+ }
+ }
+
+ /*
+ * Exit
+ */
+ exit (0);
+
+}
+
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