summaryrefslogtreecommitdiffstats
path: root/sbin/atm
diff options
context:
space:
mode:
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