Add a program for configuration of the ATM drivers and the IP over ATM

stuff. This utility allows inspection of the ATM characteristics,
the PHY layer, including statistics of both, the retrival of the
list of currently open channels and also allows access to utopia(4).
This commit is contained in:
Hartmut Brandt 2003-08-12 14:25:57 +00:00
parent b24521d779
commit 791a6fe762
10 changed files with 3017 additions and 0 deletions

View File

@ -23,6 +23,7 @@
# @(#) $FreeBSD$
SUBDIR= atm \
atmconfig \
fore_dnld \
ilmid

View File

@ -0,0 +1,17 @@
# Copyright (c) 2001-2003
# Fraunhofer Institute for Open Communication Systems (FhG Fokus).
# All rights reserved.
#
# $FreeBSD$
#
# Author: Harti Brandt <brandt@fokus.gmd.de>
#
PROG= atmconfig
SRCS= main.c diag.c natm.c
MAN= atmconfig.8
WARNS= 9
FILES= atmconfig.help
FILESDIR=/usr/share/doc/atm
.include <bsd.prog.mk>

View File

@ -0,0 +1,332 @@
.\"
.\" Copyright (c) 2001-2003
.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus).
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" Author: Hartmut Brandt <harti@freebsd.org>
.\"
.\" $FreeBSD$
.\"
.Dd August 11, 2003
.Dt ATMCONFIG 8
.Os
.Sh NAME
.Nm atmconfig
.Nd "ATM configuration tool"
.Sh SYNOPSIS
.Nm
.Op Fl htv
.Op command Op sub-command Op ...
.Op options
.Op arg ...
.Sh DESCRIPTION
The
.Nm
tool is used to configure the Netgraph ATM network sub-system.
.Pp
The command line of
.Nm
generally consists of common options followed by a command string, optionally
followed by sub-command strings, optional command specific options and
command specific arguments. Commands and sub-commands as well as command
specific options may be abbreviated as
long as there is only one match possible.
.Ss COMMON OPTIONS
The following common options change the overall behaviour of
.Nm :
.Bl -tag -width XXXX
.It Fl h
Print a very short usage info and exit.
.It Fl t
Several show-type commands output a header and then several lines
of information.
If this option is given the header is omitted, simplifying the parsing
of the output.
.It Fl v
Be more verbose.
.El
.Ss OBTAINING HELP
The
.Sq help
command has a number of useful sub-commands.
To get general help use:
.Pp
.Dl atmconfig help
.Pp
To get a list of available commands use:
.Pp
.Dl atmconfig help commands
.Pp
To get a list of available sub-commands use:
.Pp
.Dl atmconfig help Ar command
.Pp
or (if there are deeper levels of sub-commands
.Pp
.Dl atmconfig help Ar command Ar sub-command ...
.Pp
To get a list of options and arguments for a command use
.Pp
.Dl atmconfig help Ar command Ar sub-command ...
.Pp
(given, that there are no further sub-command levels).
To get a list of common options use
.Pp
.Dl atmconfig help options
.Ss DIAG COMMAND
The
.Ic diag
command allows the inspection of the ATM interfaces on the local host
and the modification of device parameters.
Sub-commands are:
.Ic list
(print a list of interfaces),
.Ic config
(print hardware configuration),
.Ic phy
(access PHY chip),
.Ic stats
(print statistics) and
.Ic vcc
(print list of VCCs).
.Pp
.Bl -tag -width XXXX
.\"----------------------------------------
.It Ic atmconfig diag list
This sub-command lists all ATM interfaces in the system.
It takes no options or arguments.
.\"----------------------------------------
.It Xo
.Ic atmconfig diag config
.Op Fl atm
.Op Fl hardware
.Op Ar device ...
.Xc
This command prints the configuration of ATM interfaces.
If no
.Ar device
is given all devices are listed, otherwise only the specified devices.
The option
.Fl atm
instructs the command to print ATM layer configuration parameters like
the number of VCI and VPI bits, whereas the
.Fl hardware
option requests card specific information like the vendor or the serial
number.
If none of the options is given the defaults is to assume
.Fl atm .
.\"----------------------------------------
.It Xo
.Ic atmconfig diag phy print
.Op Fl numeric
.Ar device
.Xc
This command prints the PHY registers in a (potential)
human comprehensible format.
If
.Fl numeric
is given the format are hex bytes.
Otherwise textual representation will be printed.
.\"----------------------------------------
.It Xo
.Ic atmconfig diag phy show
.Op Ar device ...
.Xc
This sub-command prints static information about the PHY device used
in the ATM card like the type of the PHY and the media.
.\"----------------------------------------
.It Xo
.Ic atmconfig diag phy set
.Ar device
.Ar reg
.Ar mask
.Ar val
.Xc
This sub-command allows one to change bits in PHY registers.
This should be used with great care.
The bits of the given PHY chip register for which the corresponding bit in
.Ar mask
is one are set to the values of the corresponding bits in
.Ar val .
All register bits that have a zero in
.Ar mask
are written back with their original value.
.\"----------------------------------------
.It Xo
.Ic atmconfig diag phy stats
.Op Fl clear
.Ar device
.Xc
Print the PHY statistics for the given
.Ar device .
When the optional
.Fl clear
is given, the statistics are cleared atomically.
.\"----------------------------------------
.It Xo
.Ic atmconfig diag vcc
.Op Fl abr
.Op Fl channel
.Op Fl traffic
.Op Ar device
.Xc
Retrieve the list of currently active channels on either all
or the specified interfaces.
For each channel the following information is printed depending
on the options (default is
.Fl channel
).
.Pp
.Bl -tag -width XXXX
.It Fl abr
Print ABR specific traffic parameters: ICR, TBE, NRM, TRM, ADTF, RIF, RDF,
CDF.
.It Fl channel
Print basic information: VPI, VCI, AAL, traffic type, MTU and flags.
.It Fl traffic
Print traffic parameters: PCR, SCR, MBS, MCR.
.El
.\"----------------------------------------
.It Xo
.Ic atmconfig diag stats
.Ar device
.Xc
Print driver specific statistics.
.El
.Ss NATM COMMAND
The
.Ic natm
command is used to change
.Xr natmip 4
routes on the local host.
The sub-commands for the routing table are:
.Ic add
(to add a new route),
.Ic delete
(to delete an existing route) and
.Ic show
(to print the currently installed NATM routes).
.Pp
.Bl -tag -width XXXX
.\"----------------------------------------
.It Xo
.Ic atmconfig natm add
.Ar dest
.Ar device
.Ar vpi
.Ar vci
.Ar encaps
.Xc
.It Xo
.Ic atmconfig natm add
.Ar dest
.Ar device
.Ar vpi
.Ar vci
.Ar encaps
.Ic ubr Oo Ar pcr Oc
.Xc
.It Xo
.Ic atmconfig natm add
.Ar dest
.Ar device
.Ar vpi
.Ar vci
.Ar encaps
.Ic cbr Ar pcr
.Xc
.It Xo
.Ic atmconfig natm add
.Ar dest
.Ar device
.Ar vpi
.Ar vci
.Ar encaps
.Ic vbr Ar pcr Ar scr Ar mbs
.Xc
.It Xo
.Ic atmconfig natm add
.Ar dest
.Ar device
.Ar vpi
.Ar vci
.Ar encaps
.Ic abr Ar pcr Ar mcr Ar icr Ar tbe Ar nrm Ar trm Ar adtf Ar rif Ar rdf Ar cdf
.Xc
.Pp
Add a new route to the routing table. The destination address (the address
on the other end of the link) is given in
.Ar dest .
.Ar device ,
.Ar vpi
and
.Ar vci
are the name of the ATM device and the VPI and VCI values for the link.
.Ar encaps
may be either
.Ic AAL5
or
.Ic LLC/SNAP
both of which specify AAL5 encapsulation, the first one without additional
encapsulation, the second one with LLC/SNAP headers.
The first two forms of the command add an UBR (unspecified bit rate) channel,
where the second form allows the optional specification of a peak cell
rate (PCR).
The third form adds a CBR (constant bit rate) channel where a PCR
must be given.
The fourth form adds a VBR (variable bit rate) channel.
The arguments are the peak cell rate, the sustainable cell rate and the
maximum bursts size.
The last form of the command adds an ABR (available bit rate) channel.
.\"----------------------------------------
.It Xo
.Ic atmconfig natm delete
.Ar dest
.Xc
.It Xo
.Ic atmconfig natm delete
.Ar device
.Ar vpi
.Ar vci
.Xc
.Pp
This commands deletes an NATM route.
The route may be specified either by the destination address or
by the
.Ar device ,
.Ar vpi and
.Ar vci
triple.
.\"----------------------------------------
.It Xo
.Ic atmconfig natm show
.Xc
List all NATM routes.
.El
.Sh SEE ALSO
.Xr natm 4 ,
.Xr natmip 4 ,
.Xr atm 8
.Sh AUTHORS
.An Hartmut Brandt Aq harti@freebsd.org

View File

@ -0,0 +1,96 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* $FreeBSD$
*/
#ifndef _ATMCONFIG_H
#define _ATMCONFIG_H
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/queue.h>
#include <netgraph/ng_message.h>
#define DEFAULT_INTERFACE "hatm0"
struct cmdtab {
const char *string;
const struct cmdtab *sub;
void (*func)(int, char *[]);
};
/*
* client configuration info
*/
struct amodule {
struct cmdtab cmd;
const char *help;
};
#define DEF_MODULE(CMDTAB, HELP) \
struct amodule amodule_1 = { CMDTAB, HELP };
/* print a message if we are verbose */
void verb(const char *, ...) __printflike(1, 2);
/* print heading */
void heading(const char *, ...) __printflike(1, 2);
/* before starting output */
void heading_init(void);
/* stringify an enumerated value */
struct penum {
int32_t value;
const char *str;
};
const char *penum(int32_t value, const struct penum *strtab, char *buf);
enum {
OPT_NONE,
OPT_UINT,
OPT_INT,
OPT_UINT32,
OPT_INT32,
OPT_UINT64,
OPT_INT64,
OPT_FLAG,
OPT_VCI,
OPT_STRING,
OPT_SIMPLE,
};
struct option {
const char *optstr;
int opttype;
void *optarg;
};
int parse_options(int *_pargc, char ***_pargv,
const struct option *_opts);
#endif /* _ATMCONFIG_H */

View File

@ -0,0 +1,189 @@
#
# Help file for the atmconfig utility
#
# $FreeBSD$
#
^0 intro
ATM configuration utility.
usage:
atmconfig [common-options] command [subcommand] [options]
Use 'atmconfig help' for general help or 'atmconfig help <command>' for
help on 'command'.
^0 help
Use one of the following commands to get help on atmconfig:
atmconfig help options
gives you help on common command line options
atmconfig help commands
prints a list of available commands (and help items)
atmconfig help <command>
prints help on the given command (including a list of subcommands)
atmconfig help <command> <subcommand>
gives help on the given subcommand
^0 options
Common command line options can be specified for all commands. They
are written immediately before the command. The following options are
available:
-h print short help
-t don't print headings for 'show'-type commands
-v be verbose about all actions.
^0 commands
The following commands are available:
help show help information
diag show/modify ATM hardware interfaces
^0 diag
This command shows information about the ATM hardware interfaces in the
system. A list of ATM devices is obtained by:
atmconfig [common-options] diag list
Information about the hardware configuration of the ATM interfaces is
reported by:
atmconfig [common-options] diag config [options] [<device> ...]
The phy chip can be access with:
atmconfig [common-options] diag phy print [options] <device>
atmconfig [common-options] diag phy show <device>
atmconfig [common-options] diag phy set <device> <reg> <msk> <val>
atmconfig [common-options] diag phy set stats [options] <device>
A list of open VCCs can be obtained with:
atmconfig [common-options] diag vcc [<device> ...]
Driver internal statistics are printed with
atmconfig [common-options] diag stats <device>
^1 list
usage: atmconfig [common-options] diag list
List all known ATM devices in the system.
^1 config
usage: atmconfig [common-options] diag config [-hardware] [-atm] [device ...]
options:
-hardware print hardware related information
-atm print ATM related information
If now device is given as argument information about all devices is shown.
The default is to print only ATM related information.
^1 phy
To show the type of the PHY and its state:
atmconfig [common-options] diag phy show <device>
Change a PHY register (use with care):
atmconfig [common-options] diag phy set <device> <reg> <msk> <val>
Print the PHY registers in a human readable form:
atmconfig [common-options] diag phy print [-numeric] <device>
The PHY statistics can be printed with:
atmconfig [common-options] diag phy stats [-clear] <device>
^2 show
usage: atmconfig [common-options] diag phy show <device>
Show configuration and state information about the PHY chip on the given
ATM interface.
^2 set
usage: atmconfig [common-options] diag phy set <device> <reg> <msk> <val>
Set the bits of given PHY chip register for which the corresponding bit in
<msk> is one to the value of the corresponding bit in <val>. All register
bits that have a zero in <msk> are written back with there original value.
^2 print
usage: atmconfig [common-options] diag phy print [-numeric] <device>
options:
-numeric print registers in hex
Print the registers of the PHY chip in a human readable format.
^2 stats
usage: atmconfig [common-options] diag phy stats [-clear] <device>
options:
-clear clear the statistics atomically after reading them
Prints the PHY layer statistics of the PHY chip and optionally clears them.
^1 vcc
usage: atmconfig [common-options] diag vcc [-abr] [-channel] [-traffic]
[<device> ...]
options:
-abr print ABR specific traffic parameters
-channel print VPI, VCI, AAL, traffic type and flags (default)
-traffic print traffic parameters
Prints a list of all open vccs. The default output is -channel.
^1 stats
usage: atmconfig [common-options] diag stats <device>
Prints the driver-internal statistics.
^0 natm
The group of CLIP commands is used to manage classical IP over ATM
networking via NATM (see natm(4) and natmip(4)). A new PVC is added
to a CLIP via:
atmconfig [common-options] natm add <dest> <device> <vpi> <vci>
<encaps> [<traffic> [<params> ...]]
The PVC can be deleted with:
atmconfig [common-options] natm del <device> <vpi> <vci>
The list of PVC that are currently active is retrieved with:
atmconfig [common-options] natm list
^1 add
usage: atmconfig [common-options] natm add [-printonly] <dest> <device>
<vpi> <vci> <encaps> [<traffic> [<params> ...]]
options:
-printonly don't execute, print the route(8) command
This subcommand adds a new CLIP PVC on the ATM interface <device>. The
host on the other end of the PVC has IP address <addr>. <encaps> is one
of llc/snap (LLC/SNAP encapsulated frames in AAL5) or aal5 (AAL5 frames
without LLC/SNAP). <traffic> specifies the traffic type of the PVC
and is one of UBR, CBR, VBR or ABR. If not given UBR is assumed. Depending
on the traffic type none or more parameters can follow:
ubr [<pcr>]
cbr <pcr>
vbr <pcr> <scr> <mbs>
abr <pcr> <mcr> <icr> <tbe> <nrm> <trm> <adtf> <rif> <rdf> <cdf>
^1 delete
usage: atmconfig [common-options] natm delete [-printonly] <dest>
or: atmconfig [common-options] natm delete [-printonly] <device> <vpi> <vci>
options:
-printonly don't execute, print the route(8) command
This subcommand deletes and existing CLIP PVC that can bei either identified
by the destination address or by the <device><vpi><vci> triple.
^1 show
usage: atmconfig [common-options] natm show [-abr] [-numeric]
options:
-abr show ABR parameters for ABR connections
-numeric print IP addresses numerically
This subcommand prints all ATM routes.

1080
sbin/atm/atmconfig/diag.c Normal file

File diff suppressed because it is too large Load Diff

48
sbin/atm/atmconfig/diag.h Normal file
View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* $FreeBSD$
*/
struct diagif {
TAILQ_ENTRY(diagif) link;
char ifname[IFNAMSIZ];
u_int index;
struct ifatm_mib mib;
u_int phy_type;
u_int phy_loopback;
char phy_name[100];
u_int phy_state;
u_int phy_carrier;
struct atmio_vcctable *vtab;
};
TAILQ_HEAD(diagif_list, diagif);
extern struct diagif_list diagif_list;
void diagif_fetch(void);
void diagif_fetch_vcc(struct diagif *aif, int fd);

519
sbin/atm/atmconfig/main.c Normal file
View File

@ -0,0 +1,519 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/sysctl.h>
#include <netdb.h>
#include <stdarg.h>
#include <ctype.h>
#include <limits.h>
#include <inttypes.h>
#include "atmconfig.h"
#include "private.h"
/* verbosity level */
int verbose;
/* notitle option */
static int notitle;
/* need to put heading before next output */
static int need_heading;
/*
* TOP LEVEL commands
*/
static void help_func(int argc, char *argv[]) __dead2;
static const struct cmdtab main_tab[] = {
{ "help", NULL, help_func },
{ "options", NULL, NULL },
{ "commands", NULL, NULL },
{ "diag", diag_tab, NULL },
{ "natm", natm_tab, NULL },
{ NULL, NULL, NULL }
};
static int
substr(const char *s1, const char *s2)
{
return (strlen(s1) <= strlen(s2) && strncmp(s1, s2, strlen(s1)) == 0);
}
/*
* Function to print help. The help argument is in argv[0] here.
*/
static void
help_func(int argc, char *argv[])
{
FILE *hp;
const char *start, *end;
char *fname;
off_t match, last_match;
char line[LINE_MAX];
char key[100];
int level, i;
/*
* Find the help file
*/
hp = NULL;
for (start = PATH_HELP; *start != '\0'; start = end + 1) {
for (end = start; *end != ':' && *end != '\0'; end++)
;
if (start == end) {
if (asprintf(&fname, "%s", FILE_HELP) == -1)
err(1, NULL);
} else {
if (asprintf(&fname, "%.*s/%s", (int)(end - start),
start, FILE_HELP) == -1)
err(1, NULL);
}
if ((hp = fopen(fname, "r")) != NULL)
break;
free(fname);
}
if (hp == NULL)
errx(1, "help file not found");
if (argc == 0) {
argv[0] = __DECONST(char *, "intro");
argc = 1;
}
optind = 0;
match = -1;
last_match = -1;
for (;;) {
/* read next line */
if (fgets(line, sizeof(line), hp) == NULL) {
if (ferror(hp))
err(1, fname);
/* EOF */
clearerr(hp);
level = 999;
goto stop;
}
if (line[0] != '^')
continue;
if (sscanf(line + 1, "%d%99s", &level, key) != 2)
errx(1, "error in help file '%s'", line);
if (level < optind) {
stop:
/* next higher level entry - stop this level */
if (match == -1) {
/* not found */
goto not_found;
}
/* go back to the match */
if (fseeko(hp, match, SEEK_SET) == -1)
err(1, fname);
last_match = match;
match = -1;
/* go to next key */
if (++optind >= argc)
break;
}
if (level == optind) {
if (substr(argv[optind], key)) {
if (match != -1) {
printf("Ambiguous topic.");
goto list_topics;
}
if ((match = ftello(hp)) == -1)
err(1, fname);
}
}
}
if (last_match == -1) {
if (fseek(hp, 0L, SEEK_SET) == -1)
err(1, fname);
} else {
if (fseeko(hp, last_match, SEEK_SET) == -1)
err(1, fname);
}
for (;;) {
if (fgets(line, sizeof(line), hp) == NULL) {
if (ferror(hp))
err(1, fname);
break;
}
if (line[0] == '#')
continue;
if (line[0] == '^')
break;
printf("%s", line);
}
exit(0);
not_found:
printf("Topic not found.");
list_topics:
printf(" Use one of:\natmconfig");
for (i = 0; i < optind; i++)
printf(" %s", argv[i]);
printf(" [");
/* list all the keys at this level */
if (last_match == -1) {
if (fseek(hp, 0L, SEEK_SET) == -1)
err(1, fname);
} else {
if (fseeko(hp, last_match, SEEK_SET) == -1)
err(1, fname);
}
for (;;) {
/* read next line */
if (fgets(line, sizeof(line), hp) == NULL) {
if (ferror(hp))
err(1, fname);
break;
}
if (line[0] == '#' || line[0] != '^')
continue;
if (sscanf(line + 1, "%d%99s", &level, key) != 2)
errx(1, "error in help file '%s'", line);
if (level < optind)
break;
if (level == optind)
printf(" %s", key);
}
printf(" ]\n");
exit(1);
}
int
main(int argc, char *argv[])
{
int opt, i;
const struct cmdtab *match, *cc, *tab;
while ((opt = getopt(argc, argv, "htv")) != -1)
switch (opt) {
case 'h':
help_func(0, argv);
case 'v':
verbose++;
break;
case 't':
notitle = 1;
break;
}
if (argv[optind] == NULL)
help_func(0, argv);
argc -= optind;
argv += optind;
cc = main_tab;
i = 0;
for (;;) {
/*
* Scan the table for a match
*/
tab = cc;
match = NULL;
while (cc->string != NULL) {
if (substr(argv[i], cc->string)) {
if (match != NULL) {
printf("Ambiguous option '%s'",
argv[i]);
cc = tab;
goto subopts;
}
match = cc;
}
cc++;
}
if ((cc = match) == NULL) {
printf("Unknown option '%s'", argv[i]);
cc = tab;
goto subopts;
}
/*
* Have a match. If there is no subtable, there must
* be either a handler or the command is only a help entry.
*/
if (cc->sub == NULL) {
if (cc->func != NULL)
break;
printf("Unknown option '%s'", argv[i]);
cc = tab;
goto subopts;
}
/*
* Look at the next argument. If it doesn't exist or it
* looks like a switch, terminate the scan here.
*/
if (argv[i + 1] == NULL || argv[i + 1][0] == '-') {
if (cc->func != NULL)
break;
printf("Need sub-option for '%s'", argv[i]);
cc = cc->sub;
goto subopts;
}
cc = cc->sub;
i++;
}
argc -= i + 1;
argv += i + 1;
(*cc->func)(argc, argv);
return (0);
subopts:
printf(". Select one of:\n");
while (cc->string != NULL) {
if (cc->func != NULL || cc->sub != NULL)
printf("%s ", cc->string);
cc++;
}
printf("\n");
return (1);
}
void
verb(const char *fmt, ...)
{
va_list ap;
if (verbose) {
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
}
}
void
heading(const char *fmt, ...)
{
va_list ap;
if (need_heading) {
need_heading = 0;
if (!notitle) {
va_start(ap, fmt);
fprintf(stdout, fmt, ap);
va_end(ap);
}
}
}
void
heading_init(void)
{
need_heading = 1;
}
/*
* stringify an enumerated value
*/
const char *
penum(int32_t value, const struct penum *strtab, char *buf)
{
while (strtab->str != NULL) {
if (strtab->value == value) {
strcpy(buf, strtab->str);
return (buf);
}
strtab++;
}
warnx("illegal value for enumerated variable '%d'", value);
strcpy(buf, "?");
return (buf);
}
/*
* Parse command line options
*/
int
parse_options(int *pargc, char ***pargv, const struct option *opts)
{
const struct option *o, *m;
char *arg;
u_long ularg, ularg1;
long larg;
char *end;
if (*pargc == 0)
return (-1);
arg = (*pargv)[0];
if (arg[0] != '-' || arg[1] == '\0')
return (-1);
if (arg[1] == '-' && arg[2] == '\0') {
(*pargv)++;
(*pargc)--;
return (-1);
}
m = NULL;
for (o = opts; o->optstr != NULL; o++) {
if (strlen(arg + 1) <= strlen(o->optstr) &&
strncmp(arg + 1, o->optstr, strlen(arg + 1)) == 0) {
if (m != NULL)
errx(1, "ambiguous option '%s'", arg);
m = o;
}
}
if (m == NULL)
errx(1, "unknown option '%s'", arg);
(*pargv)++;
(*pargc)--;
if (m->opttype == OPT_NONE)
return (m - opts);
if (m->opttype == OPT_SIMPLE) {
*(int *)m->optarg = 1;
return (m - opts);
}
if (*pargc == 0)
errx(1, "option requires argument '%s'", arg);
optarg = *(*pargv)++;
(*pargc)--;
switch (m->opttype) {
case OPT_UINT:
ularg = strtoul(optarg, &end, 0);
if (*end != '\0')
errx(1, "bad unsigned integer argument for '%s'", arg);
if (ularg > UINT_MAX)
errx(1, "argument to large for option '%s'", arg);
*(u_int *)m->optarg = (u_int)ularg;
break;
case OPT_INT:
larg = strtol(optarg, &end, 0);
if (*end != '\0')
errx(1, "bad integer argument for '%s'", arg);
if (larg > INT_MAX || larg < INT_MIN)
errx(1, "argument out of range for option '%s'", arg);
*(int *)m->optarg = (int)larg;
break;
case OPT_UINT32:
ularg = strtoul(optarg, &end, 0);
if (*end != '\0')
errx(1, "bad unsigned integer argument for '%s'", arg);
if (ularg > UINT32_MAX)
errx(1, "argument to large for option '%s'", arg);
*(uint32_t *)m->optarg = (uint32_t)ularg;
break;
case OPT_INT32:
larg = strtol(optarg, &end, 0);
if (*end != '\0')
errx(1, "bad integer argument for '%s'", arg);
if (larg > INT32_MAX || larg < INT32_MIN)
errx(1, "argument out of range for option '%s'", arg);
*(int32_t *)m->optarg = (int32_t)larg;
break;
case OPT_UINT64:
*(uint64_t *)m->optarg = strtoull(optarg, &end, 0);
if (*end != '\0')
errx(1, "bad unsigned integer argument for '%s'", arg);
break;
case OPT_INT64:
*(int64_t *)m->optarg = strtoll(optarg, &end, 0);
if (*end != '\0')
errx(1, "bad integer argument for '%s'", arg);
break;
case OPT_FLAG:
if (strcasecmp(optarg, "enable") == 0 ||
strcasecmp(optarg, "yes") == 0 ||
strcasecmp(optarg, "true") == 0 ||
strcasecmp(optarg, "on") == 0 ||
strcmp(optarg, "1") == 0)
*(int *)m->optarg = 1;
else if (strcasecmp(optarg, "disable") == 0 ||
strcasecmp(optarg, "no") == 0 ||
strcasecmp(optarg, "false") == 0 ||
strcasecmp(optarg, "off") == 0 ||
strcmp(optarg, "0") == 0)
*(int *)m->optarg = 0;
else
errx(1, "bad boolean argument to '%s'", arg);
break;
case OPT_VCI:
ularg = strtoul(optarg, &end, 0);
if (*end == '.') {
ularg1 = strtoul(end + 1, &end, 0);
} else {
ularg1 = ularg;
ularg = 0;
}
if (*end != '\0')
errx(1, "bad VCI value for option '%s'", arg);
if (ularg > 0xff)
errx(1, "VPI value too large for option '%s'", arg);
if (ularg1 > 0xffff)
errx(1, "VCI value too large for option '%s'", arg);
((u_int *)m->optarg)[0] = ularg;
((u_int *)m->optarg)[1] = ularg1;
break;
case OPT_STRING:
if (m->optarg != NULL)
*(const char **)m->optarg = optarg;
break;
default:
errx(1, "(internal) bad option type %u for '%s'",
m->opttype, arg);
}
return (m - opts);
}

683
sbin/atm/atmconfig/natm.c Normal file
View File

@ -0,0 +1,683 @@
/*
* Copyright (c) 2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_mib.h>
#include <net/if_atm.h>
#include <net/if_dl.h>
#include <net/route.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "atmconfig.h"
#include "private.h"
#include "diag.h"
static void natm_add(int, char *[]);
static void natm_delete(int, char *[]);
static void natm_show(int, char *[]);
const struct cmdtab natm_tab[] = {
{ "add", NULL, natm_add },
{ "delete", NULL, natm_delete },
{ "show", NULL, natm_show },
{ NULL, NULL, NULL }
};
/*
* Structure to hold a route
*/
struct natm_route {
TAILQ_ENTRY(natm_route) link;
struct in_addr host;
struct diagif *aif;
u_int flags;
int llcsnap;
u_int vpi, vci;
u_int traffic;
u_int pcr, scr, mbs, icr, mcr;
u_int tbe, nrm, trm, adtf, rif, rdf, cdf;
};
static TAILQ_HEAD(, natm_route) natm_route_list =
TAILQ_HEAD_INITIALIZER(natm_route_list);
static void
store_route(struct rt_msghdr *rtm)
{
u_int i;
struct natm_route *r;
char *cp;
struct sockaddr *sa;
struct sockaddr_in *sain;
struct sockaddr_dl *sdl;
struct diagif *aif;
u_int n;
r = malloc(sizeof(*r));
if (r == NULL)
err(1, "allocate route");
r->flags = rtm->rtm_flags;
cp = (char *)(rtm + 1);
for (i = 1; i != 0; i <<= 1) {
if (rtm->rtm_addrs & i) {
sa = (struct sockaddr *)cp;
cp += roundup(sa->sa_len, sizeof(long));
switch (i) {
case RTA_DST:
if (sa->sa_family != AF_INET) {
warnx("RTA_DST not AF_INET %u", sa->sa_family);
goto fail;
}
sain = (struct sockaddr_in *)(void *)sa;
if (sain->sin_len < 4)
r->host.s_addr = INADDR_ANY;
else
r->host = sain->sin_addr;
break;
case RTA_GATEWAY:
if (sa->sa_family != AF_LINK) {
warnx("RTA_GATEWAY not AF_LINK");
goto fail;
}
sdl = (struct sockaddr_dl *)(void *)sa;
TAILQ_FOREACH(aif, &diagif_list, link)
if (strlen(aif->ifname) ==
sdl->sdl_nlen &&
strncmp(aif->ifname, sdl->sdl_data,
sdl->sdl_nlen) == 0)
break;
if (aif == NULL) {
warnx("interface '%.*s' not found",
sdl->sdl_nlen, sdl->sdl_data);
goto fail;
}
r->aif = aif;
/* parse ATM stuff */
#define GET3() (((sdl->sdl_data[n] & 0xff) << 16) | \
((sdl->sdl_data[n + 1] & 0xff) << 8) | \
((sdl->sdl_data[n + 2] & 0xff) << 0))
#define GET2() (((sdl->sdl_data[n] & 0xff) << 8) | \
((sdl->sdl_data[n + 1] & 0xff) << 0))
#define GET1() (((sdl->sdl_data[n] & 0xff) << 0))
n = sdl->sdl_nlen;
if (sdl->sdl_alen < 4) {
warnx("RTA_GATEWAY alen too short");
goto fail;
}
r->llcsnap = GET1() & ATM_PH_LLCSNAP;
n++;
r->vpi = GET1();
n++;
r->vci = GET2();
n += 2;
if (sdl->sdl_alen == 4) {
/* old address */
r->traffic = ATMIO_TRAFFIC_UBR;
r->pcr = 0;
break;
}
/* new address */
r->traffic = GET1();
n++;
switch (r->traffic) {
case ATMIO_TRAFFIC_UBR:
if (sdl->sdl_alen >= 5 + 3) {
r->pcr = GET3();
n += 3;
} else
r->pcr = 0;
break;
case ATMIO_TRAFFIC_CBR:
if (sdl->sdl_alen < 5 + 3) {
warnx("CBR address too short");
goto fail;
}
r->pcr = GET3();
n += 3;
break;
case ATMIO_TRAFFIC_VBR:
if (sdl->sdl_alen < 5 + 3 * 3) {
warnx("VBR address too short");
goto fail;
}
r->pcr = GET3();
n += 3;
r->scr = GET3();
n += 3;
r->mbs = GET3();
n += 3;
break;
case ATMIO_TRAFFIC_ABR:
if (sdl->sdl_alen < 5 + 4 * 3 + 2 +
1 * 2 + 3) {
warnx("ABR address too short");
goto fail;
}
r->pcr = GET3();
n += 3;
r->mcr = GET3();
n += 3;
r->icr = GET3();
n += 3;
r->tbe = GET3();
n += 3;
r->nrm = GET1();
n++;
r->trm = GET1();
n++;
r->adtf = GET2();
n += 2;
r->rif = GET1();
n++;
r->rdf = GET1();
n++;
r->cdf = GET1();
n++;
break;
default:
goto fail;
}
break;
}
}
}
TAILQ_INSERT_TAIL(&natm_route_list, r, link);
return;
fail:
free(r);
}
/*
* Fetch the INET routes that a ours
*/
static void
natm_route_fetch(void)
{
int name[6];
size_t needed;
u_char *buf, *next;
struct rt_msghdr *rtm;
name[0] = CTL_NET;
name[1] = PF_ROUTE;
name[2] = 0;
name[3] = AF_INET;
name[4] = NET_RT_DUMP;
name[5] = 0;
if (sysctl(name, 6, NULL, &needed, NULL, 0) == -1)
err(1, "rtable estimate");
needed *= 2;
if ((buf = malloc(needed)) == NULL)
err(1, "rtable buffer (%zu)", needed);
if (sysctl(name, 6, buf, &needed, NULL, 0) == -1)
err(1, "rtable get");
next = buf;
while (next < buf + needed) {
rtm = (struct rt_msghdr *)(void *)next;
next += rtm->rtm_msglen;
if (rtm->rtm_type == RTM_GET) {
if ((rtm->rtm_flags & (RTF_UP | RTF_HOST |
RTF_STATIC)) == (RTF_UP | RTF_HOST | RTF_STATIC) &&
(rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY |
RTA_IFP)) == (RTA_DST | RTA_GATEWAY | RTA_IFP))
store_route(rtm);
}
}
}
static u_long
parse_num(const char *arg, const char *name, u_long limit)
{
u_long res;
char *end;
errno = 0;
res = strtoul(arg, &end, 10);
if (*end != '\0' || end == arg || errno != 0)
errx(1, "cannot parse %s '%s'", name, arg);
if (res > limit)
errx(1, "%s out of range (0...%lu)", name, limit);
return (res);
}
static void
do_route(u_int type, u_int flags, const struct sockaddr_in *sain,
const struct sockaddr_dl *sdl)
{
struct {
struct rt_msghdr h;
char space[512];
} msg;
char *ptr;
int s;
ssize_t rlen;
/* create routing message */
bzero(&msg, sizeof(msg));
msg.h.rtm_msglen = sizeof(msg.h);
msg.h.rtm_version = RTM_VERSION;
msg.h.rtm_type = type;
msg.h.rtm_index = 0;
msg.h.rtm_flags = flags;
msg.h.rtm_addrs = RTA_DST | (sdl != NULL ? RTA_GATEWAY : 0);
msg.h.rtm_pid = getpid();
ptr = (char *)&msg + sizeof(msg.h);
memcpy(ptr, sain, sain->sin_len);
ptr += roundup(sain->sin_len, sizeof(long));
msg.h.rtm_msglen += roundup(sain->sin_len, sizeof(long));
if (sdl != NULL) {
memcpy(ptr, sdl, sdl->sdl_len);
ptr += roundup(sdl->sdl_len, sizeof(long));
msg.h.rtm_msglen += roundup(sdl->sdl_len, sizeof(long));
}
/* open socket */
s = socket(PF_ROUTE, SOCK_RAW, AF_INET);
if (s == -1)
err(1, "cannot open routing socket");
rlen = write(s, &msg, msg.h.rtm_msglen);
if (rlen == -1)
err(1, "writing to routing socket");
if ((size_t)rlen != msg.h.rtm_msglen)
errx(1, "short write to routing socket: %zu %u",
(size_t)rlen, msg.h.rtm_msglen);
close(s);
}
/*
* Add a new NATM route
*/
static void
natm_add(int argc, char *argv[])
{
int opt;
struct hostent *hp;
struct sockaddr_in sain;
struct sockaddr_dl sdl;
struct diagif *aif;
u_long num, num1;
u_int idx;
static int printonly;
static const struct option opts[] = {
{ "printonly", OPT_SIMPLE, &printonly },
{ NULL, 0, NULL }
};
while ((opt = parse_options(&argc, &argv, opts)) != -1)
switch (opt) {
}
if (argc < 5)
errx(1, "missing arguments for 'natm add'");
memset(&sdl, 0, sizeof(sdl));
sdl.sdl_len = sizeof(sdl);
sdl.sdl_family = AF_LINK;
/* get the IP address for <dest> */
memset(&sain, 0, sizeof(sain));
hp = gethostbyname(argv[0]);
if (hp == NULL)
errx(1, "bad hostname %s: %s", argv[0], hstrerror(h_errno));
if (hp->h_addrtype != AF_INET)
errx(1, "bad address type for %s", argv[0]);
sain.sin_len = sizeof(sain);
sain.sin_family = AF_INET;
memcpy(&sain.sin_addr, hp->h_addr, sizeof(sain.sin_addr));
/* find interface */
diagif_fetch();
TAILQ_FOREACH(aif, &diagif_list, link)
if (strcmp(aif->ifname, argv[1]) == 0)
break;
if (aif == NULL)
errx(1, "unknown ATM interface '%s'", argv[1]);
sdl.sdl_index = aif->index;
strcpy(sdl.sdl_data, aif->ifname);
idx = sdl.sdl_nlen = strlen(aif->ifname);
idx++;
/* verify VPI/VCI */
num = parse_num(argv[2], "VPI", (1U << aif->mib.vpi_bits));
sdl.sdl_data[idx++] = num & 0xff;
num = parse_num(argv[3], "VCI", (1U << aif->mib.vci_bits));
if (num == 0)
errx(1, "VCI may not be 0");
sdl.sdl_data[idx++] = (num >> 8) & 0xff;
sdl.sdl_data[idx++] = num & 0xff;
/* encapsulation */
if (strcasecmp(argv[4], "llc/snap") == 0) {
sdl.sdl_data[sdl.sdl_nlen] = ATM_PH_LLCSNAP;
} else if (strcasecmp(argv[4], "aal5") == 0) {
sdl.sdl_data[sdl.sdl_nlen] = 0;
} else
errx(1, "bad encapsulation type '%s'", argv[4]);
/* look at the traffic */
argc -= 5;
argv += 5;
if (argc != 0) {
if (strcasecmp(argv[0], "ubr") == 0) {
sdl.sdl_data[idx++] = ATMIO_TRAFFIC_UBR;
if (argc == 1)
/* ok */;
else if (argc == 2) {
num = parse_num(argv[1], "PCR", aif->mib.pcr);
sdl.sdl_data[idx++] = (num >> 16) & 0xff;
sdl.sdl_data[idx++] = (num >> 8) & 0xff;
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
} else
errx(1, "too many parameters for UBR");
} else if (strcasecmp(argv[0], "cbr") == 0) {
sdl.sdl_data[idx++] = ATMIO_TRAFFIC_CBR;
if (argc == 1)
errx(1, "missing PCR for CBR");
if (argc > 2)
errx(1, "too many parameters for CBR");
num = parse_num(argv[1], "PCR", aif->mib.pcr);
sdl.sdl_data[idx++] = (num >> 16) & 0xff;
sdl.sdl_data[idx++] = (num >> 8) & 0xff;
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
} else if (strcasecmp(argv[0], "vbr") == 0) {
sdl.sdl_data[idx++] = ATMIO_TRAFFIC_VBR;
if (argc < 4)
errx(1, "missing arg(s) for VBR");
if (argc > 4)
errx(1, "too many parameters for VBR");
num = parse_num(argv[1], "PCR", aif->mib.pcr);
sdl.sdl_data[idx++] = (num >> 16) & 0xff;
sdl.sdl_data[idx++] = (num >> 8) & 0xff;
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
num = parse_num(argv[2], "SCR", num);
sdl.sdl_data[idx++] = (num >> 16) & 0xff;
sdl.sdl_data[idx++] = (num >> 8) & 0xff;
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
num = parse_num(argv[3], "MBS", 0xffffffLU);
sdl.sdl_data[idx++] = (num >> 16) & 0xff;
sdl.sdl_data[idx++] = (num >> 8) & 0xff;
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
} else if (strcasecmp(argv[0], "abr") == 0) {
sdl.sdl_data[idx++] = ATMIO_TRAFFIC_ABR;
if (argc < 11)
errx(1, "missing arg(s) for ABR");
if (argc > 11)
errx(1, "too many parameters for ABR");
num = parse_num(argv[1], "PCR", aif->mib.pcr);
sdl.sdl_data[idx++] = (num >> 16) & 0xff;
sdl.sdl_data[idx++] = (num >> 8) & 0xff;
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
num1 = parse_num(argv[2], "MCR", num);
sdl.sdl_data[idx++] = (num1 >> 16) & 0xff;
sdl.sdl_data[idx++] = (num1 >> 8) & 0xff;
sdl.sdl_data[idx++] = (num1 >> 0) & 0xff;
num = parse_num(argv[3], "ICR", num);
sdl.sdl_data[idx++] = (num >> 16) & 0xff;
sdl.sdl_data[idx++] = (num >> 8) & 0xff;
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
if (num < num1)
errx(1, "ICR must be >= MCR");
num = parse_num(argv[4], "TBE", 0xffffffUL);
sdl.sdl_data[idx++] = (num >> 16) & 0xff;
sdl.sdl_data[idx++] = (num >> 8) & 0xff;
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
num = parse_num(argv[5], "NRM", 0x7UL);
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
num = parse_num(argv[6], "TRM", 0x7UL);
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
num = parse_num(argv[7], "ADTF", 0x3ffUL);
sdl.sdl_data[idx++] = (num >> 8) & 0xff;
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
num = parse_num(argv[8], "RIF", 0xfUL);
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
num = parse_num(argv[9], "RDF", 0xfUL);
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
num = parse_num(argv[10], "CDF", 0x7UL);
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
} else
errx(1, "bad traffic type '%s'", argv[0]);
} else
sdl.sdl_data[idx++] = ATMIO_TRAFFIC_UBR;
sdl.sdl_alen = idx - sdl.sdl_nlen;
sdl.sdl_len += sdl.sdl_nlen + sdl.sdl_alen;
if (printonly) {
printf("route add -iface %s -link %.*s",
inet_ntoa(sain.sin_addr), sdl.sdl_nlen, sdl.sdl_data);
for (idx = 0; idx < sdl.sdl_alen; idx++)
printf("%c%x", ".:"[idx == 0],
(u_int)sdl.sdl_data[sdl.sdl_nlen + idx] & 0xffU);
printf("\n");
exit(0);
}
do_route(RTM_ADD, RTF_HOST | RTF_STATIC | RTF_UP, &sain, &sdl);
}
/*
* Delete an NATM route
*/
static void
natm_delete(int argc, char *argv[])
{
int opt;
struct hostent *hp;
struct sockaddr_in sain;
u_int vpi, vci;
struct diagif *aif;
struct natm_route *r;
static int printonly;
static const struct option opts[] = {
{ "printonly", OPT_SIMPLE, &printonly },
{ NULL, 0, NULL }
};
while ((opt = parse_options(&argc, &argv, opts)) != -1)
switch (opt) {
}
diagif_fetch();
natm_route_fetch();
memset(&sain, 0, sizeof(sain));
sain.sin_len = sizeof(sain);
sain.sin_family = AF_INET;
if (argc == 1) {
/* get the IP address for <dest> */
hp = gethostbyname(argv[0]);
if (hp == NULL)
errx(1, "bad hostname %s: %s", argv[0],
hstrerror(h_errno));
if (hp->h_addrtype != AF_INET)
errx(1, "bad address type for %s", argv[0]);
memcpy(&sain.sin_addr, hp->h_addr, sizeof(sain.sin_addr));
TAILQ_FOREACH(r, &natm_route_list, link)
if (r->host.s_addr == sain.sin_addr.s_addr)
break;
if (r == NULL)
errx(1, "no NATM route to host '%s' (%s)", argv[0],
inet_ntoa(sain.sin_addr));
} else if (argc == 3) {
TAILQ_FOREACH(aif, &diagif_list, link)
if (strcmp(aif->ifname, argv[0]) == 0)
break;
if (aif == 0)
errx(1, "no such interface '%s'", argv[0]);
vpi = parse_num(argv[1], "VPI", 0xff);
vci = parse_num(argv[2], "VCI", 0xffff);
TAILQ_FOREACH(r, &natm_route_list, link)
if (r->aif == aif && r->vpi == vpi && r->vci == vci)
break;
if (r == NULL)
errx(1, "no such NATM route %s %u %u", argv[0],
vpi, vci);
sain.sin_addr = r->host;
} else
errx(1, "bad number of arguments for 'natm delete'");
if (printonly) {
printf("route delete %s\n", inet_ntoa(r->host));
exit(0);
}
do_route(RTM_DELETE, r->flags, &sain, NULL);
}
/*
* Show NATM routes
*/
static void
natm_show(int argc, char *argv[])
{
int opt;
struct natm_route *r;
struct hostent *hp;
static const char *const traffics[] = {
[ATMIO_TRAFFIC_UBR] = "UBR",
[ATMIO_TRAFFIC_CBR] = "CBR",
[ATMIO_TRAFFIC_VBR] = "VBR",
[ATMIO_TRAFFIC_ABR] = "ABR"
};
static int numeric, abr;
static const struct option opts[] = {
{ "abr", OPT_SIMPLE, &abr },
{ "numeric", OPT_SIMPLE, &numeric },
{ NULL, 0, NULL }
};
static const char head[] =
"Destination Iface VPI VCI Encaps Trf PCR "
"SCR/MCR MBS/ICR\n";
static const char head_abr[] =
"Destination Iface VPI VCI Encaps Trf PCR "
"SCR/MCR MBS/ICR TBE NRM TRM ADTF RIF RDF CDF\n";
while ((opt = parse_options(&argc, &argv, opts)) != -1)
switch (opt) {
}
diagif_fetch();
natm_route_fetch();
heading_init();
TAILQ_FOREACH(r, &natm_route_list, link) {
heading(abr ? head_abr : head);
if (numeric)
printf("%-20s", inet_ntoa(r->host));
else if (r->host.s_addr == INADDR_ANY)
printf("%-20s", "default");
else {
hp = gethostbyaddr((char *)&r->host, sizeof(r->host),
AF_INET);
if (hp != NULL)
printf("%-20s", hp->h_name);
else
printf("%-20s", inet_ntoa(r->host));
}
printf("%-12s%-4u%-6u%-9s%-4s", r->aif->ifname, r->vpi, r->vci,
r->llcsnap ? "LLC/SNAP" : "AAL5", traffics[r->traffic]);
switch (r->traffic) {
case ATMIO_TRAFFIC_UBR:
case ATMIO_TRAFFIC_CBR:
printf("%-8u", r->pcr);
break;
case ATMIO_TRAFFIC_VBR:
printf("%-8u%-8u%-8u", r->pcr, r->scr, r->mbs);
break;
case ATMIO_TRAFFIC_ABR:
printf("%-8u%-8u%-8u", r->pcr, r->mcr, r->icr);
if (abr)
printf("%-8u%-4u%-4u%-5u%-4u%-4u%-4u",
r->tbe, r->nrm, r->trm, r->adtf,
r->rif, r->rdf, r->cdf);
break;
}
printf("\n");
}
}

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/queue.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <err.h>
#include <errno.h>
#include <netgraph.h>
#include <net/if.h>
#include <netinet/in.h>
#define PATH_HELP ".:/usr/share/doc/atm"
#define FILE_HELP "atmconfig.help"
/*
* Builtin commands
*/
extern const struct cmdtab diag_tab[];
extern const struct cmdtab natm_tab[];