From c3dd1fa899d435ea4bf79897f646a93cb80c94ac Mon Sep 17 00:00:00 2001 From: phk Date: Tue, 15 Sep 1998 08:23:17 +0000 Subject: Add new files for HARP3 Host ATM Research Platform (HARP), Network Computing Services, Inc. This software was developed with the support of the Defense Advanced Research Projects Agency (DARPA). --- sbin/atm/Makefile | 33 + sbin/atm/Makefile.inc | 30 + sbin/atm/atm/Makefile | 38 + sbin/atm/atm/atm.8 | 984 ++++++++++++++ sbin/atm/atm/atm.c | 1072 +++++++++++++++ sbin/atm/atm/atm.h | 212 +++ sbin/atm/atm/atm_eni.c | 437 +++++++ sbin/atm/atm/atm_fore200.c | 603 +++++++++ sbin/atm/atm/atm_inet.c | 164 +++ sbin/atm/atm/atm_print.c | 904 +++++++++++++ sbin/atm/atm/atm_set.c | 540 ++++++++ sbin/atm/atm/atm_show.c | 1187 +++++++++++++++++ sbin/atm/atm/atm_subr.c | 620 +++++++++ sbin/atm/fore_dnld/Makefile | 36 + sbin/atm/fore_dnld/fore_dnld.8 | 108 ++ sbin/atm/fore_dnld/fore_dnld.c | 1245 ++++++++++++++++++ sbin/atm/ilmid/Makefile | 36 + sbin/atm/ilmid/ilmid.8 | 118 ++ sbin/atm/ilmid/ilmid.c | 2810 ++++++++++++++++++++++++++++++++++++++++ 19 files changed, 11177 insertions(+) create mode 100644 sbin/atm/Makefile create mode 100644 sbin/atm/Makefile.inc create mode 100644 sbin/atm/atm/Makefile create mode 100644 sbin/atm/atm/atm.8 create mode 100644 sbin/atm/atm/atm.c create mode 100644 sbin/atm/atm/atm.h create mode 100644 sbin/atm/atm/atm_eni.c create mode 100644 sbin/atm/atm/atm_fore200.c create mode 100644 sbin/atm/atm/atm_inet.c create mode 100644 sbin/atm/atm/atm_print.c create mode 100644 sbin/atm/atm/atm_set.c create mode 100644 sbin/atm/atm/atm_show.c create mode 100644 sbin/atm/atm/atm_subr.c create mode 100644 sbin/atm/fore_dnld/Makefile create mode 100644 sbin/atm/fore_dnld/fore_dnld.8 create mode 100644 sbin/atm/fore_dnld/fore_dnld.c create mode 100644 sbin/atm/ilmid/Makefile create mode 100644 sbin/atm/ilmid/ilmid.8 create mode 100644 sbin/atm/ilmid/ilmid.c (limited to 'sbin/atm') 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 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 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 + +.ti -5 +.B atm detach + +.ti -5 +.B atm set MAC + +.ti -5 +.B atm set netif + +.ti -5 +.B atm set prefix + +.ti -5 +.B atm show config +[] +.ti -5 +.B atm show interface +[] +.ti -5 +.B atm show netif +[] +.ti -5 +.B atm show stats interface +[ [phy | dev | atm | aal0 | aal4 | aal5 | driver]] +.sp +.ti -10 +VCC management subcommands: +.ti -5 +.B atm add PVC + ... +.ti -5 +.B atm delete PVC + +.ti -5 +.B atm delete SVC + +.ti -5 +.B atm show stats VCC +[ [ []]] +.ti -5 +.B atm show VCC +[ [ [] | SVC | PVC]] +.sp +.ti -10 +IP management subcommands: +.ti -5 +.B atm add ARP +[] +.ti -5 +.B atm add PVC + IP | dynamic +.ti -5 +.B atm delete ARP +[] +.ti -5 +.B atm set arpserver + | local [ ...] +.ti -5 +.B atm show ARP +[] +.ti -5 +.B atm show arpserver +[] +.ti -5 +.B atm show IPVCC +[ | ] +.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 ...\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 \fP +.PP +where: +.in +10 +.ti -5 +\fI\fP specifies the physical interface to which the +signalling manager is to be attached, +.ti -5 +\fI\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 \fP +.PP +where: +.in +10 +.ti -5 +\fI\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 \fP +.PP +where: +.in +10 +.ti -5 +\fI\fP specifies the physical interface whose +MAC address is to be set, +.ti -5 +\fI\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 \fP +.PP +where: +.in +10 +.ti -5 +\fI\fP specifies the physical interface that the network +interface(s) are to be associated with, +.ti -5 +\fI\fP specifies the invariant part of the network +interface name, +.ti -5 +\fI\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 , where is the +prefix specified in the \fIset\fP subcommand and is a number +in the range 0 - -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 \fP +.PP +where: +.in +10 +.ti -5 +\fI\fP specifies the physical interface whose NSAP +prefix is to be set, +.ti -5 +\fI\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 [] +.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 [] +.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 [] +.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 [ [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 \fP +.br +\fIatm delete SVC \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\fP specifies the physical interface at which the +VCC to be closed terminates, +.ti -5 +\fI\fP specifies the Virtual Path Identifier (VPI) of the VCC, +.ti -5 +\fI\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 [ [ []]]\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 [ [ [] | 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 [] \fP +.PP +where: +.in +10 +.ti -5 +\fI\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\fP is the host name or IP address of the host to +be added to the ATMARP table, +.ti -5 +\fI\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 IP | dynamic\fP +.in -5 +.PP +where: +.in +10 +.ti -5 +\fI\fP specifies the physical interface where the PVC +is to terminate, +.ti -5 +\fI\fP specifies the Virtual Path Identifier (VPI) of the PVC, +.ti -5 +\fI\fP specifies the Virtual Channel Identifier (VCI) of the PVC, +.ti -5 +\fI\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\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\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 | 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 [] \fP +.PP +where: +.in +10 +.ti -5 +\fI\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\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 | local [ ...]\fP +.PP +where: +.in +10 +.ti -5 +\fI\fP specifies the network interface for which the +ATMARP server address is to be set. +.ti -5 +\fI\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 ...\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 [] +.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 [] +.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 [ | ] +.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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "atm.h" + + +/* + * Usage string + */ +#define USAGE_STR "Interface management subcommands:\n\ + attach \n\ + detach \n\ + set mac \n\ + set netif \n\ + set prefix \n\ + show config []\n\ + show interface []\n\ + show netif []\n\ + show stats interface [ phy | dev | atm | aal0 | aal4 |\n\ + aal5 | driver]\n\ +\n\ +VC management subcommands:\n\ + add pvc ...\n\ + delete pvc \n\ + delete svc \n\ + show stats vcc [ [vpi [vci]]]\n\ + show vcc [ [ [] | SVC | PVC]]\n\ +\n\ +IP management subcommands:\n\ + add arp [] \n\ + add pvc IP |\n\ + dynamic\n\ + delete arp [] \n\ + set arpserver ...\n\ + show arp []\n\ + show arpserver []\n\ + show ipvcc [ | ]\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, " " }, + { "delete", 0, 0, NULL, (char *) dlt_subcmd }, + { "detach", 1, 1, detach, "" }, + { "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, "[] " }, + { "pvc", 6, 12, pvc_add, " ..." }, + { 0, 0, 0, NULL, "" } +}; + +struct cmd dlt_subcmd[] = { + { "arp", 1, 2, arp_dlt, "[] " }, + { "pvc", 3, 3, pvc_dlt, " " }, + { "svc", 3, 3, svc_dlt, " " }, + { 0, 0, 0, NULL, "" } +}; + +struct cmd set_subcmd[] = { + { "arpserver", 2, 18, set_arpserver, " " }, + { "mac", 2, 2, set_macaddr, " " }, + { "netif", 3, 3, set_netif, " " }, + { "prefix", 2, 2, set_prefix, " " }, + { 0, 0, 0, NULL, ""} +}; + +struct cmd show_subcmd[] = { + { "arp", 0, 1, show_arp, "[]" }, + { "arpserver", 0, 1, show_arpserv, "[]" }, + { "config", 0, 1, show_config, "[]" }, + { "interface", 0, 1, show_intf, "[]" }, + { "ipvcc", 0, 3, show_ip_vcc, "[ | ]" }, + { "netif", 0, 1, show_netif, "[]" }, + { "stats", 0, 3, NULL, (char *) stats_subcmd }, + { "vcc", 0, 3, show_vcc, "[] [ [] | SVC | PVC]" }, + { "version", 0, 0, show_version, "" }, + { 0, 0, 0, NULL, "" } +}; + +struct cmd stats_subcmd[] = { + { "interface", 0, 2, show_intf_stats, "[ [cfg | phy | dev | atm | aal0 | aal4 | aal5 | driver]]" }, + { "vcc", 0, 3, show_vcc_stats, "[ [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 + * + * 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 + * + * 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 + * + * + * 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 [] + * + * 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 + * + * 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 + * + * 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 + * + * 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "atm.h" +#include + + +/* + * 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 [ [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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "atm.h" +#include +#include +#include + + +/* + * 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 [ [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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "atm.h" + + +/* + * Process add command for a TCP/IP PVC + * + * Command format: + * atm add pvc IP + * | 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, ""); + if (cp) + strcpy(cp, "ip {dyn|}"); + 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 '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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "atm.h" + + +/* + * Process ATM ARP server set command + * + * Command format: + * atm set arpserver ... + * + * 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 + * + * 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 + * + * 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 + * + * 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#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 [] + * + * 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 [] + * + * 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 [] + * + * 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 [] + * + * 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 [] + * + * 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 [] + * + * 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 [] + * + * 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 [ [ []]] + * + * 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 [ [ [] | 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#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 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#if (defined(BSD) && (BSD >= 199103)) +#include +#else +#include +#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< 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<>(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 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 +#include + +#if (defined(BSD) && (BSD >= 199103)) +#include +#endif + +#ifdef BSD +#if __FreeBSD_version < 300001 +#include +#ifdef sun +#include +#endif /* sun */ +#else +#include +#endif /* __FreeBSD_version >= 300001 */ +#endif /* BSD */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#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 + * - 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 + * - 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 data bytes + * + * Arguments: + * bufp - pointer to the buffer pointer + * + * Returns: + * bufp - updated buffer pointer + * - 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 + * 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 */ + +} + -- cgit v1.1